Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 93757ec

Browse files
committed
fix(ui): collapse Pi skill invocations
1 parent 436326e commit 93757ec

5 files changed

Lines changed: 50 additions & 6 deletions

File tree

packages/ui/src/features/sessions/components/chat-thread/ChatThread.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ import { extractCanvasInstructions } from "@posthog/ui/features/sessions/compone
8787
import { extractChannelContext } from "@posthog/ui/features/sessions/components/session-update/channelContext";
8888
import { extractCustomInstructions } from "@posthog/ui/features/sessions/components/session-update/customInstructions";
8989
import {
90+
collapsePiSkillInvocation,
9091
hasFileMentions,
9192
MentionChip,
9293
parseFileMentions,
@@ -361,9 +362,9 @@ function UserBubble({
361362
() => extractCustomInstructions(afterCanvasInstructions),
362363
[afterCanvasInstructions],
363364
);
364-
const displayContent = customInstructions
365-
? customInstructions.stripped
366-
: afterCanvasInstructions;
365+
const displayContent = collapsePiSkillInvocation(
366+
customInstructions ? customInstructions.stripped : afterCanvasInstructions,
367+
);
367368
const showChannelContextTag = !!channelContext && bluebirdEnabled;
368369
const showCanvasInstructionsTag = !!canvasInstructions && bluebirdEnabled;
369370
const showHeaderChips = showChannelContextTag || showCanvasInstructionsTag;

packages/ui/src/features/sessions/components/session-update/UserMessage.test.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ const PROMPT_WITH_CONTEXT =
3030
const PROMPT_WITH_CANVAS_INSTRUCTIONS =
3131
"add a retention chart\n\n<canvas_generation_instructions>\nauthoring contract\n</canvas_generation_instructions>";
3232

33+
const PROMPT_WITH_PI_SKILL =
34+
'<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.';
35+
3336
describe("UserMessage", () => {
3437
// useFeatureFlag falls back to import.meta.env.DEV, which is true under
3538
// vitest. Pin DEV off in the flag-gating cases so they exercise the flag
@@ -79,6 +82,14 @@ describe("UserMessage", () => {
7982
expect(screen.queryByText(/channel_context/)).not.toBeInTheDocument();
8083
});
8184

85+
it("renders Pi skill invocations as a command chip", () => {
86+
renderWithFlags(<UserMessage content={PROMPT_WITH_PI_SKILL} />, true);
87+
88+
expect(screen.getByText("/code-review")).toBeInTheDocument();
89+
expect(screen.getByText("Review this pull request.")).toBeInTheDocument();
90+
expect(screen.queryByText("Inspect the diff.")).not.toBeInTheDocument();
91+
});
92+
8293
it("shows the canvas-instructions tag when project-bluebird is enabled", () => {
8394
vi.stubEnv("DEV", false);
8495
renderWithFlags(

packages/ui/src/features/sessions/components/session-update/UserMessage.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { extractCanvasInstructions } from "./canvasInstructions";
2020
import { extractChannelContext } from "./channelContext";
2121
import { extractCustomInstructions } from "./customInstructions";
2222
import {
23+
collapsePiSkillInvocation,
2324
hasFileMentions,
2425
MentionChip,
2526
parseFileMentions,
@@ -92,9 +93,9 @@ export const UserMessage = memo(function UserMessage({
9293
() => extractCustomInstructions(afterCanvasInstructions),
9394
[afterCanvasInstructions],
9495
);
95-
const displayContent = customInstructions
96-
? customInstructions.stripped
97-
: afterCanvasInstructions;
96+
const displayContent = collapsePiSkillInvocation(
97+
customInstructions ? customInstructions.stripped : afterCanvasInstructions,
98+
);
9899
const showChannelContextTag = !!channelContext && bluebirdEnabled;
99100
const showCanvasInstructionsTag = !!canvasInstructions && bluebirdEnabled;
100101
const openChannelContextInSplit = usePanelLayoutStore(
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, expect, it } from "vitest";
2+
import { collapsePiSkillInvocation } from "./parseFileMentions";
3+
4+
describe("collapsePiSkillInvocation", () => {
5+
it("replaces Pi skill instructions with the command and user request", () => {
6+
expect(
7+
collapsePiSkillInvocation(
8+
'<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.',
9+
),
10+
).toBe("/code-review\n\nReview this pull request.");
11+
});
12+
13+
it("keeps non-skill messages unchanged", () => {
14+
expect(collapsePiSkillInvocation("Review this pull request.")).toBe(
15+
"Review this pull request.",
16+
);
17+
});
18+
});

packages/ui/src/features/sessions/components/session-update/parseFileMentions.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ const MENTION_TAG_REGEX =
1616
const MENTION_TAG_TEST =
1717
/<(?:file\s+path|folder\s+path|github_issue\s+number|github_pr\s+number|error_context\s+label)="[^"]+"/;
1818
const SLASH_COMMAND_START = /^\/([a-zA-Z][\w-]*)(?=\s|$)/;
19+
const PI_SKILL_INVOCATION =
20+
/^<skill name="([^"]+)" location="[^"]+">\n[\s\S]*?\n<\/skill>(?:\n\n([\s\S]+))?$/;
21+
22+
export function collapsePiSkillInvocation(content: string): string {
23+
const match = content.match(PI_SKILL_INVOCATION);
24+
if (!match) {
25+
return content;
26+
}
27+
28+
const name = unescapeXmlAttr(match[1]);
29+
const userMessage = match[2]?.trim();
30+
return userMessage ? `/${name}\n\n${userMessage}` : `/${name}`;
31+
}
1932

2033
const inlineComponents: Components = {
2134
...baseComponents,

0 commit comments

Comments
 (0)