fix(codex): honor yolo for MCP elicitation (#655)

Route Codex app-server MCP elicitation decisions through the live session permission mode. HAPI bridge elicitation remains accepted, non-HAPI elicitation stays cancelled in non-yolo modes, and yolo accepts future non-HAPI prompts after mode changes.\n\nAdds adapter and launcher seam tests covering default -> yolo -> default behavior.\n\nTests:\n- bunx vitest run src/codex/utils/appServerPermissionAdapter.test.ts src/codex/codexRemoteLauncher.test.ts\n- bun run typecheck
This commit is contained in:
CoColate
2026-05-21 17:09:10 +08:00
committed by GitHub
parent 8e3bba9303
commit 611c4eec49
4 changed files with 162 additions and 7 deletions
+55 -1
View File
@@ -836,6 +836,7 @@ function createSessionStub(messages = ['hello from launcher test'], mode = creat
const foundSessionIds: string[] = [];
const resetThreadCalls: string[] = [];
const collaborationModes: Array<EnhancedMode['collaborationMode'] | undefined> = [];
let currentPermissionMode: EnhancedMode['permissionMode'] = mode.permissionMode;
let currentModel: string | null | undefined = mode.model;
let currentCollaborationMode: EnhancedMode['collaborationMode'] | undefined = mode.collaborationMode;
let agentState: FakeAgentState = {
@@ -875,7 +876,7 @@ function createSessionStub(messages = ['hello from launcher test'], mode = creat
sessionId: null as string | null,
thinking: false,
getPermissionMode() {
return 'default' as const;
return currentPermissionMode;
},
setModel(nextModel: string | null) {
currentModel = nextModel;
@@ -922,6 +923,9 @@ function createSessionStub(messages = ['hello from launcher test'], mode = creat
foundSessionIds,
resetThreadCalls,
rpcHandlers,
setPermissionMode: (nextMode: EnhancedMode['permissionMode']) => {
currentPermissionMode = nextMode;
},
getModel: () => currentModel,
getCollaborationMode: () => currentCollaborationMode,
collaborationModes,
@@ -1021,6 +1025,56 @@ describe('codexRemoteLauncher', () => {
expect(session.thinking).toBe(false);
});
it('uses live permission mode for app-server MCP elicitation handlers', async () => {
const { session, setPermissionMode } = createSessionStub();
const exitReason = await codexRemoteLauncher(session as never);
expect(exitReason).toBe('exit');
const handler = harness.requestHandlers.get('mcpServer/elicitation/request');
expect(handler).toBeTypeOf('function');
const request = {
threadId: 'thread-1',
turnId: 'turn-1',
serverName: 'qmd',
mode: 'form',
message: 'Allow the qmd MCP server to run tool "status"?',
_meta: null,
requestedSchema: {
type: 'object',
properties: {
approval: {
type: 'string',
enum: ['allow', 'deny']
}
},
required: ['approval']
}
};
await expect(handler?.(request)).resolves.toEqual({
action: 'cancel',
content: null,
_meta: null
});
setPermissionMode('yolo');
await expect(handler?.(request)).resolves.toEqual({
action: 'accept',
content: {
approval: 'allow'
},
_meta: null
});
setPermissionMode('default');
await expect(handler?.(request)).resolves.toEqual({
action: 'cancel',
content: null,
_meta: null
});
});
it('sends Codex plan collaboration mode when the app-server advertises it', async () => {
const { session } = createSessionStub(['plan this'], {
permissionMode: 'default',