Skip to content

fix(hooks): extract text from ContentPart for UserPromptSubmit hook - #2176

Open
tears-mysthrala wants to merge 6 commits into
MoonshotAI:mainfrom
tears-mysthrala:fix-2148-userpromptsubmit-hook-empty-prompt
Open

fix(hooks): extract text from ContentPart for UserPromptSubmit hook#2176
tears-mysthrala wants to merge 6 commits into
MoonshotAI:mainfrom
tears-mysthrala:fix-2148-userpromptsubmit-hook-empty-prompt

Conversation

@tears-mysthrala

@tears-mysthrala tears-mysthrala commented May 7, 2026

Copy link
Copy Markdown

Related Issue

Resolve #2148

Description

The UserPromptSubmit hook received an empty prompt and matcher_value whenever user_input was a list[ContentPart] (the default for all messages). The code only handled the str case and fell back to "" for everything else, making regex matching in hooks ineffective and blocking hooks unreliable.

This fix uses Message.extract_text() — the same pattern already used later in run() for text_input — so the hook receives the concatenated text content regardless of input format.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked the related issue, if any.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have run make gen-changelog to update the changelog.

Open in Devin Review

The UserPromptSubmit hook received an empty prompt when user_input
was a list[ContentPart] (the default for all messages). The code
checked  and fell back to , so
the hook's matcher_value and prompt were always empty for non-string
inputs.

Use Message.extract_text() instead, which handles both str and
list[ContentPart] uniformly — matching the pattern already used
later in the same function for text_input.

Fixes MoonshotAI#2148
Copilot AI review requested due to automatic review settings May 7, 2026 11:36

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes the UserPromptSubmit hook payload so it receives the actual user prompt text when user_input is the default list[ContentPart] form, restoring regex matching behavior for hooks (issue #2148).

Changes:

  • Use Message.extract_text() to build matcher_value/prompt for UserPromptSubmit hooks from both str and list[ContentPart] inputs.
  • Add async tests covering both string and ContentPart-list user inputs for the hook payload.
  • Add changelog entries describing the fix.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/kimi_cli/soul/kimisoul.py Fix hook prompt extraction by using Message.extract_text() instead of falling back to "" for non-strings.
tests/core/test_user_prompt_submit_hook.py Adds regression tests ensuring the hook receives extracted text for both input shapes.
CHANGELOG.md Notes the core hook fix in the Unreleased section.
docs/en/release-notes/changelog.md Mirrors the Unreleased changelog entry in the English docs.
docs/zh/release-notes/changelog.md Adds the corresponding Unreleased changelog entry in Chinese.

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

Comment thread src/kimi_cli/soul/kimisoul.py Outdated
Comment on lines +601 to +602
user_message = Message(role="user", content=user_input)
text_input_for_hook = user_message.extract_text(" ").strip()
Signed-off-by: Tears Mysthrala <unaiup@gmail.com>
Signed-off-by: Tears Mysthrala <unaiup@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b1902ff09a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

soul = _make_runnable_soul()

with patch("kimi_cli.soul.kimisoul.wire_send"):
await soul.run("hello world")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Initialize _plan_mode before calling KimiSoul.run

The new tests build KimiSoul via object.__new__ but never initialize _plan_mode, and run() unconditionally reads that field when emitting telemetry ("plan" if self._plan_mode else "agent"). As written, this call path raises AttributeError before the hook assertions execute, so both tests fail when run. Set _plan_mode (and any other run()-required fields) in _make_runnable_soul to keep the tests runnable.

Useful? React with 👍 / 👎.

…submit-hook-empty-prompt

# Conflicts:
#	CHANGELOG.md
#	docs/en/release-notes/changelog.md
#	docs/zh/release-notes/changelog.md
… factory

KimiSoul.run() reads self._plan_mode unconditionally for telemetry, so
the object.__new__-based test double raised AttributeError before the
hook assertions. Addresses Codex review on PR MoonshotAI#2176.
The UserPromptSubmit hook block and the normal processing path both
built Message(role="user", content=user_input) and called
extract_text(); compute them once before the hook and reuse, keeping
semantics identical. Addresses Copilot review on PR MoonshotAI#2176.
@tears-mysthrala

Copy link
Copy Markdown
Author

Status update: merged the latest upstream main (1.49.0) and addressed the automated review feedback (initialized _plan_mode in the new tests; deduplicated the user_message/extract_text() computation in run()). The PR is mergeable again and the hook tests pass (tests/core/test_user_prompt_submit_hook.py). The linked issue #2148 is still reproducible on current main, so this fix remains relevant. Happy to adjust anything if you'd like a different approach.

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.

UserPromptSubmit hook receives empty prompt when user_input is list[ContentPart]

3 participants