nexus/ui/src/api/heartbeats.ts
Forgotten ef7a7ecee8 UI: Identity component, LiveRunWidget, issue identifiers, and UX improvements
Add Identity component (avatar + name) used across agent/issue displays. Add
LiveRunWidget for real-time streaming of active heartbeat runs on issue detail
pages via WebSocket. Display issue identifiers (PAP-42) instead of UUID
fragments throughout Issues, Inbox, CommandPalette, and detail pages.
Enhance CommentThread with re-open checkbox, Cmd+Enter submit, sorted display,
and run linking. Improve Activity page with richer formatting and filtering.
Update Dashboard with live metrics. Add reports-to agent link in AgentProperties.
Various small fixes: StatusIcon centering, CopyText ref init, agent detail
run-issue cross-links.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:10:07 -06:00

41 lines
1.5 KiB
TypeScript

import type { HeartbeatRun, HeartbeatRunEvent } from "@paperclip/shared";
import { api } from "./client";
export interface ActiveRunForIssue extends HeartbeatRun {
agentId: string;
agentName: string;
adapterType: string;
}
export interface LiveRunForIssue {
id: string;
status: string;
invocationSource: string;
triggerDetail: string | null;
startedAt: string | null;
finishedAt: string | null;
createdAt: string;
agentId: string;
agentName: string;
adapterType: string;
}
export const heartbeatsApi = {
list: (companyId: string, agentId?: string) => {
const params = agentId ? `?agentId=${agentId}` : "";
return api.get<HeartbeatRun[]>(`/companies/${companyId}/heartbeat-runs${params}`);
},
events: (runId: string, afterSeq = 0, limit = 200) =>
api.get<HeartbeatRunEvent[]>(
`/heartbeat-runs/${runId}/events?afterSeq=${encodeURIComponent(String(afterSeq))}&limit=${encodeURIComponent(String(limit))}`,
),
log: (runId: string, offset = 0, limitBytes = 256000) =>
api.get<{ runId: string; store: string; logRef: string; content: string; nextOffset?: number }>(
`/heartbeat-runs/${runId}/log?offset=${encodeURIComponent(String(offset))}&limitBytes=${encodeURIComponent(String(limitBytes))}`,
),
cancel: (runId: string) => api.post<void>(`/heartbeat-runs/${runId}/cancel`, {}),
liveRunsForIssue: (issueId: string) =>
api.get<LiveRunForIssue[]>(`/issues/${issueId}/live-runs`),
activeRunForIssue: (issueId: string) =>
api.get<ActiveRunForIssue | null>(`/issues/${issueId}/active-run`),
};