fix(collab): treated guest prompts as user interjections

Converted user-attributed collab prompt frames to prioritized user messages only on the model-facing path, preserving guest details in persisted transcript frames.

Added regression coverage for the provider role, steering envelope, and retained guest attribution.

Fixes #7288
This commit is contained in:
roboomp
2026-08-01 17:04:00 +00:00
parent 09a7c86563
commit 352c0fdce2
3 changed files with 57 additions and 7 deletions
@@ -7,6 +7,7 @@ import {
SKILL_PROMPT_MESSAGE_TYPE,
wrapSteeringForModel,
} from "@oh-my-pi/pi-coding-agent/session/messages";
import { COLLAB_PROMPT_MESSAGE_TYPE } from "@oh-my-pi/pi-wire";
function expectAttribution(message: Message | undefined, expected: "user" | "agent" | undefined): void {
expect(message).toBeDefined();
@@ -382,6 +383,31 @@ describe("wrapSteeringForModel", () => {
expect(wrappedText).not.toContain("&");
});
it("presents user-attributed collab prompts as wrapped user turns", () => {
const message: AgentMessage = {
role: "custom",
customType: COLLAB_PROMPT_MESSAGE_TYPE,
content: "Reply with exactly PONG",
display: true,
details: { from: "guest" },
attribution: "user",
timestamp: 1,
};
const wrapped = wrapSteeringForModel([message]);
const providerMessages = convertToLlm(wrapped);
expect(wrapped[0]?.role).toBe("user");
expect(getUserText(wrapped[0])).toContain("<system-notice>");
expect(getUserText(wrapped[0])).toContain("Reply with exactly PONG");
expect(providerMessages).toHaveLength(1);
expect(providerMessages[0]?.role).toBe("user");
expect(message).toMatchObject({
role: "custom",
details: { from: "guest" },
});
});
it("wraps buried steering messages too so wire bytes stay stable across turns", () => {
const buried: AgentMessage = {
role: "user",