fix(acp): add session/set_config_option method for mode and model configuration

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
mingholy.lmh 2026-03-03 17:15:40 +08:00
parent 407a66c959
commit 33d65af79b
4 changed files with 279 additions and 50 deletions

View file

@ -81,6 +81,14 @@ export class AgentSideConnection implements Client {
const validatedParams = schema.setModelRequestSchema.parse(params);
return agent.setModel(validatedParams);
}
case schema.AGENT_METHODS.session_set_config_option: {
if (!agent.setConfigOption) {
throw RequestError.methodNotFound();
}
const validatedParams =
schema.setConfigOptionRequestSchema.parse(params);
return agent.setConfigOption(validatedParams);
}
default:
throw RequestError.methodNotFound(method);
}
@ -489,4 +497,7 @@ export interface Agent {
cancel(params: schema.CancelNotification): Promise<void>;
setMode?(params: schema.SetModeRequest): Promise<schema.SetModeResponse>;
setModel?(params: schema.SetModelRequest): Promise<schema.SetModelResponse>;
setConfigOption?(
params: schema.SetConfigOptionRequest,
): Promise<schema.SetConfigOptionResponse>;
}

View file

@ -21,7 +21,7 @@ import {
type ConversationRecord,
type DeviceAuthorizationData,
} from '@qwen-code/qwen-code-core';
import type { ApprovalModeValue } from './schema.js';
import type { ApprovalModeValue, ConfigOption } from './schema.js';
import * as acp from './acp.js';
import { buildAuthMethods } from './authMethods.js';
import { AcpFileSystemService } from './service/filesystem.js';
@ -295,6 +295,104 @@ class GeminiAgent {
return await session.setModel(params);
}
async setConfigOption(
params: acp.SetConfigOptionRequest,
): Promise<acp.SetConfigOptionResponse> {
const { sessionId, configId, value } = params;
// Get the session's config
const session = this.sessions.get(sessionId);
if (!session) {
throw acp.RequestError.invalidParams(
`Session not found for id: ${sessionId}`,
);
}
switch (configId) {
case 'mode': {
await this.setMode({
sessionId,
modeId: value as ApprovalModeValue,
});
break;
}
case 'model': {
await this.setModel({
sessionId,
modelId: value as string,
});
break;
}
default:
throw acp.RequestError.invalidParams(
`Unsupported configId: ${configId}`,
);
}
// Return all config options with current values
return {
configOptions: this.buildConfigOptions(session.getConfig()),
};
}
private buildConfigOptions(config: Config): ConfigOption[] {
const currentApprovalMode = config.getApprovalMode();
const allConfiguredModels = config.getAllConfiguredModels();
const rawCurrentModelId = (config.getModel() || '').trim();
const currentAuthType = config.getAuthType?.();
// Check if current model is a runtime model
const activeRuntimeSnapshot = config.getActiveRuntimeModelSnapshot?.();
const currentModelId = activeRuntimeSnapshot
? formatAcpModelId(
activeRuntimeSnapshot.id,
activeRuntimeSnapshot.authType,
)
: this.formatCurrentModelId(rawCurrentModelId, currentAuthType);
// Build mode config option
const modeOptions = APPROVAL_MODES.map((mode) => ({
value: mode,
name: APPROVAL_MODE_INFO[mode].name,
description: APPROVAL_MODE_INFO[mode].description,
}));
const modeConfigOption: ConfigOption = {
id: 'mode',
name: 'Mode',
description: 'Session permission mode',
category: 'mode',
type: 'select',
currentValue: currentApprovalMode,
options: modeOptions,
};
// Build model config option
const modelOptions = allConfiguredModels.map((model) => {
const effectiveModelId =
model.isRuntimeModel && model.runtimeSnapshotId
? model.runtimeSnapshotId
: model.id;
return {
value: formatAcpModelId(effectiveModelId, model.authType),
name: model.label,
description: model.description ?? '',
};
});
const modelConfigOption: ConfigOption = {
id: 'model',
name: 'Model',
description: 'AI model to use',
category: 'model',
type: 'select',
currentValue: currentModelId,
options: modelOptions,
};
return [modeConfigOption, modelConfigOption];
}
private async ensureAuthenticated(config: Config): Promise<void> {
const selectedType = config.getModelsConfig().getCurrentAuthType();
if (!selectedType) {
@ -478,55 +576,6 @@ class GeminiAgent {
};
}
private buildConfigOptions(config: Config): acp.ConfigOption[] {
const currentApprovalMode = config.getApprovalMode();
const currentModelId = this.formatCurrentModelId(
config.getModel() || this.config.getModel() || '',
config.getAuthType(),
);
const modeOptions = APPROVAL_MODES.map((mode) => ({
value: mode,
name: APPROVAL_MODE_INFO[mode].name,
description: APPROVAL_MODE_INFO[mode].description,
}));
const allConfiguredModels = config.getAllConfiguredModels();
const modelOptions = allConfiguredModels.map((model) => {
const effectiveModelId =
model.isRuntimeModel && model.runtimeSnapshotId
? model.runtimeSnapshotId
: model.id;
return {
value: formatAcpModelId(effectiveModelId, model.authType),
name: model.label,
description: model.description ?? '',
};
});
return [
{
id: 'mode',
name: 'Mode',
description: 'Session permission mode',
category: 'mode',
type: 'select',
currentValue: currentApprovalMode,
options: modeOptions,
},
{
id: 'model',
name: 'Model',
description: 'AI model to use',
category: 'model',
type: 'select',
currentValue: currentModelId,
options: modelOptions,
},
];
}
private formatCurrentModelId(
baseModelId: string,
authType?: AuthType,

View file

@ -16,6 +16,7 @@ export const AGENT_METHODS = {
session_list: 'session/list',
session_set_mode: 'session/set_mode',
session_set_model: 'session/set_model',
session_set_config_option: 'session/set_config_option',
};
export const CLIENT_METHODS = {
@ -475,6 +476,23 @@ export const configOptionSchema = z.object({
export type ConfigOption = z.infer<typeof configOptionSchema>;
export const setConfigOptionRequestSchema = z.object({
sessionId: z.string(),
configId: z.string(),
value: z.unknown(),
});
export const setConfigOptionResponseSchema = z.object({
configOptions: z.array(configOptionSchema),
});
export type SetConfigOptionRequest = z.infer<
typeof setConfigOptionRequestSchema
>;
export type SetConfigOptionResponse = z.infer<
typeof setConfigOptionResponseSchema
>;
// newSessionResponseSchema includes modes and configOptions for ACP/Zed integration
export const newSessionResponseSchema = z.object({
sessionId: z.string(),
@ -684,6 +702,7 @@ export const agentRequestSchema = z.union([
listSessionsRequestSchema,
setModeRequestSchema,
setModelRequestSchema,
setConfigOptionRequestSchema,
]);
export const agentNotificationSchema = sessionNotificationSchema;