Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import {
MentionChip,
parseFileMentions,
} from "@posthog/ui/features/sessions/components/session-update/parseFileMentions";
import { collapsePiSkillInvocation } from "@posthog/ui/features/sessions/components/session-update/piSkillInvocation";
import { SessionUpdateView } from "@posthog/ui/features/sessions/components/session-update/SessionUpdateView";
import { UserShellExecuteView } from "@posthog/ui/features/sessions/components/session-update/UserShellExecuteView";
import { UserMessageAttachments } from "@posthog/ui/features/sessions/components/UserMessageAttachments";
Expand Down Expand Up @@ -361,9 +362,9 @@ function UserBubble({
() => extractCustomInstructions(afterCanvasInstructions),
[afterCanvasInstructions],
);
const displayContent = customInstructions
? customInstructions.stripped
: afterCanvasInstructions;
const displayContent = collapsePiSkillInvocation(
customInstructions ? customInstructions.stripped : afterCanvasInstructions,
);
const showChannelContextTag = !!channelContext && bluebirdEnabled;
const showCanvasInstructionsTag = !!canvasInstructions && bluebirdEnabled;
const showHeaderChips = showChannelContextTag || showCanvasInstructionsTag;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ const PROMPT_WITH_CONTEXT =
const PROMPT_WITH_CANVAS_INSTRUCTIONS =
"add a retention chart\n\n<canvas_generation_instructions>\nauthoring contract\n</canvas_generation_instructions>";

const PROMPT_WITH_PI_SKILL =
'<skill name="code-review" location="/skills/code-review/SKILL.md">\nReferences are relative to /skills/code-review.\n\n# Review\n\nInspect the diff.\n</skill>\n\nReview this pull request.';

describe("UserMessage", () => {
// useFeatureFlag falls back to import.meta.env.DEV, which is true under
// vitest. Pin DEV off in the flag-gating cases so they exercise the flag
Expand Down Expand Up @@ -79,6 +82,14 @@ describe("UserMessage", () => {
expect(screen.queryByText(/channel_context/)).not.toBeInTheDocument();
});

it("renders Pi skill invocations as a command chip", () => {
renderWithFlags(<UserMessage content={PROMPT_WITH_PI_SKILL} />, true);

expect(screen.getByText("/code-review")).toBeInTheDocument();
expect(screen.getByText("Review this pull request.")).toBeInTheDocument();
expect(screen.queryByText("Inspect the diff.")).not.toBeInTheDocument();
});

it("shows the canvas-instructions tag when project-bluebird is enabled", () => {
vi.stubEnv("DEV", false);
renderWithFlags(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
MentionChip,
parseFileMentions,
} from "./parseFileMentions";
import { collapsePiSkillInvocation } from "./piSkillInvocation";

interface UserMessageProps {
content: string;
Expand Down Expand Up @@ -92,9 +93,9 @@ export const UserMessage = memo(function UserMessage({
() => extractCustomInstructions(afterCanvasInstructions),
[afterCanvasInstructions],
);
const displayContent = customInstructions
? customInstructions.stripped
: afterCanvasInstructions;
const displayContent = collapsePiSkillInvocation(
customInstructions ? customInstructions.stripped : afterCanvasInstructions,
);
const showChannelContextTag = !!channelContext && bluebirdEnabled;
const showCanvasInstructionsTag = !!canvasInstructions && bluebirdEnabled;
const openChannelContextInSplit = usePanelLayoutStore(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { describe, expect, it } from "vitest";
import { collapsePiSkillInvocation } from "./piSkillInvocation";

describe("collapsePiSkillInvocation", () => {
it("replaces Pi skill instructions with the command and user request", () => {
expect(
collapsePiSkillInvocation(
'<skill name="code-review" location="/skills/code-review/SKILL.md">\nReferences are relative to /skills/code-review.\n\n# Review\n\nInspect the diff.\n</skill>\n\nReview this pull request.',
),
).toBe("/code-review\n\nReview this pull request.");
});

it("keeps non-skill messages unchanged", () => {
expect(collapsePiSkillInvocation("Review this pull request.")).toBe(
"Review this pull request.",
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { unescapeXmlAttr } from "@posthog/shared";

const PI_SKILL_INVOCATION =
/^<skill name="([^"]+)" location="[^"]+">\n[\s\S]*?\n<\/skill>(?:\n\n([\s\S]+))?$/;

export function collapsePiSkillInvocation(content: string): string {
const match = content.match(PI_SKILL_INVOCATION);
if (!match) {
return content;
}

const name = unescapeXmlAttr(match[1]);
const userMessage = match[2]?.trim();
return userMessage ? `/${name}\n\n${userMessage}` : `/${name}`;
}
Loading