Skip to content

fix(cli): filter isMeta and isCompactSummary messages in local and remote mode#359

Merged
tiann merged 2 commits intotiann:mainfrom
hqhq1025:fix/filter-meta-and-compact-messages
Mar 24, 2026
Merged

fix(cli): filter isMeta and isCompactSummary messages in local and remote mode#359
tiann merged 2 commits intotiann:mainfrom
hqhq1025:fix/filter-meta-and-compact-messages

Conversation

@hqhq1025
Copy link
Contributor

Summary

When Claude Code loads a skill, it injects the full skill content as a user message with isMeta: true. This message bypasses existing filters in both local and remote mode, causing the full skill text to render as a regular chat message in the web UI.

Root cause

Verified by inspecting real JSONL session data — skill injection messages have this structure:

{ "type": "user", "isMeta": true, "message": { "content": [{ "type": "text", "text": "# Full skill content..." }] } }
  • Local mode (claudeLocalLauncher): only filtered summary and invisible system messages — isMeta user messages passed through
  • Remote mode (OutgoingMessageQueue): only filtered type === 'system' — skill injections have type: 'user' and slipped through

Also adds isCompactSummary filtering at the source for consistency with the web normalizer (normalizeAgent.ts:201-202), which already checks both fields.

Changes

File Change
claudeLocalLauncher.ts Add isMeta and isCompactSummary checks before sending
OutgoingMessageQueue.ts Add isMeta and isCompactSummary checks in send filter
claudeLocalLauncher.test.ts +2 tests (isMeta, isCompactSummary)
OutgoingMessageQueue.test.ts New file, 4 tests covering all filter conditions

Relates to #235

Test plan

  • 10 unit tests: local launcher (6) + outgoing queue (4), all passing
  • bun run typecheck passes
  • Load a skill in local mode, confirm skill content no longer appears as chat text
  • Load a skill in remote mode, confirm same
  • Confirm normal messages, tool calls, and visible system events (api_error) still display correctly

…mote mode

When Claude Code loads a skill, it injects the full skill content as a
user message with isMeta: true. In local mode, this message passes
through all existing filters (it's not a summary, not a system message)
and reaches the web UI where it renders as a regular chat message.

In remote mode, the OutgoingMessageQueue only filtered system-type
messages. Skill injections have type 'user' with isMeta: true and
slipped through.

Also filter isCompactSummary messages at the source for consistency
with the web normalizer, which already checks both fields.

Changes:
- claudeLocalLauncher: add isMeta and isCompactSummary checks
- OutgoingMessageQueue: add isMeta and isCompactSummary checks
- Add tests for both local launcher (6 tests) and queue (4 tests)

Relates to tiann#235
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Findings

  • None.

Summary
Review mode: initial. No issues found in modified lines. Residual risk: runtime behavior depends on message flags; manual local/remote UI verification not run.

Testing

  • Not run (automation)

HAPI Bot

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Findings

  • None.

Summary
Review mode: follow-up after new commits. No issues found in modified lines. Residual risk: runtime behavior depends on message flags; manual local/remote UI verification not run.

Testing

  • Not run (automation)

HAPI Bot

@tiann tiann merged commit 6384697 into tiann:main Mar 24, 2026
2 checks passed
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.

2 participants