forked from farhoodlabs/paperclip
[codex] Add runtime lifecycle recovery and live issue visibility (#4419)
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
import type { HeartbeatRun, HeartbeatRunEvent, InstanceSchedulerHeartbeatAgent, WorkspaceOperation } from "@paperclipai/shared";
|
||||
import type {
|
||||
HeartbeatRun,
|
||||
HeartbeatRunEvent,
|
||||
InstanceSchedulerHeartbeatAgent,
|
||||
WorkspaceOperation,
|
||||
} from "@paperclipai/shared";
|
||||
import { api } from "./client";
|
||||
|
||||
export interface RunLivenessFields {
|
||||
@@ -20,12 +25,15 @@ export interface ActiveRunForIssue {
|
||||
agentId: string;
|
||||
agentName: string;
|
||||
adapterType: string;
|
||||
logBytes?: number | null;
|
||||
lastOutputBytes?: number | null;
|
||||
issueId?: string | null;
|
||||
livenessState?: RunLivenessFields["livenessState"];
|
||||
livenessReason?: string | null;
|
||||
continuationAttempt?: number;
|
||||
lastUsefulActionAt?: string | Date | null;
|
||||
nextAction?: string | null;
|
||||
outputSilence?: HeartbeatRun["outputSilence"];
|
||||
}
|
||||
|
||||
export interface LiveRunForIssue {
|
||||
@@ -39,12 +47,23 @@ export interface LiveRunForIssue {
|
||||
agentId: string;
|
||||
agentName: string;
|
||||
adapterType: string;
|
||||
logBytes?: number | null;
|
||||
lastOutputBytes?: number | null;
|
||||
issueId?: string | null;
|
||||
livenessState?: RunLivenessFields["livenessState"];
|
||||
livenessReason?: string | null;
|
||||
continuationAttempt?: number;
|
||||
lastUsefulActionAt?: string | null;
|
||||
nextAction?: string | null;
|
||||
outputSilence?: HeartbeatRun["outputSilence"];
|
||||
}
|
||||
|
||||
export interface WatchdogDecisionInput {
|
||||
runId: string;
|
||||
decision: "snooze" | "continue" | "dismissed_false_positive";
|
||||
evaluationIssueId?: string | null;
|
||||
reason?: string | null;
|
||||
snoozedUntil?: string | null;
|
||||
}
|
||||
|
||||
export const heartbeatsApi = {
|
||||
@@ -71,12 +90,31 @@ export const heartbeatsApi = {
|
||||
`/workspace-operations/${operationId}/log?offset=${encodeURIComponent(String(offset))}&limitBytes=${encodeURIComponent(String(limitBytes))}`,
|
||||
),
|
||||
cancel: (runId: string) => api.post<void>(`/heartbeat-runs/${runId}/cancel`, {}),
|
||||
recordWatchdogDecision: (input: WatchdogDecisionInput) =>
|
||||
api.post(`/heartbeat-runs/${input.runId}/watchdog-decisions`, {
|
||||
decision: input.decision,
|
||||
evaluationIssueId: input.evaluationIssueId ?? null,
|
||||
reason: input.reason ?? null,
|
||||
snoozedUntil: input.snoozedUntil ?? null,
|
||||
}),
|
||||
liveRunsForIssue: (issueId: string) =>
|
||||
api.get<LiveRunForIssue[]>(`/issues/${issueId}/live-runs`),
|
||||
activeRunForIssue: (issueId: string) =>
|
||||
api.get<ActiveRunForIssue | null>(`/issues/${issueId}/active-run`),
|
||||
liveRunsForCompany: (companyId: string, minCount?: number) =>
|
||||
api.get<LiveRunForIssue[]>(`/companies/${companyId}/live-runs${minCount ? `?minCount=${minCount}` : ""}`),
|
||||
liveRunsForCompany: (
|
||||
companyId: string,
|
||||
options?: number | { minCount?: number; limit?: number },
|
||||
) => {
|
||||
const searchParams = new URLSearchParams();
|
||||
if (typeof options === "number") {
|
||||
searchParams.set("minCount", String(options));
|
||||
} else if (options) {
|
||||
if (options.minCount) searchParams.set("minCount", String(options.minCount));
|
||||
if (options.limit) searchParams.set("limit", String(options.limit));
|
||||
}
|
||||
const qs = searchParams.toString();
|
||||
return api.get<LiveRunForIssue[]>(`/companies/${companyId}/live-runs${qs ? `?${qs}` : ""}`);
|
||||
},
|
||||
listInstanceSchedulerAgents: () =>
|
||||
api.get<InstanceSchedulerHeartbeatAgent[]>("/instance/scheduler-heartbeats"),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user