fix(ui): bound review projection fields before trimming

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-11-02 23:56:13 -06:00
1 parent 17236e1736
commit 50600786f7
2 files changed
+23 -3

No files matched your search

@@ -1308,6 +1308,26 @@ describe("IssueThreadInteractionCard tool-action card", () => {
expect(Array.from(host.querySelectorAll("button")).find(button => button.textContent === "Approve & run")?.disabled).toBe(true);
});
it.each(["argumentsSummaryJson", "argumentsHash"] as const)("rejects oversized whitespace before trimming %s", field => {
const interaction = structuredClone(pendingToolActionWriteInteraction);
const oversized = " ".repeat(field === "argumentsSummaryJson" ? 20_001 : 256);
interaction.payload.toolAction![field] = oversized;
const trim = String.prototype.trim;
let oversizedTrimCalls = 0;
const spy = vi.spyOn(String.prototype, "trim").mockImplementation(function (this: string) {
if (String(this) === oversized) oversizedTrimCalls++;
return trim.call(this);
});
try {
const host = renderCard({ interaction });
expect(host.querySelector("details")).toBeNull();
expect(host.textContent).toContain("Request arguments are unavailable.");
expect(oversizedTrimCalls).toBe(0);
} finally {
spy.mockRestore();
}
});
it("keeps the destructive request warning and approval styling", () => {
const host = renderCard({ interaction: pendingToolActionDestructiveInteraction, onAcceptInteraction: vi.fn(), onRejectInteraction: vi.fn() });
expect(host.textContent).toContain("cannot be undone");
@@ -1801,9 +1801,9 @@ function RequestToolActionCard({
const variant = payload.risk === "destructive" ? "destructive" : "cta";
// This server projection is already redacted and bounded by the interaction schema.
const inspectableArguments = typeof payload.argumentsSummaryJson === "string"
&& payload.argumentsSummaryJson.trim().length > 0 && payload.argumentsSummaryJson.length <= 20_000
&& typeof payload.argumentsHash === "string" && payload.argumentsHash.trim().length > 0
&& payload.argumentsHash.length <= 255;
&& payload.argumentsSummaryJson.length <= 20_000 && payload.argumentsSummaryJson.trim().length > 0
&& typeof payload.argumentsHash === "string" && payload.argumentsHash.length <= 255
&& payload.argumentsHash.trim().length > 0;
useEffect(() => {