Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions packages/cli/src/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,30 @@ describe('loadCliConfig tool exclusions', () => {
expect(config.getExcludeTools()).toContain('ask_user');
});

it('should exclude ask_user in interactive mode when --acp is provided', async () => {
process.stdin.isTTY = true;
process.argv = ['node', 'script.js', '--acp'];
const argv = await parseArguments(createTestMergedSettings());
const config = await loadCliConfig(
createTestMergedSettings(),
'test-session',
argv,
);
expect(config.getExcludeTools()).toContain('ask_user');
});

it('should exclude ask_user in interactive mode when --experimental-acp is provided', async () => {
process.stdin.isTTY = true;
process.argv = ['node', 'script.js', '--experimental-acp'];
const argv = await parseArguments(createTestMergedSettings());
const config = await loadCliConfig(
createTestMergedSettings(),
'test-session',
argv,
);
expect(config.getExcludeTools()).toContain('ask_user');
});

it('should not exclude shell tool in non-interactive mode when --allowed-tools="ShellTool" is set', async () => {
process.stdin.isTTY = false;
process.argv = [
Expand Down
7 changes: 5 additions & 2 deletions packages/cli/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -649,12 +649,16 @@ export async function loadCliConfig(

const allowedTools = argv.allowedTools || settings.tools?.allowed || [];

const isAcpMode = !!argv.acp || !!argv.experimentalAcp;

// In non-interactive mode, exclude tools that require a prompt.
const extraExcludes: string[] = [];
if (!interactive) {
if (!interactive || isAcpMode) {
// The Policy Engine natively handles headless safety by translating ASK_USER
// decisions to DENY. However, we explicitly block ask_user here to guarantee
// it can never be allowed via a high-priority policy rule when no human is present.
// We also exclude it in ACP mode as IDEs intercept tool calls and ask for permission,
// breaking conversational flows.
extraExcludes.push(ASK_USER_TOOL_NAME);
}

Expand Down Expand Up @@ -770,7 +774,6 @@ export async function loadCliConfig(
}
}

const isAcpMode = !!argv.acp || !!argv.experimentalAcp;
let clientName: string | undefined = undefined;
if (isAcpMode) {
const ide = detectIdeFromEnv();
Expand Down
Loading