clawd-code-sdk 0.1.89__tar.gz → 0.2.0__tar.gz
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.
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/PKG-INFO +1 -1
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/pyproject.toml +1 -1
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/__init__.py +9 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/transport/subprocess_cli.py +34 -17
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/__init__.py +12 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/options.py +137 -46
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/session.py +5 -4
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_integration.py +2 -1
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_session.py +7 -5
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_transport.py +61 -7
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/.gitignore +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/LICENSE +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/README.md +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_bundled/.gitignore +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_errors.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/__init__.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/message_parser.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/query.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/transport/__init__.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_version.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/anthropic_types.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/client.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/mcp_utils.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/agents.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/base.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/content_blocks.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/control.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/hooks.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/input_types.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/mcp.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/messages.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/output_types.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/permissions.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/sandbox.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/server_info.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/ts_output_types.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/py.typed +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/query.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/ARCHITECTURE.md +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/__init__.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/helpers.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/models.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/replay.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/usage.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/conftest.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/mcp_server.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_changelog.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_client.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_errors.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_image.png +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_message_parser.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_sdk_mcp_integration.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_streaming_client.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_subprocess_buffering.py +0 -0
- {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_tool_callbacks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clawd-code-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Python SDK for Claude Code
|
|
5
5
|
Project-URL: Documentation, https://github.com/phil65/claude-agent-sdk-python
|
|
6
6
|
Project-URL: Homepage, https://github.com/phil65/claude-agent-sdk-python
|
|
@@ -22,6 +22,7 @@ from .anthropic_types import ToolResultContentBlock
|
|
|
22
22
|
from .client import ClaudeSDKClient
|
|
23
23
|
from .models import (
|
|
24
24
|
AgentDefinition,
|
|
25
|
+
ContinueLatest,
|
|
25
26
|
AssistantMessage,
|
|
26
27
|
BaseHookInput,
|
|
27
28
|
CanUseTool,
|
|
@@ -74,6 +75,9 @@ from .models import (
|
|
|
74
75
|
UserPromptMessage,
|
|
75
76
|
UserPromptMessageContent,
|
|
76
77
|
UserPromptSubmitHookInput,
|
|
78
|
+
NewSession,
|
|
79
|
+
ResumeSession,
|
|
80
|
+
SessionConfig,
|
|
77
81
|
)
|
|
78
82
|
from .query import query
|
|
79
83
|
from .mcp_utils import SdkMcpTool, tool, create_sdk_mcp_server
|
|
@@ -98,6 +102,11 @@ __all__ = [
|
|
|
98
102
|
# Transport
|
|
99
103
|
"Transport",
|
|
100
104
|
"ClaudeSDKClient",
|
|
105
|
+
# Session config
|
|
106
|
+
"ContinueLatest",
|
|
107
|
+
"NewSession",
|
|
108
|
+
"ResumeSession",
|
|
109
|
+
"SessionConfig",
|
|
101
110
|
# Types
|
|
102
111
|
"PermissionMode",
|
|
103
112
|
"McpServerConfig",
|
|
@@ -115,14 +115,40 @@ class SubprocessCLITransport(Transport):
|
|
|
115
115
|
if self._options.permission_mode:
|
|
116
116
|
cmd.extend(["--permission-mode", self._options.permission_mode])
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
# Session configuration
|
|
119
|
+
from clawd_code_sdk.models.options import (
|
|
120
|
+
ContinueLatest,
|
|
121
|
+
NewSession,
|
|
122
|
+
ResumeSession,
|
|
123
|
+
resolve_session_config,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
session = resolve_session_config(self._options.session)
|
|
127
|
+
match session:
|
|
128
|
+
case NewSession(session_id=sid, persist=persist):
|
|
129
|
+
if sid is not None:
|
|
130
|
+
cmd.extend(["--session-id", sid])
|
|
131
|
+
if not persist:
|
|
132
|
+
cmd.append("--no-persist-session")
|
|
133
|
+
case ResumeSession(
|
|
134
|
+
session_id=sid,
|
|
135
|
+
fork=fork,
|
|
136
|
+
at_message=at_msg,
|
|
137
|
+
persist=persist,
|
|
138
|
+
):
|
|
139
|
+
cmd.extend(["--resume", sid])
|
|
140
|
+
if fork:
|
|
141
|
+
cmd.append("--fork-session")
|
|
142
|
+
if at_msg is not None:
|
|
143
|
+
cmd.extend(["--resume-session-at", at_msg])
|
|
144
|
+
if not persist:
|
|
145
|
+
cmd.append("--no-persist-session")
|
|
146
|
+
case ContinueLatest(fork=fork, persist=persist):
|
|
147
|
+
cmd.append("--continue")
|
|
148
|
+
if fork:
|
|
149
|
+
cmd.append("--fork-session")
|
|
150
|
+
if not persist:
|
|
151
|
+
cmd.append("--no-persist-session")
|
|
126
152
|
|
|
127
153
|
# Handle settings and sandbox: merge sandbox into settings if both are provided
|
|
128
154
|
if settings_value := self._options.build_settings_value():
|
|
@@ -149,18 +175,9 @@ class SubprocessCLITransport(Transport):
|
|
|
149
175
|
if self._options.agent:
|
|
150
176
|
cmd.extend(["--agent", self._options.agent])
|
|
151
177
|
|
|
152
|
-
if self._options.fork_session:
|
|
153
|
-
cmd.append("--fork-session")
|
|
154
|
-
|
|
155
|
-
if self._options.persist_session is False:
|
|
156
|
-
cmd.append("--no-persist-session")
|
|
157
|
-
|
|
158
178
|
if self._options.allow_dangerously_skip_permissions:
|
|
159
179
|
cmd.append("--dangerously-skip-permissions")
|
|
160
180
|
|
|
161
|
-
if self._options.resume_session_at:
|
|
162
|
-
cmd.extend(["--resume-session-at", self._options.resume_session_at])
|
|
163
|
-
|
|
164
181
|
if self._options.debug_file:
|
|
165
182
|
cmd.extend(["--debug-file", self._options.debug_file])
|
|
166
183
|
|
|
@@ -228,6 +228,13 @@ from .messages import (
|
|
|
228
228
|
system_message_adapter,
|
|
229
229
|
)
|
|
230
230
|
from .options import ClaudeAgentOptions
|
|
231
|
+
from .options import (
|
|
232
|
+
ContinueLatest,
|
|
233
|
+
NewSession,
|
|
234
|
+
ResumeSession,
|
|
235
|
+
SessionConfig,
|
|
236
|
+
resolve_session_config,
|
|
237
|
+
)
|
|
231
238
|
from .permissions import (
|
|
232
239
|
CanUseTool,
|
|
233
240
|
PermissionResult,
|
|
@@ -364,6 +371,11 @@ __all__ = [
|
|
|
364
371
|
"system_message_adapter",
|
|
365
372
|
# options
|
|
366
373
|
"ClaudeAgentOptions",
|
|
374
|
+
"ContinueLatest",
|
|
375
|
+
"NewSession",
|
|
376
|
+
"ResumeSession",
|
|
377
|
+
"SessionConfig",
|
|
378
|
+
"resolve_session_config",
|
|
367
379
|
# control
|
|
368
380
|
"ControlErrorResponse",
|
|
369
381
|
"ControlRequestUnion",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""ClaudeAgentOptions
|
|
1
|
+
"""ClaudeAgentOptions and session configuration types."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ from dataclasses import dataclass, field
|
|
|
6
6
|
import json
|
|
7
7
|
import logging
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
@@ -24,64 +24,161 @@ if TYPE_CHECKING:
|
|
|
24
24
|
logger = logging.getLogger(__name__)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
# ============================================================================
|
|
28
|
+
# Session configuration
|
|
29
|
+
# ============================================================================
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(kw_only=True)
|
|
33
|
+
class NewSession:
|
|
34
|
+
"""Start a fresh session.
|
|
35
|
+
|
|
36
|
+
Attributes:
|
|
37
|
+
session_id: Deterministic session ID, or None to auto-generate a UUID.
|
|
38
|
+
persist: Whether to persist the session to disk.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
mode: Literal["new"] = "new"
|
|
42
|
+
session_id: str | None = None
|
|
43
|
+
persist: bool = True
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(kw_only=True)
|
|
47
|
+
class ResumeSession:
|
|
48
|
+
"""Resume an existing session by ID.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
session_id: The session ID to resume.
|
|
52
|
+
fork: If True, fork to a new session ID instead of continuing in-place.
|
|
53
|
+
at_message: Resume from a specific message UUID within the session.
|
|
54
|
+
persist: Whether to persist the session to disk.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
mode: Literal["resume"] = "resume"
|
|
58
|
+
session_id: str
|
|
59
|
+
fork: bool = False
|
|
60
|
+
at_message: str | None = None
|
|
61
|
+
persist: bool = True
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(kw_only=True)
|
|
65
|
+
class ContinueLatest:
|
|
66
|
+
"""Continue the most recent conversation.
|
|
67
|
+
|
|
68
|
+
Attributes:
|
|
69
|
+
fork: If True, fork to a new session ID instead of continuing in-place.
|
|
70
|
+
persist: Whether to persist the session to disk.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
mode: Literal["continue"] = "continue"
|
|
74
|
+
fork: bool = False
|
|
75
|
+
persist: bool = True
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
SessionConfig = NewSession | ResumeSession | ContinueLatest
|
|
79
|
+
"""Union of all session configuration types.
|
|
80
|
+
|
|
81
|
+
Can also be specified as a plain ``str``, which is a shortcut for
|
|
82
|
+
``ResumeSession(session_id=str)``.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def resolve_session_config(value: str | SessionConfig | None) -> SessionConfig:
|
|
87
|
+
"""Normalize a session config value.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
value: A SessionConfig instance, a session ID string (shortcut for
|
|
91
|
+
ResumeSession), or None (defaults to NewSession).
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
A concrete SessionConfig instance.
|
|
95
|
+
"""
|
|
96
|
+
match value:
|
|
97
|
+
case None:
|
|
98
|
+
return NewSession()
|
|
99
|
+
case str() as session_id:
|
|
100
|
+
return ResumeSession(session_id=session_id)
|
|
101
|
+
case NewSession() | ResumeSession() | ContinueLatest() as config:
|
|
102
|
+
return config
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# ============================================================================
|
|
106
|
+
# Main options
|
|
107
|
+
# ============================================================================
|
|
108
|
+
|
|
109
|
+
|
|
27
110
|
@dataclass
|
|
28
111
|
class ClaudeAgentOptions:
|
|
29
112
|
"""Query options for Claude SDK."""
|
|
30
113
|
|
|
114
|
+
# Tools
|
|
31
115
|
tools: list[str] | ToolsPreset | None = None
|
|
32
116
|
"""Tools available to the agent."""
|
|
33
117
|
allowed_tools: list[str] | None = None
|
|
34
118
|
"""Tools which execute without prompting for permission."""
|
|
35
|
-
|
|
36
|
-
"""
|
|
119
|
+
disallowed_tools: list[str] | None = None
|
|
120
|
+
"""Tools that are removed from agent context and cant be used."""
|
|
121
|
+
# MCP
|
|
37
122
|
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
|
|
38
123
|
"""MCP servers for the agent."""
|
|
124
|
+
chrome: bool = False
|
|
125
|
+
"""Add the chrome-tools MCP server (-> Claude Code browser extension) to the agent."""
|
|
126
|
+
strict_mcp_config: bool = False
|
|
127
|
+
"""Enforce strict validation of MCP server configurations."""
|
|
128
|
+
# Permissions
|
|
39
129
|
permission_mode: PermissionMode | None = None
|
|
40
130
|
"""Permission mode."""
|
|
41
|
-
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
"""
|
|
131
|
+
allow_dangerously_skip_permissions: bool = False
|
|
132
|
+
"""Must be True when using permission_mode='bypassPermissions'."""
|
|
133
|
+
permission_prompt_tool_name: str | None = None
|
|
134
|
+
"""MCP tool to handle permission prompts."""
|
|
135
|
+
can_use_tool: CanUseTool | None = None
|
|
136
|
+
"""Tool permission callback."""
|
|
137
|
+
# Session
|
|
138
|
+
session: str | SessionConfig | None = None
|
|
139
|
+
"""Session configuration.
|
|
140
|
+
|
|
141
|
+
Controls how the CLI session is started:
|
|
142
|
+
- ``None`` or ``NewSession()``: Start a fresh session.
|
|
143
|
+
- ``"session-id"`` or ``ResumeSession(session_id="...")``: Resume by ID.
|
|
144
|
+
- ``ContinueLatest()``: Continue the most recent conversation.
|
|
145
|
+
"""
|
|
146
|
+
# Limits
|
|
47
147
|
max_turns: int | None = None
|
|
48
148
|
"""Maximum allowed amount of agentic turns."""
|
|
49
149
|
max_budget_usd: float | None = None
|
|
50
150
|
"""Maximum amount of USD budget which may be consumed."""
|
|
51
|
-
|
|
52
|
-
"""Tools that are removed from agent context and cant be used."""
|
|
151
|
+
# Model
|
|
53
152
|
model: ModelName | str | None = None
|
|
54
153
|
"""Session model."""
|
|
55
154
|
fallback_model: ModelName | str | None = None
|
|
56
155
|
"""Fallback model in case default one is overloaded."""
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
156
|
+
# Thinking
|
|
157
|
+
thinking: ThinkingConfig | None = None
|
|
158
|
+
"""Controls thinking behavior."""
|
|
159
|
+
effort: ReasoningEffort | None = None
|
|
160
|
+
"""Effort level for thinking depth."""
|
|
161
|
+
# CLI SubProcess
|
|
61
162
|
cli_path: str | Path | None = None
|
|
62
163
|
"""CLI path override (auto-detects by default)."""
|
|
63
|
-
settings: str | None = None
|
|
64
|
-
"""Path to a settings JSON file or a JSON string."""
|
|
65
|
-
add_dirs: list[str | Path] = field(default_factory=list)
|
|
66
|
-
"""Add additional working directories."""
|
|
67
|
-
env: dict[str, str] = field(default_factory=dict)
|
|
68
|
-
"""Environment variables for the CLI subprocess."""
|
|
69
164
|
extra_args: dict[str, str | None] = field(default_factory=dict)
|
|
70
165
|
"""Arbitrary extra CLI flags."""
|
|
71
166
|
max_buffer_size: int | None = None
|
|
72
167
|
"""Max bytes when buffering CLI stdout."""
|
|
73
168
|
stderr: Callable[[str], None] | None = None
|
|
74
169
|
"""Callback for stderr output from CLI."""
|
|
75
|
-
|
|
76
|
-
"""
|
|
77
|
-
hooks: dict[HookEvent, list[HookMatcher]] | None = None
|
|
78
|
-
"""Hook configurations."""
|
|
170
|
+
env: dict[str, str] = field(default_factory=dict)
|
|
171
|
+
"""Environment variables for the CLI subprocess."""
|
|
79
172
|
user: str | None = None
|
|
80
173
|
"""User for the AnyIO process."""
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
174
|
+
# CWD
|
|
175
|
+
add_dirs: list[str | Path] = field(default_factory=list)
|
|
176
|
+
"""Add additional working directories."""
|
|
177
|
+
cwd: str | Path | None = None
|
|
178
|
+
"""The working directory for the agent."""
|
|
179
|
+
# Settings
|
|
180
|
+
settings: str | None = None
|
|
181
|
+
"""Path to a settings JSON file or a JSON string."""
|
|
85
182
|
setting_sources: list[SettingSource] | None = None
|
|
86
183
|
"""List of sources to load settings from."""
|
|
87
184
|
sandbox: SandboxSettings | None = None
|
|
@@ -90,17 +187,23 @@ class ClaudeAgentOptions:
|
|
|
90
187
|
Filesystem and network restrictions are derived from permission rules (Read/Edit/WebFetch),
|
|
91
188
|
not from these sandbox settings.
|
|
92
189
|
"""
|
|
190
|
+
debug_file: str | None = None
|
|
191
|
+
"""Write debug logs to a specific file path. Implicitly enables debug mode."""
|
|
192
|
+
# Agent config
|
|
193
|
+
system_prompt: str | SystemPromptPreset | None = None
|
|
194
|
+
"""System prompt for the agent."""
|
|
195
|
+
hooks: dict[HookEvent, list[HookMatcher]] | None = None
|
|
196
|
+
"""Hook configurations."""
|
|
197
|
+
agents: dict[str, AgentDefinition] | None = None
|
|
198
|
+
"""SubAgent definitions."""
|
|
93
199
|
plugins: list[SdkPluginConfig] = field(default_factory=list)
|
|
94
200
|
""""Plugin configurations to load."""
|
|
95
|
-
thinking: ThinkingConfig | None = None
|
|
96
|
-
"""Controls thinking behavior."""
|
|
97
|
-
effort: ReasoningEffort | None = None
|
|
98
|
-
"""Effort level for thinking depth."""
|
|
99
201
|
output_format: dict[str, Any] | None = None
|
|
100
202
|
"""Output format for structured outputs (matches Messages API structure)
|
|
101
203
|
|
|
102
204
|
Example: {"type": "json_schema", "schema": {"type": "object", "properties": {...}}}
|
|
103
205
|
"""
|
|
206
|
+
# Other
|
|
104
207
|
enable_file_checkpointing: bool = False
|
|
105
208
|
"""Enable file checkpointing to track file changes during the session.
|
|
106
209
|
|
|
@@ -109,24 +212,12 @@ class ClaudeAgentOptions:
|
|
|
109
212
|
"""
|
|
110
213
|
agent: str | None = None
|
|
111
214
|
"""Agent name for the main thread. The agent must be defined in `agents` or settings."""
|
|
112
|
-
persist_session: bool | None = None
|
|
113
|
-
"""Whether to persist the session to disk."""
|
|
114
|
-
allow_dangerously_skip_permissions: bool = False
|
|
115
|
-
"""Must be True when using permission_mode='bypassPermissions'."""
|
|
116
|
-
resume_session_at: str | None = None
|
|
117
|
-
"""Resume from a specific message UUID (use with `resume`)."""
|
|
118
|
-
debug_file: str | None = None
|
|
119
|
-
"""Write debug logs to a specific file path. Implicitly enables debug mode."""
|
|
120
|
-
strict_mcp_config: bool = False
|
|
121
|
-
"""Enforce strict validation of MCP server configurations."""
|
|
122
215
|
context_1m: bool = False
|
|
123
216
|
"""Enable 1M token context window (Sonnet 4/4.5 only)."""
|
|
124
217
|
prompt_suggestions: bool | None = None
|
|
125
218
|
"""Whether to create prompt suggestions."""
|
|
126
219
|
worktree: bool | str = False
|
|
127
220
|
"""Create a new git worktree for the session (with optional name)."""
|
|
128
|
-
chrome: bool = False
|
|
129
|
-
"""Add the chrome-tools MCP server (-> Claude Code browser extension) to the agent."""
|
|
130
221
|
|
|
131
222
|
def build_settings_value(self) -> str | None:
|
|
132
223
|
"""Build settings value, merging sandbox settings if provided.
|
|
@@ -311,20 +311,21 @@ class SessionManager:
|
|
|
311
311
|
) -> Session:
|
|
312
312
|
"""Resume a previously persisted session by ID.
|
|
313
313
|
|
|
314
|
-
Sets ``
|
|
314
|
+
Sets ``session`` to a :class:`ResumeSession` config on the options,
|
|
315
315
|
then connects.
|
|
316
316
|
|
|
317
317
|
Args:
|
|
318
318
|
session_id: The session ID to resume.
|
|
319
|
-
options: Session-specific options (``
|
|
320
|
-
``continue_conversation`` are set automatically).
|
|
319
|
+
options: Session-specific options (``session`` is set automatically).
|
|
321
320
|
transport: Optional custom transport.
|
|
322
321
|
|
|
323
322
|
Raises:
|
|
324
323
|
ValueError: If session_id already exists in this manager.
|
|
325
324
|
"""
|
|
325
|
+
from clawd_code_sdk.models.options import ResumeSession
|
|
326
|
+
|
|
326
327
|
base = options or Opts()
|
|
327
|
-
merged = replace(base, session_id=session_id
|
|
328
|
+
merged = replace(base, session=ResumeSession(session_id=session_id))
|
|
328
329
|
return await self.create_session(
|
|
329
330
|
session_id=session_id,
|
|
330
331
|
options=merged,
|
|
@@ -14,6 +14,7 @@ from clawd_code_sdk import (
|
|
|
14
14
|
AssistantMessage,
|
|
15
15
|
ClaudeAgentOptions,
|
|
16
16
|
CLINotFoundError,
|
|
17
|
+
ContinueLatest,
|
|
17
18
|
ResultMessage,
|
|
18
19
|
query,
|
|
19
20
|
)
|
|
@@ -226,7 +227,7 @@ class TestIntegration:
|
|
|
226
227
|
messages = []
|
|
227
228
|
async for msg in query(
|
|
228
229
|
prompt="Continue",
|
|
229
|
-
options=ClaudeAgentOptions(
|
|
230
|
+
options=ClaudeAgentOptions(session=ContinueLatest()),
|
|
230
231
|
transport=mock_transport,
|
|
231
232
|
):
|
|
232
233
|
messages.append(msg)
|
|
@@ -563,7 +563,8 @@ class TestSessionManager:
|
|
|
563
563
|
anyio.run(_test)
|
|
564
564
|
|
|
565
565
|
def test_resume_session(self):
|
|
566
|
-
"""resume_session() sets
|
|
566
|
+
"""resume_session() sets session to ResumeSession."""
|
|
567
|
+
from clawd_code_sdk.models.options import ResumeSession
|
|
567
568
|
|
|
568
569
|
async def _test():
|
|
569
570
|
transport = _create_mock_transport_with_messages([])
|
|
@@ -571,14 +572,15 @@ class TestSessionManager:
|
|
|
571
572
|
async with SessionManager() as mgr:
|
|
572
573
|
session = await mgr.resume_session("prev-session-id", transport=transport)
|
|
573
574
|
assert session.session_id == "prev-session-id"
|
|
574
|
-
assert session.client.options.
|
|
575
|
-
assert session.client.options.
|
|
575
|
+
assert isinstance(session.client.options.session, ResumeSession)
|
|
576
|
+
assert session.client.options.session.session_id == "prev-session-id"
|
|
576
577
|
assert session.state == "idle"
|
|
577
578
|
|
|
578
579
|
anyio.run(_test)
|
|
579
580
|
|
|
580
581
|
def test_resume_session_with_options(self):
|
|
581
582
|
"""resume_session() merges caller options with resume fields."""
|
|
583
|
+
from clawd_code_sdk.models.options import ResumeSession
|
|
582
584
|
|
|
583
585
|
async def _test():
|
|
584
586
|
transport = _create_mock_transport_with_messages([])
|
|
@@ -587,7 +589,7 @@ class TestSessionManager:
|
|
|
587
589
|
async with SessionManager() as mgr:
|
|
588
590
|
session = await mgr.resume_session("prev-id", options=opts, transport=transport)
|
|
589
591
|
assert session.client.options.model == "claude-sonnet-4-5-20250514"
|
|
590
|
-
assert session.client.options.
|
|
591
|
-
assert session.client.options.
|
|
592
|
+
assert isinstance(session.client.options.session, ResumeSession)
|
|
593
|
+
assert session.client.options.session.session_id == "prev-id"
|
|
592
594
|
|
|
593
595
|
anyio.run(_test)
|
|
@@ -181,23 +181,77 @@ class TestSubprocessCLITransport:
|
|
|
181
181
|
assert dir1 in dirs_in_cmd
|
|
182
182
|
assert str(dir2) in dirs_in_cmd
|
|
183
183
|
|
|
184
|
-
def
|
|
185
|
-
"""Test session
|
|
186
|
-
|
|
184
|
+
def test_session_resume(self):
|
|
185
|
+
"""Test resume session options."""
|
|
186
|
+
from clawd_code_sdk.models.options import ResumeSession
|
|
187
|
+
|
|
188
|
+
opts = make_options(session=ResumeSession(session_id="session-123"))
|
|
189
|
+
transport = SubprocessCLITransport(prompt="Continue from before", options=opts)
|
|
190
|
+
cmd = transport._build_command()
|
|
191
|
+
assert "--resume" in cmd
|
|
192
|
+
assert "session-123" in cmd
|
|
193
|
+
|
|
194
|
+
def test_session_resume_shortcut(self):
|
|
195
|
+
"""Test resume session with string shortcut."""
|
|
196
|
+
opts = make_options(session="session-123")
|
|
187
197
|
transport = SubprocessCLITransport(prompt="Continue from before", options=opts)
|
|
188
198
|
cmd = transport._build_command()
|
|
189
|
-
assert "--continue" in cmd
|
|
190
199
|
assert "--resume" in cmd
|
|
191
200
|
assert "session-123" in cmd
|
|
192
201
|
|
|
193
|
-
def
|
|
194
|
-
"""Test
|
|
195
|
-
|
|
202
|
+
def test_session_continue_latest(self):
|
|
203
|
+
"""Test continue latest session option."""
|
|
204
|
+
from clawd_code_sdk.models.options import ContinueLatest
|
|
205
|
+
|
|
206
|
+
opts = make_options(session=ContinueLatest())
|
|
207
|
+
transport = SubprocessCLITransport(prompt="Continue", options=opts)
|
|
208
|
+
cmd = transport._build_command()
|
|
209
|
+
assert "--continue" in cmd
|
|
210
|
+
|
|
211
|
+
def test_session_resume_with_fork(self):
|
|
212
|
+
"""Test resume session with fork."""
|
|
213
|
+
from clawd_code_sdk.models.options import ResumeSession
|
|
214
|
+
|
|
215
|
+
opts = make_options(session=ResumeSession(session_id="prev-id", fork=True))
|
|
216
|
+
transport = SubprocessCLITransport(prompt="test", options=opts)
|
|
217
|
+
cmd = transport._build_command()
|
|
218
|
+
assert "--resume" in cmd
|
|
219
|
+
assert "prev-id" in cmd
|
|
220
|
+
assert "--fork-session" in cmd
|
|
221
|
+
|
|
222
|
+
def test_session_resume_at_message(self):
|
|
223
|
+
"""Test resume session at a specific message."""
|
|
224
|
+
from clawd_code_sdk.models.options import ResumeSession
|
|
225
|
+
|
|
226
|
+
opts = make_options(
|
|
227
|
+
session=ResumeSession(session_id="prev-id", at_message="msg-uuid"),
|
|
228
|
+
)
|
|
229
|
+
transport = SubprocessCLITransport(prompt="test", options=opts)
|
|
230
|
+
cmd = transport._build_command()
|
|
231
|
+
assert "--resume" in cmd
|
|
232
|
+
assert "prev-id" in cmd
|
|
233
|
+
assert "--resume-session-at" in cmd
|
|
234
|
+
assert "msg-uuid" in cmd
|
|
235
|
+
|
|
236
|
+
def test_build_command_with_new_session_id(self):
|
|
237
|
+
"""Test building CLI command with explicit new session ID."""
|
|
238
|
+
from clawd_code_sdk.models.options import NewSession
|
|
239
|
+
|
|
240
|
+
opts = make_options(session=NewSession(session_id="my-session-uuid"))
|
|
196
241
|
transport = SubprocessCLITransport(prompt="test", options=opts)
|
|
197
242
|
cmd = transport._build_command()
|
|
198
243
|
assert "--session-id" in cmd
|
|
199
244
|
assert "my-session-uuid" in cmd
|
|
200
245
|
|
|
246
|
+
def test_session_no_persist(self):
|
|
247
|
+
"""Test session with persist=False."""
|
|
248
|
+
from clawd_code_sdk.models.options import NewSession
|
|
249
|
+
|
|
250
|
+
opts = make_options(session=NewSession(persist=False))
|
|
251
|
+
transport = SubprocessCLITransport(prompt="test", options=opts)
|
|
252
|
+
cmd = transport._build_command()
|
|
253
|
+
assert "--no-persist-session" in cmd
|
|
254
|
+
|
|
201
255
|
def test_connect_close(self):
|
|
202
256
|
"""Test connect and close lifecycle."""
|
|
203
257
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/message_parser.py
RENAMED
|
File without changes
|
|
File without changes
|
{clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/transport/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|