

























@@ -17,6 +17,7 @@ import {
1717} from "../acp/control-plane/spawn.js";
1818import { isAcpEnabledByPolicy, resolveAcpAgentPolicyError } from "../acp/policy.js";
1919import { DEFAULT_HEARTBEAT_EVERY } from "../auto-reply/heartbeat.js";
20+import { formatThinkingLevels } from "../auto-reply/thinking.js";
2021import {
2122resolveChannelDefaultBindingPlacement,
2223resolveInboundConversationResolution,
@@ -82,6 +83,10 @@ import {
8283inheritedToolDenyPatch,
8384} from "./inherited-tool-deny.js";
8485import { AGENT_LANE_SUBAGENT } from "./lanes.js";
86+import {
87+resolveConfiguredSubagentSpawnModelSelection,
88+resolveThinkingDefault,
89+} from "./model-selection.js";
8590import { resolveSandboxRuntimeStatus } from "./sandbox/runtime-status.js";
8691import { resolveRequesterOriginForChild } from "./spawn-requester-origin.js";
8792import { resolveSpawnedWorkspaceInheritance } from "./spawned-context.js";
@@ -93,6 +98,8 @@ import {
9398} from "./subagent-capabilities.js";
9499import { getSubagentDepthFromSessionStore } from "./subagent-depth.js";
95100import { countActiveRunsForSession, getSubagentRunByChildSessionKey } from "./subagent-registry.js";
101+import { splitModelRef } from "./subagent-spawn-plan.js";
102+import { resolveSubagentThinkingOverride } from "./subagent-spawn-thinking.js";
96103import { resolveSubagentTargetPolicy } from "./subagent-target-policy.js";
97104import { resolveInternalSessionKey, resolveMainSessionAlias } from "./tools/sessions-helpers.js";
98105@@ -437,7 +444,7 @@ function hasSessionLocalHeartbeatRelayRoute(params: {
437444function resolveTargetAcpAgentId(params: {
438445requestedAgentId?: string;
439446cfg: OpenClawConfig;
440-}): { ok: true; agentId: string } | { ok: false; error: string } {
447+}): { ok: true; agentId: string; configAgentId?: string } | { ok: false; error: string } {
441448const requested = normalizeOptionalAgentId(params.requestedAgentId);
442449if (requested) {
443450const configuredAgent = params.cfg.agents?.list?.find(
@@ -447,6 +454,7 @@ function resolveTargetAcpAgentId(params: {
447454return {
448455ok: true,
449456agentId: normalizeOptionalAgentId(configuredAgent.runtime.acp?.agent) ?? requested,
457+configAgentId: requested,
450458};
451459}
452460if (configuredAgent && !isExplicitlyAllowedAcpAgent(params.cfg, requested)) {
@@ -458,7 +466,11 @@ function resolveTargetAcpAgentId(params: {
458466'Use runtime="acp" only with external ACP harness ids such as codex, claude, droid, gemini, or opencode, or configure agents.list[].runtime.type="acp" with runtime.acp.agent.',
459467};
460468}
461-return { ok: true, agentId: requested };
469+return {
470+ok: true,
471+agentId: requested,
472+ ...(configuredAgent ? { configAgentId: requested } : {}),
473+};
462474}
463475464476const configuredDefault = normalizeOptionalAgentId(params.cfg.acp?.defaultAgent);
@@ -975,15 +987,71 @@ function validateAcpResumeSessionOwnership(params: {
975987};
976988}
977989990+type AcpSpawnRuntimeOptions = {
991+model?: string;
992+thinking?: string;
993+timeoutSeconds?: number;
994+};
995+996+function resolveAcpSpawnRuntimeOptions(params: {
997+cfg: OpenClawConfig;
998+targetAgentId: string;
999+configAgentId?: string;
1000+model?: string;
1001+thinking?: string;
1002+runTimeoutSeconds?: number;
1003+}): { ok: true; runtimeOptions?: AcpSpawnRuntimeOptions } | { ok: false; error: string } {
1004+const policyAgentId = params.configAgentId ?? params.targetAgentId;
1005+const model = resolveConfiguredSubagentSpawnModelSelection({
1006+cfg: params.cfg,
1007+agentId: policyAgentId,
1008+modelOverride: params.model,
1009+includeAgentPrimary: false,
1010+});
1011+const targetAgentConfig = resolveAgentConfig(params.cfg, policyAgentId);
1012+const thinkingPlan = resolveSubagentThinkingOverride({
1013+cfg: params.cfg,
1014+ targetAgentConfig,
1015+thinkingOverrideRaw: params.thinking,
1016+});
1017+if (thinkingPlan.status === "error") {
1018+const { provider, model: modelId } = splitModelRef(model);
1019+return {
1020+ok: false,
1021+error: `Invalid thinking level "${thinkingPlan.thinkingCandidateRaw}". Use one of: ${formatThinkingLevels(provider, modelId)}.`,
1022+};
1023+}
1024+1025+let thinking = thinkingPlan.thinkingOverride;
1026+if (!thinking && model) {
1027+const { provider, model: modelId } = splitModelRef(model);
1028+if (provider && modelId) {
1029+thinking = resolveThinkingDefault({
1030+cfg: params.cfg,
1031+ provider,
1032+model: modelId,
1033+});
1034+}
1035+}
1036+1037+const runtimeOptions =
1038+model || thinking || params.runTimeoutSeconds
1039+ ? {
1040+ ...(model ? { model } : {}),
1041+ ...(thinking ? { thinking } : {}),
1042+ ...(params.runTimeoutSeconds ? { timeoutSeconds: params.runTimeoutSeconds } : {}),
1043+}
1044+ : undefined;
1045+return { ok: true, runtimeOptions };
1046+}
1047+9781048async function initializeAcpSpawnRuntime(params: {
9791049cfg: OpenClawConfig;
9801050sessionKey: string;
9811051targetAgentId: string;
9821052runtimeMode: AcpRuntimeSessionMode;
9831053resumeSessionId?: string;
984-model?: string;
985-thinking?: string;
986-runTimeoutSeconds?: number;
1054+runtimeOptions?: AcpSpawnRuntimeOptions;
9871055cwd?: string;
9881056}): Promise<AcpSpawnInitializedRuntime> {
9891057const storePath = resolveStorePath(params.cfg.session?.store, { agentId: params.targetAgentId });
@@ -1008,14 +1076,7 @@ async function initializeAcpSpawnRuntime(params: {
10081076agent: params.targetAgentId,
10091077mode: params.runtimeMode,
10101078resumeSessionId: params.resumeSessionId,
1011-runtimeOptions:
1012-params.model || params.thinking || params.runTimeoutSeconds
1013- ? {
1014- ...(params.model ? { model: params.model } : {}),
1015- ...(params.thinking ? { thinking: params.thinking } : {}),
1016- ...(params.runTimeoutSeconds ? { timeoutSeconds: params.runTimeoutSeconds } : {}),
1017-}
1018- : undefined,
1079+runtimeOptions: params.runtimeOptions,
10191080cwd: params.cwd,
10201081backendId: params.cfg.acp?.backend,
10211082});
@@ -1320,6 +1381,21 @@ export async function spawnAcpDirect(
13201381error: resumeAuthorization.error,
13211382});
13221383}
1384+const runtimeOptionsResult = resolveAcpSpawnRuntimeOptions({
1385+ cfg,
1386+ targetAgentId,
1387+configAgentId: targetAgentResult.configAgentId,
1388+model: params.model,
1389+thinking: params.thinking,
1390+runTimeoutSeconds: params.runTimeoutSeconds,
1391+});
1392+if (!runtimeOptionsResult.ok) {
1393+return createAcpSpawnFailure({
1394+status: "error",
1395+errorCode: "spawn_failed",
1396+error: runtimeOptionsResult.error,
1397+});
1398+}
13231399const { effectiveStreamToParent } = resolveAcpSpawnStreamPlan({
13241400 spawnMode,
13251401 requestThreadBinding,
@@ -1392,9 +1468,7 @@ export async function spawnAcpDirect(
13921468 targetAgentId,
13931469 runtimeMode,
13941470resumeSessionId: params.resumeSessionId,
1395-model: params.model,
1396-thinking: params.thinking,
1397-runTimeoutSeconds: params.runTimeoutSeconds,
1471+runtimeOptions: runtimeOptionsResult.runtimeOptions,
13981472cwd: runtimeCwd,
13991473});
14001474initializedRuntime = initializedSession.runtimeCloseHandle;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。