claude-agent-sdk 0.0.23__py3-none-any.whl → 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-agent-sdk might be problematic. Click here for more details.

@@ -213,13 +213,18 @@ class Query:
213
213
 
214
214
  # Convert PermissionResult to expected dict format
215
215
  if isinstance(response, PermissionResultAllow):
216
- response_data = {"allow": True}
216
+ response_data = {"behavior": "allow"}
217
217
  if response.updated_input is not None:
218
- response_data["input"] = response.updated_input
219
- # TODO: Handle updatedPermissions when control protocol supports it
218
+ response_data["updatedInput"] = response.updated_input
219
+ if response.updated_permissions is not None:
220
+ response_data["updatedPermissions"] = [
221
+ permission.to_dict()
222
+ for permission in response.updated_permissions
223
+ ]
220
224
  elif isinstance(response, PermissionResultDeny):
221
- response_data = {"allow": False, "reason": response.message}
222
- # TODO: Handle interrupt flag when control protocol supports it
225
+ response_data = {"behavior": "deny", "message": response.message}
226
+ if response.interrupt:
227
+ response_data["interrupt"] = response.interrupt
223
228
  else:
224
229
  raise TypeError(
225
230
  f"Tool permission callback must return PermissionResult (PermissionResultAllow or PermissionResultDeny), got {type(response)}"
@@ -3,7 +3,9 @@
3
3
  import json
4
4
  import logging
5
5
  import os
6
+ import re
6
7
  import shutil
8
+ import sys
7
9
  from collections.abc import AsyncIterable, AsyncIterator
8
10
  from contextlib import suppress
9
11
  from dataclasses import asdict
@@ -24,7 +26,8 @@ from . import Transport
24
26
 
25
27
  logger = logging.getLogger(__name__)
26
28
 
27
- _MAX_BUFFER_SIZE = 1024 * 1024 # 1MB buffer limit
29
+ _DEFAULT_MAX_BUFFER_SIZE = 1024 * 1024 # 1MB buffer limit
30
+ MINIMUM_CLAUDE_CODE_VERSION = "2.0.0"
28
31
 
29
32
 
30
33
  class SubprocessCLITransport(Transport):
@@ -48,6 +51,11 @@ class SubprocessCLITransport(Transport):
48
51
  self._stderr_task_group: anyio.abc.TaskGroup | None = None
49
52
  self._ready = False
50
53
  self._exit_error: Exception | None = None # Track process exit errors
54
+ self._max_buffer_size = (
55
+ options.max_buffer_size
56
+ if options.max_buffer_size is not None
57
+ else _DEFAULT_MAX_BUFFER_SIZE
58
+ )
51
59
 
52
60
  def _find_cli(self) -> str:
53
61
  """Find Claude Code CLI binary."""
@@ -66,15 +74,6 @@ class SubprocessCLITransport(Transport):
66
74
  if path.exists() and path.is_file():
67
75
  return str(path)
68
76
 
69
- node_installed = shutil.which("node") is not None
70
-
71
- if not node_installed:
72
- error_msg = "Claude Code requires Node.js, which is not installed.\n\n"
73
- error_msg += "Install Node.js from: https://nodejs.org/\n"
74
- error_msg += "\nAfter installing Node.js, install Claude Code:\n"
75
- error_msg += " npm install -g @anthropic-ai/claude-code"
76
- raise CLINotFoundError(error_msg)
77
-
78
77
  raise CLINotFoundError(
79
78
  "Claude Code not found. Install with:\n"
80
79
  " npm install -g @anthropic-ai/claude-code\n"
@@ -206,6 +205,8 @@ class SubprocessCLITransport(Transport):
206
205
  if self._process:
207
206
  return
208
207
 
208
+ await self._check_claude_version()
209
+
209
210
  cmd = self._build_command()
210
211
  try:
211
212
  # Merge environment variables: system -> user -> SDK required
@@ -411,12 +412,13 @@ class SubprocessCLITransport(Transport):
411
412
  # Keep accumulating partial JSON until we can parse it
412
413
  json_buffer += json_line
413
414
 
414
- if len(json_buffer) > _MAX_BUFFER_SIZE:
415
+ if len(json_buffer) > self._max_buffer_size:
416
+ buffer_length = len(json_buffer)
415
417
  json_buffer = ""
416
418
  raise SDKJSONDecodeError(
417
- f"JSON message exceeded maximum buffer size of {_MAX_BUFFER_SIZE} bytes",
419
+ f"JSON message exceeded maximum buffer size of {self._max_buffer_size} bytes",
418
420
  ValueError(
419
- f"Buffer size {len(json_buffer)} exceeds limit {_MAX_BUFFER_SIZE}"
421
+ f"Buffer size {buffer_length} exceeds limit {self._max_buffer_size}"
420
422
  ),
421
423
  )
422
424
 
@@ -427,7 +429,7 @@ class SubprocessCLITransport(Transport):
427
429
  except json.JSONDecodeError:
428
430
  # We are speculatively decoding the buffer until we get
429
431
  # a full JSON object. If there is an actual issue, we
430
- # raise an error after _MAX_BUFFER_SIZE.
432
+ # raise an error after exceeding the configured limit.
431
433
  continue
432
434
 
433
435
  except anyio.ClosedResourceError:
@@ -451,6 +453,46 @@ class SubprocessCLITransport(Transport):
451
453
  )
452
454
  raise self._exit_error
453
455
 
456
+ async def _check_claude_version(self) -> None:
457
+ """Check Claude Code version and warn if below minimum."""
458
+ version_process = None
459
+ try:
460
+ with anyio.fail_after(2): # 2 second timeout
461
+ version_process = await anyio.open_process(
462
+ [self._cli_path, "-v"],
463
+ stdout=PIPE,
464
+ stderr=PIPE,
465
+ )
466
+
467
+ if version_process.stdout:
468
+ stdout_bytes = await version_process.stdout.receive()
469
+ version_output = stdout_bytes.decode().strip()
470
+
471
+ match = re.match(r"([0-9]+\.[0-9]+\.[0-9]+)", version_output)
472
+ if match:
473
+ version = match.group(1)
474
+ version_parts = [int(x) for x in version.split(".")]
475
+ min_parts = [
476
+ int(x) for x in MINIMUM_CLAUDE_CODE_VERSION.split(".")
477
+ ]
478
+
479
+ if version_parts < min_parts:
480
+ warning = (
481
+ f"Warning: Claude Code version {version} is unsupported in the Agent SDK. "
482
+ f"Minimum required version is {MINIMUM_CLAUDE_CODE_VERSION}. "
483
+ "Some features may not work correctly."
484
+ )
485
+ logger.warning(warning)
486
+ print(warning, file=sys.stderr)
487
+ except Exception:
488
+ pass
489
+ finally:
490
+ if version_process:
491
+ with suppress(Exception):
492
+ version_process.terminate()
493
+ with suppress(Exception):
494
+ await version_process.wait()
495
+
454
496
  def is_ready(self) -> bool:
455
497
  """Check if transport is ready for communication."""
456
498
  return self._ready
@@ -1,3 +1,3 @@
1
1
  """Version information for claude-agent-sdk."""
2
2
 
3
- __version__ = "0.0.23"
3
+ __version__ = "0.1.1"
@@ -6,6 +6,7 @@ from collections.abc import AsyncIterable, AsyncIterator
6
6
  from dataclasses import replace
7
7
  from typing import Any
8
8
 
9
+ from . import Transport
9
10
  from ._errors import CLIConnectionError
10
11
  from .types import ClaudeAgentOptions, HookEvent, HookMatcher, Message, ResultMessage
11
12
 
@@ -51,12 +52,17 @@ class ClaudeSDKClient:
51
52
  exist.
52
53
  """
53
54
 
54
- def __init__(self, options: ClaudeAgentOptions | None = None):
55
+ def __init__(
56
+ self,
57
+ options: ClaudeAgentOptions | None = None,
58
+ transport: Transport | None = None,
59
+ ):
55
60
  """Initialize Claude SDK client."""
56
61
  if options is None:
57
62
  options = ClaudeAgentOptions()
58
63
  self.options = options
59
- self._transport: Any | None = None
64
+ self._custom_transport = transport
65
+ self._transport: Transport | None = None
60
66
  self._query: Any | None = None
61
67
  os.environ["CLAUDE_CODE_ENTRYPOINT"] = "sdk-py-client"
62
68
 
@@ -115,10 +121,14 @@ class ClaudeSDKClient:
115
121
  else:
116
122
  options = self.options
117
123
 
118
- self._transport = SubprocessCLITransport(
119
- prompt=actual_prompt,
120
- options=options,
121
- )
124
+ # Use provided custom transport or create subprocess transport
125
+ if self._custom_transport:
126
+ self._transport = self._custom_transport
127
+ else:
128
+ self._transport = SubprocessCLITransport(
129
+ prompt=actual_prompt,
130
+ options=options,
131
+ )
122
132
  await self._transport.connect()
123
133
 
124
134
  # Extract SDK MCP servers from options
@@ -222,7 +232,7 @@ class ClaudeSDKClient:
222
232
 
223
233
  Args:
224
234
  model: The model to use, or None to use default. Examples:
225
- - 'claude-sonnet-4-20250514'
235
+ - 'claude-sonnet-4-5'
226
236
  - 'claude-opus-4-1-20250805'
227
237
  - 'claude-opus-4-20250514'
228
238
 
@@ -233,7 +243,7 @@ class ClaudeSDKClient:
233
243
  await client.query("Help me understand this problem")
234
244
 
235
245
  # Switch to a different model for implementation
236
- await client.set_model('claude-3-5-sonnet-20241022')
246
+ await client.set_model('claude-sonnet-4-5')
237
247
  await client.query("Now implement the solution")
238
248
  ```
239
249
  """
claude_agent_sdk/types.py CHANGED
@@ -70,6 +70,42 @@ class PermissionUpdate:
70
70
  directories: list[str] | None = None
71
71
  destination: PermissionUpdateDestination | None = None
72
72
 
73
+ def to_dict(self) -> dict[str, Any]:
74
+ """Convert PermissionUpdate to dictionary format matching TypeScript control protocol."""
75
+ result: dict[str, Any] = {
76
+ "type": self.type,
77
+ }
78
+
79
+ # Add destination for all variants
80
+ if self.destination is not None:
81
+ result["destination"] = self.destination
82
+
83
+ # Handle different type variants
84
+ if self.type in ["addRules", "replaceRules", "removeRules"]:
85
+ # Rules-based variants require rules and behavior
86
+ if self.rules is not None:
87
+ result["rules"] = [
88
+ {
89
+ "toolName": rule.tool_name,
90
+ "ruleContent": rule.rule_content,
91
+ }
92
+ for rule in self.rules
93
+ ]
94
+ if self.behavior is not None:
95
+ result["behavior"] = self.behavior
96
+
97
+ elif self.type == "setMode":
98
+ # Mode variant requires mode
99
+ if self.mode is not None:
100
+ result["mode"] = self.mode
101
+
102
+ elif self.type in ["addDirectories", "removeDirectories"]:
103
+ # Directory variants require directories
104
+ if self.directories is not None:
105
+ result["directories"] = self.directories
106
+
107
+ return result
108
+
73
109
 
74
110
  # Tool callback types
75
111
  @dataclass
@@ -320,6 +356,7 @@ class ClaudeAgentOptions:
320
356
  extra_args: dict[str, str | None] = field(
321
357
  default_factory=dict
322
358
  ) # Pass arbitrary CLI flags
359
+ max_buffer_size: int | None = None # Max bytes when buffering CLI stdout
323
360
  debug_stderr: Any = (
324
361
  sys.stderr
325
362
  ) # Deprecated: File-like object for debug output. Use stderr callback instead.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-agent-sdk
3
- Version: 0.0.23
3
+ Version: 0.1.1
4
4
  Summary: Python SDK for Claude Code
5
5
  Project-URL: Homepage, https://github.com/anthropics/claude-agent-sdk-python
6
6
  Project-URL: Documentation, https://docs.anthropic.com/en/docs/claude-code/sdk
@@ -43,8 +43,8 @@ pip install claude-agent-sdk
43
43
 
44
44
  **Prerequisites:**
45
45
  - Python 3.10+
46
- - Node.js
47
- - Claude Code: `npm install -g @anthropic-ai/claude-code`
46
+ - Node.js
47
+ - Claude Code 2.0.0+: `npm install -g @anthropic-ai/claude-code`
48
48
 
49
49
  ## Quick Start
50
50
 
@@ -92,7 +92,7 @@ options = ClaudeAgentOptions(
92
92
  )
93
93
 
94
94
  async for message in query(
95
- prompt="Create a hello.py file",
95
+ prompt="Create a hello.py file",
96
96
  options=options
97
97
  ):
98
98
  # Process tool use and results
@@ -304,6 +304,15 @@ See [examples/quick_start.py](examples/quick_start.py) for a complete working ex
304
304
 
305
305
  See [examples/streaming_mode.py](examples/streaming_mode.py) for comprehensive examples involving `ClaudeSDKClient`. You can even run interactive examples in IPython from [examples/streaming_mode_ipython.py](examples/streaming_mode_ipython.py).
306
306
 
307
+ ## Migrating from Claude Code SDK
308
+
309
+ If you're upgrading from the Claude Code SDK (versions < 0.1.0), please see the [CHANGELOG.md](CHANGELOG.md#010) for details on breaking changes and new features, including:
310
+
311
+ - `ClaudeCodeOptions` → `ClaudeAgentOptions` rename
312
+ - Merged system prompt configuration
313
+ - Settings isolation and explicit control
314
+ - New programmatic subagents and session forking features
315
+
307
316
  ## License
308
317
 
309
318
  MIT
@@ -0,0 +1,17 @@
1
+ claude_agent_sdk/__init__.py,sha256=ZwJ2YpPdvDRdg1j73TGmK5FEfriv00MbgB5GbEkgqEs,11584
2
+ claude_agent_sdk/_errors.py,sha256=nSdJNNeszvXG1PfnXd2sQpVNORqMct-MfPaiM3XeJL4,1579
3
+ claude_agent_sdk/_version.py,sha256=yIo_daGf7IiorFxtDROWUbETCsox9r8uyNEv2NuZUfQ,71
4
+ claude_agent_sdk/client.py,sha256=Bye3QKb-iTg6Yq34ZPGHzaMg1isT9RvyHs5TkC2jWDI,13926
5
+ claude_agent_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ claude_agent_sdk/query.py,sha256=WebhztsMZPdaxyy1LBEZv4_j23vjp_ceX9DtrBsZqCA,4530
7
+ claude_agent_sdk/types.py,sha256=0GcWj57sqRqh7Rv3UXm8uTQkH9ENMr4AdDsm8_cUY7g,11841
8
+ claude_agent_sdk/_internal/__init__.py,sha256=zDdgjqp8SI9mTnwZbP2Be-w4LWlv4a3kA-TS2i75jsM,39
9
+ claude_agent_sdk/_internal/client.py,sha256=Z06Fj4t5mHkKHKBUwxmHMTEo7lzs3X4_D_c-xq6Wg4I,4603
10
+ claude_agent_sdk/_internal/message_parser.py,sha256=xxpOU3E8X21FCoy2OtLWKfEQr3AFYM454qJt6Xa0tmc,6475
11
+ claude_agent_sdk/_internal/query.py,sha256=b1JhWIKEIanVEA6g8SRqaYVVBsXjHWp-6rQXhIw8z70,20961
12
+ claude_agent_sdk/_internal/transport/__init__.py,sha256=sv8Iy1b9YmPlXu4XsdN98gJIlyrLtwq8PKQyF4qnQLk,1978
13
+ claude_agent_sdk/_internal/transport/subprocess_cli.py,sha256=ViZxmHoAx3NdFNgLUFgNYuCjJZdVqKk2sxHlB57Z2ng,19097
14
+ claude_agent_sdk-0.1.1.dist-info/METADATA,sha256=rNgqZ08Pq6tKo9n13C3d_R8EwdHZcqnP7vAiGHDJm5w,9648
15
+ claude_agent_sdk-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ claude_agent_sdk-0.1.1.dist-info/licenses/LICENSE,sha256=zr3eio-57lnl6q7RlXi_gIWqcEdWIlnDHzjyJcJvaBI,1070
17
+ claude_agent_sdk-0.1.1.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- claude_agent_sdk/__init__.py,sha256=ZwJ2YpPdvDRdg1j73TGmK5FEfriv00MbgB5GbEkgqEs,11584
2
- claude_agent_sdk/_errors.py,sha256=nSdJNNeszvXG1PfnXd2sQpVNORqMct-MfPaiM3XeJL4,1579
3
- claude_agent_sdk/_version.py,sha256=sLNUvI_d4RrYrZJlKrqcizYyZ0sKyQE6-uuWZ8slc1Y,72
4
- claude_agent_sdk/client.py,sha256=je82F2J_BtB9Gh4PRUcjeTI1wrYVENMsAasOaUkO-3Y,13613
5
- claude_agent_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- claude_agent_sdk/query.py,sha256=WebhztsMZPdaxyy1LBEZv4_j23vjp_ceX9DtrBsZqCA,4530
7
- claude_agent_sdk/types.py,sha256=yGDK3TfoICruVIGY1t8lnLSZGd4McRY7gEZm3n_ZoTc,10447
8
- claude_agent_sdk/_internal/__init__.py,sha256=zDdgjqp8SI9mTnwZbP2Be-w4LWlv4a3kA-TS2i75jsM,39
9
- claude_agent_sdk/_internal/client.py,sha256=Z06Fj4t5mHkKHKBUwxmHMTEo7lzs3X4_D_c-xq6Wg4I,4603
10
- claude_agent_sdk/_internal/message_parser.py,sha256=xxpOU3E8X21FCoy2OtLWKfEQr3AFYM454qJt6Xa0tmc,6475
11
- claude_agent_sdk/_internal/query.py,sha256=G2CxNrMhrmae2V9oh8ctJsWIFOCU2VEkBQvH1-nXC6w,20721
12
- claude_agent_sdk/_internal/transport/__init__.py,sha256=sv8Iy1b9YmPlXu4XsdN98gJIlyrLtwq8PKQyF4qnQLk,1978
13
- claude_agent_sdk/_internal/transport/subprocess_cli.py,sha256=UFD5D5NKJitd-apg9_A5mQnmBALaer_ROUaPeDpQexc,17405
14
- claude_agent_sdk-0.0.23.dist-info/METADATA,sha256=1xMFPeoP6u76JDH5IkBAe1-Pqcj-XKrPjcmLtogUPSY,9242
15
- claude_agent_sdk-0.0.23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- claude_agent_sdk-0.0.23.dist-info/licenses/LICENSE,sha256=zr3eio-57lnl6q7RlXi_gIWqcEdWIlnDHzjyJcJvaBI,1070
17
- claude_agent_sdk-0.0.23.dist-info/RECORD,,