Skip to content

fix(hook): inject stderr context from pass hooks into tool output - #85

Merged
terisuke merged 3 commits into
devfrom
fix/hook-stderr-context-injection
Apr 5, 2026
Merged

terisuke merged 3 commits into
devfrom
fix/hook-stderr-context-injection

Conversation

@terisuke

@terisuke terisuke commented Apr 5, 2026

Copy link
Copy Markdown

Summary

  • prompt.ts の4つのhook呼び出し箇所で、pass時の hookResult.message を <hook-context> タグとしてtool outputに注入
  • Built-in tools: PreToolUse → prefix、PostToolUse → suffix
  • MCP tools: 同様のパターンでcontent配列に注入
  • .catch() の戻り値型を HookResult に修正
  • 8テスト追加、全43 hookテストパス

What

Issue #47 の受入基準「exit 0: stderrがあればコンテキスト注入」を実装。runHooks() は正しく pass message を返していたが、prompt.ts が action === "block" のみチェックして破棄していた。

Type

  • Bug fix

Verify

  • bun test test/hook/ — 43テスト全パス (既存22 + schema13 + 新規8)
  • bun typecheck — 全パッケージパス
  • hook が stderr 出力 + exit 0 → <hook-context> がtool outputに含まれることを確認

Checklist

  • Built-in tools PreToolUse/PostToolUse 注入
  • MCP tools PreToolUse/PostToolUse 注入
  • .catch() 型修正
  • テスト追加 (8件)
  • execute.ts 変更なし

Issue

Closes #80

🤖 Generated with Claude Code

terisuke and others added 2 commits April 5, 2026 21:30
When hooks exit 0 with stderr messages, the context was being discarded
at all 4 hook call sites in prompt.ts. This adds <hook-context> wrapping
to inject PreToolUse messages as prefix and PostToolUse messages as suffix
into tool output for both built-in and MCP tools, fulfilling Issue #47
acceptance criteria for "exit 0: stderr context injection".

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The .catch() handlers on PostToolUse runHooks calls returned
{ action: "pass" } without message property, causing TS2339 when
accessing .message on the union type. Using HookResult as the return
type resolves this since it includes message?: string.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copilot AI review requested due to automatic review settings April 5, 2026 12:33
@github-actions

github-actions Bot commented Apr 5, 2026

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

github-actions Bot commented Apr 5, 2026

Copy link
Copy Markdown

The following comment was made by an LLM, it may be inaccurate:

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes hook “pass-with-stderr” behavior so that hook stderr (exit 0) is surfaced to the LLM by injecting it into tool output as <hook-context> for both built-in tools and MCP tools, aligning with the acceptance criteria from the hook issues.

Changes:

  • Inject PreToolUse hook message as a prefix and PostToolUse hook message as a suffix in built-in tool outputs.
  • Apply the same injection pattern to MCP tool outputs.
  • Add hook context-injection tests and tighten .catch() fallback typing to HookResult.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
packages/opencode/src/session/prompt.ts Injects <hook-context> into tool outputs for built-in + MCP tools; adjusts post-hook .catch() typing.
packages/opencode/test/hook/context-injection.test.ts Adds tests covering pass/block behavior and the expected <hook-context> prefix/suffix formatting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/opencode/src/session/prompt.ts Outdated
Comment on lines +506 to +509
// Inject PreToolUse hook context into output
if (hookResult.message) {
output.output = `<hook-context>\n${hookResult.message}\n</hook-context>\n\n${output.output}`
}

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hook context injection is applied after the tool output has already been truncated (built-in tools are truncated in Tool.wrap). This can re-expand the final output beyond the truncation limits / provider size constraints if a hook writes a lot to stderr. Consider truncating again after injecting (or cap/summarize hookResult.message before injection) so tool outputs remain bounded.

Copilot uses AI. Check for mistakes.
Comment on lines +634 to +641
// Inject hook context from PreToolUse and PostToolUse
let mcpOutput = truncated.content
if (mcpHookResult.message) {
mcpOutput = `<hook-context>\n${mcpHookResult.message}\n</hook-context>\n\n${mcpOutput}`
}
if (mcpPostResult.message) {
mcpOutput = `${mcpOutput}\n\n<hook-context>\n${mcpPostResult.message}\n</hook-context>`
}

Copilot AI Apr 5, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For MCP tools, hook context is injected after truncate.output(...) has produced truncated.content, so the final mcpOutput can exceed the truncation limits if hook stderr is large. Consider truncating the combined string (hook context + truncated content) or bounding hook messages before concatenation to keep tool results within expected size limits.

Copilot uses AI. Check for mistakes.
Replace direct mutation of const output.output with let finalOutput
reassignment and spread return, matching the MCP path's immutable pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@terisuke
terisuke merged commit fa50949 into dev Apr 5, 2026
3 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(hook): exit 0 stderr context injection not surfaced to LLM

2 participants