fix(types): add missing dontAsk permission mode#719
Conversation
There was a problem hiding this comment.
LGTM — straightforward addition of missing permission mode literals with tests.
Extended reasoning...
Overview
This PR adds three missing permission modes (dontAsk, auto, bubble) to the PermissionMode Literal type in types.py, updates the SDKControlSetPermissionModeRequest.mode field from bare str to PermissionMode (resolving an existing TODO), and adds corresponding tests in test_types.py and test_transport.py. Three files changed with ~25 lines added.
Security risks
None. This is a type annotation change only — no runtime behavior is modified. Permission mode validation still happens in the CLI itself.
Level of scrutiny
Low scrutiny warranted. This is a mechanical type definition expansion adding well-known CLI modes that were simply missing from the SDK type. The changes follow established patterns exactly.
Other factors
The inline bug comment about set_permission_mode method signatures in client.py and query.py still accepting str is a valid consistency nit, but does not affect correctness — Python does not enforce type annotations at runtime, and the CLI validates the mode string server-side. The PR accomplishes its stated goal cleanly. No CODEOWNERS file exists. Tests cover the new modes adequately.
There was a problem hiding this comment.
LGTM — previous feedback addressed, straightforward type annotation fix with tests.
Extended reasoning...
Overview
This PR adds three missing permission modes (dontAsk, auto, bubble) to the PermissionMode Literal type, tightens SDKControlSetPermissionModeRequest.mode from str to PermissionMode, and updates the set_permission_mode method signatures in both client.py and _internal/query.py to use PermissionMode. Tests are added for the new modes in both test_types.py and test_transport.py.
Security risks
None. This is a type annotation change with no runtime behavior impact. Permission modes are validated by the CLI itself, and no new code paths are introduced.
Level of scrutiny
Low scrutiny appropriate. This is a mechanical type definition update — adding literal values to an existing union type and propagating the type annotation to method signatures. The diff is small (under 50 lines of non-test code) and follows established patterns.
Other factors
My previous review flagged that the set_permission_mode signatures still accepted bare str and the docstring was incomplete. Both issues have been fully addressed in this revision. The remaining inline nit about query.py's docstring is a pre-existing documentation gap (not introduced by this PR) and is minor enough not to block approval.
There was a problem hiding this comment.
LGTM — all prior feedback addressed, straightforward type annotation fix with tests.
Extended reasoning...
Overview
This PR adds three missing permission modes (dontAsk, auto, bubble) to the PermissionMode Literal type, updates SDKControlSetPermissionModeRequest.mode from bare str to PermissionMode, updates the set_permission_mode method signatures in both client.py and _internal/query.py to use PermissionMode, and updates docstrings in client.py and query.py to list all 7 valid modes. Tests are added for the new modes in both test_types.py and test_transport.py.
Security risks
None. This is a type annotation change with no runtime behavioral impact. Permission mode validation still happens in the CLI.
Level of scrutiny
Low scrutiny is appropriate. The changes are mechanical: expanding a Literal type, updating type annotations and docstrings for consistency, and adding simple assertion-based tests. No logic changes, no new code paths.
Other factors
Both issues I raised in prior reviews (signature consistency and docstring completeness) have been fully addressed in the current diff. The first inline comment is marked resolved. The PR includes test coverage for all three new modes. No CODEOWNERS concerns for these files.
There was a problem hiding this comment.
LGTM — previous feedback addressed, type annotations and docstrings are consistent.
Extended reasoning...
Overview
This PR adds dontAsk to the PermissionMode Literal type, tightens SDKControlSetPermissionModeRequest.mode from bare str to PermissionMode (resolving an inline TODO), updates method signatures in client.py and _internal/query.py to use PermissionMode, updates docstrings in both client.py and query.py, and adds corresponding tests.
Security risks
None. This is a type annotation change only — Python does not enforce type annotations at runtime, and the CLI validates mode strings server-side. No auth, crypto, or permission logic is altered.
Level of scrutiny
Low scrutiny is appropriate. The changes are mechanical: adding a literal value to a type union, updating function signatures to use that type, and updating docstrings. The pattern follows existing code exactly. Both my prior review comments have been addressed and resolved.
Other factors
Tests have been added for the new permission mode (test_build_command_with_dont_ask_permission_mode, test_claude_code_options_with_permission_mode extended). A human reviewer (qing-ant) confirmed E2E testing passes. All 328 unit tests pass. No CODEOWNERS concerns. The bug hunting system found no issues.
The PermissionMode type was missing three modes that the CLI supports: dontAsk, auto, and bubble. This caused type errors when users tried to use these modes via ClaudeAgentOptions. - Add dontAsk, auto, bubble to PermissionMode Literal type - Fix SDKControlSetPermissionModeRequest.mode to use PermissionMode instead of bare str (resolves TODO) - Add tests for new permission modes in types and transport Fixes #483
Update ClaudeSDKClient.set_permission_mode() and InternalQuery.set_permission_mode() to accept PermissionMode instead of bare str, enabling static type checkers to catch invalid mode strings at call sites. Also update the client docstring to document all seven valid permission modes including the three new ones (dontAsk, auto, bubble).
Only expose permission modes that are in the public CLI SDK schema: default, acceptEdits, plan, bypassPermissions, dontAsk. auto and bubble are internal-only modes used by the coordinator system and should not be exposed to external SDK users. :house: Remote-Dev: homespace
ef73a99 to
f6dd0d0
Compare
There was a problem hiding this comment.
LGTM — all previous feedback has been addressed; the final diff correctly adds only dontAsk and tightens the type signatures.
Extended reasoning...
Overview
This PR touches 4 source files and 2 test files. It adds dontAsk to the PermissionMode Literal type, updates SDKControlSetPermissionModeRequest.mode from str to PermissionMode (resolving an inline TODO), tightens the set_permission_mode method signatures in both client.py and _internal/query.py from str to PermissionMode, updates docstrings in both client.py and query.py to list plan and dontAsk, and adds test coverage for the new mode.
Security risks
No security risks. The changes are purely type annotation and documentation improvements. Permission modes are validated by the CLI at runtime regardless of the SDK type annotations.
Level of scrutiny
This is a low-risk change — type annotation tightening, docstring updates, and a new Literal value. No runtime behavior changes. The maintainer (qing-ant) has already E2E tested and confirmed correctness. All 328 unit tests pass.
Other factors
My previous inline comments went through several iterations as the PR evolved. The final state correctly excludes auto and bubble from the public PermissionMode type, consistent with the maintainer's explicit decision (commit e2a35bb) that these are internal-only coordinator modes. My last unresolved inline comment (about re-introducing auto/bubble) is now stale — the current diff does not include those modes. The PR title/description still references all three modes, but the actual implementation is correct. No CODEOWNERS file exists for this repository.
E2E Test ResultsTest script: """E2E test for PR #719: dontAsk permission mode works end-to-end.
This test verifies that the newly added 'dontAsk' permission mode can be
passed via ClaudeAgentOptions and works correctly with a live SDK instance.
"""
import asyncio
import sys
import claude_agent_sdk
from claude_agent_sdk import ClaudeAgentOptions
async def main() -> None:
print(f"SDK version: {claude_agent_sdk.__version__}")
print()
print("Sending query with permission_mode='dontAsk', max_turns=1...")
print()
messages = []
try:
async for msg in claude_agent_sdk.query(
prompt="Reply with exactly: hello world",
options=ClaudeAgentOptions(max_turns=1, permission_mode="dontAsk"),
):
messages.append(msg)
except Exception as exc:
print(f"FAIL: query raised {type(exc).__name__}: {exc}", file=sys.stderr)
sys.exit(1)
print(f"Received {len(messages)} messages:")
print()
found_hello = False
for i, msg in enumerate(messages):
msg_type = type(msg).__name__
content = getattr(msg, "content", None)
if isinstance(content, list):
content_str = ", ".join(str(c)[:100] for c in content)
elif isinstance(content, str):
content_str = content[:200]
else:
content_str = str(content)[:200] if content else ""
print(f" [{i}] {msg_type}: {content_str}")
if isinstance(content, str) and "hello world" in content.lower():
found_hello = True
elif isinstance(content, list):
for block in content:
text = getattr(block, "text", "")
if "hello world" in text.lower():
found_hello = True
print()
if found_hello:
print("PASS: query() completed successfully with permission_mode='dontAsk'")
print("The dontAsk permission mode is properly accepted and forwarded to the CLI.")
else:
all_text = " ".join(str(m) for m in messages)
if "hello world" in all_text.lower():
print("PASS: query() completed successfully with permission_mode='dontAsk'")
else:
print("FAIL: Did not find expected 'hello world' in responses.", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())Output: |
Summary
The
PermissionModetype was missingdontAsk, which the CLI supports and is documented at https://platform.claude.com/docs/en/agent-sdk/permissions#available-modes. This caused type errors when users tried to use it viaClaudeAgentOptions.Fixes #483
Changes
dontAsktoPermissionModeLiteral type — now matches the TS SDK'sExternalPermissionModeexactly (default,acceptEdits,plan,bypassPermissions,dontAsk)set_permission_mode(mode)asPermissionModeinstead of barestrin bothclient.pyand_internal/query.py(resolves inline TODO onSDKControlSetPermissionModeRequest.mode)plananddontAskto the docstrings inclient.pyandquery.py(planwas already in the type but missing from docs)dontAskin types and transportNote:
autoandbubblewere considered but intentionally excluded — they are internal-only modes in the TS SDK (InternalPermissionMode), not part of the publicExternalPermissionModesurface.