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,474 @@
|
|
|
1
|
+
"""Claude Code message history loader and converter.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for loading Claude Code's conversation history
|
|
4
|
+
from ~/.claude/projects/ and converting it to pydantic-ai message format.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
import json
|
|
11
|
+
from typing import TYPE_CHECKING, Annotated, Any, Literal
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from pydantic_ai import ModelRequest, ModelResponse
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel, Field
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Claude Code history entry types
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ClaudeCodeUsage(BaseModel):
|
|
26
|
+
"""Token usage information from Claude Code."""
|
|
27
|
+
|
|
28
|
+
input_tokens: int = 0
|
|
29
|
+
output_tokens: int = 0
|
|
30
|
+
cache_creation_input_tokens: int = 0
|
|
31
|
+
cache_read_input_tokens: int = 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ClaudeCodeTextContent(BaseModel):
|
|
35
|
+
"""Text content block in Claude Code messages."""
|
|
36
|
+
|
|
37
|
+
type: Literal["text"]
|
|
38
|
+
text: str
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class ClaudeCodeToolUseContent(BaseModel):
|
|
42
|
+
"""Tool use content block in Claude Code messages."""
|
|
43
|
+
|
|
44
|
+
type: Literal["tool_use"]
|
|
45
|
+
id: str
|
|
46
|
+
name: str
|
|
47
|
+
input: dict[str, Any]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ClaudeCodeToolResultContent(BaseModel):
|
|
51
|
+
"""Tool result content block in Claude Code messages."""
|
|
52
|
+
|
|
53
|
+
type: Literal["tool_result"]
|
|
54
|
+
tool_use_id: str
|
|
55
|
+
content: list[ClaudeCodeTextContent] | str
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ClaudeCodeThinkingContent(BaseModel):
|
|
59
|
+
"""Thinking content block in Claude Code messages."""
|
|
60
|
+
|
|
61
|
+
type: Literal["thinking"]
|
|
62
|
+
thinking: str
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
ClaudeCodeContentBlock = Annotated[
|
|
66
|
+
ClaudeCodeTextContent
|
|
67
|
+
| ClaudeCodeToolUseContent
|
|
68
|
+
| ClaudeCodeToolResultContent
|
|
69
|
+
| ClaudeCodeThinkingContent,
|
|
70
|
+
Field(discriminator="type"),
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class ClaudeCodeUserMessage(BaseModel):
|
|
75
|
+
"""User message payload in Claude Code format."""
|
|
76
|
+
|
|
77
|
+
role: Literal["user"]
|
|
78
|
+
content: str | list[ClaudeCodeContentBlock]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class ClaudeCodeAssistantMessage(BaseModel):
|
|
82
|
+
"""Assistant message payload in Claude Code format."""
|
|
83
|
+
|
|
84
|
+
model: str | None = None
|
|
85
|
+
id: str | None = None
|
|
86
|
+
type: Literal["message"] = "message"
|
|
87
|
+
role: Literal["assistant"]
|
|
88
|
+
content: list[ClaudeCodeContentBlock]
|
|
89
|
+
stop_reason: str | None = None
|
|
90
|
+
usage: ClaudeCodeUsage | None = None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class ClaudeCodeUserEntry(BaseModel):
|
|
94
|
+
"""A user entry in Claude Code's JSONL history."""
|
|
95
|
+
|
|
96
|
+
type: Literal["user"]
|
|
97
|
+
message: ClaudeCodeUserMessage
|
|
98
|
+
uuid: str
|
|
99
|
+
parent_uuid: str | None = Field(default=None, alias="parentUuid")
|
|
100
|
+
session_id: str = Field(alias="sessionId")
|
|
101
|
+
timestamp: datetime
|
|
102
|
+
cwd: str | None = None
|
|
103
|
+
version: str | None = None
|
|
104
|
+
git_branch: str | None = Field(default=None, alias="gitBranch")
|
|
105
|
+
is_sidechain: bool = Field(default=False, alias="isSidechain")
|
|
106
|
+
user_type: str | None = Field(default=None, alias="userType")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class ClaudeCodeAssistantEntry(BaseModel):
|
|
110
|
+
"""An assistant entry in Claude Code's JSONL history."""
|
|
111
|
+
|
|
112
|
+
type: Literal["assistant"]
|
|
113
|
+
message: ClaudeCodeAssistantMessage
|
|
114
|
+
uuid: str
|
|
115
|
+
parent_uuid: str | None = Field(default=None, alias="parentUuid")
|
|
116
|
+
session_id: str = Field(alias="sessionId")
|
|
117
|
+
timestamp: datetime
|
|
118
|
+
request_id: str | None = Field(default=None, alias="requestId")
|
|
119
|
+
cwd: str | None = None
|
|
120
|
+
version: str | None = None
|
|
121
|
+
git_branch: str | None = Field(default=None, alias="gitBranch")
|
|
122
|
+
is_sidechain: bool = Field(default=False, alias="isSidechain")
|
|
123
|
+
user_type: str | None = Field(default=None, alias="userType")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class ClaudeCodeQueueOperation(BaseModel):
|
|
127
|
+
"""A queue operation entry (metadata, not a message)."""
|
|
128
|
+
|
|
129
|
+
type: Literal["queue-operation"]
|
|
130
|
+
operation: str
|
|
131
|
+
timestamp: datetime
|
|
132
|
+
session_id: str = Field(alias="sessionId")
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class ClaudeCodeSummary(BaseModel):
|
|
136
|
+
"""A summary entry in Claude Code's history."""
|
|
137
|
+
|
|
138
|
+
type: Literal["summary"]
|
|
139
|
+
summary: str
|
|
140
|
+
uuid: str
|
|
141
|
+
parent_uuid: str | None = Field(default=None, alias="parentUuid")
|
|
142
|
+
session_id: str = Field(alias="sessionId")
|
|
143
|
+
timestamp: datetime
|
|
144
|
+
is_sidechain: bool = Field(default=False, alias="isSidechain")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
ClaudeCodeEntry = Annotated[
|
|
148
|
+
ClaudeCodeUserEntry | ClaudeCodeAssistantEntry | ClaudeCodeQueueOperation | ClaudeCodeSummary,
|
|
149
|
+
Field(discriminator="type"),
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
# Message entries that have uuid and parent_uuid (excludes queue operations)
|
|
153
|
+
ClaudeCodeMessageEntry = ClaudeCodeUserEntry | ClaudeCodeAssistantEntry | ClaudeCodeSummary
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def parse_entry(line: str) -> ClaudeCodeEntry | None:
|
|
157
|
+
"""Parse a single JSONL line into a Claude Code entry.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
line: A single line from the JSONL file
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Parsed entry or None if the line is empty or unparseable
|
|
164
|
+
"""
|
|
165
|
+
line = line.strip()
|
|
166
|
+
if not line:
|
|
167
|
+
return None
|
|
168
|
+
|
|
169
|
+
data = json.loads(line)
|
|
170
|
+
entry_type = data.get("type")
|
|
171
|
+
|
|
172
|
+
match entry_type:
|
|
173
|
+
case "user":
|
|
174
|
+
return ClaudeCodeUserEntry.model_validate(data)
|
|
175
|
+
case "assistant":
|
|
176
|
+
return ClaudeCodeAssistantEntry.model_validate(data)
|
|
177
|
+
case "queue-operation":
|
|
178
|
+
return ClaudeCodeQueueOperation.model_validate(data)
|
|
179
|
+
case "summary":
|
|
180
|
+
return ClaudeCodeSummary.model_validate(data)
|
|
181
|
+
case _:
|
|
182
|
+
return None
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def load_session(session_path: Path) -> list[ClaudeCodeEntry]:
|
|
186
|
+
"""Load all entries from a Claude Code session file.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
session_path: Path to the .jsonl session file
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
List of parsed entries
|
|
193
|
+
"""
|
|
194
|
+
with session_path.open() as f:
|
|
195
|
+
return [entry for line in f if (entry := parse_entry(line))]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_main_conversation(
|
|
199
|
+
entries: list[ClaudeCodeEntry],
|
|
200
|
+
*,
|
|
201
|
+
include_sidechains: bool = False,
|
|
202
|
+
) -> list[ClaudeCodeMessageEntry]:
|
|
203
|
+
"""Extract the main conversation thread from entries.
|
|
204
|
+
|
|
205
|
+
Claude Code supports forking conversations via parentUuid. This function
|
|
206
|
+
follows the parent chain to reconstruct the main conversation, optionally
|
|
207
|
+
including or excluding sidechain messages.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
entries: All entries from the session
|
|
211
|
+
include_sidechains: If True, include sidechain entries. If False (default),
|
|
212
|
+
only include the main conversation thread.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Entries in conversation order, following the parent chain
|
|
216
|
+
"""
|
|
217
|
+
# Filter to message entries (not queue operations)
|
|
218
|
+
message_entries: list[ClaudeCodeMessageEntry] = [
|
|
219
|
+
e
|
|
220
|
+
for e in entries
|
|
221
|
+
if isinstance(e, ClaudeCodeUserEntry | ClaudeCodeAssistantEntry | ClaudeCodeSummary)
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
if not message_entries:
|
|
225
|
+
return []
|
|
226
|
+
|
|
227
|
+
# Build children lookup
|
|
228
|
+
children: dict[str | None, list[ClaudeCodeMessageEntry]] = {}
|
|
229
|
+
for entry in message_entries:
|
|
230
|
+
parent = entry.parent_uuid
|
|
231
|
+
children.setdefault(parent, []).append(entry)
|
|
232
|
+
|
|
233
|
+
# Find root(s) - entries with no parent
|
|
234
|
+
roots = children.get(None, [])
|
|
235
|
+
|
|
236
|
+
if not roots:
|
|
237
|
+
# No roots found, fall back to file order
|
|
238
|
+
if include_sidechains:
|
|
239
|
+
return message_entries
|
|
240
|
+
return [e for e in message_entries if not e.is_sidechain]
|
|
241
|
+
|
|
242
|
+
# Walk the tree, preferring non-sidechain entries
|
|
243
|
+
result: list[ClaudeCodeMessageEntry] = []
|
|
244
|
+
|
|
245
|
+
def walk(entry: ClaudeCodeMessageEntry) -> None:
|
|
246
|
+
if include_sidechains or not entry.is_sidechain:
|
|
247
|
+
result.append(entry)
|
|
248
|
+
|
|
249
|
+
# Get children of this entry
|
|
250
|
+
entry_children = children.get(entry.uuid, [])
|
|
251
|
+
|
|
252
|
+
# Sort children: non-sidechains first, then by timestamp
|
|
253
|
+
entry_children.sort(key=lambda e: (e.is_sidechain, e.timestamp))
|
|
254
|
+
|
|
255
|
+
for child in entry_children:
|
|
256
|
+
walk(child)
|
|
257
|
+
|
|
258
|
+
# Start from roots (sorted by timestamp)
|
|
259
|
+
roots.sort(key=lambda e: e.timestamp)
|
|
260
|
+
for root in roots:
|
|
261
|
+
walk(root)
|
|
262
|
+
|
|
263
|
+
return result
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def get_claude_data_dir() -> Path:
|
|
267
|
+
"""Get the Claude Code data directory path.
|
|
268
|
+
|
|
269
|
+
Claude Code stores data in ~/.claude rather than the XDG data directory.
|
|
270
|
+
"""
|
|
271
|
+
from pathlib import Path
|
|
272
|
+
|
|
273
|
+
return Path.home() / ".claude"
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def get_claude_projects_dir() -> Path:
|
|
277
|
+
"""Get the Claude Code projects directory path."""
|
|
278
|
+
return get_claude_data_dir() / "projects"
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def path_to_claude_dir_name(project_path: str) -> str:
|
|
282
|
+
"""Convert a filesystem path to Claude Code's directory naming format.
|
|
283
|
+
|
|
284
|
+
Claude Code replaces '/' with '-', so '/home/user/project' becomes '-home-user-project'.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
project_path: The filesystem path
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
The Claude Code directory name format
|
|
291
|
+
"""
|
|
292
|
+
return project_path.replace("/", "-")
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def list_project_sessions(project_path: str) -> list[Path]:
|
|
296
|
+
"""List all session files for a project.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
project_path: The project path (will be converted to Claude's format)
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
List of session file paths, sorted by modification time (newest first)
|
|
303
|
+
"""
|
|
304
|
+
projects_dir = get_claude_projects_dir()
|
|
305
|
+
project_dir_name = path_to_claude_dir_name(project_path)
|
|
306
|
+
project_dir = projects_dir / project_dir_name
|
|
307
|
+
|
|
308
|
+
if not project_dir.exists():
|
|
309
|
+
return []
|
|
310
|
+
|
|
311
|
+
sessions = list(project_dir.glob("*.jsonl"))
|
|
312
|
+
return sorted(sessions, key=lambda p: p.stat().st_mtime, reverse=True)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def convert_to_pydantic_ai(
|
|
316
|
+
entries: list[ClaudeCodeEntry],
|
|
317
|
+
*,
|
|
318
|
+
include_sidechains: bool = False,
|
|
319
|
+
follow_parent_chain: bool = True,
|
|
320
|
+
) -> list[ModelRequest | ModelResponse]:
|
|
321
|
+
"""Convert Claude Code entries to pydantic-ai message format.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
entries: List of Claude Code history entries
|
|
325
|
+
include_sidechains: If True, include sidechain (forked) messages
|
|
326
|
+
follow_parent_chain: If True (default), reconstruct conversation order
|
|
327
|
+
by following parentUuid links. If False, use file order.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
List of ModelRequest and ModelResponse objects
|
|
331
|
+
"""
|
|
332
|
+
from pydantic_ai import ModelRequest, ModelResponse
|
|
333
|
+
|
|
334
|
+
# Optionally reconstruct proper conversation order
|
|
335
|
+
conversation: list[ClaudeCodeEntry] | list[ClaudeCodeMessageEntry]
|
|
336
|
+
if follow_parent_chain:
|
|
337
|
+
conversation = get_main_conversation(entries, include_sidechains=include_sidechains)
|
|
338
|
+
else:
|
|
339
|
+
conversation = entries
|
|
340
|
+
from pydantic_ai.messages import (
|
|
341
|
+
TextPart,
|
|
342
|
+
ThinkingPart,
|
|
343
|
+
ToolCallPart,
|
|
344
|
+
ToolReturnPart,
|
|
345
|
+
UserPromptPart,
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
messages: list[ModelRequest | ModelResponse] = []
|
|
349
|
+
|
|
350
|
+
for entry in conversation:
|
|
351
|
+
match entry:
|
|
352
|
+
case ClaudeCodeUserEntry():
|
|
353
|
+
parts: list[Any] = []
|
|
354
|
+
metadata = {
|
|
355
|
+
"uuid": entry.uuid,
|
|
356
|
+
"timestamp": entry.timestamp.isoformat(),
|
|
357
|
+
"sessionId": entry.session_id,
|
|
358
|
+
"cwd": entry.cwd,
|
|
359
|
+
"gitBranch": entry.git_branch,
|
|
360
|
+
"isSidechain": entry.is_sidechain,
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
content = entry.message.content
|
|
364
|
+
if isinstance(content, str):
|
|
365
|
+
parts.append(UserPromptPart(content=content))
|
|
366
|
+
else:
|
|
367
|
+
for block in content:
|
|
368
|
+
match block:
|
|
369
|
+
case ClaudeCodeTextContent():
|
|
370
|
+
parts.append(UserPromptPart(content=block.text))
|
|
371
|
+
case ClaudeCodeToolResultContent():
|
|
372
|
+
# Extract text from tool result content
|
|
373
|
+
if isinstance(block.content, str):
|
|
374
|
+
result_content = block.content
|
|
375
|
+
else:
|
|
376
|
+
result_content = "\n".join(
|
|
377
|
+
c.text
|
|
378
|
+
for c in block.content
|
|
379
|
+
if isinstance(c, ClaudeCodeTextContent)
|
|
380
|
+
)
|
|
381
|
+
parts.append(
|
|
382
|
+
ToolReturnPart(
|
|
383
|
+
tool_name="", # Not available in history
|
|
384
|
+
content=result_content,
|
|
385
|
+
tool_call_id=block.tool_use_id,
|
|
386
|
+
)
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
if parts:
|
|
390
|
+
messages.append(ModelRequest(parts=parts, metadata=metadata))
|
|
391
|
+
|
|
392
|
+
case ClaudeCodeAssistantEntry():
|
|
393
|
+
parts = []
|
|
394
|
+
metadata = {
|
|
395
|
+
"uuid": entry.uuid,
|
|
396
|
+
"timestamp": entry.timestamp.isoformat(),
|
|
397
|
+
"sessionId": entry.session_id,
|
|
398
|
+
"requestId": entry.request_id,
|
|
399
|
+
"cwd": entry.cwd,
|
|
400
|
+
"gitBranch": entry.git_branch,
|
|
401
|
+
"isSidechain": entry.is_sidechain,
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
for block in entry.message.content:
|
|
405
|
+
match block:
|
|
406
|
+
case ClaudeCodeTextContent():
|
|
407
|
+
parts.append(TextPart(content=block.text))
|
|
408
|
+
case ClaudeCodeToolUseContent():
|
|
409
|
+
parts.append(
|
|
410
|
+
ToolCallPart(
|
|
411
|
+
tool_name=block.name,
|
|
412
|
+
args=block.input,
|
|
413
|
+
tool_call_id=block.id,
|
|
414
|
+
)
|
|
415
|
+
)
|
|
416
|
+
case ClaudeCodeThinkingContent():
|
|
417
|
+
parts.append(ThinkingPart(content=block.thinking))
|
|
418
|
+
|
|
419
|
+
if parts:
|
|
420
|
+
messages.append(
|
|
421
|
+
ModelResponse(
|
|
422
|
+
parts=parts,
|
|
423
|
+
model_name=entry.message.model,
|
|
424
|
+
provider_response_id=entry.message.id,
|
|
425
|
+
metadata=metadata,
|
|
426
|
+
)
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
case ClaudeCodeSummary():
|
|
430
|
+
# Summaries can be added as system context if needed
|
|
431
|
+
metadata = {
|
|
432
|
+
"uuid": entry.uuid,
|
|
433
|
+
"timestamp": entry.timestamp.isoformat(),
|
|
434
|
+
"sessionId": entry.session_id,
|
|
435
|
+
"type": "summary",
|
|
436
|
+
}
|
|
437
|
+
messages.append(
|
|
438
|
+
ModelRequest(
|
|
439
|
+
parts=[UserPromptPart(content=f"[Summary]: {entry.summary}")],
|
|
440
|
+
metadata=metadata,
|
|
441
|
+
)
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
case ClaudeCodeQueueOperation():
|
|
445
|
+
# Skip queue operations - they're metadata, not messages
|
|
446
|
+
pass
|
|
447
|
+
|
|
448
|
+
return messages
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def load_session_as_pydantic_ai(session_path: Path) -> list[ModelRequest | ModelResponse]:
|
|
452
|
+
"""Load a Claude Code session and convert to pydantic-ai format.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
session_path: Path to the .jsonl session file
|
|
456
|
+
|
|
457
|
+
Returns:
|
|
458
|
+
List of ModelRequest and ModelResponse objects
|
|
459
|
+
"""
|
|
460
|
+
entries = load_session(session_path)
|
|
461
|
+
return convert_to_pydantic_ai(entries)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def get_latest_session(project_path: str) -> Path | None:
|
|
465
|
+
"""Get the most recent session file for a project.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
project_path: The project path
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
Path to the latest session file, or None if no sessions exist
|
|
472
|
+
"""
|
|
473
|
+
sessions = list_project_sessions(project_path)
|
|
474
|
+
return sessions[0] if sessions else None
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Pydantic models for Claude Code server info structures."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ClaudeCodeBasemodel(BaseModel):
|
|
9
|
+
"""Base model."""
|
|
10
|
+
|
|
11
|
+
model_config = ConfigDict(populate_by_name=True)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ClaudeCodeModelInfo(ClaudeCodeBasemodel):
|
|
15
|
+
"""Information about an available AI model from Claude Code."""
|
|
16
|
+
|
|
17
|
+
value: str
|
|
18
|
+
"""Model identifier used in API calls (e.g., "default", "opus", "haiku")."""
|
|
19
|
+
|
|
20
|
+
display_name: str = Field(..., alias="displayName")
|
|
21
|
+
"""Human-readable display name (e.g., "Opus", "Default (recommended)")."""
|
|
22
|
+
|
|
23
|
+
description: str
|
|
24
|
+
"""Full description including capabilities and pricing."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ClaudeCodeCommandInfo(ClaudeCodeBasemodel):
|
|
28
|
+
"""Information about an available slash command from Claude Code."""
|
|
29
|
+
|
|
30
|
+
name: str
|
|
31
|
+
"""Command name without the / prefix (e.g., "compact", "review")."""
|
|
32
|
+
|
|
33
|
+
description: str
|
|
34
|
+
"""Full description of what the command does."""
|
|
35
|
+
|
|
36
|
+
argument_hint: str = Field(..., alias="argumentHint")
|
|
37
|
+
"""Usage hint for command arguments (may be empty string)."""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ClaudeCodeAccountInfo(ClaudeCodeBasemodel):
|
|
41
|
+
"""Account information from Claude Code."""
|
|
42
|
+
|
|
43
|
+
email: str | None = None
|
|
44
|
+
"""User email address."""
|
|
45
|
+
|
|
46
|
+
subscription_type: str | None = Field(default=None, alias="subscriptionType")
|
|
47
|
+
"""Subscription type (e.g., "Claude API")."""
|
|
48
|
+
|
|
49
|
+
token_source: str | None = Field(default=None, alias="tokenSource")
|
|
50
|
+
"""Where tokens come from (e.g., "claude.ai")."""
|
|
51
|
+
|
|
52
|
+
api_key_source: str | None = Field(default=None, alias="apiKeySource")
|
|
53
|
+
"""Where API key comes from (e.g., "ANTHROPIC_API_KEY")."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class ClaudeCodeServerInfo(ClaudeCodeBasemodel):
|
|
57
|
+
"""Complete server initialization info from Claude Code.
|
|
58
|
+
|
|
59
|
+
This is returned by the Claude Code server during initialization and contains
|
|
60
|
+
all available capabilities including models, commands, output styles, and
|
|
61
|
+
account information.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
models: list[ClaudeCodeModelInfo] = Field(default_factory=list)
|
|
65
|
+
"""List of available AI models."""
|
|
66
|
+
|
|
67
|
+
commands: list[ClaudeCodeCommandInfo] = Field(default_factory=list)
|
|
68
|
+
"""List of available slash commands."""
|
|
69
|
+
|
|
70
|
+
output_style: str = Field(default="default")
|
|
71
|
+
"""Current output style setting."""
|
|
72
|
+
|
|
73
|
+
available_output_styles: list[str] = Field(default_factory=list)
|
|
74
|
+
"""List of all available output styles."""
|
|
75
|
+
|
|
76
|
+
account: ClaudeCodeAccountInfo | None = Field(default=None)
|
|
77
|
+
"""Account and authentication information."""
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Static model information."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from tokonomics.model_discovery.model_info import ModelInfo, ModelPricing
|
|
8
|
+
|
|
9
|
+
from agentpool.agents.modes import ModeInfo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from claude_agent_sdk import PermissionMode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
VALID_MODES: set[PermissionMode] = {
|
|
17
|
+
"default",
|
|
18
|
+
"acceptEdits",
|
|
19
|
+
"plan",
|
|
20
|
+
"bypassPermissions",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
# Static Claude Code models - these are the simple IDs the SDK accepts
|
|
24
|
+
# Use id_override to ensure pydantic_ai_id returns simple names like "opus"
|
|
25
|
+
|
|
26
|
+
OPUS = ModelInfo(
|
|
27
|
+
id="claude-opus-4-5",
|
|
28
|
+
name="Claude Opus",
|
|
29
|
+
provider="anthropic",
|
|
30
|
+
description="Claude Opus - most capable model",
|
|
31
|
+
context_window=200000,
|
|
32
|
+
max_output_tokens=32000,
|
|
33
|
+
input_modalities={"text", "image"},
|
|
34
|
+
output_modalities={"text"},
|
|
35
|
+
pricing=ModelPricing(
|
|
36
|
+
prompt=0.000005, # $5 per 1M tokens
|
|
37
|
+
completion=0.000025, # $25 per 1M tokens
|
|
38
|
+
),
|
|
39
|
+
id_override="opus", # Claude Code SDK uses simple names
|
|
40
|
+
)
|
|
41
|
+
SONNET = ModelInfo(
|
|
42
|
+
id="claude-sonnet-4-5",
|
|
43
|
+
name="Claude Sonnet",
|
|
44
|
+
provider="anthropic",
|
|
45
|
+
description="Claude Sonnet - balanced performance and speed",
|
|
46
|
+
context_window=200000,
|
|
47
|
+
max_output_tokens=16000,
|
|
48
|
+
input_modalities={"text", "image"},
|
|
49
|
+
output_modalities={"text"},
|
|
50
|
+
pricing=ModelPricing(
|
|
51
|
+
prompt=0.000003, # $3 per 1M tokens
|
|
52
|
+
completion=0.000015, # $15 per 1M tokens
|
|
53
|
+
),
|
|
54
|
+
id_override="sonnet", # Claude Code SDK uses simple names
|
|
55
|
+
)
|
|
56
|
+
HAIKU = ModelInfo(
|
|
57
|
+
id="claude-haiku-4-5",
|
|
58
|
+
name="Claude Haiku",
|
|
59
|
+
provider="anthropic",
|
|
60
|
+
description="Claude Haiku - fast and cost-effective",
|
|
61
|
+
context_window=200000,
|
|
62
|
+
max_output_tokens=8000,
|
|
63
|
+
input_modalities={"text", "image"},
|
|
64
|
+
output_modalities={"text"},
|
|
65
|
+
pricing=ModelPricing(
|
|
66
|
+
prompt=0.000001, # $1.00 per 1M tokens
|
|
67
|
+
completion=0.000005, # $5 per 1M tokens
|
|
68
|
+
),
|
|
69
|
+
id_override="haiku", # Claude Code SDK uses simple names
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
MODELS = [OPUS, SONNET, HAIKU]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
MODES = [
|
|
76
|
+
ModeInfo(
|
|
77
|
+
id="default",
|
|
78
|
+
name="Default",
|
|
79
|
+
description="Require confirmation for tool usage",
|
|
80
|
+
category_id="permissions",
|
|
81
|
+
),
|
|
82
|
+
ModeInfo(
|
|
83
|
+
id="acceptEdits",
|
|
84
|
+
name="Accept Edits",
|
|
85
|
+
description="Auto-approve file edits without confirmation",
|
|
86
|
+
category_id="permissions",
|
|
87
|
+
),
|
|
88
|
+
ModeInfo(
|
|
89
|
+
id="plan",
|
|
90
|
+
name="Plan",
|
|
91
|
+
description="Planning mode - no tool execution",
|
|
92
|
+
category_id="permissions",
|
|
93
|
+
),
|
|
94
|
+
ModeInfo(
|
|
95
|
+
id="bypassPermissions",
|
|
96
|
+
name="Bypass Permissions",
|
|
97
|
+
description="Skip all permission checks (use with caution)",
|
|
98
|
+
category_id="permissions",
|
|
99
|
+
),
|
|
100
|
+
]
|