diff --git a/skills/paperclip/SKILL.md b/skills/paperclip/SKILL.md index 06fde062..898dd175 100644 --- a/skills/paperclip/SKILL.md +++ b/skills/paperclip/SKILL.md @@ -125,10 +125,14 @@ After: pls show the costs in either token or dollars on the /issues/{id} page. Make a plan first. + [your plan here] + ``` +\*make sure to have a newline after/before your tags + ## Key Endpoints (Quick Reference) | Action | Endpoint | diff --git a/ui/src/components/ActiveAgentsPanel.tsx b/ui/src/components/ActiveAgentsPanel.tsx index d13ab088..35551b80 100644 --- a/ui/src/components/ActiveAgentsPanel.tsx +++ b/ui/src/components/ActiveAgentsPanel.tsx @@ -140,14 +140,8 @@ interface ActiveAgentsPanelProps { companyId: string; } -interface AgentRunGroup { - agentId: string; - agentName: string; - runs: LiveRunForIssue[]; -} - export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { - const [feedByAgent, setFeedByAgent] = useState>(new Map()); + const [feedByRun, setFeedByRun] = useState>(new Map()); const seenKeysRef = useRef(new Set()); const pendingByRunRef = useRef(new Map()); const nextIdRef = useRef(1); @@ -161,19 +155,6 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { const runById = useMemo(() => new Map(runs.map((r) => [r.id, r])), [runs]); const activeRunIds = useMemo(() => new Set(runs.map((r) => r.id)), [runs]); - const agentGroups = useMemo(() => { - const map = new Map(); - for (const run of runs) { - let group = map.get(run.agentId); - if (!group) { - group = { agentId: run.agentId, agentName: run.agentName, runs: [] }; - map.set(run.agentId, group); - } - group.runs.push(run); - } - return Array.from(map.values()); - }, [runs]); - // Clean up pending buffers for runs that ended useEffect(() => { const stillActive = new Set(); @@ -196,12 +177,12 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { let reconnectTimer: number | null = null; let socket: WebSocket | null = null; - const appendItems = (agentId: string, items: FeedItem[]) => { + const appendItems = (runId: string, items: FeedItem[]) => { if (items.length === 0) return; - setFeedByAgent((prev) => { + setFeedByRun((prev) => { const next = new Map(prev); - const existing = next.get(agentId) ?? []; - next.set(agentId, [...existing, ...items].slice(-MAX_FEED_ITEMS)); + const existing = next.get(runId) ?? []; + next.set(runId, [...existing, ...items].slice(-MAX_FEED_ITEMS)); return next; }); }; @@ -246,7 +227,7 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { if (seenKeysRef.current.size > 2000) seenKeysRef.current.clear(); const tone = eventType === "error" ? "error" : eventType === "lifecycle" ? "warn" : "info"; const item = createFeedItem(run, event.createdAt, messageText, tone, nextIdRef.current++); - if (item) appendItems(run.agentId, [item]); + if (item) appendItems(run.id, [item]); return; } @@ -258,7 +239,7 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { if (seenKeysRef.current.size > 2000) seenKeysRef.current.clear(); const tone = status === "failed" || status === "timed_out" ? "error" : "warn"; const item = createFeedItem(run, event.createdAt, `run ${status}`, tone, nextIdRef.current++); - if (item) appendItems(run.agentId, [item]); + if (item) appendItems(run.id, [item]); return; } @@ -267,10 +248,10 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { if (!chunk) return; const stream = readString(payload["stream"]) === "stderr" ? "stderr" : "stdout"; if (stream === "stderr") { - appendItems(run.agentId, parseStderrChunk(run, chunk, event.createdAt, pendingByRunRef.current, nextIdRef)); + appendItems(run.id, parseStderrChunk(run, chunk, event.createdAt, pendingByRunRef.current, nextIdRef)); return; } - appendItems(run.agentId, parseStdoutChunk(run, chunk, event.createdAt, pendingByRunRef.current, nextIdRef)); + appendItems(run.id, parseStdoutChunk(run, chunk, event.createdAt, pendingByRunRef.current, nextIdRef)); } }; @@ -297,7 +278,7 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { }; }, [activeRunIds, companyId, runById]); - if (agentGroups.length === 0) return null; + if (runs.length === 0) return null; return (
@@ -305,11 +286,11 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { Active Agents
- {agentGroups.map((group) => ( + {runs.map((run) => ( ))}
@@ -317,10 +298,9 @@ export function ActiveAgentsPanel({ companyId }: ActiveAgentsPanelProps) { ); } -function AgentRunCard({ group, feed }: { group: AgentRunGroup; feed: FeedItem[] }) { +function AgentRunCard({ run, feed }: { run: LiveRunForIssue; feed: FeedItem[] }) { const bodyRef = useRef(null); const recent = feed.slice(-20); - const primaryRun = group.runs[0]; useEffect(() => { const body = bodyRef.current; @@ -336,23 +316,19 @@ function AgentRunCard({ group, feed }: { group: AgentRunGroup; feed: FeedItem[] - + Live - {group.runs.length > 1 && ( - - ({group.runs.length} runs) - - )} + + {run.id.slice(0, 8)} +
- {primaryRun && ( - - Open run - - - )} + + Open run + +
@@ -381,21 +357,6 @@ function AgentRunCard({ group, feed }: { group: AgentRunGroup; feed: FeedItem[]
))} - - {group.runs.length > 1 && ( -
- {group.runs.map((run) => ( - - {run.id.slice(0, 8)} - - - ))} -
- )} ); }