claude-agent-sdk 1.2.1 → 1.3.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -71
- data/README.md +40 -40
- data/UPGRADING-1.0.md +1 -1
- data/docs/client.md +1 -1
- data/docs/configuration.md +6 -6
- data/docs/errors.md +2 -2
- data/docs/hooks-and-permissions.md +36 -7
- data/docs/mcp-servers.md +1 -1
- data/docs/observability.md +1 -1
- data/docs/rails.md +5 -5
- data/docs/sessions.md +1 -1
- data/docs/subagents.md +1 -1
- data/docs/types.md +2 -2
- data/lib/claude_agent_sdk/cli_installer.rb +1 -1
- data/lib/claude_agent_sdk/query.rb +48 -220
- data/lib/claude_agent_sdk/types/hooks.rb +378 -243
- data/lib/claude_agent_sdk/types/messages.rb +14 -3
- data/lib/claude_agent_sdk/version.rb +1 -1
- data/lib/generators/claude_agent_sdk/install/install_generator.rb +1 -1
- data/lib/generators/claude_agent_sdk/install/templates/claude_agent_sdk.rb.tt +1 -1
- data/sig/claude_agent_sdk/types/hooks.rbs +286 -3
- data/sig/claude_agent_sdk/types/messages.rbs +15 -0
- metadata +6 -6
|
@@ -868,227 +868,55 @@ module ClaudeAgentSDK
|
|
|
868
868
|
@callback_request_signals.delete(request_id)
|
|
869
869
|
end
|
|
870
870
|
|
|
871
|
-
|
|
871
|
+
# The typed input built for each hook event the SDK models; any other
|
|
872
|
+
# event becomes an UnknownHookInput.
|
|
873
|
+
HOOK_INPUT_CLASSES = {
|
|
874
|
+
'PreToolUse' => PreToolUseHookInput,
|
|
875
|
+
'PostToolUse' => PostToolUseHookInput,
|
|
876
|
+
'PostToolUseFailure' => PostToolUseFailureHookInput,
|
|
877
|
+
'UserPromptSubmit' => UserPromptSubmitHookInput,
|
|
878
|
+
'Stop' => StopHookInput,
|
|
879
|
+
'SubagentStop' => SubagentStopHookInput,
|
|
880
|
+
'Notification' => NotificationHookInput,
|
|
881
|
+
'SubagentStart' => SubagentStartHookInput,
|
|
882
|
+
'PermissionRequest' => PermissionRequestHookInput,
|
|
883
|
+
'PreCompact' => PreCompactHookInput,
|
|
884
|
+
'SessionStart' => SessionStartHookInput,
|
|
885
|
+
'SessionEnd' => SessionEndHookInput,
|
|
886
|
+
'Setup' => SetupHookInput,
|
|
887
|
+
'TeammateIdle' => TeammateIdleHookInput,
|
|
888
|
+
'TaskCompleted' => TaskCompletedHookInput,
|
|
889
|
+
'ConfigChange' => ConfigChangeHookInput,
|
|
890
|
+
'WorktreeCreate' => WorktreeCreateHookInput,
|
|
891
|
+
'WorktreeRemove' => WorktreeRemoveHookInput,
|
|
892
|
+
'StopFailure' => StopFailureHookInput,
|
|
893
|
+
'PostCompact' => PostCompactHookInput,
|
|
894
|
+
'PermissionDenied' => PermissionDeniedHookInput,
|
|
895
|
+
'TaskCreated' => TaskCreatedHookInput,
|
|
896
|
+
'Elicitation' => ElicitationHookInput,
|
|
897
|
+
'ElicitationResult' => ElicitationResultHookInput,
|
|
898
|
+
'InstructionsLoaded' => InstructionsLoadedHookInput,
|
|
899
|
+
'CwdChanged' => CwdChangedHookInput,
|
|
900
|
+
'FileChanged' => FileChangedHookInput,
|
|
901
|
+
'PostToolBatch' => PostToolBatchHookInput,
|
|
902
|
+
'UserPromptExpansion' => UserPromptExpansionHookInput,
|
|
903
|
+
'PreModelSwitch' => PreModelSwitchHookInput,
|
|
904
|
+
'PostModelSwitch' => PostModelSwitchHookInput,
|
|
905
|
+
'DirectoryAdded' => DirectoryAddedHookInput,
|
|
906
|
+
'MessageDisplay' => MessageDisplayHookInput
|
|
907
|
+
}.freeze
|
|
908
|
+
private_constant :HOOK_INPUT_CLASSES
|
|
909
|
+
|
|
910
|
+
# Every field of the payload that the class declares is assigned (the
|
|
911
|
+
# lenient parse path: other keys are skipped, not rejected), and the
|
|
912
|
+
# whole payload is kept as #raw_input, so a field the CLI added after this
|
|
913
|
+
# SDK version is still readable there.
|
|
914
|
+
def parse_hook_input(input_data)
|
|
915
|
+
input_data = {} unless input_data.is_a?(Hash)
|
|
872
916
|
event_name = input_data[:hook_event_name] || input_data['hook_event_name']
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
elsif input_data.key?(key.to_s)
|
|
877
|
-
input_data[key.to_s]
|
|
878
|
-
end
|
|
879
|
-
end
|
|
880
|
-
base_args = {
|
|
881
|
-
session_id: fetch.call(:session_id),
|
|
882
|
-
transcript_path: fetch.call(:transcript_path),
|
|
883
|
-
cwd: fetch.call(:cwd),
|
|
884
|
-
permission_mode: fetch.call(:permission_mode)
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
# Subagent context fields shared by tool-lifecycle hooks
|
|
888
|
-
subagent_args = {
|
|
889
|
-
agent_id: fetch.call(:agent_id),
|
|
890
|
-
agent_type: fetch.call(:agent_type)
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
case event_name
|
|
894
|
-
when 'PreToolUse'
|
|
895
|
-
PreToolUseHookInput.new(
|
|
896
|
-
tool_name: fetch.call(:tool_name),
|
|
897
|
-
tool_input: fetch.call(:tool_input),
|
|
898
|
-
tool_use_id: fetch.call(:tool_use_id),
|
|
899
|
-
**subagent_args, **base_args
|
|
900
|
-
)
|
|
901
|
-
when 'PostToolUse'
|
|
902
|
-
PostToolUseHookInput.new(
|
|
903
|
-
tool_name: fetch.call(:tool_name),
|
|
904
|
-
tool_input: fetch.call(:tool_input),
|
|
905
|
-
tool_response: fetch.call(:tool_response),
|
|
906
|
-
tool_use_id: fetch.call(:tool_use_id),
|
|
907
|
-
**subagent_args, **base_args
|
|
908
|
-
)
|
|
909
|
-
when 'PostToolUseFailure'
|
|
910
|
-
PostToolUseFailureHookInput.new(
|
|
911
|
-
tool_name: fetch.call(:tool_name),
|
|
912
|
-
tool_input: fetch.call(:tool_input),
|
|
913
|
-
tool_use_id: fetch.call(:tool_use_id),
|
|
914
|
-
error: fetch.call(:error),
|
|
915
|
-
is_interrupt: fetch.call(:is_interrupt),
|
|
916
|
-
**subagent_args, **base_args
|
|
917
|
-
)
|
|
918
|
-
when 'UserPromptSubmit'
|
|
919
|
-
UserPromptSubmitHookInput.new(
|
|
920
|
-
prompt: fetch.call(:prompt),
|
|
921
|
-
**base_args
|
|
922
|
-
)
|
|
923
|
-
when 'Stop'
|
|
924
|
-
StopHookInput.new(
|
|
925
|
-
stop_hook_active: fetch.call(:stop_hook_active),
|
|
926
|
-
last_assistant_message: fetch.call(:last_assistant_message),
|
|
927
|
-
background_tasks: fetch.call(:background_tasks),
|
|
928
|
-
session_crons: fetch.call(:session_crons),
|
|
929
|
-
**base_args
|
|
930
|
-
)
|
|
931
|
-
when 'SubagentStop'
|
|
932
|
-
SubagentStopHookInput.new(
|
|
933
|
-
stop_hook_active: fetch.call(:stop_hook_active),
|
|
934
|
-
agent_id: fetch.call(:agent_id),
|
|
935
|
-
agent_transcript_path: fetch.call(:agent_transcript_path),
|
|
936
|
-
agent_type: fetch.call(:agent_type),
|
|
937
|
-
last_assistant_message: fetch.call(:last_assistant_message),
|
|
938
|
-
background_tasks: fetch.call(:background_tasks),
|
|
939
|
-
session_crons: fetch.call(:session_crons),
|
|
940
|
-
**base_args
|
|
941
|
-
)
|
|
942
|
-
when 'Notification'
|
|
943
|
-
NotificationHookInput.new(
|
|
944
|
-
message: fetch.call(:message),
|
|
945
|
-
title: fetch.call(:title),
|
|
946
|
-
notification_type: fetch.call(:notification_type),
|
|
947
|
-
**base_args
|
|
948
|
-
)
|
|
949
|
-
when 'SubagentStart'
|
|
950
|
-
SubagentStartHookInput.new(
|
|
951
|
-
agent_id: fetch.call(:agent_id),
|
|
952
|
-
agent_type: fetch.call(:agent_type),
|
|
953
|
-
**base_args
|
|
954
|
-
)
|
|
955
|
-
when 'PermissionRequest'
|
|
956
|
-
PermissionRequestHookInput.new(
|
|
957
|
-
tool_name: fetch.call(:tool_name),
|
|
958
|
-
tool_input: fetch.call(:tool_input),
|
|
959
|
-
permission_suggestions: fetch.call(:permission_suggestions),
|
|
960
|
-
**subagent_args, **base_args
|
|
961
|
-
)
|
|
962
|
-
when 'PreCompact'
|
|
963
|
-
PreCompactHookInput.new(
|
|
964
|
-
trigger: fetch.call(:trigger),
|
|
965
|
-
custom_instructions: fetch.call(:custom_instructions),
|
|
966
|
-
**base_args
|
|
967
|
-
)
|
|
968
|
-
when 'SessionStart'
|
|
969
|
-
SessionStartHookInput.new(
|
|
970
|
-
source: fetch.call(:source),
|
|
971
|
-
agent_type: fetch.call(:agent_type),
|
|
972
|
-
model: fetch.call(:model),
|
|
973
|
-
**base_args
|
|
974
|
-
)
|
|
975
|
-
when 'SessionEnd'
|
|
976
|
-
SessionEndHookInput.new(
|
|
977
|
-
reason: fetch.call(:reason),
|
|
978
|
-
**base_args
|
|
979
|
-
)
|
|
980
|
-
when 'Setup'
|
|
981
|
-
SetupHookInput.new(
|
|
982
|
-
trigger: fetch.call(:trigger),
|
|
983
|
-
**base_args
|
|
984
|
-
)
|
|
985
|
-
when 'TeammateIdle'
|
|
986
|
-
TeammateIdleHookInput.new(
|
|
987
|
-
teammate_name: fetch.call(:teammate_name),
|
|
988
|
-
team_name: fetch.call(:team_name),
|
|
989
|
-
**base_args
|
|
990
|
-
)
|
|
991
|
-
when 'TaskCompleted'
|
|
992
|
-
TaskCompletedHookInput.new(
|
|
993
|
-
task_id: fetch.call(:task_id),
|
|
994
|
-
task_subject: fetch.call(:task_subject),
|
|
995
|
-
task_description: fetch.call(:task_description),
|
|
996
|
-
teammate_name: fetch.call(:teammate_name),
|
|
997
|
-
team_name: fetch.call(:team_name),
|
|
998
|
-
**base_args
|
|
999
|
-
)
|
|
1000
|
-
when 'ConfigChange'
|
|
1001
|
-
ConfigChangeHookInput.new(
|
|
1002
|
-
source: fetch.call(:source),
|
|
1003
|
-
file_path: fetch.call(:file_path),
|
|
1004
|
-
**base_args
|
|
1005
|
-
)
|
|
1006
|
-
when 'WorktreeCreate'
|
|
1007
|
-
WorktreeCreateHookInput.new(
|
|
1008
|
-
name: fetch.call(:name),
|
|
1009
|
-
**base_args
|
|
1010
|
-
)
|
|
1011
|
-
when 'WorktreeRemove'
|
|
1012
|
-
WorktreeRemoveHookInput.new(
|
|
1013
|
-
worktree_path: fetch.call(:worktree_path),
|
|
1014
|
-
**base_args
|
|
1015
|
-
)
|
|
1016
|
-
when 'StopFailure'
|
|
1017
|
-
StopFailureHookInput.new(
|
|
1018
|
-
error: fetch.call(:error),
|
|
1019
|
-
error_details: fetch.call(:error_details),
|
|
1020
|
-
last_assistant_message: fetch.call(:last_assistant_message),
|
|
1021
|
-
**base_args
|
|
1022
|
-
)
|
|
1023
|
-
when 'PostCompact'
|
|
1024
|
-
PostCompactHookInput.new(
|
|
1025
|
-
trigger: fetch.call(:trigger),
|
|
1026
|
-
compact_summary: fetch.call(:compact_summary),
|
|
1027
|
-
**base_args
|
|
1028
|
-
)
|
|
1029
|
-
when 'PermissionDenied'
|
|
1030
|
-
PermissionDeniedHookInput.new(
|
|
1031
|
-
tool_name: fetch.call(:tool_name),
|
|
1032
|
-
tool_input: fetch.call(:tool_input),
|
|
1033
|
-
tool_use_id: fetch.call(:tool_use_id),
|
|
1034
|
-
reason: fetch.call(:reason),
|
|
1035
|
-
**subagent_args, **base_args
|
|
1036
|
-
)
|
|
1037
|
-
when 'TaskCreated'
|
|
1038
|
-
TaskCreatedHookInput.new(
|
|
1039
|
-
task_id: fetch.call(:task_id),
|
|
1040
|
-
task_subject: fetch.call(:task_subject),
|
|
1041
|
-
task_description: fetch.call(:task_description),
|
|
1042
|
-
teammate_name: fetch.call(:teammate_name),
|
|
1043
|
-
team_name: fetch.call(:team_name),
|
|
1044
|
-
**base_args
|
|
1045
|
-
)
|
|
1046
|
-
when 'Elicitation'
|
|
1047
|
-
ElicitationHookInput.new(
|
|
1048
|
-
mcp_server_name: fetch.call(:mcp_server_name),
|
|
1049
|
-
message: fetch.call(:message),
|
|
1050
|
-
mode: fetch.call(:mode),
|
|
1051
|
-
url: fetch.call(:url),
|
|
1052
|
-
elicitation_id: fetch.call(:elicitation_id),
|
|
1053
|
-
requested_schema: fetch.call(:requested_schema),
|
|
1054
|
-
**base_args
|
|
1055
|
-
)
|
|
1056
|
-
when 'ElicitationResult'
|
|
1057
|
-
ElicitationResultHookInput.new(
|
|
1058
|
-
mcp_server_name: fetch.call(:mcp_server_name),
|
|
1059
|
-
elicitation_id: fetch.call(:elicitation_id),
|
|
1060
|
-
mode: fetch.call(:mode),
|
|
1061
|
-
action: fetch.call(:action),
|
|
1062
|
-
content: fetch.call(:content),
|
|
1063
|
-
**base_args
|
|
1064
|
-
)
|
|
1065
|
-
when 'InstructionsLoaded'
|
|
1066
|
-
InstructionsLoadedHookInput.new(
|
|
1067
|
-
file_path: fetch.call(:file_path),
|
|
1068
|
-
memory_type: fetch.call(:memory_type),
|
|
1069
|
-
load_reason: fetch.call(:load_reason),
|
|
1070
|
-
globs: fetch.call(:globs),
|
|
1071
|
-
trigger_file_path: fetch.call(:trigger_file_path),
|
|
1072
|
-
**base_args
|
|
1073
|
-
)
|
|
1074
|
-
when 'CwdChanged'
|
|
1075
|
-
CwdChangedHookInput.new(
|
|
1076
|
-
old_cwd: fetch.call(:old_cwd),
|
|
1077
|
-
new_cwd: fetch.call(:new_cwd),
|
|
1078
|
-
**base_args
|
|
1079
|
-
)
|
|
1080
|
-
when 'FileChanged'
|
|
1081
|
-
FileChangedHookInput.new(
|
|
1082
|
-
file_path: fetch.call(:file_path),
|
|
1083
|
-
event: fetch.call(:event),
|
|
1084
|
-
**base_args
|
|
1085
|
-
)
|
|
1086
|
-
else
|
|
1087
|
-
# Unknown event: preserve the wire event name and full raw payload
|
|
1088
|
-
# rather than dropping event-specific fields (Python passes the raw
|
|
1089
|
-
# dict through, so nothing is lost there).
|
|
1090
|
-
UnknownHookInput.new(hook_event_name: event_name, raw_input: input_data, **base_args)
|
|
1091
|
-
end
|
|
917
|
+
hook_input = HOOK_INPUT_CLASSES.fetch(event_name, UnknownHookInput).from_hash(input_data)
|
|
918
|
+
hook_input.raw_input = input_data
|
|
919
|
+
hook_input
|
|
1092
920
|
end
|
|
1093
921
|
|
|
1094
922
|
def handle_mcp_message(request_data)
|