Skip to content

Commit fe1c965

Browse files
fix: remove deleted api field availableDecisions
1 parent de2b2db commit fe1c965

3 files changed

Lines changed: 13 additions & 109 deletions

File tree

src/CodexApprovalHandler.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,7 @@ export class CodexApprovalHandler implements ApprovalHandler {
8787
private buildCommandDecisionOptions(
8888
params: CommandExecutionRequestApprovalParams
8989
): CommandDecisionOption[] {
90-
// Older app-server versions did not send availableDecisions; they only
91-
// sent proposed amendment fields. Reconstruct that older decision list
92-
// as a compatibility fallback.
93-
const decisions = params.availableDecisions ?? this.buildLegacyFallbackCommandDecisions(params);
90+
const decisions = this.buildCommandDecisions(params);
9491
let execAmendmentCount = 0;
9592
let networkAmendmentCount = 0;
9693

@@ -105,7 +102,7 @@ export class CodexApprovalHandler implements ApprovalHandler {
105102
});
106103
}
107104

108-
private buildLegacyFallbackCommandDecisions(
105+
private buildCommandDecisions(
109106
params: CommandExecutionRequestApprovalParams
110107
): CommandExecutionApprovalDecision[] {
111108
const decisions: CommandExecutionApprovalDecision[] = ["accept", "acceptForSession"];
@@ -218,9 +215,9 @@ export class CodexApprovalHandler implements ApprovalHandler {
218215
return `${decision}, and don't ask again for network access to \`${amendment.host}\``;
219216
}
220217

221-
// ACP responses only return the selected optionId. The legacy network field
222-
// is plural and availableDecisions is an array, so repeated amendments need
223-
// unique IDs while the common single-amendment ID stays stable.
218+
// ACP responses only return the selected optionId. The network field is
219+
// plural, so repeated amendments need unique IDs while the common
220+
// single-amendment ID stays stable.
224221
private indexedOptionId(optionId: ApprovalOptionId, index: number): ApprovalOptionId | string {
225222
return index === 0 ? optionId : `${optionId}:${index}`;
226223
}

src/__tests__/CodexACPAgent/approval-events.test.ts

Lines changed: 2 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -107,47 +107,7 @@ describe('Approval Events', () => {
107107
await promptPromise;
108108
});
109109

110-
it('should map available execpolicy amendment approval to Codex decision', async () => {
111-
const { promptPromise, completeTurn } = setupSessionWithPendingPrompt();
112-
const execpolicyAmendment = ['env', 'GRADLE_USER_HOME=/workspace/.gradle-home', './gradlew', 'build'];
113-
fixture.setPermissionResponse({
114-
outcome: { outcome: 'selected', optionId: 'allow_command_prefix_rule' }
115-
});
116-
117-
const params: CommandExecutionRequestApprovalParams = {
118-
threadId: sessionId,
119-
turnId: 'turn-1',
120-
itemId: 'item-prefix-rule',
121-
reason: 'Build the project',
122-
proposedExecpolicyAmendment: ['ignored-fallback'],
123-
availableDecisions: [
124-
'accept',
125-
{ acceptWithExecpolicyAmendment: { execpolicy_amendment: execpolicyAmendment } },
126-
'decline',
127-
],
128-
};
129-
130-
const response = await fixture.sendServerRequest(
131-
'item/commandExecution/requestApproval',
132-
params
133-
);
134-
135-
expect(response).toEqual({
136-
decision: {
137-
acceptWithExecpolicyAmendment: {
138-
execpolicy_amendment: execpolicyAmendment,
139-
},
140-
},
141-
});
142-
await expect(fixture.getAcpConnectionDump(['_meta'])).toMatchFileSnapshot(
143-
'data/approval-command-prefix-rule.json'
144-
);
145-
146-
completeTurn();
147-
await promptPromise;
148-
});
149-
150-
it('should add fallback execpolicy amendment option when availableDecisions is absent', async () => {
110+
it('should map execpolicy amendment approval to Codex decision', async () => {
151111
const { promptPromise, completeTurn } = setupSessionWithPendingPrompt();
152112
const execpolicyAmendment = ['npm', 'run'];
153113
fixture.setPermissionResponse({
@@ -179,34 +139,6 @@ describe('Approval Events', () => {
179139
await promptPromise;
180140
});
181141

182-
it('should respect availableDecisions when prefix-rule approval is omitted', async () => {
183-
const { promptPromise, completeTurn } = setupSessionWithPendingPrompt();
184-
fixture.setPermissionResponse({
185-
outcome: { outcome: 'selected', optionId: 'allow_once' }
186-
});
187-
188-
const params: CommandExecutionRequestApprovalParams = {
189-
threadId: sessionId,
190-
turnId: 'turn-1',
191-
itemId: 'item-no-prefix-rule',
192-
reason: 'Run exact command only',
193-
proposedExecpolicyAmendment: ['npm', 'run'],
194-
availableDecisions: ['accept', 'decline'],
195-
};
196-
197-
await fixture.sendServerRequest(
198-
'item/commandExecution/requestApproval',
199-
params
200-
);
201-
202-
await expect(fixture.getAcpConnectionDump(['_meta'])).toMatchFileSnapshot(
203-
'data/approval-command-available-decisions-without-prefix.json'
204-
);
205-
206-
completeTurn();
207-
await promptPromise;
208-
});
209-
210142
it('should map network policy amendment approval to Codex decision', async () => {
211143
const { promptPromise, completeTurn } = setupSessionWithPendingPrompt();
212144
const networkPolicyAmendment = { host: 'registry.npmjs.org', action: 'allow' } as const;
@@ -220,11 +152,7 @@ describe('Approval Events', () => {
220152
itemId: 'item-network-policy',
221153
reason: 'Allow network access',
222154
proposedExecpolicyAmendment: null,
223-
availableDecisions: [
224-
'accept',
225-
{ applyNetworkPolicyAmendment: { network_policy_amendment: networkPolicyAmendment } },
226-
'cancel',
227-
],
155+
proposedNetworkPolicyAmendments: [networkPolicyAmendment],
228156
};
229157

230158
const response = await fixture.sendServerRequest(
@@ -247,32 +175,6 @@ describe('Approval Events', () => {
247175
await promptPromise;
248176
});
249177

250-
it('should map explicit cancel option to cancel when advertised', async () => {
251-
const { promptPromise, completeTurn } = setupSessionWithPendingPrompt();
252-
fixture.setPermissionResponse({
253-
outcome: { outcome: 'selected', optionId: 'cancel' }
254-
});
255-
256-
const params: CommandExecutionRequestApprovalParams = {
257-
threadId: sessionId,
258-
turnId: 'turn-1',
259-
itemId: 'item-explicit-cancel',
260-
reason: 'Test command',
261-
proposedExecpolicyAmendment: null,
262-
availableDecisions: ['accept', 'cancel'],
263-
};
264-
265-
const response = await fixture.sendServerRequest(
266-
'item/commandExecution/requestApproval',
267-
params
268-
);
269-
270-
expect(response).toEqual({ decision: 'cancel' });
271-
272-
completeTurn();
273-
await promptPromise;
274-
});
275-
276178
it('should return cancel when no handler registered', async () => {
277179
const params: CommandExecutionRequestApprovalParams = {
278180
threadId: 'non-existent-session',

src/__tests__/CodexACPAgent/data/approval-command-network-policy.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@
2424
"name": "Yes, proceed",
2525
"kind": "allow_once"
2626
},
27+
{
28+
"optionId": "allow_for_session",
29+
"name": "Yes, and don't ask again for this exact command",
30+
"kind": "allow_always"
31+
},
2732
{
2833
"optionId": "apply_network_policy_amendment",
2934
"name": "Yes, and don't ask again for network access to `registry.npmjs.org`",
3035
"kind": "allow_always"
3136
},
3237
{
33-
"optionId": "cancel",
38+
"optionId": "reject_once",
3439
"name": "No, and tell Codex what to do differently",
3540
"kind": "reject_once"
3641
}

0 commit comments

Comments
 (0)