3119bfced5
* fix(coding-agent): add explicit initiator attribution Use message-level attribution for Copilot X-Initiator with role-based fallback, and persist attribution across custom/hook session paths. Fixes #237 * fix(coding-agent): preserve legacy custom attribution fallback * fix(coding-agent): remove async-result role special-case * fix(coding-agent): inherit before_agent_start attribution from prompt * test(coding-agent): tighten typing in attribution regressions
96 lines
2.7 KiB
TypeScript
96 lines
2.7 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
import type { Message } from "@oh-my-pi/pi-ai";
|
|
import { inferCopilotInitiator } from "@oh-my-pi/pi-ai/providers/github-copilot-headers";
|
|
import { convertToLlm } from "@oh-my-pi/pi-coding-agent/session/messages";
|
|
|
|
function expectAttribution(message: Message | undefined, expected: "user" | "agent" | undefined): void {
|
|
expect(message).toBeDefined();
|
|
if (!message) return;
|
|
if (message.role === "assistant") {
|
|
throw new Error("Assistant messages do not expose attribution");
|
|
}
|
|
expect(message.attribution).toBe(expected);
|
|
}
|
|
|
|
describe("convertToLlm custom message mapping", () => {
|
|
it("uses async-result attribution without special role mapping", () => {
|
|
const messages: AgentMessage[] = [
|
|
{
|
|
role: "custom",
|
|
customType: "async-result",
|
|
content: "Background task completed",
|
|
display: true,
|
|
attribution: "agent",
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const converted = convertToLlm(messages);
|
|
|
|
expect(converted).toHaveLength(1);
|
|
expect(converted[0]?.role).toBe("user");
|
|
expectAttribution(converted[0], "agent");
|
|
expect(inferCopilotInitiator(converted)).toBe("agent");
|
|
});
|
|
|
|
it("preserves missing attribution for legacy custom messages", () => {
|
|
const messages: AgentMessage[] = [
|
|
{
|
|
role: "custom",
|
|
customType: "skill-prompt",
|
|
content: "Run this skill with my arguments",
|
|
display: true,
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const converted = convertToLlm(messages);
|
|
|
|
expect(converted).toHaveLength(1);
|
|
expect(converted[0]?.role).toBe("user");
|
|
expectAttribution(converted[0], undefined);
|
|
expect(inferCopilotInitiator(converted)).toBe("user");
|
|
});
|
|
|
|
it("uses explicit agent attribution for custom messages", () => {
|
|
const messages: AgentMessage[] = [
|
|
{
|
|
role: "custom",
|
|
customType: "ttsr-injection",
|
|
content: "<system-reminder>Read file</system-reminder>",
|
|
display: false,
|
|
attribution: "agent",
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const converted = convertToLlm(messages);
|
|
|
|
expect(converted).toHaveLength(1);
|
|
expect(converted[0]?.role).toBe("user");
|
|
expectAttribution(converted[0], "agent");
|
|
expect(inferCopilotInitiator(converted)).toBe("agent");
|
|
});
|
|
|
|
it("allows custom messages to opt into user attribution", () => {
|
|
const messages: AgentMessage[] = [
|
|
{
|
|
role: "custom",
|
|
customType: "skill-prompt",
|
|
content: "Run this skill with my arguments",
|
|
display: true,
|
|
attribution: "user",
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const converted = convertToLlm(messages);
|
|
|
|
expect(converted).toHaveLength(1);
|
|
expect(converted[0]?.role).toBe("user");
|
|
expectAttribution(converted[0], "user");
|
|
expect(inferCopilotInitiator(converted)).toBe("user");
|
|
});
|
|
});
|