diff --git a/frontend/src/features/accounts/api.ts b/frontend/src/features/accounts/api.ts
index 656db72ea..ba79bde55 100644
--- a/frontend/src/features/accounts/api.ts
+++ b/frontend/src/features/accounts/api.ts
@@ -13,6 +13,8 @@ import {
AccountRoutingPolicyUpdateRequestSchema,
AccountRoutingPolicyUpdateResponseSchema,
AccountTrendsResponseSchema,
+ AccountProbeRequestSchema,
+ AccountProbeResponseSchema,
ManualOauthCallbackRequestSchema,
ManualOauthCallbackResponseSchema,
OauthCompleteRequestSchema,
@@ -99,6 +101,15 @@ export function getAccountTrends(accountId: string) {
);
}
+export function probeAccount(accountId: string, payload?: unknown) {
+ const validated = payload === undefined ? undefined : AccountProbeRequestSchema.parse(payload);
+ return post(
+ `${ACCOUNTS_BASE_PATH}/${encodeURIComponent(accountId)}/probe`,
+ AccountProbeResponseSchema,
+ validated ? { body: validated } : undefined,
+ );
+}
+
export function exportAccountAuth(accountId: string) {
return post(
`${ACCOUNTS_BASE_PATH}/${encodeURIComponent(accountId)}/export/auth`,
diff --git a/frontend/src/features/accounts/components/account-actions.test.tsx b/frontend/src/features/accounts/components/account-actions.test.tsx
index 41f935d71..2aad534b6 100644
--- a/frontend/src/features/accounts/components/account-actions.test.tsx
+++ b/frontend/src/features/accounts/components/account-actions.test.tsx
@@ -1,4 +1,5 @@
import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { AccountActions } from "@/features/accounts/components/account-actions";
@@ -15,6 +16,7 @@ describe("AccountActions", () => {
busy={false}
onPause={vi.fn()}
onResume={vi.fn()}
+ onProbe={vi.fn()}
onDelete={vi.fn()}
onReauth={vi.fn()}
onExportAuth={vi.fn()}
@@ -40,6 +42,7 @@ describe("AccountActions", () => {
busy={false}
onPause={vi.fn()}
onResume={vi.fn()}
+ onProbe={vi.fn()}
onDelete={vi.fn()}
onReauth={onReauth}
onExportAuth={vi.fn()}
@@ -59,4 +62,63 @@ describe("AccountActions", () => {
screen.queryByRole("combobox", { name: "Routing policy" }),
).not.toBeInTheDocument();
});
+
+ it("fires the per-account probe callback for active accounts", async () => {
+ const user = userEvent.setup();
+ const account = createAccountSummary();
+ const onProbe = vi.fn();
+
+ render(
+ ,
+ );
+
+ await user.click(screen.getByRole("button", { name: "Force probe" }));
+
+ expect(onProbe).toHaveBeenCalledWith(account.accountId);
+ expect(onProbe).toHaveBeenCalledTimes(1);
+ });
+
+ it.each(["paused", "deactivated"] as const)(
+ "disables force probe for %s accounts",
+ async (status) => {
+ const user = userEvent.setup();
+ const account = createAccountSummary({ status });
+ const onProbe = vi.fn();
+
+ render(
+ ,
+ );
+
+ const button = screen.getByRole("button", { name: "Force probe" });
+ expect(button).toBeDisabled();
+
+ await user.click(button);
+
+ expect(onProbe).not.toHaveBeenCalled();
+ },
+ );
});
diff --git a/frontend/src/features/accounts/components/account-actions.tsx b/frontend/src/features/accounts/components/account-actions.tsx
index 03ea1acfd..de70df4ff 100644
--- a/frontend/src/features/accounts/components/account-actions.tsx
+++ b/frontend/src/features/accounts/components/account-actions.tsx
@@ -1,4 +1,5 @@
import {
+ Activity,
Download,
Pause,
Play,
@@ -28,6 +29,7 @@ export type AccountActionsProps = {
busy: boolean;
onPause: (accountId: string) => void;
onResume: (accountId: string) => void;
+ onProbe: (accountId: string) => void;
onDelete: (accountId: string) => void;
onReauth: () => void;
onExportAuth: (accountId: string) => void;
@@ -44,6 +46,7 @@ export function AccountActions({
busy,
onPause,
onResume,
+ onProbe,
onDelete,
onReauth,
onExportAuth,
@@ -53,6 +56,8 @@ export function AccountActions({
}: AccountActionsProps) {
const showOperatorRecoveryAction =
account.status === "reauth_required" || account.status === "deactivated";
+ const probeDisabled =
+ busy || account.status === "paused" || showOperatorRecoveryAction;
return (
@@ -142,6 +147,18 @@ export function AccountActions({
) : null}
+
+