Stop hook surfaces raw <teammate-message> XML as the notification title when an Agent Teams message is the last user-type transcript entry
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 68/100
Hướng nghiên cứu
Start with plugins/warp/scripts/on-stop.sh, especially the jq filter at lines 39-51 and truncation at lines 60-62. Reproduce the Stop hook with an Agent Teams or cross-session message, then trace how the last user-type entry becomes QUERY. Done means recognized internal envelopes are handled as described, summaries can supply a title when needed, and unrecognized input still passes through unchanged.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
plugins/warp/scripts/on-stop.sh derives the notification title ("the user's last prompt") by scraping the session transcript for the last type: "user" entry containing a text block. Claude Code's Agent Teams feature records incoming teammate messages as type: "user" entries whose content is the raw internal delivery envelope — so when a teammate message is the most recent user-type entry at Stop time, Warp's in-app notification displays serialization internals instead of anything human-readable:
Another Claude session sent a message:
<teammate-message teammate_id="oss-record-researcher" color="…Task completed.
(The mid-attribute cutoff is the script's 197-char slice; Warp's own title clamp compounds it.)
Environment
- Warp Stable
0.2026.07.01.09.21.01, macOS (Darwin 27) - Claude Code
2.1.205 - Plugin
warp@claude-code-warp2.1.0(installed via Warp's in-app prompt)
Reproduction
- In Warp, run a Claude Code session with the plugin installed.
- Have another Claude Code session send it a message (Agent Teams
SendMessage, or any cross-session message — e.g. a background teammate reporting completion). - Let the receiving session finish its turn so the
Stophook fires while the teammate message is the most recent user-type transcript entry. - The completion toast shows the raw
<teammate-message …>envelope as its title.
Root cause
plugins/warp/scripts/on-stop.sh:39-51 — the jq filter selects the last type == "user" entry that has string content or at least one text block, on the assumption (per the comment at lines 33-38) that this distinguishes human prompts from tool-result messages. That assumption no longer holds: Claude Code injects teammate/cross-session messages into the transcript as user-type entries with plain-text content, beginning with a framing line followed by a <teammate-message teammate_id="…" color="…" summary="…">…</teammate-message> envelope. The filter has no provenance awareness (no handling of teammate, system-reminder, or meta-flagged entries anywhere in the repo), so the envelope is captured verbatim as QUERY, blindly truncated at 197 chars + ... (lines 60-62), and shipped to Warp, which renders query as the toast title.
Suggested fix (defense in depth — improve recognized patterns, pass everything else through)
The hook can't control what Claude Code writes into the transcript, so the goal is: accept garbage in, and only improve the output when the content is confidently recognized. Never reject or blank out unrecognized input — an odd-looking title is better than a missing notification.
- Skip confidently-recognized internal injections when selecting the "last user prompt", falling back to the previous qualifying entry. Anchor detection on the XML envelope tags (
<teammate-messageat the start of the text; content consisting solely of a<system-reminder>…</system-reminder>block) — these are stable ASCII identifiers that won't change under localization. The human-language framing line ("Another Claude session sent a message") may be translated in localized Claude Code builds, so treat it only as a secondary, best-effort signal, never the sole trigger. Matching must be Unicode-safe (message bodies can contain arbitrary Unicode; only the tag anchors are assumed ASCII). If Claude Code's transcript format exposes a meta/provenance flag (e.g.isMeta) on injected entries, prefer that over string matching entirely. - When the last entry is a recognized teammate-message envelope and no earlier human prompt exists, extract its
summary="…"attribute as the title instead — it's the sender's own human-readable one-liner, exactly what a notification wants. - Anything not confidently recognized passes through unchanged. No generic XML stripping, no rejection of "weird" input — only rewrite patterns that are positively identified as Claude Code internals.
This is Claude-transcript-specific knowledge, so the fix belongs in this plugin's scripts only — no shared/abstracted change that would affect the codex/gemini/antigravity integrations (though those repos may want an equivalent audit if their CLIs grow multi-session messaging).
Related
- The same last-user-entry scraping pattern appears in other scripts in this repo;
on-stop.shis the one that reproduces this symptom, but the class of bug is latent wherever user-type entries are assumed human-authored. - Defense-in-depth on the Warp side would also help: Warp core uses the plugin-supplied
queryas a notification title verbatim; preferring the payload'ssummaryfield or applying word-aware truncation there would soften any future plugin-side regression. Happy to file that separately againstwarpdotdev/warpif useful.
- Ngôn ngữ chính
- Shell
- Star
- 234
- Fork
- 59
- Merge trung bình
- 2 ngày 8 giờ
- Pull request đã merge (30 ngày)
- 2
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của warpdotdev/claude-code-warp
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 85/100
warpdotdev/claude-code-warp#96 · 2 bình luận ·
-
on-stop.sh slurps the entire transcript with jq -s every turn — ~1 GB RSS on long sessions, triggered a host OOMCó thể đã có người làm @GeiserX đã nhận 19 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
warpdotdev/claude-code-warp#90 · 1 bình luận ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
Tất cả issue của warpdotdev/claude-code-warp
Issue tương tự
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 70/100
-
Renovate config partially updates OVMS URLCó thể đã có người làm @farshidtz đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
-
Regression: IME preedit still shown in plaintext on lock/polkit — #13002 fix is not in 4.0.6Có thể đã có người làm @AnPod đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
fullsend-ai/agents#1833 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
gnosis/gnosis_vpn#661 ·
Maintainer thường phản hồi trong vòng 1 ngày