chenbhao commited on
Commit
6bb6a3c
·
1 Parent(s): 3d0fee2

fix: subagent can't created in opencode free model /login no apikey

Browse files
.gitignore CHANGED
@@ -1,4 +1,5 @@
1
  node_modules/
2
  dist/
3
  cli
 
4
  VersperClaw
 
1
  node_modules/
2
  dist/
3
  cli
4
+ .codex
5
  VersperClaw
src/utils/auth.ts CHANGED
@@ -307,7 +307,7 @@ export function getOpenRouterApiKeyWithSource(): {
307
  : { key: null, source: 'none' }
308
  }
309
 
310
- export function getConfiguredAuthProvider(): 'anthropic' | 'openrouter' | 'openai' | 'local' | null {
311
  // First try to get from cache for performance
312
  const storedProvider = getGlobalConfig().authProvider
313
  if (storedProvider) {
@@ -319,13 +319,13 @@ export function getConfiguredAuthProvider(): 'anthropic' | 'openrouter' | 'opena
319
  }
320
 
321
  // Read authProvider directly from file to bypass cache
322
- export function getConfiguredAuthProviderFromFile(): 'anthropic' | 'openrouter' | 'openai' | 'local' | null {
323
  try {
324
  // eslint-disable-next-line @typescript-eslint/no-require-imports
325
  const { readFileSync } = require('fs') as typeof import('fs')
326
  const raw = readFileSync(getGlobalClaudeFile(), 'utf8')
327
  const config = JSON.parse(raw) as {
328
- authProvider?: 'anthropic' | 'openrouter' | 'openai' | 'local'
329
  }
330
 
331
  if (config.authProvider) {
 
307
  : { key: null, source: 'none' }
308
  }
309
 
310
+ export function getConfiguredAuthProvider(): 'anthropic' | 'openrouter' | 'openai' | 'local' | 'opencode' | null {
311
  // First try to get from cache for performance
312
  const storedProvider = getGlobalConfig().authProvider
313
  if (storedProvider) {
 
319
  }
320
 
321
  // Read authProvider directly from file to bypass cache
322
+ export function getConfiguredAuthProviderFromFile(): 'anthropic' | 'openrouter' | 'openai' | 'local' | 'opencode' | null {
323
  try {
324
  // eslint-disable-next-line @typescript-eslint/no-require-imports
325
  const { readFileSync } = require('fs') as typeof import('fs')
326
  const raw = readFileSync(getGlobalClaudeFile(), 'utf8')
327
  const config = JSON.parse(raw) as {
328
+ authProvider?: 'anthropic' | 'openrouter' | 'openai' | 'local' | 'opencode'
329
  }
330
 
331
  if (config.authProvider) {
src/utils/model/agent.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
  parseUserSpecifiedModel,
9
  } from './model.js'
10
  import { getAPIProvider } from './providers.js'
 
11
 
12
  export const AGENT_MODEL_OPTIONS = [...MODEL_ALIASES, 'inherit'] as const
13
  export type AgentModelAlias = (typeof AGENT_MODEL_OPTIONS)[number]
@@ -48,6 +49,14 @@ export function getAgentModel(
48
  // This ensures subagents use the same cross-region inference profile (e.g., "eu.", "us.")
49
  // as the parent, which is required when IAM permissions only allow specific regions.
50
  const parentRegionPrefix = getBedrockRegionPrefix(parentModel)
 
 
 
 
 
 
 
 
51
 
52
  // Helper to apply parent region prefix for Bedrock models.
53
  // `originalSpec` is the raw model string before resolution (alias or full ID).
@@ -59,15 +68,31 @@ export function getAgentModel(
59
  resolvedModel: string,
60
  originalSpec: string,
61
  ): string => {
62
- if (parentRegionPrefix && getAPIProvider() === 'bedrock') {
63
  if (getBedrockRegionPrefix(originalSpec)) return resolvedModel
64
  return applyBedrockRegionPrefix(resolvedModel, parentRegionPrefix)
65
  }
66
  return resolvedModel
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  // Prioritize tool-specified model if provided
70
  if (toolSpecifiedModel) {
 
 
 
71
  if (aliasMatchesParentTier(toolSpecifiedModel, parentModel)) {
72
  return parentModel
73
  }
@@ -87,6 +112,10 @@ export function getAgentModel(
87
  })
88
  }
89
 
 
 
 
 
90
  if (aliasMatchesParentTier(agentModelWithExp, parentModel)) {
91
  return parentModel
92
  }
 
8
  parseUserSpecifiedModel,
9
  } from './model.js'
10
  import { getAPIProvider } from './providers.js'
11
+ import { getOpenCodeApiKey } from '../auth.js'
12
 
13
  export const AGENT_MODEL_OPTIONS = [...MODEL_ALIASES, 'inherit'] as const
14
  export type AgentModelAlias = (typeof AGENT_MODEL_OPTIONS)[number]
 
49
  // This ensures subagents use the same cross-region inference profile (e.g., "eu.", "us.")
50
  // as the parent, which is required when IAM permissions only allow specific regions.
51
  const parentRegionPrefix = getBedrockRegionPrefix(parentModel)
52
+ const provider = getAPIProvider()
53
+
54
+ // OpenCode free-mode sessions are known to be more reliable when subagents
55
+ // stay on the parent's already-working model instead of switching to alias-
56
+ // derived variants like haiku -> gpt-5-nano. If the user has configured an
57
+ // OpenCode API key, keep honoring explicit alias-based model selection.
58
+ const shouldInheritParentForKeylessOpenCode =
59
+ provider === 'opencode' && !getOpenCodeApiKey()
60
 
61
  // Helper to apply parent region prefix for Bedrock models.
62
  // `originalSpec` is the raw model string before resolution (alias or full ID).
 
68
  resolvedModel: string,
69
  originalSpec: string,
70
  ): string => {
71
+ if (parentRegionPrefix && provider === 'bedrock') {
72
  if (getBedrockRegionPrefix(originalSpec)) return resolvedModel
73
  return applyBedrockRegionPrefix(resolvedModel, parentRegionPrefix)
74
  }
75
  return resolvedModel
76
  }
77
 
78
+ const shouldStickToParentModel = (spec: string): boolean => {
79
+ if (!shouldInheritParentForKeylessOpenCode) {
80
+ return false
81
+ }
82
+ const normalized = spec.toLowerCase()
83
+ return (
84
+ normalized === 'haiku' ||
85
+ normalized === 'sonnet' ||
86
+ normalized === 'opus' ||
87
+ normalized === 'best'
88
+ )
89
+ }
90
+
91
  // Prioritize tool-specified model if provided
92
  if (toolSpecifiedModel) {
93
+ if (shouldStickToParentModel(toolSpecifiedModel)) {
94
+ return parentModel
95
+ }
96
  if (aliasMatchesParentTier(toolSpecifiedModel, parentModel)) {
97
  return parentModel
98
  }
 
112
  })
113
  }
114
 
115
+ if (shouldStickToParentModel(agentModelWithExp)) {
116
+ return parentModel
117
+ }
118
+
119
  if (aliasMatchesParentTier(agentModelWithExp, parentModel)) {
120
  return parentModel
121
  }
src/utils/swarm/spawnUtils.ts CHANGED
@@ -94,6 +94,10 @@ export function buildInheritedCliFlags(options?: {
94
  * parent's env, so we forward any that are set in the current process.
95
  */
96
  const TEAMMATE_ENV_VARS = [
 
 
 
 
97
  // API provider selection — without these, teammates default to firstParty
98
  // and send requests to the wrong endpoint (GitHub issue #23561)
99
  'CLAUDE_CODE_USE_BEDROCK',
@@ -121,6 +125,15 @@ const TEAMMATE_ENV_VARS = [
121
  'http_proxy',
122
  'NO_PROXY',
123
  'no_proxy',
 
 
 
 
 
 
 
 
 
124
  'SSL_CERT_FILE',
125
  'NODE_EXTRA_CA_CERTS',
126
  'REQUESTS_CA_BUNDLE',
 
94
  * parent's env, so we forward any that are set in the current process.
95
  */
96
  const TEAMMATE_ENV_VARS = [
97
+ // Explicit provider override — without these, spawned teammates can fall
98
+ // back to firstParty even when the leader is pinned to OpenCode/OpenAI/etc.
99
+ 'BETTER_CLAWD_API_PROVIDER',
100
+ 'CLAUDE_CODE_API_PROVIDER',
101
  // API provider selection — without these, teammates default to firstParty
102
  // and send requests to the wrong endpoint (GitHub issue #23561)
103
  'CLAUDE_CODE_USE_BEDROCK',
 
125
  'http_proxy',
126
  'NO_PROXY',
127
  'no_proxy',
128
+ // Third-party provider endpoints / auth overrides that may be configured
129
+ // only in the parent shell environment.
130
+ 'OPENAI_API_KEY',
131
+ 'OPENAI_ACCESS_TOKEN',
132
+ 'CODEX_ACCESS_TOKEN',
133
+ 'OPENROUTER_API_KEY',
134
+ 'OPENAI_BASE_URL',
135
+ 'OPENROUTER_BASE_URL',
136
+ 'OPENCODE_BASE_URL',
137
  'SSL_CERT_FILE',
138
  'NODE_EXTRA_CA_CERTS',
139
  'REQUESTS_CA_BUNDLE',