1+ #!/usr/bin/env ruby
2+ require 'bundler/setup'
3+ require 'claude_code_sdk'
4+ require 'json'
5+
6+ # Example: AllSpark Builder Integration with Dynamic Hooks
7+ puts "AllSpark Builder - Claude Code SDK Integration Example"
8+ puts "=" * 55
9+
10+ # Example hooks configuration that AllSpark Builder would generate
11+ session_id = "build-session-#{ Time . now . to_i } "
12+ project_id = "project-123"
13+ webhook_url = "http://allspark_builder-web:3000/api/v2/code_agent_hooks/webhook"
14+
15+ # This is what CodeAgentHooksService.generate_settings_for_sdk would return
16+ allspark_hooks_json = {
17+ "hooks" => {
18+ "PostToolUse" => [
19+ {
20+ "matcher" => "Bash|LS|Glob|Grep" ,
21+ "hooks" => [ {
22+ "type" => "command" ,
23+ "command" => <<~BASH . strip
24+ if [ -n "$HOOK_INPUT" ]; then
25+ echo "$HOOK_INPUT" | ruby -rjson -rtime -e '
26+ input = JSON.parse(STDIN.read)
27+ enhanced = {
28+ "original_hook_data" => input,
29+ "metadata" => {
30+ "hook_type" => "PostToolUse",
31+ "tool_type" => "Command",
32+ "session_id" => "#{ session_id } ",
33+ "project_id" => "#{ project_id } ",
34+ "timestamp" => Time.now.iso8601
35+ }
36+ }
37+ puts enhanced.to_json
38+ ' | curl -s -X POST "#{ webhook_url } " \
39+ -H "Content-Type: application/json" \
40+ -H "X-Hook-Auth: mock-jwt-token" \
41+ -d @- \
42+ --max-time 5 \
43+ > /dev/null 2>&1 || true
44+ fi
45+ BASH
46+ } ]
47+ } ,
48+ {
49+ "matcher" => "Write|Edit|MultiEdit|Read" ,
50+ "hooks" => [ {
51+ "type" => "command" ,
52+ "command" => <<~BASH . strip
53+ if [ -n "$HOOK_INPUT" ]; then
54+ echo "$HOOK_INPUT" | ruby -rjson -rtime -e '
55+ input = JSON.parse(STDIN.read)
56+ enhanced = {
57+ "original_hook_data" => input,
58+ "metadata" => {
59+ "hook_type" => "PostToolUse",
60+ "tool_type" => "FileChange",
61+ "session_id" => "#{ session_id } ",
62+ "project_id" => "#{ project_id } ",
63+ "timestamp" => Time.now.iso8601
64+ }
65+ }
66+ puts enhanced.to_json
67+ ' | curl -s -X POST "#{ webhook_url } " \
68+ -H "Content-Type: application/json" \
69+ -H "X-Hook-Auth: mock-jwt-token" \
70+ -d @- \
71+ --max-time 5 \
72+ > /dev/null 2>&1 || true
73+ fi
74+ BASH
75+ } ]
76+ }
77+ ] ,
78+ "PreToolUse" => [
79+ {
80+ "matcher" => "Bash|LS|Glob|Grep" ,
81+ "hooks" => [ {
82+ "type" => "command" ,
83+ "command" => <<~BASH . strip
84+ if [ -n "$HOOK_INPUT" ]; then
85+ echo "$HOOK_INPUT" | ruby -rjson -rtime -e '
86+ input = JSON.parse(STDIN.read)
87+ enhanced = {
88+ "original_hook_data" => input,
89+ "metadata" => {
90+ "hook_type" => "PreToolUse",
91+ "tool_type" => "WorkingDirectory",
92+ "session_id" => "#{ session_id } ",
93+ "project_id" => "#{ project_id } ",
94+ "timestamp" => Time.now.iso8601
95+ }
96+ }
97+ puts enhanced.to_json
98+ ' | curl -s -X POST "#{ webhook_url } " \
99+ -H "Content-Type: application/json" \
100+ -H "X-Hook-Auth: mock-jwt-token" \
101+ -d @- \
102+ --max-time 5 \
103+ > /dev/null 2>&1 || true
104+ fi
105+ BASH
106+ } ]
107+ }
108+ ]
109+ }
110+ } . to_json
111+
112+ puts "\n 1. AllSpark Hooks Configuration:"
113+ puts " Session ID: #{ session_id } "
114+ puts " Project ID: #{ project_id } "
115+ puts " Webhook URL: #{ webhook_url } "
116+ puts " JSON Length: #{ allspark_hooks_json . length } characters"
117+
118+ puts "\n 2. Creating Claude Code SDK Options with AllSpark hooks:"
119+
120+ # This is how AllSpark Builder would use the SDK
121+ options = ClaudeCodeSDK ::Options . new (
122+ system_prompt : "You are a helpful coding assistant for AllSpark Builder project #{ project_id } " ,
123+ allowed_tools : [ "Bash" , "Read" , "Write" , "Edit" , "LS" , "Glob" , "Grep" ] ,
124+ permission_mode : ClaudeCodeSDK ::PermissionMode ::ACCEPT_EDITS ,
125+ settings : allspark_hooks_json # JSON string from CodeAgentHooksService
126+ )
127+
128+ puts " ✅ Options created successfully"
129+ puts " ✅ Settings type: #{ options . settings . class } "
130+ puts " ✅ Settings length: #{ options . settings . length } characters"
131+
132+ puts "\n 3. Generating CLI Arguments:"
133+
134+ cli_args = options . to_cli_args
135+ settings_index = cli_args . index ( "--settings" )
136+
137+ puts " ✅ CLI args generated: #{ cli_args . length } total arguments"
138+ puts " ✅ --settings flag found: #{ settings_index ? "Yes (index #{ settings_index } )" : "No" } "
139+
140+ if settings_index
141+ settings_value = cli_args [ settings_index + 1 ]
142+ puts " ✅ Settings value type: #{ settings_value . class } "
143+ puts " ✅ Settings JSON valid: #{ JSON . parse ( settings_value ) ? "Yes" : "No" rescue "No" } "
144+ puts " ✅ Settings preview: #{ settings_value [ 0 ..100 ] } ..."
145+ end
146+
147+ puts "\n 4. Testing JSON Detection Logic:"
148+
149+ # Test the SDK's JSON detection
150+ test_cases = [
151+ [ 'Hash object' , { "hooks" => { } } ] ,
152+ [ 'JSON string' , '{"hooks": {"PostToolUse": []}}' ] ,
153+ [ 'File path' , '/path/to/settings.json' ] ,
154+ [ 'Pathname object' , Pathname . new ( '/tmp/settings.json' ) ]
155+ ]
156+
157+ test_cases . each do |name , value |
158+ begin
159+ test_options = ClaudeCodeSDK ::Options . new ( settings : value )
160+ test_args = test_options . to_cli_args
161+ settings_idx = test_args . index ( "--settings" )
162+ result = settings_idx ? test_args [ settings_idx + 1 ] : "NOT FOUND"
163+ puts " ✅ #{ name } : #{ result . class } - #{ result [ 0 ..50 ] } ..."
164+ rescue => e
165+ puts " ❌ #{ name } : ERROR - #{ e . message } "
166+ end
167+ end
168+
169+ puts "\n 5. Simulating ClaudeCodeRubyExecutorJob Integration:"
170+
171+ # This simulates what happens in the actual job
172+ puts " Building SDK options in job context..."
173+
174+ job_options_hash = {
175+ system_prompt : "AllSpark Builder Assistant" ,
176+ allowed_tools : [ "Bash" , "Read" , "Write" , "Edit" ] ,
177+ settings : allspark_hooks_json # This comes from build_hook_settings(session)
178+ }
179+
180+ job_options = ClaudeCodeSDK ::Options . new ( **job_options_hash )
181+ job_cli_args = job_options . to_cli_args
182+
183+ puts " ✅ Job options created successfully"
184+ puts " ✅ Job CLI args: #{ job_cli_args . length } arguments"
185+ puts " ✅ Hooks included: #{ job_cli_args . include? ( '--settings' ) ? 'Yes' : 'No' } "
186+
187+ puts "\n " + "=" * 55
188+ puts "✅ AllSpark Builder integration test completed successfully!"
189+ puts "✅ The Claude Code SDK now supports dynamic hooks via JSON strings"
190+ puts "✅ AllSpark Builder can inject session-specific hooks into Claude Code"
191+
192+ # Show final CLI command that would be executed
193+ puts "\n Final CLI command (abbreviated):"
194+ puts "claude-code #{ job_cli_args [ 0 ..5 ] . join ( ' ' ) } --settings '{...}' [prompt]"
0 commit comments