feat(plan): support plan mode in non-interactive mode (#22670)

This commit is contained in:
ruomeng
2026-03-18 16:00:26 -04:00
committed by GitHub
parent c12fc340c1
commit 1725ec346b
13 changed files with 343 additions and 40 deletions
+35 -1
View File
@@ -47,6 +47,7 @@ describe('ExitPlanModeTool', () => {
storage: {
getPlansDir: vi.fn().mockReturnValue(mockPlansDir),
} as unknown as Config['storage'],
isInteractive: vi.fn().mockReturnValue(true),
};
tool = new ExitPlanModeTool(
mockConfig as Config,
@@ -359,6 +360,36 @@ Ask the user for specific feedback on how to improve the plan.`,
});
});
describe('getAllowApprovalMode (internal)', () => {
it('should return YOLO when config.isInteractive() is false', async () => {
mockConfig.isInteractive = vi.fn().mockReturnValue(false);
const planRelativePath = createPlanFile('test.md', '# Content');
const invocation = tool.build({ plan_path: planRelativePath });
// Directly call execute to trigger the internal getAllowApprovalMode
const result = await invocation.execute(new AbortController().signal);
expect(result.llmContent).toContain('YOLO mode');
expect(mockConfig.setApprovalMode).toHaveBeenCalledWith(
ApprovalMode.YOLO,
);
});
it('should return DEFAULT when config.isInteractive() is true', async () => {
mockConfig.isInteractive = vi.fn().mockReturnValue(true);
const planRelativePath = createPlanFile('test.md', '# Content');
const invocation = tool.build({ plan_path: planRelativePath });
// Directly call execute to trigger the internal getAllowApprovalMode
const result = await invocation.execute(new AbortController().signal);
expect(result.llmContent).toContain('Default mode');
expect(mockConfig.setApprovalMode).toHaveBeenCalledWith(
ApprovalMode.DEFAULT,
);
});
});
describe('getApprovalModeDescription (internal)', () => {
it('should handle all valid approval modes', async () => {
const planRelativePath = createPlanFile('test.md', '# Content');
@@ -387,6 +418,10 @@ Ask the user for specific feedback on how to improve the plan.`,
ApprovalMode.DEFAULT,
'Default mode (edits will require confirmation)',
);
await testMode(
ApprovalMode.YOLO,
'YOLO mode (all tool calls auto-approved)',
);
});
it('should throw for invalid post-planning modes', async () => {
@@ -409,7 +444,6 @@ Ask the user for specific feedback on how to improve the plan.`,
).rejects.toThrow(/Unexpected approval mode/);
};
await testInvalidMode(ApprovalMode.YOLO);
await testInvalidMode(ApprovalMode.PLAN);
});
});