Skip to content

Follow Python SDK #1331/#1332: hook types, raw hook input, init fields - #174

Open
ya-luotao wants to merge 1 commit into
mainfrom
feat/hook-types-python-parity
Open

ya-luotao wants to merge 1 commit into
mainfrom
feat/hook-types-python-parity

Conversation

@ya-luotao

Copy link
Copy Markdown
Collaborator

Summary

Follows the two unreleased Python SDK changes on main (anthropics/claude-agent-sdk-python#1331, #1332), and fixes the Ruby-side gap that made the first one matter: typed hook inputs used to drop every field the SDK did not list by hand.

Hook inputs

  • Query#parse_hook_input was a 27-branch case that copied a fixed field list per event, so any field a newer CLI added (prompt_id, effort, duration_ms, ...) never reached the callback. It is now an event → class table (HOOK_INPUT_CLASSES, like MessageParser::SYSTEM_MESSAGE_CLASSES) built with the lenient from_hash, and every hook input keeps the payload as #raw_input (previously UnknownHookInput only).
  • New fields: prompt_id, effort (all inputs); duration_ms (PostToolUse / PostToolUseFailure); session_title, source (UserPromptSubmit); session_title, seconds_since_last_response, prompt_cache_likely_expired, context_tokens, estimated_cache_write_usd (SessionStart); parent_file_path (InstructionsLoaded).
  • New typed inputs for PostToolBatch, UserPromptExpansion, PreModelSwitch, PostModelSwitch, DirectoryAdded, MessageDisplay; HOOK_EVENTS now matches the CLI's 33 events.
  • Fields beyond Python's list come from the hook input schemas in the Claude Code 2.1.273 and 2.1.295 binaries. mcp_server (new in 2.1.295, marked @internal) is left to raw_input.

Hook-specific outputs

  • The *HookSpecificOutput classes are declared through a small @api private HookSpecificOutputFields helper that takes wire keys from HookOutputKeys::HOOK_SPECIFIC, so the table is the single vocabulary instead of being kept in step with 12 hand-written #to_hs.
  • Adds the 10 output classes from #1331 (PostToolBatch, UserPromptExpansion, Stop, SubagentStop, PreModelSwitch, PostModelSwitch, Elicitation, ElicitationResult, WorktreeCreate, MessageDisplay) and the new UserPromptSubmit / SessionStart fields. Hash outputs could already send these keys; the typed classes raised ArgumentError.

InitMessage

  • capabilities, plugin_errors, terminal_slash_commands, fast_mode_disabled_reason (#1332's SystemInitData).

Behavior changes (in CHANGELOG)

  • PermissionDeniedHookSpecificOutput#retry defaults to nil and is omitted (was false, always sent; the CLI reads both the same).
  • An output field set to false is now sent; only nil is omitted (most fields used to drop false too).

sig/, docs/hooks-and-permissions.md (new output-class table), docs/types.md and CHANGELOG are updated.

Test plan

  • bundle exec rspec: 4310 examples, 0 failures (query_hook_input_spec now has rows for all 33 events, checks raw_input, and covers an unknown event)
  • bundle exec rubocop: no offenses
  • bundle exec rake rbs:validate rbs:test: 3899 examples, 0 failures
  • Real session against CLI 2.1.295: InitMessage#capabilities / #fast_mode_disabled_reason populated, UserPromptSubmitHookInput#prompt_id received, typed UserPromptSubmitHookSpecificOutput(session_title:) accepted. Tool-use and Stop hooks were not exercised live (the test account's API credit was exhausted).

https://ampcode.com/threads/T-01a127a8-ad00-706d-a216-afc5c6d86e27

- Build hook inputs from the whole payload through an event => class
  table instead of a per-event field list, and keep the payload as
  #raw_input on every hook input, so CLI fields the SDK does not model
  are no longer dropped.
- Add prompt_id/effort, duration_ms and the other input fields the CLI
  sends; typed inputs for PostToolBatch, UserPromptExpansion,
  PreModelSwitch, PostModelSwitch, DirectoryAdded and MessageDisplay.
- Declare the *HookSpecificOutput classes from HookOutputKeys and add
  the ten output classes and new fields of Python #1331.
- PermissionDeniedHookSpecificOutput#retry defaults to nil.
- InitMessage: capabilities, plugin_errors, terminal_slash_commands,
  fast_mode_disabled_reason (Python #1332).

Amp-Thread-ID: https://ampcode.com/threads/T-01a127a8-ad00-706d-a216-afc5c6d86e27
Co-authored-by: ya-luotao <luotao@hey.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants