Просмотр исходного кода

Merge pull request #1022 from zjm54321/fix/agent-model-array-variant

fix: preserve primary model variant for subagents
Alvin 3 недель назад
Родитель
Сommit
c42f90ea01
2 измененных файлов с 57 добавлено и 2 удалено
  1. 43 0
      src/agents/index.test.ts
  2. 14 2
      src/agents/index.ts

+ 43 - 0
src/agents/index.test.ts

@@ -269,6 +269,31 @@ describe('orchestrator agent', () => {
 });
 
 describe('per-model variant in array config', () => {
+  test('generic subagents propagate primary inline variants to SDK configs', () => {
+    const config: PluginConfig = {
+      agents: {
+        explorer: {
+          model: [
+            { id: 'google/gemini-3-flash', variant: 'low' },
+            'openai/gpt-4o-mini',
+          ],
+        },
+        librarian: {
+          model: [
+            { id: 'anthropic/claude-haiku-4-5', variant: 'fast' },
+            'openai/gpt-4o-mini',
+          ],
+        },
+      },
+    };
+    const configs = getAgentConfigs(runtimeFor(config));
+
+    expect(configs.explorer.model).toBe('google/gemini-3-flash');
+    expect(configs.explorer.variant).toBe('low');
+    expect(configs.librarian.model).toBe('anthropic/claude-haiku-4-5');
+    expect(configs.librarian.variant).toBe('fast');
+  });
+
   test('subagent stores model array with per-model variants', () => {
     const config: PluginConfig = {
       agents: {
@@ -289,6 +314,24 @@ describe('per-model variant in array config', () => {
     expect(explorer?.config.model).toBe('google/gemini-3-flash');
   });
 
+  test('explicit agent-level variant overrides the primary inline variant', () => {
+    const configs = getAgentConfigs(
+      runtimeFor({
+        agents: {
+          librarian: {
+            model: [
+              { id: 'anthropic/claude-haiku-4-5', variant: 'fast' },
+              'openai/gpt-4o-mini',
+            ],
+            variant: 'high',
+          },
+        },
+      }),
+    );
+
+    expect(configs.librarian.variant).toBe('high');
+  });
+
   test('top-level variant preserved alongside per-model variants', () => {
     const config: PluginConfig = {
       agents: {

+ 14 - 2
src/agents/index.ts

@@ -132,7 +132,8 @@ function isSafeDisplayName(displayName: string): boolean {
  * Apply user-provided overrides to an agent's configuration.
  * Supports overriding model (string or priority array), variant, and temperature.
  * When model is an array, stores it as _modelArray for runtime fallback resolution
- * and clears config.model so OpenCode does not pre-resolve a stale value.
+ * and selects its primary entry for ephemeral subagents. The orchestrator leaves
+ * config.model unset so its live runtime selection is not overwritten.
  */
 function applyOverrides(
   agent: AgentDefinition,
@@ -143,6 +144,7 @@ function applyOverrides(
       agent._modelArray = override.model.map((m) =>
         typeof m === 'string' ? { id: m } : m,
       );
+      const primaryModel = agent._modelArray[0];
       // Subagents are ephemeral, freshly-created sessions with no prior
       // runtime state to preserve, so giving them a concrete config.model
       // at launch time (the array's primary entry) is safe — see #9100e59.
@@ -160,7 +162,17 @@ function applyOverrides(
       // added by #639). Leaving it undefined for the orchestrator lets
       // that later, precedence-aware guard be the sole source of truth.
       agent.config.model =
-        agent.name === 'orchestrator' ? undefined : agent._modelArray[0].id;
+        agent.name === 'orchestrator' ? undefined : primaryModel.id;
+      // Subagents launch with the primary model, so carry its inline variant
+      // into the OpenCode config too. An explicit agent-level variant below
+      // intentionally takes precedence.
+      if (
+        agent.name !== 'orchestrator' &&
+        override.variant === undefined &&
+        primaryModel.variant !== undefined
+      ) {
+        agent.config.variant = primaryModel.variant;
+      }
     } else {
       agent.config.model = override.model;
     }