mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-16 10:50:38 +09:00
[codex] Add runtime lifecycle recovery and live issue visibility (#4419)
This commit is contained in:
parent
9a8d219949
commit
5a0c1979cf
121 changed files with 9625 additions and 2044 deletions
|
|
@ -9,6 +9,7 @@ import type {
|
|||
IssueComment,
|
||||
} from "@paperclipai/shared";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { ArrowRight, Check, Copy, Paperclip } from "lucide-react";
|
||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { Identity } from "./Identity";
|
||||
|
|
@ -32,6 +33,7 @@ interface CommentWithRunMeta extends IssueComment {
|
|||
clientStatus?: "pending" | "queued";
|
||||
queueState?: "queued";
|
||||
queueTargetRunId?: string | null;
|
||||
followUpRequested?: boolean;
|
||||
}
|
||||
|
||||
interface LinkedRunItem {
|
||||
|
|
@ -341,6 +343,7 @@ function CommentCard({
|
|||
const isHighlighted = highlightCommentId === comment.id;
|
||||
const isPending = comment.clientStatus === "pending";
|
||||
const isQueued = queued || comment.queueState === "queued" || comment.clientStatus === "queued";
|
||||
const followUpRequested = comment.followUpRequested === true;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -371,6 +374,11 @@ function CommentCard({
|
|||
Queued
|
||||
</span>
|
||||
) : null}
|
||||
{followUpRequested ? (
|
||||
<Badge variant="outline" className="text-[10px] uppercase tracking-[0.14em]">
|
||||
Follow-up
|
||||
</Badge>
|
||||
) : null}
|
||||
{companyId && !isPending ? (
|
||||
<PluginSlotOutlet
|
||||
slotTypes={["commentContextMenuItem"]}
|
||||
|
|
@ -478,6 +486,7 @@ function TimelineEventCard({
|
|||
currentUserId?: string | null;
|
||||
}) {
|
||||
const actorName = formatTimelineActorName(event.actorType, event.actorId, agentMap, currentUserId);
|
||||
const actionLabel = event.followUpRequested ? "requested follow-up" : "updated this task";
|
||||
|
||||
return (
|
||||
<div id={`activity-${event.id}`} className="flex items-start gap-2.5 py-1.5">
|
||||
|
|
@ -488,7 +497,7 @@ function TimelineEventCard({
|
|||
<div className="min-w-0 flex-1 space-y-1.5">
|
||||
<div className="flex flex-wrap items-baseline gap-x-1.5 gap-y-1 text-sm">
|
||||
<span className="font-medium text-foreground">{actorName}</span>
|
||||
<span className="text-muted-foreground">updated this task</span>
|
||||
<span className="text-muted-foreground">{actionLabel}</span>
|
||||
<a
|
||||
href={`#activity-${event.id}`}
|
||||
className="text-sm text-muted-foreground transition-colors hover:text-foreground hover:underline"
|
||||
|
|
@ -742,12 +751,20 @@ export function CommentThread({
|
|||
const hasScrolledRef = useRef(false);
|
||||
|
||||
const timeline = useMemo<TimelineItem[]>(() => {
|
||||
const commentItems: TimelineItem[] = comments.map((comment) => ({
|
||||
kind: "comment",
|
||||
id: comment.id,
|
||||
createdAtMs: new Date(comment.createdAt).getTime(),
|
||||
comment,
|
||||
}));
|
||||
const followUpCommentIds = new Set(
|
||||
timelineEvents
|
||||
.filter((event) => event.followUpRequested && event.commentId)
|
||||
.map((event) => event.commentId as string),
|
||||
);
|
||||
const commentItems: TimelineItem[] = comments.map((comment) => {
|
||||
const followUpRequested = comment.followUpRequested === true || followUpCommentIds.has(comment.id);
|
||||
return {
|
||||
kind: "comment",
|
||||
id: comment.id,
|
||||
createdAtMs: new Date(comment.createdAt).getTime(),
|
||||
comment: followUpRequested ? { ...comment, followUpRequested } : comment,
|
||||
};
|
||||
});
|
||||
const approvalItems: TimelineItem[] = linkedApprovals.map((approval) => ({
|
||||
kind: "approval",
|
||||
id: approval.id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue