claude-agent-sdk 0.1.1__tar.gz → 0.1.2__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.
Potentially problematic release.
This version of claude-agent-sdk might be problematic. Click here for more details.
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/PKG-INFO +1 -1
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/pyproject.toml +1 -1
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/__init__.py +2 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/query.py +9 -3
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_version.py +1 -1
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/types.py +65 -9
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_streaming_client.py +13 -6
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_tool_callbacks.py +133 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_transport.py +23 -12
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/.gitignore +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/LICENSE +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/README.md +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_errors.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/__init__.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/client.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/message_parser.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/transport/__init__.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/transport/subprocess_cli.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/client.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/py.typed +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/query.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/conftest.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_changelog.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_client.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_errors.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_integration.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_message_parser.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_sdk_mcp_integration.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_subprocess_buffering.py +0 -0
- {claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/tests/test_types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-agent-sdk
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
@@ -23,6 +23,7 @@ from .types import (
|
|
|
23
23
|
ContentBlock,
|
|
24
24
|
HookCallback,
|
|
25
25
|
HookContext,
|
|
26
|
+
HookJSONOutput,
|
|
26
27
|
HookMatcher,
|
|
27
28
|
McpSdkServerConfig,
|
|
28
29
|
McpServerConfig,
|
|
@@ -308,6 +309,7 @@ __all__ = [
|
|
|
308
309
|
"PermissionUpdate",
|
|
309
310
|
"HookCallback",
|
|
310
311
|
"HookContext",
|
|
312
|
+
"HookJSONOutput",
|
|
311
313
|
"HookMatcher",
|
|
312
314
|
# Agent support
|
|
313
315
|
"AgentDefinition",
|
|
@@ -195,6 +195,7 @@ class Query:
|
|
|
195
195
|
|
|
196
196
|
if subtype == "can_use_tool":
|
|
197
197
|
permission_request: SDKControlPermissionRequest = request_data # type: ignore[assignment]
|
|
198
|
+
original_input = permission_request["input"]
|
|
198
199
|
# Handle tool permission request
|
|
199
200
|
if not self.can_use_tool:
|
|
200
201
|
raise Exception("canUseTool callback is not provided")
|
|
@@ -213,9 +214,14 @@ class Query:
|
|
|
213
214
|
|
|
214
215
|
# Convert PermissionResult to expected dict format
|
|
215
216
|
if isinstance(response, PermissionResultAllow):
|
|
216
|
-
response_data = {
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
response_data = {
|
|
218
|
+
"behavior": "allow",
|
|
219
|
+
"updatedInput": (
|
|
220
|
+
response.updated_input
|
|
221
|
+
if response.updated_input is not None
|
|
222
|
+
else original_input
|
|
223
|
+
),
|
|
224
|
+
}
|
|
219
225
|
if response.updated_permissions is not None:
|
|
220
226
|
response_data["updatedPermissions"] = [
|
|
221
227
|
permission.to_dict()
|
|
@@ -157,18 +157,74 @@ HookEvent = (
|
|
|
157
157
|
)
|
|
158
158
|
|
|
159
159
|
|
|
160
|
+
# Hook-specific output types
|
|
161
|
+
class PreToolUseHookSpecificOutput(TypedDict):
|
|
162
|
+
"""Hook-specific output for PreToolUse events."""
|
|
163
|
+
|
|
164
|
+
hookEventName: Literal["PreToolUse"]
|
|
165
|
+
permissionDecision: NotRequired[Literal["allow", "deny", "ask"]]
|
|
166
|
+
permissionDecisionReason: NotRequired[str]
|
|
167
|
+
updatedInput: NotRequired[dict[str, Any]]
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class PostToolUseHookSpecificOutput(TypedDict):
|
|
171
|
+
"""Hook-specific output for PostToolUse events."""
|
|
172
|
+
|
|
173
|
+
hookEventName: Literal["PostToolUse"]
|
|
174
|
+
additionalContext: NotRequired[str]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class UserPromptSubmitHookSpecificOutput(TypedDict):
|
|
178
|
+
"""Hook-specific output for UserPromptSubmit events."""
|
|
179
|
+
|
|
180
|
+
hookEventName: Literal["UserPromptSubmit"]
|
|
181
|
+
additionalContext: NotRequired[str]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class SessionStartHookSpecificOutput(TypedDict):
|
|
185
|
+
"""Hook-specific output for SessionStart events."""
|
|
186
|
+
|
|
187
|
+
hookEventName: Literal["SessionStart"]
|
|
188
|
+
additionalContext: NotRequired[str]
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
HookSpecificOutput = (
|
|
192
|
+
PreToolUseHookSpecificOutput
|
|
193
|
+
| PostToolUseHookSpecificOutput
|
|
194
|
+
| UserPromptSubmitHookSpecificOutput
|
|
195
|
+
| SessionStartHookSpecificOutput
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
160
199
|
# See https://docs.anthropic.com/en/docs/claude-code/hooks#advanced%3A-json-output
|
|
161
|
-
# for documentation of the output types.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
200
|
+
# for documentation of the output types.
|
|
201
|
+
class AsyncHookJSONOutput(TypedDict):
|
|
202
|
+
"""Async hook output that defers hook execution."""
|
|
203
|
+
|
|
204
|
+
async_: Literal[True] # Using async_ to avoid Python keyword
|
|
205
|
+
asyncTimeout: NotRequired[int]
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class SyncHookJSONOutput(TypedDict):
|
|
209
|
+
"""Synchronous hook output with control and decision fields."""
|
|
210
|
+
|
|
211
|
+
# Common control fields
|
|
212
|
+
continue_: NotRequired[bool] # Using continue_ to avoid Python keyword
|
|
213
|
+
suppressOutput: NotRequired[bool]
|
|
214
|
+
stopReason: NotRequired[str]
|
|
215
|
+
|
|
216
|
+
# Decision fields
|
|
217
|
+
# Note: "approve" is deprecated for PreToolUse (use permissionDecision instead)
|
|
218
|
+
# For other hooks, only "block" is meaningful
|
|
165
219
|
decision: NotRequired[Literal["block"]]
|
|
166
|
-
# Optionally add a system message that is not visible to Claude but saved in
|
|
167
|
-
# the chat transcript.
|
|
168
220
|
systemMessage: NotRequired[str]
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
221
|
+
reason: NotRequired[str]
|
|
222
|
+
|
|
223
|
+
# Hook-specific outputs
|
|
224
|
+
hookSpecificOutput: NotRequired[HookSpecificOutput]
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput
|
|
172
228
|
|
|
173
229
|
|
|
174
230
|
@dataclass
|
|
@@ -633,21 +633,28 @@ assert '"Second"' in stdin_messages[1]
|
|
|
633
633
|
print('{"type": "result", "subtype": "success", "duration_ms": 100, "duration_api_ms": 50, "is_error": false, "num_turns": 1, "session_id": "test", "total_cost_usd": 0.001}')
|
|
634
634
|
""")
|
|
635
635
|
|
|
636
|
-
|
|
636
|
+
# Make script executable (Unix-style systems)
|
|
637
|
+
if sys.platform != "win32":
|
|
638
|
+
Path(test_script).chmod(0o755)
|
|
637
639
|
|
|
638
640
|
try:
|
|
639
|
-
# Mock _find_cli to return
|
|
641
|
+
# Mock _find_cli to return the test script path directly
|
|
640
642
|
with patch.object(
|
|
641
|
-
SubprocessCLITransport, "_find_cli", return_value=
|
|
643
|
+
SubprocessCLITransport, "_find_cli", return_value=test_script
|
|
642
644
|
):
|
|
643
|
-
# Mock _build_command to
|
|
645
|
+
# Mock _build_command to properly execute Python script
|
|
644
646
|
original_build_command = SubprocessCLITransport._build_command
|
|
645
647
|
|
|
646
648
|
def mock_build_command(self):
|
|
647
649
|
# Get original command
|
|
648
650
|
cmd = original_build_command(self)
|
|
649
|
-
#
|
|
650
|
-
|
|
651
|
+
# On Windows, we need to use python interpreter to run the script
|
|
652
|
+
if sys.platform == "win32":
|
|
653
|
+
# Replace first element with python interpreter and script
|
|
654
|
+
cmd[0:1] = [sys.executable, test_script]
|
|
655
|
+
else:
|
|
656
|
+
# On Unix, just use the script directly
|
|
657
|
+
cmd[0] = test_script
|
|
651
658
|
return cmd
|
|
652
659
|
|
|
653
660
|
with patch.object(
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"""Tests for tool permission callbacks and hook callbacks."""
|
|
2
2
|
|
|
3
|
+
import json
|
|
4
|
+
|
|
3
5
|
import pytest
|
|
4
6
|
|
|
5
7
|
from claude_agent_sdk import (
|
|
6
8
|
ClaudeAgentOptions,
|
|
7
9
|
HookContext,
|
|
10
|
+
HookJSONOutput,
|
|
8
11
|
HookMatcher,
|
|
9
12
|
PermissionResultAllow,
|
|
10
13
|
PermissionResultDeny,
|
|
@@ -257,6 +260,136 @@ class TestHookCallbacks:
|
|
|
257
260
|
last_response = transport.written_messages[-1]
|
|
258
261
|
assert '"processed": true' in last_response
|
|
259
262
|
|
|
263
|
+
@pytest.mark.asyncio
|
|
264
|
+
async def test_hook_output_fields(self):
|
|
265
|
+
"""Test that all SyncHookJSONOutput fields are properly handled."""
|
|
266
|
+
|
|
267
|
+
# Test all SyncHookJSONOutput fields together
|
|
268
|
+
async def comprehensive_hook(
|
|
269
|
+
input_data: dict, tool_use_id: str | None, context: HookContext
|
|
270
|
+
) -> HookJSONOutput:
|
|
271
|
+
return {
|
|
272
|
+
# Control fields
|
|
273
|
+
"continue_": True,
|
|
274
|
+
"suppressOutput": False,
|
|
275
|
+
"stopReason": "Test stop reason",
|
|
276
|
+
# Decision fields
|
|
277
|
+
"decision": "block",
|
|
278
|
+
"systemMessage": "Test system message",
|
|
279
|
+
"reason": "Test reason for blocking",
|
|
280
|
+
# Hook-specific output with all PreToolUse fields
|
|
281
|
+
"hookSpecificOutput": {
|
|
282
|
+
"hookEventName": "PreToolUse",
|
|
283
|
+
"permissionDecision": "deny",
|
|
284
|
+
"permissionDecisionReason": "Security policy violation",
|
|
285
|
+
"updatedInput": {"modified": "input"},
|
|
286
|
+
},
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
transport = MockTransport()
|
|
290
|
+
hooks = {
|
|
291
|
+
"PreToolUse": [
|
|
292
|
+
{"matcher": {"tool": "TestTool"}, "hooks": [comprehensive_hook]}
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
query = Query(
|
|
297
|
+
transport=transport, is_streaming_mode=True, can_use_tool=None, hooks=hooks
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
callback_id = "test_comprehensive_hook"
|
|
301
|
+
query.hook_callbacks[callback_id] = comprehensive_hook
|
|
302
|
+
|
|
303
|
+
request = {
|
|
304
|
+
"type": "control_request",
|
|
305
|
+
"request_id": "test-comprehensive",
|
|
306
|
+
"request": {
|
|
307
|
+
"subtype": "hook_callback",
|
|
308
|
+
"callback_id": callback_id,
|
|
309
|
+
"input": {"test": "data"},
|
|
310
|
+
"tool_use_id": "tool-456",
|
|
311
|
+
},
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
await query._handle_control_request(request)
|
|
315
|
+
|
|
316
|
+
# Check response contains all the fields
|
|
317
|
+
assert len(transport.written_messages) > 0
|
|
318
|
+
last_response = transport.written_messages[-1]
|
|
319
|
+
|
|
320
|
+
# Parse the JSON response
|
|
321
|
+
response_data = json.loads(last_response)
|
|
322
|
+
# The hook result is nested at response.response
|
|
323
|
+
result = response_data["response"]["response"]
|
|
324
|
+
|
|
325
|
+
# Verify control fields are present
|
|
326
|
+
assert result.get("continue_") is True or result.get("continue") is True
|
|
327
|
+
assert result.get("suppressOutput") is False
|
|
328
|
+
assert result.get("stopReason") == "Test stop reason"
|
|
329
|
+
|
|
330
|
+
# Verify decision fields are present
|
|
331
|
+
assert result.get("decision") == "block"
|
|
332
|
+
assert result.get("reason") == "Test reason for blocking"
|
|
333
|
+
assert result.get("systemMessage") == "Test system message"
|
|
334
|
+
|
|
335
|
+
# Verify hook-specific output is present
|
|
336
|
+
hook_output = result.get("hookSpecificOutput", {})
|
|
337
|
+
assert hook_output.get("hookEventName") == "PreToolUse"
|
|
338
|
+
assert hook_output.get("permissionDecision") == "deny"
|
|
339
|
+
assert (
|
|
340
|
+
hook_output.get("permissionDecisionReason") == "Security policy violation"
|
|
341
|
+
)
|
|
342
|
+
assert "updatedInput" in hook_output
|
|
343
|
+
|
|
344
|
+
@pytest.mark.asyncio
|
|
345
|
+
async def test_async_hook_output(self):
|
|
346
|
+
"""Test AsyncHookJSONOutput type with proper async fields."""
|
|
347
|
+
|
|
348
|
+
async def async_hook(
|
|
349
|
+
input_data: dict, tool_use_id: str | None, context: HookContext
|
|
350
|
+
) -> HookJSONOutput:
|
|
351
|
+
# Test that async hooks properly use async_ and asyncTimeout fields
|
|
352
|
+
return {
|
|
353
|
+
"async_": True,
|
|
354
|
+
"asyncTimeout": 5000,
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
transport = MockTransport()
|
|
358
|
+
hooks = {"PreToolUse": [{"matcher": None, "hooks": [async_hook]}]}
|
|
359
|
+
|
|
360
|
+
query = Query(
|
|
361
|
+
transport=transport, is_streaming_mode=True, can_use_tool=None, hooks=hooks
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
callback_id = "test_async_hook"
|
|
365
|
+
query.hook_callbacks[callback_id] = async_hook
|
|
366
|
+
|
|
367
|
+
request = {
|
|
368
|
+
"type": "control_request",
|
|
369
|
+
"request_id": "test-async",
|
|
370
|
+
"request": {
|
|
371
|
+
"subtype": "hook_callback",
|
|
372
|
+
"callback_id": callback_id,
|
|
373
|
+
"input": {"test": "async_data"},
|
|
374
|
+
"tool_use_id": None,
|
|
375
|
+
},
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
await query._handle_control_request(request)
|
|
379
|
+
|
|
380
|
+
# Check response contains async fields
|
|
381
|
+
assert len(transport.written_messages) > 0
|
|
382
|
+
last_response = transport.written_messages[-1]
|
|
383
|
+
|
|
384
|
+
# Parse the JSON response
|
|
385
|
+
response_data = json.loads(last_response)
|
|
386
|
+
# The hook result is nested at response.response
|
|
387
|
+
result = response_data["response"]["response"]
|
|
388
|
+
|
|
389
|
+
# The SDK should preserve the async_ field (or convert to "async")
|
|
390
|
+
assert result.get("async_") is True or result.get("async") is True
|
|
391
|
+
assert result.get("asyncTimeout") == 5000
|
|
392
|
+
|
|
260
393
|
|
|
261
394
|
class TestClaudeAgentOptionsIntegration:
|
|
262
395
|
"""Test that callbacks work through ClaudeAgentOptions."""
|
|
@@ -44,13 +44,15 @@ class TestSubprocessCLITransport:
|
|
|
44
44
|
"""Test that cli_path accepts pathlib.Path objects."""
|
|
45
45
|
from pathlib import Path
|
|
46
46
|
|
|
47
|
+
path = Path("/usr/bin/claude")
|
|
47
48
|
transport = SubprocessCLITransport(
|
|
48
49
|
prompt="Hello",
|
|
49
50
|
options=ClaudeAgentOptions(),
|
|
50
|
-
cli_path=
|
|
51
|
+
cli_path=path,
|
|
51
52
|
)
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
# Path object is converted to string, compare with str(path)
|
|
55
|
+
assert transport._cli_path == str(path)
|
|
54
56
|
|
|
55
57
|
def test_build_command_with_system_prompt_string(self):
|
|
56
58
|
"""Test building CLI command with system prompt as string."""
|
|
@@ -129,19 +131,25 @@ class TestSubprocessCLITransport:
|
|
|
129
131
|
"""Test building CLI command with add_dirs option."""
|
|
130
132
|
from pathlib import Path
|
|
131
133
|
|
|
134
|
+
dir1 = "/path/to/dir1"
|
|
135
|
+
dir2 = Path("/path/to/dir2")
|
|
132
136
|
transport = SubprocessCLITransport(
|
|
133
137
|
prompt="test",
|
|
134
|
-
options=ClaudeAgentOptions(
|
|
135
|
-
add_dirs=["/path/to/dir1", Path("/path/to/dir2")]
|
|
136
|
-
),
|
|
138
|
+
options=ClaudeAgentOptions(add_dirs=[dir1, dir2]),
|
|
137
139
|
cli_path="/usr/bin/claude",
|
|
138
140
|
)
|
|
139
141
|
|
|
140
142
|
cmd = transport._build_command()
|
|
141
|
-
cmd_str = " ".join(cmd)
|
|
142
143
|
|
|
143
|
-
# Check that
|
|
144
|
-
assert "--add-dir
|
|
144
|
+
# Check that both directories are in the command
|
|
145
|
+
assert "--add-dir" in cmd
|
|
146
|
+
add_dir_indices = [i for i, x in enumerate(cmd) if x == "--add-dir"]
|
|
147
|
+
assert len(add_dir_indices) == 2
|
|
148
|
+
|
|
149
|
+
# The directories should appear after --add-dir flags
|
|
150
|
+
dirs_in_cmd = [cmd[i + 1] for i in add_dir_indices]
|
|
151
|
+
assert dir1 in dirs_in_cmd
|
|
152
|
+
assert str(dir2) in dirs_in_cmd
|
|
145
153
|
|
|
146
154
|
def test_session_continuation(self):
|
|
147
155
|
"""Test session continuation options."""
|
|
@@ -322,28 +330,31 @@ class TestSubprocessCLITransport:
|
|
|
322
330
|
from pathlib import Path
|
|
323
331
|
|
|
324
332
|
# Test with string path
|
|
333
|
+
string_path = "/path/to/mcp-config.json"
|
|
325
334
|
transport = SubprocessCLITransport(
|
|
326
335
|
prompt="test",
|
|
327
|
-
options=ClaudeAgentOptions(mcp_servers=
|
|
336
|
+
options=ClaudeAgentOptions(mcp_servers=string_path),
|
|
328
337
|
cli_path="/usr/bin/claude",
|
|
329
338
|
)
|
|
330
339
|
|
|
331
340
|
cmd = transport._build_command()
|
|
332
341
|
assert "--mcp-config" in cmd
|
|
333
342
|
mcp_idx = cmd.index("--mcp-config")
|
|
334
|
-
assert cmd[mcp_idx + 1] ==
|
|
343
|
+
assert cmd[mcp_idx + 1] == string_path
|
|
335
344
|
|
|
336
345
|
# Test with Path object
|
|
346
|
+
path_obj = Path("/path/to/mcp-config.json")
|
|
337
347
|
transport = SubprocessCLITransport(
|
|
338
348
|
prompt="test",
|
|
339
|
-
options=ClaudeAgentOptions(mcp_servers=
|
|
349
|
+
options=ClaudeAgentOptions(mcp_servers=path_obj),
|
|
340
350
|
cli_path="/usr/bin/claude",
|
|
341
351
|
)
|
|
342
352
|
|
|
343
353
|
cmd = transport._build_command()
|
|
344
354
|
assert "--mcp-config" in cmd
|
|
345
355
|
mcp_idx = cmd.index("--mcp-config")
|
|
346
|
-
|
|
356
|
+
# Path object gets converted to string, compare with str(path_obj)
|
|
357
|
+
assert cmd[mcp_idx + 1] == str(path_obj)
|
|
347
358
|
|
|
348
359
|
def test_build_command_with_mcp_servers_as_json_string(self):
|
|
349
360
|
"""Test building CLI command with mcp_servers as JSON string."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_agent_sdk-0.1.1 → claude_agent_sdk-0.1.2}/src/claude_agent_sdk/_internal/message_parser.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
|