diff --git a/.changeset/approval-allow-cancel.md b/.changeset/approval-allow-cancel.md new file mode 100644 index 000000000..30de64ad4 --- /dev/null +++ b/.changeset/approval-allow-cancel.md @@ -0,0 +1,5 @@ +--- +"eve": minor +--- + +Tool approval responses now use `cancel` instead of `deny`, while retaining `approve` for the positive response, aligning the public protocol with the user-facing flow-control semantics. diff --git a/docs/concepts/sessions-runs-and-streaming.md b/docs/concepts/sessions-runs-and-streaming.md index 6e2a9fbb7..99fa238c3 100644 --- a/docs/concepts/sessions-runs-and-streaming.md +++ b/docs/concepts/sessions-runs-and-streaming.md @@ -85,7 +85,7 @@ curl -X POST http://127.0.0.1:2000/eve/v1/session/ \ The follow-up reuses the same durable session: same history, same state. -If the session is waiting on a human-in-the-loop approval, a matching text reply such as `approve` or `deny` answers the approval. Other follow-up text is held until the approval is answered, so an unrelated message does not implicitly deny the pending tool call. +If the session is waiting on a human-in-the-loop approval, a matching text reply such as `approve` or `cancel` answers the approval. Other follow-up text is held until the approval is answered, so an unrelated message does not implicitly deny the pending tool call. If the session is waiting on `ask_question`, a follow-up message clears that pending request before the model continues. An exact option match or permitted freeform response answers the question; any other message marks the question unanswered and starts the follow-up turn. diff --git a/docs/guides/frontend/overview.mdx b/docs/guides/frontend/overview.mdx index 06ee672bb..ff55c57c9 100644 --- a/docs/guides/frontend/overview.mdx +++ b/docs/guides/frontend/overview.mdx @@ -123,7 +123,7 @@ if (request) { } ``` -`request.prompt` and `request.options` give you what you need to render the approve and deny UI. The default reducer marks the part as responded immediately, then updates it again once eve streams the resumed result. +`request.prompt` and `request.options` give you what you need to render the approve and cancel UI. The default reducer marks the part as responded immediately, then updates it again once eve streams the resumed result. ## Authorization prompts diff --git a/docs/tools/human-in-the-loop.md b/docs/tools/human-in-the-loop.md index 3d0e1db4f..01e008f2a 100644 --- a/docs/tools/human-in-the-loop.md +++ b/docs/tools/human-in-the-loop.md @@ -100,7 +100,7 @@ Approvals and questions share one protocol: 1. The model requests input (an approval, or an `ask_question`). 2. eve emits an `input.requested` stream event carrying the pending requests. 3. The turn parks at `session.waiting`, durably, for as long as it takes. -4. The client answers with `inputResponses` (structured, keyed by `requestId`) or a normal follow-up `message`. A follow-up whose text matches an option ID, option label, or numeric option index resolves automatically, including approval options such as `approve` and `deny`. +4. The client answers with `inputResponses` (structured, keyed by `requestId`) or a normal follow-up `message`. A follow-up whose text matches an option ID, option label, or numeric option index resolves automatically, including approval options such as `approve` and `cancel`. The run picks back up exactly where it parked. Because the pause is durable, nothing is held in memory while it waits — the process can restart and the parked turn survives. diff --git a/docs/tutorial/ship-it.mdx b/docs/tutorial/ship-it.mdx index 2db857152..cd97365a1 100644 --- a/docs/tutorial/ship-it.mdx +++ b/docs/tutorial/ship-it.mdx @@ -73,7 +73,7 @@ export default function Page() { } ``` -`agent.data.messages` and `agent.status` cover most chat UIs. The hook also surfaces HITL prompts (the spend approval from [Step 8](./guard-the-spend)), so the dashboard can render approve/deny controls. For the full API, see [Frontend](../guides/frontend/overview). +`agent.data.messages` and `agent.status` cover most chat UIs. The hook also surfaces HITL prompts (the spend approval from [Step 8](./guard-the-spend)), so the dashboard can render approve/cancel controls. For the full API, see [Frontend](../guides/frontend/overview). ## Replace `placeholderAuth` diff --git a/packages/eve/src/channel/resolve-text.test.ts b/packages/eve/src/channel/resolve-text.test.ts index efafab930..0c5ebc507 100644 --- a/packages/eve/src/channel/resolve-text.test.ts +++ b/packages/eve/src/channel/resolve-text.test.ts @@ -8,7 +8,7 @@ const APPROVAL_REQUEST: InputRequest = { display: "confirmation", options: [ { id: "approve", label: "Approve", style: "primary" }, - { id: "deny", label: "Deny", style: "danger" }, + { id: "cancel", label: "Cancel", style: "danger" }, ], prompt: 'Approve tool "bash"?', requestId: "req-1", diff --git a/packages/eve/src/cli/dev/tui/runner.test.ts b/packages/eve/src/cli/dev/tui/runner.test.ts index 2a82253fc..d86b63123 100644 --- a/packages/eve/src/cli/dev/tui/runner.test.ts +++ b/packages/eve/src/cli/dev/tui/runner.test.ts @@ -905,7 +905,7 @@ describe("EveTUIRunner native continuation state", () => { display: "confirmation", options: [ { id: "approve", label: "Approve" }, - { id: "deny", label: "Deny" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve get_weather?", requestId: "request-1", diff --git a/packages/eve/src/cli/dev/tui/runner.ts b/packages/eve/src/cli/dev/tui/runner.ts index 851402668..d52557a50 100644 --- a/packages/eve/src/cli/dev/tui/runner.ts +++ b/packages/eve/src/cli/dev/tui/runner.ts @@ -868,7 +868,7 @@ export class EveTUIRunner { const response = await this.#renderer.readToolApproval(request, { title }); responses.push({ requestId: request.approvalId, - optionId: response.approved ? "approve" : "deny", + optionId: response.approved ? "approve" : "cancel", }); this.#pendingInputRequests.delete(request.approvalId); } diff --git a/packages/eve/src/client/message-reducer.test.ts b/packages/eve/src/client/message-reducer.test.ts index 1bde0298f..1adf4f961 100644 --- a/packages/eve/src/client/message-reducer.test.ts +++ b/packages/eve/src/client/message-reducer.test.ts @@ -373,7 +373,7 @@ describe("defaultMessageReducer", () => { display: "confirmation", options: [ { id: "approve", label: "Yes", style: "primary" }, - { id: "deny", label: "No", style: "danger" }, + { id: "cancel", label: "No", style: "danger" }, ], prompt: "Approve tool call: bash", requestId: "approval_1", @@ -409,7 +409,7 @@ describe("defaultMessageReducer", () => { display: "confirmation", options: [ { id: "approve", label: "Yes", style: "primary" }, - { id: "deny", label: "No", style: "danger" }, + { id: "cancel", label: "No", style: "danger" }, ], prompt: "Approve tool call: bash", requestId: "approval_1", @@ -443,7 +443,7 @@ describe("defaultMessageReducer", () => { display: "confirmation", options: [ { id: "approve", label: "Yes", style: "primary" }, - { id: "deny", label: "No", style: "danger" }, + { id: "cancel", label: "No", style: "danger" }, ], prompt: "Approve tool call: bash", requestId: "approval_1", @@ -458,7 +458,7 @@ describe("defaultMessageReducer", () => { data = reducer.reduce(data, { data: { createdAt: 1, - responses: [{ optionId: "deny", requestId: "approval_1" }], + responses: [{ optionId: "cancel", requestId: "approval_1" }], }, type: "client.input.responded", }); @@ -487,12 +487,12 @@ describe("defaultMessageReducer", () => { display: "confirmation", options: [ { id: "approve", label: "Yes", style: "primary" }, - { id: "deny", label: "No", style: "danger" }, + { id: "cancel", label: "No", style: "danger" }, ], prompt: "Approve tool call: bash", requestId: "approval_1", }, - inputResponse: { optionId: "deny", requestId: "approval_1" }, + inputResponse: { optionId: "cancel", requestId: "approval_1" }, kind: "tool-call", name: "bash", }, @@ -522,7 +522,7 @@ describe("defaultMessageReducer", () => { display: "confirmation", options: [ { id: "approve", label: "Yes", style: "primary" }, - { id: "deny", label: "No", style: "danger" }, + { id: "cancel", label: "No", style: "danger" }, ], prompt: "Approve tool call: bash", requestId: "approval_1", diff --git a/packages/eve/src/evals/runner/execute-task.test.ts b/packages/eve/src/evals/runner/execute-task.test.ts index 11a7f281c..4aead71c4 100644 --- a/packages/eve/src/evals/runner/execute-task.test.ts +++ b/packages/eve/src/evals/runner/execute-task.test.ts @@ -81,7 +81,7 @@ describe("executeTask", () => { const request = t.requireInputRequest({ display: "confirmation", input: { command: "pwd" }, - optionIds: ["approve", "deny"], + optionIds: ["approve", "cancel"], prompt: /Approve/, toolName: "bash", }); @@ -720,7 +720,7 @@ function inputRequested( display: "confirmation", options: [ { id: "approve", label: "Approve" }, - { id: "deny", label: "Deny" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve?", requestId, diff --git a/packages/eve/src/execution/subagent-adapter.test.ts b/packages/eve/src/execution/subagent-adapter.test.ts index 9daa0f835..7e5752beb 100644 --- a/packages/eve/src/execution/subagent-adapter.test.ts +++ b/packages/eve/src/execution/subagent-adapter.test.ts @@ -55,7 +55,7 @@ function sampleRequest(): InputRequest { }, options: [ { id: "approve", label: "Approve" }, - { id: "deny", label: "Deny" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve?", requestId: "req-1", diff --git a/packages/eve/src/execution/subagent-hitl-proxy.integration.test.ts b/packages/eve/src/execution/subagent-hitl-proxy.integration.test.ts index 95b759c6e..ec67ec7d0 100644 --- a/packages/eve/src/execution/subagent-hitl-proxy.integration.test.ts +++ b/packages/eve/src/execution/subagent-hitl-proxy.integration.test.ts @@ -142,7 +142,7 @@ function buildApprovalRequest(requestId: string): InputRequest { display: "confirmation", options: [ { id: "approve", label: "Approve", style: "primary" }, - { id: "deny", label: "Deny", style: "danger" }, + { id: "cancel", label: "Cancel", style: "danger" }, ], prompt: "Approve?", requestId, @@ -421,7 +421,7 @@ describe("subagent HITL proxy → concurrent-descendant routing", () => { payload: { inputResponses: [ { optionId: "approve", requestId: "req-a" }, - { optionId: "deny", requestId: "req-b" }, + { optionId: "cancel", requestId: "req-b" }, ], }, state: parkedSession.state, @@ -440,7 +440,7 @@ describe("subagent HITL proxy → concurrent-descendant routing", () => { inputResponses: [{ optionId: "approve", requestId: "req-a" }], }); expect(byChild.get("subagent:parent:call-b")).toEqual({ - inputResponses: [{ optionId: "deny", requestId: "req-b" }], + inputResponses: [{ optionId: "cancel", requestId: "req-b" }], }); // A response whose requestId does not match any proxy entry diff --git a/packages/eve/src/execution/subagent-hitl-proxy.test.ts b/packages/eve/src/execution/subagent-hitl-proxy.test.ts index 0421a9ed4..ea207f6eb 100644 --- a/packages/eve/src/execution/subagent-hitl-proxy.test.ts +++ b/packages/eve/src/execution/subagent-hitl-proxy.test.ts @@ -35,7 +35,7 @@ describe("routeDeliverPayload", () => { payload: { inputResponses: [ { optionId: "approve", requestId: "req-a" }, - { optionId: "deny", requestId: "req-b" }, + { optionId: "cancel", requestId: "req-b" }, { optionId: "ignore", requestId: "req-parent" }, ], }, @@ -46,7 +46,7 @@ describe("routeDeliverPayload", () => { const childA = routed.forChildren.find((c) => c.childContinuationToken === "child-a"); const childB = routed.forChildren.find((c) => c.childContinuationToken === "child-b"); expect(childA?.payload.inputResponses).toEqual([{ optionId: "approve", requestId: "req-a" }]); - expect(childB?.payload.inputResponses).toEqual([{ optionId: "deny", requestId: "req-b" }]); + expect(childB?.payload.inputResponses).toEqual([{ optionId: "cancel", requestId: "req-b" }]); expect(routed.forSelf?.inputResponses).toEqual([ { optionId: "ignore", requestId: "req-parent" }, diff --git a/packages/eve/src/execution/workflow-steps.test.ts b/packages/eve/src/execution/workflow-steps.test.ts index ed804a817..9668410c8 100644 --- a/packages/eve/src/execution/workflow-steps.test.ts +++ b/packages/eve/src/execution/workflow-steps.test.ts @@ -1484,7 +1484,7 @@ describe("runProxySubagentEventStep", () => { }, options: [ { id: "approve", label: "Approve" }, - { id: "deny", label: "Deny" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve?", requestId: "req-1", diff --git a/packages/eve/src/harness/input-extraction.test.ts b/packages/eve/src/harness/input-extraction.test.ts index c818179de..cfe4ff35f 100644 --- a/packages/eve/src/harness/input-extraction.test.ts +++ b/packages/eve/src/harness/input-extraction.test.ts @@ -12,7 +12,7 @@ describe("extractQuestionInputRequests", () => { toolCalls: [ { input: { - options: [{ id: "yes", label: "Yes" }], + options: [{ id: "yes", label: "Approve" }], prompt: "Continue?", }, toolCallId: "call-1", @@ -27,14 +27,14 @@ describe("extractQuestionInputRequests", () => { action: { callId: "call-1", input: { - options: [{ id: "yes", label: "Yes" }], + options: [{ id: "yes", label: "Approve" }], prompt: "Continue?", }, kind: "tool-call", toolName: "ask_question", }, display: "select", - options: [{ id: "yes", label: "Yes" }], + options: [{ id: "yes", label: "Approve" }], prompt: "Continue?", requestId: "call-1", }, @@ -118,8 +118,8 @@ describe("extractToolApprovalInputRequests", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -155,8 +155,8 @@ describe("extractToolApprovalInputRequests", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", diff --git a/packages/eve/src/harness/input-extraction.ts b/packages/eve/src/harness/input-extraction.ts index eb1cedc0b..f151e8ff4 100644 --- a/packages/eve/src/harness/input-extraction.ts +++ b/packages/eve/src/harness/input-extraction.ts @@ -157,8 +157,8 @@ function extractApprovalRequests(input: { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: `Approve tool call: ${toolCall.toolName}`, requestId: approval.approvalId, diff --git a/packages/eve/src/harness/input-requests.test.ts b/packages/eve/src/harness/input-requests.test.ts index 65fc4586c..246b5ae79 100644 --- a/packages/eve/src/harness/input-requests.test.ts +++ b/packages/eve/src/harness/input-requests.test.ts @@ -142,7 +142,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -266,7 +266,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -296,7 +296,7 @@ describe("resolvePendingInput", () => { // Deliver an approval response AND a message simultaneously. const result = resolvePendingInput({ stepInput: { - inputResponses: [{ requestId: "approval-1", optionId: "deny" }], + inputResponses: [{ requestId: "approval-1", optionId: "cancel" }], message: "Ignore that and say hi instead.", }, session, @@ -333,7 +333,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -392,7 +392,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -456,7 +456,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: vercel__list_projects", requestId: "approval-1", @@ -522,7 +522,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -551,7 +551,7 @@ describe("resolvePendingInput", () => { const result = resolvePendingInput({ stepInput: { - inputResponses: [{ requestId: "approval-1", optionId: "deny" }], + inputResponses: [{ requestId: "approval-1", optionId: "cancel" }], }, session, }); @@ -591,7 +591,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -603,7 +603,7 @@ describe("resolvePendingInput", () => { const result = resolvePendingInput({ stepInput: { - inputResponses: [{ requestId: "approval-1", optionId: "deny" }], + inputResponses: [{ requestId: "approval-1", optionId: "cancel" }], }, session, }); @@ -648,7 +648,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -684,7 +684,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -724,7 +724,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -783,7 +783,7 @@ describe("resolvePendingInput", () => { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: linear_whoami", requestId: "approval-1", diff --git a/packages/eve/src/harness/input-requests.ts b/packages/eve/src/harness/input-requests.ts index 7d412e222..8118fe91f 100644 --- a/packages/eve/src/harness/input-requests.ts +++ b/packages/eve/src/harness/input-requests.ts @@ -505,7 +505,7 @@ function resolveApprovalOutcome(response: InputResponse | undefined): { }; } - if (response.optionId === "deny") { + if (response.optionId === "cancel") { return { approved: false, reason: TOOL_EXECUTION_DENIED_MESSAGE, @@ -604,7 +604,7 @@ function buildToolResponsePartsForRequest( }, ]; /* - * On denial (explicit "deny" or auto-deny when the user continues + * On denial (explicit "cancel" or auto-deny when the user continues * without responding), splice in the matching `execution-denied` * tool-result. AI SDK's `streamText` synthesizes this for the * current turn's `initialResponseMessages`, but that synthesis is @@ -643,12 +643,12 @@ function buildToolResponsePartsForRequest( ]; } -/** Shared approval predicate: a request whose options are exactly `approve` / `deny`. */ +/** Shared approval predicate: a request whose options are exactly `allow` / `cancel`. */ export function isApprovalRequest(request: InputRequest): boolean { return ( request.options?.length === 2 && request.options[0]?.id === "approve" && - request.options[1]?.id === "deny" + request.options[1]?.id === "cancel" ); } diff --git a/packages/eve/src/harness/stale-input-responses.test.ts b/packages/eve/src/harness/stale-input-responses.test.ts index b0575e568..c51829025 100644 --- a/packages/eve/src/harness/stale-input-responses.test.ts +++ b/packages/eve/src/harness/stale-input-responses.test.ts @@ -61,10 +61,10 @@ it("converts a stale approval into a non-authorizing user message", () => { throw new Error("Expected the stale response to be converted."); } - expect(result.displayMessage).toBe("Yes"); + expect(result.displayMessage).toBe("Approve"); expect(result.stepInput.inputResponses).toBeUndefined(); expect(result.stepInput.message).toEqual(expect.stringContaining("Approve tool call: bash")); - expect(result.stepInput.message).toEqual(expect.stringContaining('"label": "Yes"')); + expect(result.stepInput.message).toEqual(expect.stringContaining('"label": "Approve"')); expect(result.stepInput.message).toEqual( expect.stringContaining("This does not authorize an earlier action"), ); diff --git a/packages/eve/src/harness/tool-loop-generate-approval-resume.integration.test.ts b/packages/eve/src/harness/tool-loop-generate-approval-resume.integration.test.ts index bae7a600a..965947322 100644 --- a/packages/eve/src/harness/tool-loop-generate-approval-resume.integration.test.ts +++ b/packages/eve/src/harness/tool-loop-generate-approval-resume.integration.test.ts @@ -65,7 +65,7 @@ function createPendingApprovalSession(): HarnessSession { display: "confirmation", options: [ { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "cancel", label: "No" }, ], prompt: "Approve tool call: bash", requestId: approvalRequest.approvalId, diff --git a/packages/eve/src/harness/tool-loop.test.ts b/packages/eve/src/harness/tool-loop.test.ts index 74ea2c3ed..9d8f2339d 100644 --- a/packages/eve/src/harness/tool-loop.test.ts +++ b/packages/eve/src/harness/tool-loop.test.ts @@ -428,8 +428,8 @@ function createPendingBashApprovalSession(): HarnessSession { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -478,8 +478,8 @@ function createPendingProtectedActionApprovalSession(): HarnessSession { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: protected_action", requestId: "approval-1", @@ -2283,8 +2283,8 @@ describe("createToolLoopHarness", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -6401,8 +6401,8 @@ describe("createToolLoopHarness", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -6588,8 +6588,8 @@ describe("createToolLoopHarness", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -6646,7 +6646,7 @@ describe("createToolLoopHarness", () => { expect(hasDeferredStepInput(firstResult.session)).toBe(true); const deniedResult = await createToolLoopHarness(config)(firstResult.session, { - inputResponses: [{ requestId: "approval-1", optionId: "deny" }], + inputResponses: [{ requestId: "approval-1", optionId: "cancel" }], }); expect(typeof deniedResult.next).toBe("function"); @@ -6752,8 +6752,8 @@ describe("createToolLoopHarness", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: guarded_echo", requestId: "approval-1", @@ -6999,8 +6999,8 @@ describe("createToolLoopHarness", () => { allowFreeform: false, display: "confirmation", options: [ - { id: "approve", label: "Yes" }, - { id: "deny", label: "No" }, + { id: "approve", label: "Approve" }, + { id: "cancel", label: "Cancel" }, ], prompt: "Approve tool call: bash", requestId: "approval-1", @@ -7059,7 +7059,7 @@ describe("createToolLoopHarness", () => { // Step 2: user denies the approval; the deferred message is NOT in this call. const deniedResult = await createToolLoopHarness(config)(firstResult.session, { - inputResponses: [{ requestId: "approval-1", optionId: "deny" }], + inputResponses: [{ requestId: "approval-1", optionId: "cancel" }], }); expect(typeof deniedResult.next).toBe("function"); const step2Last = generateCalls[0]?.at(-1); diff --git a/packages/eve/src/public/channels/chat-sdk/chatSdkChannel.test.ts b/packages/eve/src/public/channels/chat-sdk/chatSdkChannel.test.ts index 8fde03791..028142f9e 100644 --- a/packages/eve/src/public/channels/chat-sdk/chatSdkChannel.test.ts +++ b/packages/eve/src/public/channels/chat-sdk/chatSdkChannel.test.ts @@ -507,7 +507,7 @@ describe("chatSdkChannel", () => { display: "confirmation", options: [ { id: "approve", label: "Approve", style: "primary" }, - { id: "deny", label: "Deny", style: "danger" }, + { id: "cancel", label: "Cancel", style: "danger" }, ], prompt: "Deploy?", requestId: "request-1", @@ -534,11 +534,11 @@ describe("chatSdkChannel", () => { value: "approve", }, { - id: "eve_input:request-1:deny", - label: "Deny", + id: "eve_input:request-1:cancel", + label: "Cancel", style: "danger", type: "button", - value: "deny", + value: "cancel", }, ], type: "actions", diff --git a/packages/eve/src/public/channels/discord/hitl.test.ts b/packages/eve/src/public/channels/discord/hitl.test.ts index aa63b35e3..4a9ed7d42 100644 --- a/packages/eve/src/public/channels/discord/hitl.test.ts +++ b/packages/eve/src/public/channels/discord/hitl.test.ts @@ -42,7 +42,7 @@ describe("renderInputRequestComponents", () => { display: "confirmation", options: [ { id: "approve", label: "Approve", style: "primary" }, - { id: "deny", label: "Deny", style: "danger" }, + { id: "cancel", label: "Cancel", style: "danger" }, ], }), ); diff --git a/packages/eve/src/public/channels/eve.test.ts b/packages/eve/src/public/channels/eve.test.ts index 909fcf753..9beffca28 100644 --- a/packages/eve/src/public/channels/eve.test.ts +++ b/packages/eve/src/public/channels/eve.test.ts @@ -642,7 +642,7 @@ describe("eveChannel — onMessage", () => { const response = await handler.fetch( createJsonMessageRequest({ continuationToken: "http:existing", - inputResponses: [{ requestId: "req-1", optionId: "deny" }], + inputResponses: [{ requestId: "req-1", optionId: "cancel" }], }), ); @@ -1284,7 +1284,7 @@ describe("eveChannel — continue session HITL (inputResponses)", () => { const response = await handler.fetch( createJsonMessageRequest({ continuationToken: "http:existing", - inputResponses: [{ requestId: "req-1", optionId: "deny" }], + inputResponses: [{ requestId: "req-1", optionId: "cancel" }], }), ); @@ -1292,7 +1292,7 @@ describe("eveChannel — continue session HITL (inputResponses)", () => { expect(handler.send).toHaveBeenCalledTimes(1); const payload = handler.send.mock.calls[0]?.[0] as SendPayload; expect(payload.message).toBeUndefined(); - expect(payload.inputResponses).toEqual([{ requestId: "req-1", optionId: "deny" }]); + expect(payload.inputResponses).toEqual([{ requestId: "req-1", optionId: "cancel" }]); }); }); diff --git a/packages/eve/src/public/channels/linear/hitl.test.ts b/packages/eve/src/public/channels/linear/hitl.test.ts index bf9e12e89..b645e0693 100644 --- a/packages/eve/src/public/channels/linear/hitl.test.ts +++ b/packages/eve/src/public/channels/linear/hitl.test.ts @@ -21,14 +21,14 @@ describe("Linear HITL helpers", () => { makeRequest({ options: [ { id: "approve", label: "Approve" }, - { id: "deny", label: "Deny", description: "Stop the deployment" }, + { id: "cancel", label: "Cancel", description: "Stop the deployment" }, ], }), ]); expect(rendered).toContain("Approve deployment?"); expect(rendered).toContain("1. Approve"); - expect(rendered).toContain("2. Deny - Stop the deployment"); + expect(rendered).toContain("2. Cancel - Stop the deployment"); expect(rendered).not.toContain("eve-input"); expect(rendered).not.toContain("