feat(mcp): inherit target's unattended mode when caller is unattended cross-provider
create_agent previously threw on cross-provider inheritance unless an explicit mode was passed. In practice, sub-agents launched without a mode should run unattended — keying permissions per sub-agent rarely makes sense. When the caller is in an unattended mode (Claude bypassPermissions, Codex/OpenCode full-access, Copilot autopilot) and no mode is requested, default the child to the target provider's own unattended mode. Non-unattended callers still require an explicit cross-provider mode, and explicit modes always win.
This commit is contained in:
@@ -635,18 +635,33 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom
|
||||
setupContinuation: AgentWorktreeSetupContinuation | undefined;
|
||||
}
|
||||
|
||||
const getAvailableModeIds = (provider: AgentProvider): string[] | undefined => {
|
||||
const getProviderModes = (provider: AgentProvider) => {
|
||||
const fromRegistry = providerRegistry?.[provider];
|
||||
if (fromRegistry) {
|
||||
return fromRegistry.modes.map((mode) => mode.id);
|
||||
return fromRegistry.modes;
|
||||
}
|
||||
try {
|
||||
return getAgentProviderDefinition(provider).modes.map((mode) => mode.id);
|
||||
return getAgentProviderDefinition(provider).modes;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const getAvailableModeIds = (provider: AgentProvider): string[] | undefined => {
|
||||
return getProviderModes(provider)?.map((mode) => mode.id);
|
||||
};
|
||||
|
||||
const getUnattendedModeId = (provider: AgentProvider): string | undefined => {
|
||||
return getProviderModes(provider)?.find((mode) => mode.isUnattended)?.id;
|
||||
};
|
||||
|
||||
const isParentInUnattendedMode = (provider: AgentProvider, modeId: string | null): boolean => {
|
||||
if (modeId === null) return false;
|
||||
const modes = getProviderModes(provider);
|
||||
if (!modes) return false;
|
||||
return modes.some((mode) => mode.id === modeId && mode.isUnattended === true);
|
||||
};
|
||||
|
||||
const resolveCallerCreateAgentArgs = (
|
||||
args: unknown,
|
||||
parentAgentId: string,
|
||||
@@ -667,8 +682,13 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom
|
||||
const resolvedMode = resolveAndValidateCreateAgentMode({
|
||||
requestedMode: callerArgs.mode,
|
||||
targetProvider: provider,
|
||||
parent: { provider: parentAgent.provider, modeId: parentAgent.currentModeId },
|
||||
parent: {
|
||||
provider: parentAgent.provider,
|
||||
modeId: parentAgent.currentModeId,
|
||||
isUnattended: isParentInUnattendedMode(parentAgent.provider, parentAgent.currentModeId),
|
||||
},
|
||||
availableModes: getAvailableModeIds(provider),
|
||||
targetUnattendedMode: getUnattendedModeId(provider),
|
||||
});
|
||||
return {
|
||||
provider,
|
||||
@@ -696,6 +716,7 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom
|
||||
targetProvider: resolvedProviderModel.provider,
|
||||
parent: null,
|
||||
availableModes: getAvailableModeIds(resolvedProviderModel.provider),
|
||||
targetUnattendedMode: getUnattendedModeId(resolvedProviderModel.provider),
|
||||
});
|
||||
let resolvedCwd = expandUserPath(cwd);
|
||||
let setupContinuation: AgentWorktreeSetupContinuation | undefined;
|
||||
|
||||
Reference in New Issue
Block a user