* Parse elicitation-specific fields from a HookOutsideReplResult. * Mirrors the relevant branches of processHookJSONOutput for Elicitation * and ElicitationResult hook events.
( result: HookOutsideReplResult, expectedEventName: 'Elicitation' | 'ElicitationResult', )
| 4386 | * and ElicitationResult hook events. |
| 4387 | */ |
| 4388 | function parseElicitationHookOutput( |
| 4389 | result: HookOutsideReplResult, |
| 4390 | expectedEventName: 'Elicitation' | 'ElicitationResult', |
| 4391 | ): { |
| 4392 | response?: ElicitationResponse |
| 4393 | blockingError?: HookBlockingError |
| 4394 | } { |
| 4395 | // Exit code 2 = blocking (same as executeHooks path) |
| 4396 | if (result.blocked && !result.succeeded) { |
| 4397 | return { |
| 4398 | blockingError: { |
| 4399 | blockingError: result.output || `Elicitation blocked by hook`, |
| 4400 | command: result.command, |
| 4401 | }, |
| 4402 | } |
| 4403 | } |
| 4404 | |
| 4405 | if (!result.output.trim()) { |
| 4406 | return {} |
| 4407 | } |
| 4408 | |
| 4409 | // Try to parse JSON output for structured elicitation response |
| 4410 | const trimmed = result.output.trim() |
| 4411 | if (!trimmed.startsWith('{')) { |
| 4412 | return {} |
| 4413 | } |
| 4414 | |
| 4415 | try { |
| 4416 | const parsed = hookJSONOutputSchema().parse(JSON.parse(trimmed)) |
| 4417 | if (isAsyncHookJSONOutput(parsed)) { |
| 4418 | return {} |
| 4419 | } |
| 4420 | if (!isSyncHookJSONOutput(parsed)) { |
| 4421 | return {} |
| 4422 | } |
| 4423 | |
| 4424 | // Check for top-level decision: 'block' (exit code 0 + JSON block) |
| 4425 | if (parsed.decision === 'block' || result.blocked) { |
| 4426 | return { |
| 4427 | blockingError: { |
| 4428 | blockingError: parsed.reason || 'Elicitation blocked by hook', |
| 4429 | command: result.command, |
| 4430 | }, |
| 4431 | } |
| 4432 | } |
| 4433 | |
| 4434 | const specific = parsed.hookSpecificOutput |
| 4435 | if (!specific || specific.hookEventName !== expectedEventName) { |
| 4436 | return {} |
| 4437 | } |
| 4438 | |
| 4439 | if (!specific.action) { |
| 4440 | return {} |
| 4441 | } |
| 4442 | |
| 4443 | const response: ElicitationResponse = { |
| 4444 | action: specific.action, |
| 4445 | content: specific.content as ElicitationResponse['content'] | undefined, |
no test coverage detected