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.
Files changed (55) hide show
  1. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/PKG-INFO +1 -1
  2. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/pyproject.toml +1 -1
  3. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/__init__.py +9 -0
  4. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/transport/subprocess_cli.py +34 -17
  5. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/__init__.py +12 -0
  6. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/options.py +137 -46
  7. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/session.py +5 -4
  8. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_integration.py +2 -1
  9. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_session.py +7 -5
  10. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_transport.py +61 -7
  11. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/.gitignore +0 -0
  12. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/LICENSE +0 -0
  13. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/README.md +0 -0
  14. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_bundled/.gitignore +0 -0
  15. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_errors.py +0 -0
  16. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/__init__.py +0 -0
  17. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/message_parser.py +0 -0
  18. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/query.py +0 -0
  19. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_internal/transport/__init__.py +0 -0
  20. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/_version.py +0 -0
  21. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/anthropic_types.py +0 -0
  22. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/client.py +0 -0
  23. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/mcp_utils.py +0 -0
  24. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/agents.py +0 -0
  25. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/base.py +0 -0
  26. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/content_blocks.py +0 -0
  27. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/control.py +0 -0
  28. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/hooks.py +0 -0
  29. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/input_types.py +0 -0
  30. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/mcp.py +0 -0
  31. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/messages.py +0 -0
  32. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/output_types.py +0 -0
  33. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/permissions.py +0 -0
  34. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/sandbox.py +0 -0
  35. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/server_info.py +0 -0
  36. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/models/ts_output_types.py +0 -0
  37. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/py.typed +0 -0
  38. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/query.py +0 -0
  39. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/ARCHITECTURE.md +0 -0
  40. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/__init__.py +0 -0
  41. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/helpers.py +0 -0
  42. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/models.py +0 -0
  43. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/storage/replay.py +0 -0
  44. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/src/clawd_code_sdk/usage.py +0 -0
  45. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/conftest.py +0 -0
  46. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/mcp_server.py +0 -0
  47. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_changelog.py +0 -0
  48. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_client.py +0 -0
  49. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_errors.py +0 -0
  50. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_image.png +0 -0
  51. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_message_parser.py +0 -0
  52. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_sdk_mcp_integration.py +0 -0
  53. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_streaming_client.py +0 -0
  54. {clawd_code_sdk-0.1.89 → clawd_code_sdk-0.2.0}/tests/test_subprocess_buffering.py +0 -0
  55. {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.1.89
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "clawd-code-sdk"
3
- version = "0.1.89"
3
+ version = "0.2.0"
4
4
  description = "Python SDK for Claude Code"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -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
- if self._options.continue_conversation:
119
- cmd.append("--continue")
120
-
121
- if self._options.resume:
122
- cmd.extend(["--resume", self._options.resume])
123
-
124
- if self._options.session_id:
125
- cmd.extend(["--session-id", self._options.session_id])
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 - main options dataclass."""
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
- system_prompt: str | SystemPromptPreset | None = None
36
- """System prompt for the agent."""
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
- session_id: str | None = None
42
- """Deterministic session ID for a new session."""
43
- continue_conversation: bool = False
44
- """Continue most recent conversation."""
45
- resume: str | None = None
46
- """Resume a conversation by session id."""
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
- disallowed_tools: list[str] | None = None
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
- permission_prompt_tool_name: str | None = None
58
- """MCP tool to handle permission prompts."""
59
- cwd: str | Path | None = None
60
- """The working directory for the agent."""
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
- can_use_tool: CanUseTool | None = None
76
- """Tool permission callback."""
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
- fork_session: bool = False
82
- """Make resumed sessions forked to a new session ID instead of continuing."""
83
- agents: dict[str, AgentDefinition] | None = None
84
- """SubAgent definitions."""
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 ``continue_conversation=True`` and ``session_id`` on the options,
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 (``session_id`` and
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, continue_conversation=True)
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(continue_conversation=True),
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 continue_conversation and session_id."""
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.session_id == "prev-session-id"
575
- assert session.client.options.continue_conversation is True
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.session_id == "prev-id"
591
- assert session.client.options.continue_conversation is True
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 test_session_continuation(self):
185
- """Test session continuation options."""
186
- opts = make_options(continue_conversation=True, resume="session-123")
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 test_build_command_with_session_id(self):
194
- """Test building CLI command with session_id option."""
195
- opts = make_options(session_id="my-session-uuid")
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