mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 12:04:41 +01:00
Gate watchdog state callout behind task watchdog flag
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
78e0f80358
commit
fc2af3841b
2 files changed
+67
-1
No files matched your search
@@ -469,6 +469,28 @@ function createIssue(overrides: Partial<Issue> = {}): Issue {
|
||||
} as Issue;
|
||||
}
|
||||
|
||||
function createWatchdogSummary(
|
||||
overrides: Partial<NonNullable<Issue["watchdog"]>> = {},
|
||||
): NonNullable<Issue["watchdog"]> {
|
||||
return {
|
||||
id: "watchdog-1",
|
||||
companyId: "company-1",
|
||||
issueId: "issue-1",
|
||||
watchdogAgentId: "agent-1",
|
||||
instructions: "Watch for stalled proof obligations.",
|
||||
status: "active",
|
||||
watchdogIssueId: "watchdog-issue-1",
|
||||
lastObservedFingerprint: "task_watchdog_stop:observed",
|
||||
lastReviewedFingerprint: "task_watchdog_stop:reviewed",
|
||||
lastTriggeredAt: null,
|
||||
lastCompletedAt: null,
|
||||
triggerCount: 1,
|
||||
createdAt: new Date("2026-04-21T00:00:00.000Z"),
|
||||
updatedAt: new Date("2026-04-21T00:00:00.000Z"),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function createAttachment(overrides: Partial<IssueAttachment> & { id: string }): IssueAttachment {
|
||||
const { id, ...attachmentOverrides } = overrides;
|
||||
return {
|
||||
@@ -1655,6 +1677,49 @@ describe("IssueDetail", () => {
|
||||
expect(container.textContent).toContain("Ask mode");
|
||||
});
|
||||
|
||||
it("does not pass watchdog state to the issue chat thread when task watchdogs are disabled", async () => {
|
||||
mockIssuesApi.get.mockResolvedValue(createIssue({ watchdog: createWatchdogSummary() }));
|
||||
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<IssueDetail />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
});
|
||||
await flushReact();
|
||||
|
||||
expect(mockIssueChatThreadRender.mock.calls.at(-1)?.[0]).toMatchObject({
|
||||
watchdog: null,
|
||||
});
|
||||
});
|
||||
|
||||
it("passes watchdog state to the issue chat thread when task watchdogs are enabled", async () => {
|
||||
const watchdog = createWatchdogSummary();
|
||||
mockInstanceSettingsApi.getExperimental.mockResolvedValue({
|
||||
enableIssuePlanDecompositions: false,
|
||||
enableExperimentalFileViewer: false,
|
||||
enableExternalObjects: false,
|
||||
enableTaskWatchdogs: true,
|
||||
});
|
||||
mockIssuesApi.get.mockResolvedValue(createIssue({ watchdog }));
|
||||
|
||||
await act(async () => {
|
||||
root.render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<IssueDetail />
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
});
|
||||
await flushReact();
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(mockIssueChatThreadRender.mock.calls.at(-1)?.[0]).toMatchObject({
|
||||
watchdog,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to execCommand when copying the task from an insecure context", async () => {
|
||||
const clipboardWrite = vi.fn(async () => {
|
||||
throw new Error("Clipboard API blocked");
|
||||
|
||||
@@ -1563,6 +1563,7 @@ export function IssueDetail() {
|
||||
const showPlanDecompositionsSection =
|
||||
instanceExperimentalSettings?.enableIssuePlanDecompositions === true;
|
||||
const fileViewerEnabled = instanceExperimentalSettings?.enableExperimentalFileViewer === true;
|
||||
const taskWatchdogsEnabled = instanceExperimentalSettings?.enableTaskWatchdogs === true;
|
||||
const { orderedProjects } = useProjectOrder({
|
||||
projects: projects ?? [],
|
||||
companyId: selectedCompanyId,
|
||||
@@ -4234,7 +4235,7 @@ export function IssueDetail() {
|
||||
successfulRunHandoff={issue.successfulRunHandoff ?? null}
|
||||
scheduledRetry={issue.scheduledRetry ?? null}
|
||||
recoveryAction={issue.activeRecoveryAction ?? null}
|
||||
watchdog={issue.watchdog ?? null}
|
||||
watchdog={taskWatchdogsEnabled ? issue.watchdog ?? null : null}
|
||||
monitorNextCheckAt={issue.monitorNextCheckAt ?? null}
|
||||
onResolveRecoveryAction={handleResolveRecoveryAction}
|
||||
canFalsePositiveRecoveryAction={canResolveBoardRecoveryAction}
|
||||
|
||||
Reference in new issue
Block a user