fix(server): 支持按 prompt 动态切换 agent

- sessionHandle 添加 --agent spawn 参数和 setAgent() 控制请求
- prompt/prompt_async 路由提取 body.agent 并调用 setAgent
- print.ts 添加 set_agent 控制请求处理
- controlSchemas 添加 SDKControlSetAgentRequestSchema

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
costrict 2026-05-12 14:42:42 +08:00 committed by Askhz
parent c147cf7578
commit b6c353977d
4 changed files with 39 additions and 0 deletions

View File

@ -3097,6 +3097,13 @@ function runHeadlessStreaming(
notifySessionMetadataChanged({ model }) notifySessionMetadataChanged({ model })
injectModelSwitchBreadcrumbs(requestedModel, model) injectModelSwitchBreadcrumbs(requestedModel, model)
sendControlResponseSuccess(msg)
} else if (msg.request.subtype === 'set_agent') {
const agent = typeof msg.request.agent === 'string' ? msg.request.agent : undefined
if (agent) {
setMainThreadAgentType(agent)
saveAgentSetting(agent)
}
sendControlResponseSuccess(msg) sendControlResponseSuccess(msg)
} else if (msg.request.subtype === 'set_max_thinking_tokens') { } else if (msg.request.subtype === 'set_max_thinking_tokens') {
if (msg.request.max_thinking_tokens === null) { if (msg.request.max_thinking_tokens === null) {

View File

@ -143,6 +143,15 @@ export const SDKControlSetModelRequestSchema = lazySchema(() =>
.describe('Sets the model to use for subsequent conversation turns.'), .describe('Sets the model to use for subsequent conversation turns.'),
) )
export const SDKControlSetAgentRequestSchema = lazySchema(() =>
z
.object({
subtype: z.literal('set_agent'),
agent: z.string().optional(),
})
.describe('Sets the agent for subsequent conversation turns.'),
)
export const SDKControlSetMaxThinkingTokensRequestSchema = lazySchema(() => export const SDKControlSetMaxThinkingTokensRequestSchema = lazySchema(() =>
z z
.object({ .object({
@ -556,6 +565,7 @@ export const SDKControlRequestInnerSchema = lazySchema(() =>
SDKControlInitializeRequestSchema(), SDKControlInitializeRequestSchema(),
SDKControlSetPermissionModeRequestSchema(), SDKControlSetPermissionModeRequestSchema(),
SDKControlSetModelRequestSchema(), SDKControlSetModelRequestSchema(),
SDKControlSetAgentRequestSchema(),
SDKControlSetMaxThinkingTokensRequestSchema(), SDKControlSetMaxThinkingTokensRequestSchema(),
SDKControlMcpStatusRequestSchema(), SDKControlMcpStatusRequestSchema(),
SDKControlGetContextUsageRequestSchema(), SDKControlGetContextUsageRequestSchema(),

View File

@ -373,6 +373,7 @@ export function createSessionRoutes(
files?: string[] files?: string[]
images?: unknown[] images?: unknown[]
model?: { providerID?: string; modelID?: string } model?: { providerID?: string; modelID?: string }
agent?: string
}>() }>()
const textContent = body.content ?? body.parts const textContent = body.content ?? body.parts
@ -390,6 +391,10 @@ export function createSessionRoutes(
if (body.model?.modelID) { if (body.model?.modelID) {
try { await handle.setModel(body.model.modelID) } catch {} try { await handle.setModel(body.model.modelID) } catch {}
} }
const effectiveAgent = body.agent ?? (agentParts[0] as Record<string, unknown> | undefined)?.name as string | undefined
if (effectiveAgent && effectiveAgent !== handle.agent) {
try { await handle.setAgent(effectiveAgent) } catch {}
}
return ssePrompt(handle, id, content, c, body.parts) return ssePrompt(handle, id, content, c, body.parts)
}) })
@ -421,6 +426,7 @@ export function createSessionRoutes(
files?: string[] files?: string[]
images?: unknown[] images?: unknown[]
model?: { providerID?: string; modelID?: string } model?: { providerID?: string; modelID?: string }
agent?: string
}>() }>()
const textContent = body.content ?? body.parts const textContent = body.content ?? body.parts
@ -447,6 +453,10 @@ export function createSessionRoutes(
if (body.model?.modelID) { if (body.model?.modelID) {
try { await handle.setModel(body.model.modelID) } catch {} try { await handle.setModel(body.model.modelID) } catch {}
} }
const effectiveAgent = body.agent ?? (agentParts[0] as Record<string, unknown> | undefined)?.name as string | undefined
if (effectiveAgent && effectiveAgent !== handle.agent) {
try { await handle.setAgent(effectiveAgent) } catch {}
}
handle.prompt(content, { parts: body.parts }).catch(() => {}) handle.prompt(content, { parts: body.parts }).catch(() => {})
} catch {} } catch {}
})() })()

