mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-27 02:44:50 +01:00
fix(apps): tolerate stale activity API
Use the omitted-window contract for all-time activity so mixed-version restarts do not reject the page, and remove the obsolete audit footer. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
5f7926a5d5
commit
ad8f869278
4 files changed
+40
-7
No files matched your search
@@ -0,0 +1,34 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const mockApi = vi.hoisted(() => ({
|
||||
get: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./client", () => ({
|
||||
api: mockApi,
|
||||
}));
|
||||
|
||||
import { toolsApi } from "./tools";
|
||||
|
||||
describe("toolsApi.listActivity", () => {
|
||||
beforeEach(() => {
|
||||
mockApi.get.mockReset();
|
||||
mockApi.get.mockResolvedValue({ events: [], nextCursor: null });
|
||||
});
|
||||
|
||||
it("uses the omitted-window contract for all-time activity", async () => {
|
||||
await toolsApi.listActivity("company-1", { window: "all", limit: 50 });
|
||||
|
||||
expect(mockApi.get).toHaveBeenCalledWith(
|
||||
"/tool-gateway/audit?companyId=company-1&limit=50",
|
||||
);
|
||||
});
|
||||
|
||||
it("sends bounded activity windows explicitly", async () => {
|
||||
await toolsApi.listActivity("company-1", { window: "30d", limit: 50 });
|
||||
|
||||
expect(mockApi.get).toHaveBeenCalledWith(
|
||||
"/tool-gateway/audit?companyId=company-1&window=30d&limit=50",
|
||||
);
|
||||
});
|
||||
});
|
||||
+4
-1
@@ -470,7 +470,10 @@ export const toolsApi = {
|
||||
if (params.app) search.set("app", params.app);
|
||||
if (params.agent) search.set("agent", params.agent);
|
||||
if (params.outcome) search.set("outcome", params.outcome);
|
||||
if (params.window) search.set("window", params.window);
|
||||
// Omitting the window is the API's canonical all-time request. This also
|
||||
// keeps the page usable during a rolling restart against an older server
|
||||
// that does not recognize the newer explicit `all` value.
|
||||
if (params.window && params.window !== "all") search.set("window", params.window);
|
||||
if (params.search) search.set("search", params.search);
|
||||
if (params.cursor) search.set("cursor", params.cursor);
|
||||
search.set("limit", String(params.limit ?? 50));
|
||||
|
||||
@@ -125,14 +125,14 @@ describe("AuditTab", () => {
|
||||
});
|
||||
}
|
||||
|
||||
it("renders humanized sentences, the outcome chip, and the footer note", async () => {
|
||||
it("renders humanized sentences and the outcome chip without the old footer note", async () => {
|
||||
await render();
|
||||
|
||||
expect(container.textContent).toContain("Fable");
|
||||
expect(container.textContent).toContain("Send Email");
|
||||
expect(container.textContent).toContain("Gmail");
|
||||
expect(container.textContent).toContain("Blocked");
|
||||
expect(container.textContent).toContain("Recorded by Paperclip — entries can't be edited.");
|
||||
expect(container.textContent).not.toContain("Recorded by Paperclip — entries can't be edited.");
|
||||
expect(listActivityMock).toHaveBeenCalledWith("company-1", expect.objectContaining({ window: "all" }));
|
||||
// Vocabulary gate: no raw tool ID or ops terms in the sentence list.
|
||||
expect(container.textContent).not.toContain("mail:send_email");
|
||||
|
||||
@@ -514,10 +514,6 @@ export function AuditTab({ companyId }: { companyId: string }) {
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Recorded by Paperclip — entries can't be edited. Sensitive values are never stored.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user