From 3d75152a577cce609a90146e7bec7f305943a2dd Mon Sep 17 00:00:00 2001 From: Dotta Date: Fri, 24 Apr 2026 19:28:44 -0500 Subject: [PATCH] Storybook: cover external object decoration in chat threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an `External object decoration` scenario to the CommentThread matrix and threads `externalReferences` into the live IssueChatThread story so the new comment/document/chat plumbing renders the §2 status chip on resolved URLs while leaving unknown URLs and code-fenced URLs unchanged. Co-Authored-By: Paperclip --- .../stories/chat-comments.stories.tsx | 84 ++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/ui/storybook/stories/chat-comments.stories.tsx b/ui/storybook/stories/chat-comments.stories.tsx index 041293f9b17..7ed50e53ef7 100644 --- a/ui/storybook/stories/chat-comments.stories.tsx +++ b/ui/storybook/stories/chat-comments.stories.tsx @@ -4,6 +4,7 @@ import type { TranscriptEntry } from "@/adapters"; import type { LiveRunForIssue } from "@/api/heartbeats"; import { CommentThread } from "@/components/CommentThread"; import { IssueChatThread } from "@/components/IssueChatThread"; +import type { MarkdownExternalReferenceMap } from "@/components/MarkdownBody"; import { RunChatSurface } from "@/components/RunChatSurface"; import type { InlineEntityOption } from "@/components/InlineEntitySelector"; import type { MentionOption } from "@/components/MarkdownEditor"; @@ -376,14 +377,14 @@ const liveRunTranscript: TranscriptEntry[] = [ const issueChatComments: IssueChatComment[] = [ createComment({ id: "comment-issue-board", - body: "Please turn the comment thread into a reviewable chat surface. I need to see operator messages, agent output, system events, and live run progress together.", + body: "Please turn the comment thread into a reviewable chat surface. I need to see operator messages, agent output, system events, and live run progress together.\n\nFollow-up tracked in https://github.com/acme/web/pull/241 (merged) and https://github.com/acme/web/pull/243 (review pending).", createdAt: new Date("2026-04-20T13:44:00.000Z"), }), createComment({ id: "comment-issue-agent", authorAgentId: codexAgent.id, authorUserId: null, - body: "I kept the existing component contracts and added fixtures with realistic Paperclip work: checkout, comments, linked runs, and review feedback.", + body: "I kept the existing component contracts and added fixtures with realistic Paperclip work: checkout, comments, linked runs, and review feedback.\n\nFlaky CI lives in https://github.com/acme/web/pull/242 — re-running. Plain control link: https://random.example.com/path stays undecorated.", createdAt: new Date("2026-04-20T13:50:00.000Z"), runId: "run-issue-chat-01", runAgentId: codexAgent.id, @@ -592,10 +593,12 @@ function ThreadProps({ comments, queuedComments = [], timelineEvents = [], + externalReferences, }: { comments: StoryComment[]; queuedComments?: StoryComment[]; timelineEvents?: IssueTimelineEvent[]; + externalReferences?: MarkdownExternalReferenceMap; }) { return ( {}} + externalReferences={externalReferences} /> ); } +const externalReferenceComments: StoryComment[] = [ + createComment({ + id: "comment-external-board", + body: [ + "Tracking work that just landed:", + "", + "- Merged PR: https://github.com/acme/web/pull/241", + "- Awaiting review: https://github.com/acme/web/pull/243", + "- Auth-blocked: https://app.hubspot.com/leads/99", + "- Plain control link (no decoration): https://random.example.com/path", + ].join("\n"), + createdAt: new Date("2026-04-20T14:02:00.000Z"), + }), + createComment({ + id: "comment-external-agent", + authorAgentId: codexAgent.id, + authorUserId: null, + body: [ + "Confirmed handoff updated.", + "Failed CI on https://github.com/acme/web/pull/242 needs a rerun.", + "", + "```", + "Code-fenced URLs stay plain: https://github.com/acme/web/pull/241", + "```", + ].join("\n"), + createdAt: new Date("2026-04-20T14:05:00.000Z"), + runId: "run-external-01", + runAgentId: codexAgent.id, + }), +]; + +const externalReferences: MarkdownExternalReferenceMap = { + "https://github.com/acme/web/pull/241": { + providerKey: "github", + objectType: "pull_request", + statusCategory: "succeeded", + liveness: "fresh", + statusLabel: "Merged", + displayTitle: "Add external refs", + }, + "https://github.com/acme/web/pull/242": { + providerKey: "github", + objectType: "pull_request", + statusCategory: "failed", + liveness: "stale", + statusLabel: "CI failed", + displayTitle: "Flaky tests", + }, + "https://github.com/acme/web/pull/243": { + providerKey: "github", + objectType: "pull_request", + statusCategory: "waiting", + liveness: "fresh", + statusLabel: "Awaiting review", + displayTitle: "Add liveness overlay", + }, + "https://app.hubspot.com/leads/99": { + providerKey: "hubspot", + objectType: "lead", + statusCategory: "auth_required", + liveness: "auth_required", + statusLabel: "Reconnect", + displayTitle: "Acme deal", + }, +}; + function CommentThreadMatrix() { return (
@@ -635,6 +705,15 @@ function CommentThreadMatrix() { + + +
); @@ -709,6 +788,7 @@ function IssueChatMatrix() { includeSucceededRunsWithoutOutput onInterruptQueued={async () => {}} onCancelQueued={() => undefined} + externalReferences={externalReferences} />