View File

@ -18,6 +18,7 @@ export type SessionHandleOptions = {
sessionId: string sessionId: string
cwd: string cwd: string
model?: string model?: string
agent?: string
permissionMode?: string permissionMode?: string
systemPrompt?: string systemPrompt?: string
resumeSessionId?: string resumeSessionId?: string
@ -39,6 +40,7 @@ export class SessionHandle {
private _status: SessionState = 'starting' private _status: SessionState = 'starting'
private _busyStatus: SessionBusyStatus = { type: 'idle' } private _busyStatus: SessionBusyStatus = { type: 'idle' }
private _model?: string private _model?: string
private _agent?: string
private _providerId?: string private _providerId?: string
private _permissionMode?: string private _permissionMode?: string
private _title?: string private _title?: string
@ -74,6 +76,9 @@ export class SessionHandle {
get model(): string | undefined { get model(): string | undefined {
return this._model return this._model
} }
get agent(): string | undefined {
return this._agent
}
get permissionMode(): string | undefined { get permissionMode(): string | undefined {
return this._permissionMode return this._permissionMode
} }
@ -147,6 +152,7 @@ export class SessionHandle {
this.cwd = opts.cwd this.cwd = opts.cwd
this.eventBus = opts.eventBus this.eventBus = opts.eventBus
this._model = opts.model this._model = opts.model
this._agent = opts.agent
this._permissionMode = opts.permissionMode ?? 'acceptEdits' this._permissionMode = opts.permissionMode ?? 'acceptEdits'
this.verbose = opts.verbose ?? false this.verbose = opts.verbose ?? false
} }
@ -165,6 +171,7 @@ export class SessionHandle {
'stream-json', 'stream-json',
...(this.opts.resumeSessionId ? [] : ['--session-id', this.sessionId]), ...(this.opts.resumeSessionId ? [] : ['--session-id', this.sessionId]),
...(this.opts.model ? ['--model', this.opts.model] : []), ...(this.opts.model ? ['--model', this.opts.model] : []),
...(this._agent ? ['--agent', this._agent] : []),
'--permission-mode', '--permission-mode',
this._permissionMode, this._permissionMode,
'--permission-prompt-tool', '--permission-prompt-tool',
@ -446,6 +453,11 @@ export class SessionHandle {
await this.sendControlRequest({ subtype: 'set_model', model }) await this.sendControlRequest({ subtype: 'set_model', model })
} }
async setAgent(agent: string): Promise<void> {
this._agent = agent
await this.sendControlRequest({ subtype: 'set_agent', agent })
}
async setPermissionMode(mode: string): Promise<void> { async setPermissionMode(mode: string): Promise<void> {
this._permissionMode = mode this._permissionMode = mode
await this.sendControlRequest({ subtype: 'set_permission_mode', mode }) await this.sendControlRequest({ subtype: 'set_permission_mode', mode })