Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions src/CodexEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
CommandExecutionOutputDeltaNotification,
ConfigWarningNotification,
ErrorNotification,
GuardianWarningNotification,
ItemGuardianApprovalReviewCompletedNotification,
ItemGuardianApprovalReviewStartedNotification,
ItemCompletedNotification,
Expand Down Expand Up @@ -131,7 +130,7 @@ export class CodexEventHandler {
case "warning":
return this.createWarningEvent(notification.params);
case "guardianWarning":
return this.createGuardianWarningEvent(notification.params);
return null;
case "item/autoApprovalReview/started":
return this.handleGuardianApprovalReviewStarted(notification.params);
case "item/autoApprovalReview/completed":
Expand Down Expand Up @@ -237,16 +236,6 @@ export class CodexEventHandler {
};
}

private createGuardianWarningEvent(event: GuardianWarningNotification): UpdateSessionEvent {
return {
sessionUpdate: "agent_message_chunk",
content: {
type: "text",
text: `Guardian warning: ${event.message}\n\n`
}
};
}

private createModelReroutedEvent(event: ModelReroutedNotification): UpdateSessionEvent {
return {
sessionUpdate: "agent_thought_chunk",
Expand Down
3 changes: 3 additions & 0 deletions src/CodexToolCallMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ function createGuardianApprovalReviewContent(
if (review.riskLevel) {
lines.push(`Risk: ${review.riskLevel}`);
}
if (review.userAuthorization) {
lines.push(`Authorization: ${review.userAuthorization}`);
}
if (review.rationale?.trim()) {
lines.push(`Rationale: ${review.rationale}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"type": "content",
"content": {
"type": "text",
"text": "Status: Denied\nAction: network access to api.example.com\nRisk: high\nRationale: The network target is not permitted."
"text": "Status: Denied\nAction: network access to api.example.com\nRisk: high\nAuthorization: low\nRationale: The network target is not permitted."
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"type": "content",
"content": {
"type": "text",
"text": "Status: In progress\nAction: exec /bin/ls -l\nRisk: medium\nRationale: Checking whether this command should run automatically."
"text": "Status: In progress\nAction: exec /bin/ls -l\nRisk: medium\nAuthorization: unknown\nRationale: Checking whether this command should run automatically."
}
}
],
Expand Down Expand Up @@ -59,7 +59,7 @@
"type": "content",
"content": {
"type": "text",
"text": "Status: Approved\nAction: exec /bin/ls -l\nRisk: low\nRationale: The command only lists files."
"text": "Status: Approved\nAction: exec /bin/ls -l\nRisk: low\nAuthorization: medium\nRationale: The command only lists files."
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,27 @@ describe("CodexEventHandler - Guardian approval review events", () => {
},
},
};
const duplicateWarning: ServerNotification = {
method: "guardianWarning",
params: {
threadId: sessionId,
message: "Automatic approval review approved (risk: low, authorization: medium): The command only lists files.",
},
};

await setupPromptAndSendNotifications(mockFixture, sessionId, sessionState, [started, completed]);
await setupPromptAndSendNotifications(mockFixture, sessionId, sessionState, [
started,
duplicateWarning,
completed,
]);

await expect(mockFixture.getAcpConnectionDump([])).toMatchFileSnapshot(
const dump = mockFixture.getAcpConnectionDump([]);
expect(dump).not.toContain("agent_message_chunk");
expect(dump).not.toContain("Guardian warning");
expect(dump).not.toContain("Automatic approval review approved");
expect(dump).toContain("tool_call_update");
expect(dump).toContain("Authorization: medium");
await expect(dump).toMatchFileSnapshot(
"data/guardian-approval-review-flow.json"
);
});
Expand Down Expand Up @@ -114,4 +131,21 @@ describe("CodexEventHandler - Guardian approval review events", () => {
"data/guardian-approval-review-completed-without-start.json"
);
});

it("ignores Guardian warnings that are not approval review summaries", async () => {
const warning: ServerNotification = {
method: "guardianWarning",
params: {
threadId: sessionId,
message: "Automatic approval review rejected too many approval requests for this turn (3 consecutive, 5 in the last 10 reviews); interrupting the turn.",
},
};

vi.spyOn(mockFixture.getCodexAcpAgent(), "getSessionState").mockReturnValue(sessionState);
mockFixture.sendServerNotification(warning);
await mockFixture.getCodexAcpClient().waitForSessionNotifications(sessionId);

const dump = mockFixture.getAcpConnectionDump([]);
expect(dump).toBe("");
});
});
Loading