Skip to content

fix(agent-core-v2): surface SessionStart hook stdout in context and transcript - #4138

Open
haiyu614 wants to merge 1 commit into
MoonshotAI:mainfrom
haiyu614:fix/session-start-hook-output
Open

haiyu614 wants to merge 1 commit into
MoonshotAI:mainfrom
haiyu614:fix/session-start-hook-output

Conversation

@haiyu614

@haiyu614 haiyu614 commented Oct 6, 2026

Copy link
Copy Markdown

Related Issue

Fixes #2873

Problem

SessionStart hook commands execute, but the session-scope external hooks service discards the returned HookResult[] — triggerSessionStart() never publishes a hook.result event and never appends the hook stdout to the conversation context. Users see nothing despite the documented hook contract ("stdout content (if any) may be appended to context"), and the model never receives SessionStart output either.

Verified on 2.1.1 (Windows): a SessionStart hook with echo hello-from-sessionstart-hook writes its side effects but the main agent's wire.jsonl contains no hook.result event and no context entry for the stdout.

Fix

After the session-scope trigger completes, SessionExternalHooksService now surfaces successful hook results through the main agent:

  • extracts non-empty messages from results with action !== 'block' (reusing the same extraction rules as UserPromptSubmit: skip timed out / errored / non-zero exits, prefer message, fall back to stdout),
  • appends each message to the main agent's context as an assistant message with origin: { kind: 'hook_result', event: 'SessionStart' } and the same <hook_result hook_event="..."> wrapper used by other hook results, so the model sees the output and session replay renders it as a transcript entry,
  • dispatches a hook.result agent event per message, so attached clients (TUI / print / SDK) render it exactly like UserPromptSubmit hook results.

If the main agent does not exist yet (session created without a main agent binding), the results are dropped as before — no behavior change in that edge case. SessionEnd / heartbeat / subagent triggers remain fire-and-forget.

hookResultMessage() (previously the private userPromptHookMessage) is exported from internal/userPrompt.ts so both scopes share the same extraction rules.

Tests

  • New integration test: surfaces SessionStart hook stdout on the main agent as a hook result and context entry — fires the SessionStart lifecycle event with a real runner, asserts the context append (role/origin/wrapped text) and the dispatched hook.result event, and asserts SessionEnd output is still not surfaced.
  • Existing session-hook tests updated with an IAgentLifecycleService stub (the service now injects it).
  • pnpm --filter @moonshot-ai/agent-core-v2 test: no new failures vs. clean baseline on Windows (the pre-existing failures are identical before/after; new test passes).
  • Manual end-to-end check: kimi -p with a SessionStart hook now records the <hook_result hook_event="SessionStart"> context message in the main agent's wire.jsonl.

@changeset-bot

changeset-bot Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b0a0f89

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@haiyu614
haiyu614 force-pushed the fix/session-start-hook-output branch from 57916c6 to b0a0f89 Compare October 6, 2026 16:59
@haiyu614
haiyu614 marked this pull request as ready for review October 6, 2026 17:11

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.

SessionStart hook stdout is silently discarded — hook output is never displayed in the TUI

1 participant