mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 15:31:27 +00:00
Merge pull request #2763 from QwenLM/fix/2754-allow-webfetch-in-plan-mode
fix: allow web fetch approvals in plan mode
This commit is contained in:
commit
311f971ba7
4 changed files with 170 additions and 37 deletions
|
|
@ -346,6 +346,71 @@ describe('Session', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('allows info confirmation tools in plan mode', async () => {
|
||||
const executeSpy = vi.fn().mockResolvedValue({
|
||||
llmContent: 'ok',
|
||||
returnDisplay: 'ok',
|
||||
});
|
||||
const onConfirmSpy = vi.fn().mockResolvedValue(undefined);
|
||||
const invocation = {
|
||||
params: {
|
||||
url: 'https://example.com/docs',
|
||||
prompt: 'Summarize the docs',
|
||||
},
|
||||
getDefaultPermission: vi.fn().mockResolvedValue('ask'),
|
||||
getConfirmationDetails: vi.fn().mockResolvedValue({
|
||||
type: 'info',
|
||||
title: 'Confirm Web Fetch',
|
||||
prompt: 'Allow fetching docs?',
|
||||
urls: ['https://example.com/docs'],
|
||||
onConfirm: onConfirmSpy,
|
||||
}),
|
||||
getDescription: vi.fn().mockReturnValue('Fetch docs'),
|
||||
toolLocations: vi.fn().mockReturnValue([]),
|
||||
execute: executeSpy,
|
||||
};
|
||||
const tool = {
|
||||
name: 'web_fetch',
|
||||
kind: core.Kind.Fetch,
|
||||
build: vi.fn().mockReturnValue(invocation),
|
||||
};
|
||||
|
||||
mockToolRegistry.getTool.mockReturnValue(tool);
|
||||
mockConfig.getApprovalMode = vi.fn().mockReturnValue(ApprovalMode.PLAN);
|
||||
mockConfig.getPermissionManager = vi.fn().mockReturnValue(null);
|
||||
mockChat.sendMessageStream = vi.fn().mockResolvedValue(
|
||||
(async function* () {
|
||||
yield {
|
||||
type: core.StreamEventType.CHUNK,
|
||||
value: {
|
||||
functionCalls: [
|
||||
{
|
||||
id: 'call-info-plan',
|
||||
name: 'web_fetch',
|
||||
args: {
|
||||
url: 'https://example.com/docs',
|
||||
prompt: 'Summarize the docs',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
})(),
|
||||
);
|
||||
|
||||
await session.prompt({
|
||||
sessionId: 'test-session-id',
|
||||
prompt: [{ type: 'text', text: 'research the docs first' }],
|
||||
});
|
||||
|
||||
expect(mockClient.requestPermission).toHaveBeenCalled();
|
||||
expect(onConfirmSpy).toHaveBeenCalledWith(
|
||||
core.ToolConfirmationOutcome.ProceedOnce,
|
||||
{ answers: undefined },
|
||||
);
|
||||
expect(executeSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns permission error for disabled tools (L1 isToolEnabled check)', async () => {
|
||||
const executeSpy = vi.fn();
|
||||
const invocation = {
|
||||
|
|
|
|||
|
|
@ -674,22 +674,6 @@ export class Session implements SessionContext {
|
|||
const approvalMode = this.config.getApprovalMode();
|
||||
const isPlanMode = approvalMode === ApprovalMode.PLAN;
|
||||
|
||||
// PLAN mode: block non-read-only tools
|
||||
if (
|
||||
isPlanMode &&
|
||||
!isExitPlanModeTool &&
|
||||
!isAskUserQuestionTool &&
|
||||
needsConfirmation
|
||||
) {
|
||||
return earlyErrorResponse(
|
||||
new Error(
|
||||
`Plan mode is active. The tool "${fc.name}" cannot be executed because it modifies the system. ` +
|
||||
'Please use the exit_plan_mode tool to present your plan and exit plan mode before making changes.',
|
||||
),
|
||||
fc.name,
|
||||
);
|
||||
}
|
||||
|
||||
if (finalPermission === 'deny') {
|
||||
return earlyErrorResponse(
|
||||
new Error(
|
||||
|
|
@ -702,14 +686,30 @@ export class Session implements SessionContext {
|
|||
}
|
||||
|
||||
let didRequestPermission = false;
|
||||
let confirmationDetails: ToolCallConfirmationDetails | undefined;
|
||||
|
||||
if (needsConfirmation) {
|
||||
const confirmationDetails =
|
||||
confirmationDetails =
|
||||
await invocation.getConfirmationDetails(abortSignal);
|
||||
|
||||
// Centralised rule injection (for display and persistence)
|
||||
injectPermissionRulesIfMissing(confirmationDetails, pmCtx);
|
||||
|
||||
if (
|
||||
isPlanMode &&
|
||||
!isExitPlanModeTool &&
|
||||
!isAskUserQuestionTool &&
|
||||
confirmationDetails.type !== 'info'
|
||||
) {
|
||||
return earlyErrorResponse(
|
||||
new Error(
|
||||
`Plan mode is active. The tool "${fc.name}" cannot be executed because it modifies the system. ` +
|
||||
'Please use the exit_plan_mode tool to present your plan and exit plan mode before making changes.',
|
||||
),
|
||||
fc.name,
|
||||
);
|
||||
}
|
||||
|
||||
const messageBus = this.config.getMessageBus?.();
|
||||
const hooksEnabled = !this.config.getDisableAllHooks?.();
|
||||
let hookHandled = false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue