Skip to content

feat(core): improve Anthropic proxy compatibility and enable global prompt cache scope#4020

Merged
pomelo-nwu merged 10 commits into
mainfrom
feat/anthropic-proxy-compat-and-cache-scope
May 11, 2026
Merged

feat(core): improve Anthropic proxy compatibility and enable global prompt cache scope#4020
pomelo-nwu merged 10 commits into
mainfrom
feat/anthropic-proxy-compat-and-cache-scope

Conversation

@wenshao

@wenshao wenshao commented May 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Improve compatibility with IdeaLab-style Anthropic-compatible proxies and enable cross-session prompt caching — while keeping the direct api.anthropic.com path on its existing behavior.

Proxy identity (non-Anthropic-native baseURLs only)

For baseURLs that are not *.anthropic.com:

  • Construct the SDK with authToken so requests carry Authorization: Bearer <key> instead of the SDK-default x-api-key. This avoids the dual-header conflict that IdeaLab-style proxies reject.
  • Send User-Agent: claude-cli/<version> (external, cli) and x-app: cli to satisfy proxy Team rules that gate by client identity.

For Anthropic-native baseURLs (api.anthropic.com / unset):

  • Keep the SDK-default apiKey / x-api-key auth (no Bearer flip → no 401 against the real Anthropic API).
  • Keep a truthful User-Agent: QwenCode/<version> (<platform>; <arch>), no x-app, so usage isn't misattributed in Anthropic's logs/quotas.

Adaptive thinking for Claude 4.6+

  • Send thinking: { type: 'adaptive' } for claude-(opus|sonnet|haiku)-<major>-<minor> where major > 4 || (major === 4 && minor >= 6). Numeric compare (not a [6-9] character class) so haiku, 4-10+, and a future 5-x aren't silently dropped onto the budget path and tripping HTTP 400.
  • Older 4.x models still use the existing { type: 'enabled', budget_tokens } ladder.
  • Explicit reasoning.budget_tokens is honored before the adaptive branch — adaptive omits the budget field entirely, so checking it second would silently discard the user-supplied escape-hatch budget on 4.6+ models.

Cross-session prompt caching

  • When enableCacheControl !== false, send anthropic-beta: prompt-caching-scope-2026-01-05 and attach cache_control: { type: 'ephemeral', scope: 'global' } on both the system text block and the last tool entry. Tools tend to be the largest, slowest-changing prefix, so cross-session reuse there is where most of the hit-rate improvement shows up.
  • Disabling enableCacheControl drops the beta header along with the body-side cache_control, so backends that don't recognize the flag don't 4xx — and the betas.length === 0 early-return stays meaningful.
  • Type widening: introduces AnthropicCacheControl / AnthropicTextBlockParam so scope: 'global' is part of the static type instead of a misleading as { type: 'ephemeral' } cast that erased it from the type while leaving it on the wire.

Test plan

  • claude-opus-4-7 through an IdeaLab-style proxy (no 401/400)
  • Direct api.anthropic.com request keeps x-api-key + QwenCode UA + no x-app
  • DeepSeek anthropic-compatible (api.deepseek.com/anthropic) unaffected — existing thinking-injection workaround still triggers; effort: 'max' still passes through unclamped
  • enableCacheControl: false does not ship the cache-scope beta; reasoning-only requests still send interleaved-thinking / effort betas
  • Adaptive thinking selected for opus-4-6 / sonnet-4-6 / opus-4-7 / haiku-4-6 / opus-4-10 / opus-5-1; budget path retained for opus-4-5
  • Explicit reasoning.budget_tokens overrides adaptive on 4.6+ models
  • packages/core test suite green (89 generator/converter tests, 7541 across the package)

@github-actions

github-actions Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 75.54% 75.54% 76.52% 80.25%
Core 77.66% 77.66% 80.42% 82.64%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   75.54 |    80.25 |   76.52 |   75.54 |                   
 src               |   73.64 |    67.35 |   76.47 |   73.64 |                   
  gemini.tsx       |   61.11 |    59.13 |   66.66 |   61.11 | ...18,835-838,846 
  ...ractiveCli.ts |   80.02 |    68.61 |   78.57 |   80.02 | ...1021,1059,1162 
  ...liCommands.ts |   76.17 |    73.33 |     100 |   76.17 | ...50-274,299,401 
  ...ActiveAuth.ts |     100 |     87.5 |     100 |     100 | 66-80             
 ...cp-integration |   53.94 |    66.66 |   58.82 |   53.94 |                   
  acpAgent.ts      |   56.25 |    67.01 |   65.51 |   56.25 | ...71-873,887-895 
  authMethods.ts   |   12.19 |      100 |       0 |   12.19 | 11-31,34-38,41-50 
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   68.65 |    83.33 |   66.66 |   68.65 |                   
  filesystem.ts    |   68.65 |    83.33 |   66.66 |   68.65 | ...32,77-94,97-98 
 ...ration/session |   76.02 |    70.59 |      84 |   76.02 |                   
  ...ryReplayer.ts |   65.93 |    75.67 |   81.81 |   65.93 | ...40-255,268-269 
  Session.ts       |   75.12 |    68.89 |    85.1 |   75.12 | ...2456,2462-2465 
  ...entTracker.ts |   90.85 |    84.84 |      90 |   90.85 | ...35,199,251-260 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   84.21 |    77.77 |     100 |   84.21 | ...37-153,209-211 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ssion/emitters |   96.01 |    90.75 |    92.3 |   96.01 |                   
  BaseEmitter.ts   |   76.92 |    66.66 |      80 |   76.92 | 23-24,39-40,55-56 
  ...ageEmitter.ts |     100 |    89.47 |     100 |     100 | 109,111           
  PlanEmitter.ts   |     100 |      100 |     100 |     100 |                   
  ...allEmitter.ts |   98.06 |     92.3 |     100 |   98.06 | 227-228,327,335   
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
 ...ession/rewrite |   89.69 |    85.89 |   94.11 |   89.69 |                   
  LlmRewriter.ts   |   80.53 |    79.31 |     100 |   80.53 | ...17-119,170-174 
  ...Middleware.ts |   95.83 |    85.71 |     100 |   95.83 | 119,127-129       
  TurnBuffer.ts    |     100 |      100 |     100 |     100 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/auth          |   97.68 |    94.85 |   95.45 |   97.68 |                   
  allProviders.ts  |     100 |      100 |     100 |     100 |                   
  ...iderConfig.ts |    97.6 |    95.04 |     100 |    97.6 | ...61,411,433-434 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 src/auth/install  |   98.57 |    88.88 |     100 |   98.57 |                   
  ...nstallPlan.ts |   98.57 |    88.88 |     100 |   98.57 | 80,93             
 ...viders/alibaba |   96.96 |    66.66 |   66.66 |   96.96 |                   
  ...baStandard.ts |     100 |      100 |     100 |     100 |                   
  codingPlan.ts    |   93.67 |    66.66 |   66.66 |   93.67 | 83,87-89,94       
  tokenPlan.ts     |     100 |      100 |     100 |     100 |                   
 ...oviders/custom |     100 |      100 |     100 |     100 |                   
  ...omProvider.ts |     100 |      100 |     100 |     100 |                   
 ...roviders/oauth |    91.5 |    77.03 |   97.05 |    91.5 |                   
  openrouter.ts    |   84.37 |    33.33 |     100 |   84.37 | 43-48             
  ...outerOAuth.ts |    91.9 |    79.06 |   96.87 |    91.9 | ...53-655,699-701 
 ...ers/thirdParty |     100 |      100 |     100 |     100 |                   
  deepseek.ts      |     100 |      100 |     100 |     100 |                   
  idealab.ts       |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  zai.ts           |     100 |      100 |     100 |     100 |                   
 src/commands      |   80.92 |    85.71 |      50 |   80.92 |                   
  auth.ts          |     100 |    83.33 |     100 |     100 | 11,14             
  channel.ts       |   56.66 |      100 |       0 |   56.66 | 15-19,27-34       
  extensions.tsx   |   96.55 |      100 |      50 |   96.55 | 37                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   94.73 |      100 |      50 |   94.73 | 28                
  review.ts        |   51.85 |      100 |       0 |   51.85 | 24-35,38          
 ...mmands/channel |   39.17 |    79.45 |      50 |   39.17 |                   
  ...l-registry.ts |    8.57 |      100 |       0 |    8.57 | 6-21,24-42        
  config-utils.ts  |   91.89 |      100 |   66.66 |   91.89 | 20-25             
  configure.ts     |    14.7 |      100 |       0 |    14.7 | 18-21,23-84       
  pairing.ts       |   26.31 |      100 |       0 |   26.31 | ...30,40-50,52-65 
  pidfile.ts       |   96.34 |    86.95 |     100 |   96.34 | 49,59,91          
  start.ts         |   30.98 |       52 |   69.23 |   30.98 | ...72-475,484-486 
  status.ts        |   17.85 |      100 |       0 |   17.85 | 15-26,32-76       
  stop.ts          |      20 |      100 |       0 |      20 | 14-48             
 ...nds/extensions |   84.53 |    88.95 |   81.81 |   84.53 |                   
  consent.ts       |   71.65 |    89.28 |   42.85 |   71.65 | ...85-141,156-162 
  disable.ts       |     100 |      100 |     100 |     100 |                   
  enable.ts        |     100 |      100 |     100 |     100 |                   
  install.ts       |    75.6 |    66.66 |   66.66 |    75.6 | ...39-142,145-153 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |      100 |     100 |     100 |                   
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  uninstall.ts     |    37.5 |      100 |   33.33 |    37.5 | 23-45,57-64,67-70 
  update.ts        |   96.32 |      100 |     100 |   96.32 | 101-105           
  utils.ts         |   60.24 |    28.57 |     100 |   60.24 | ...81,83-87,89-93 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 src/commands/mcp  |   92.29 |    86.08 |   88.88 |   92.29 |                   
  add.ts           |     100 |    98.03 |     100 |     100 | 293               
  list.ts          |   91.22 |    80.76 |      80 |   91.22 | ...19-121,146-147 
  reconnect.ts     |   76.72 |    71.42 |   85.71 |   76.72 | 35-48,153-175     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...ommands/review |   11.57 |      100 |       0 |   11.57 |                   
  cleanup.ts       |   17.94 |      100 |       0 |   17.94 | ...01-106,108-109 
  deterministic.ts |   13.75 |      100 |       0 |   13.75 | ...22-738,740-741 
  fetch-pr.ts      |   11.36 |      100 |       0 |   11.36 | ...80-201,203-204 
  load-rules.ts    |   11.32 |      100 |       0 |   11.32 | ...41-153,155-156 
  pr-context.ts    |    6.22 |      100 |       0 |    6.22 | ...97-312,314-315 
  presubmit.ts     |    9.35 |      100 |       0 |    9.35 | ...62-287,289-290 
 ...nds/review/lib |      30 |      100 |       0 |      30 |                   
  gh.ts            |   22.58 |      100 |       0 |   22.58 | ...49,53-54,62-69 
  git.ts           |   22.72 |      100 |       0 |   22.72 | 15-18,29-39,43-44 
  paths.ts         |   52.94 |      100 |       0 |   52.94 | ...26,37-38,42-43 
 src/config        |   92.67 |    85.18 |   85.71 |   92.67 |                   
  auth.ts          |   86.98 |    80.32 |     100 |   86.98 | ...26-227,243-244 
  config.ts        |   88.19 |     85.3 |      76 |   88.19 | ...1692,1716-1717 
  keyBindings.ts   |   96.11 |       50 |     100 |   96.11 | 169-172           
  ...idersScope.ts |      92 |       90 |     100 |      92 | 11-12             
  sandboxConfig.ts |    58.9 |    61.53 |   66.66 |    58.9 | ...54-68,73,77-89 
  settings.ts      |   85.51 |    87.19 |   86.48 |   85.51 | ...1148,1153-1156 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...tedFolders.ts |   96.22 |       94 |     100 |   96.22 | ...88-190,205-206 
 ...nfig/migration |   94.89 |    78.94 |   83.33 |   94.89 |                   
  index.ts         |   94.87 |    88.88 |     100 |   94.87 | 91-92             
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   94.74 |       96 |     100 |   94.74 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |    90.19 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
  v3-to-v4.ts      |     100 |      100 |     100 |     100 |                   
 src/core          |     100 |      100 |     100 |     100 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  initializer.ts   |     100 |      100 |     100 |     100 |                   
  theme.ts         |     100 |      100 |     100 |     100 |                   
 src/dualOutput    |   63.09 |    64.51 |   55.55 |   63.09 |                   
  ...tputBridge.ts |   62.94 |    65.51 |   56.25 |   62.94 | ...22-323,331-334 
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/export        |       0 |        0 |       0 |       0 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-7               
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   84.88 |    78.88 |   66.66 |   84.88 |                   
  index.ts         |   70.44 |       74 |   53.84 |   70.44 | ...71-272,282-287 
  languages.ts     |   95.33 |    86.48 |     100 |   95.33 | ...67,195-198,213 
  ...nslateKeys.ts |     100 |      100 |     100 |     100 |                   
  ...lationDict.ts |   93.33 |    66.66 |     100 |   93.33 | 15                
 src/i18n/locales  |     100 |      100 |     100 |     100 |                   
  ca.js            |     100 |      100 |     100 |     100 |                   
  de.js            |     100 |      100 |     100 |     100 |                   
  en.js            |     100 |      100 |     100 |     100 |                   
  fr.js            |     100 |      100 |     100 |     100 |                   
  ja.js            |     100 |      100 |     100 |     100 |                   
  pt.js            |     100 |      100 |     100 |     100 |                   
  ru.js            |     100 |      100 |     100 |     100 |                   
  zh-TW.js         |     100 |      100 |     100 |     100 |                   
  zh.js            |     100 |      100 |     100 |     100 |                   
 ...nonInteractive |   72.75 |    72.14 |   74.07 |   72.75 |                   
  session.ts       |   76.94 |    70.45 |   85.71 |   76.94 | ...80-781,790-800 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...80-581,584-585 
 ...active/control |   77.04 |    88.23 |      80 |   77.04 |                   
  ...rolContext.ts |    7.14 |        0 |       0 |    7.14 | 49-84             
  ...Dispatcher.ts |   91.66 |    91.83 |   88.88 |   91.66 | ...54-372,388,391 
  ...rolService.ts |       8 |        0 |       0 |       8 | 46-179            
 ...ol/controllers |    7.04 |       80 |   13.33 |    7.04 |                   
  ...Controller.ts |   19.32 |      100 |      60 |   19.32 | 81-118,127-210    
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |    3.96 |      100 |   11.11 |    3.96 | ...61-379,389-494 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |     5.2 |      100 |       0 |     5.2 | ...21-433,442-472 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   97.98 |    93.72 |   95.18 |   97.98 |                   
  ...putAdapter.ts |   97.89 |    92.82 |   98.07 |   97.89 | ...1303,1398-1399 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.28 |      100 |      90 |   98.28 | 81-82,122-123     
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/remoteInput   |   86.98 |       75 |   85.71 |   86.98 |                   
  ...utContext.tsx |     100 |      100 |     100 |     100 |                   
  ...putWatcher.ts |   88.12 |    76.08 |   91.66 |   88.12 | ...21-222,233-236 
  index.ts         |       0 |        0 |       0 |       0 | 1-8               
 src/services      |   92.84 |     90.9 |   98.36 |   92.84 |                   
  ...mandLoader.ts |     100 |     92.3 |     100 |     100 | 91                
  ...killLoader.ts |     100 |    96.15 |     100 |     100 | 45                
  ...andService.ts |   98.75 |      100 |     100 |   98.75 | 111               
  ...ionService.ts |   97.19 |    89.77 |     100 |   97.19 | ...84,422-423,427 
  ...mandLoader.ts |   86.83 |    83.87 |     100 |   86.83 | ...30-335,340-345 
  ...omptLoader.ts |   76.05 |    80.64 |   83.33 |   76.05 | ...12-213,279-280 
  ...mandLoader.ts |     100 |      100 |     100 |     100 |                   
  ...nd-factory.ts |    91.5 |    91.66 |     100 |    91.5 | 129,138-145       
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...ndMetadata.ts |   98.21 |    96.66 |     100 |   98.21 | 83,87             
  commandUtils.ts  |      96 |    91.66 |     100 |      96 | 48                
  ...and-parser.ts |   90.69 |    85.71 |     100 |   90.69 | 63-66             
  ...ionService.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   85.95 |    86.42 |   90.47 |   85.95 |                   
  DataProcessor.ts |   85.68 |    86.46 |   92.85 |   85.68 | ...1110,1114-1121 
  ...tGenerator.ts |   98.21 |    85.71 |     100 |   98.21 | 46                
  ...teRenderer.ts |   45.45 |      100 |       0 |   45.45 | 13-51             
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/services/tips |   97.35 |    83.07 |     100 |   97.35 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  tipHistory.ts    |   92.45 |       70 |     100 |   92.45 | ...22,144,151,160 
  tipRegistry.ts   |     100 |    95.23 |     100 |     100 | 33                
  tipScheduler.ts  |     100 |    91.66 |     100 |     100 | 55                
 src/test-utils    |   93.75 |    83.33 |      80 |   93.75 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   65.19 |    67.73 |   54.76 |   65.19 |                   
  App.tsx          |     100 |      100 |     100 |     100 |                   
  AppContainer.tsx |   68.02 |     62.4 |      75 |   68.02 | ...2430,2434-2438 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |   29.23 |      100 |       0 |   29.23 | 25-75             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |   52.72 |      100 |   23.52 |   52.72 | ...52,54-55,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.91 |    96.42 |     100 |   95.91 | 25-26             
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   48.01 |    58.73 |   21.42 |   48.01 |                   
  AuthDialog.tsx   |   64.26 |    44.44 |   16.66 |   64.26 | ...59,366-388,392 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  ...etupSteps.tsx |    9.61 |      100 |       0 |    9.61 | ...35-352,391-476 
  useAuth.ts       |   76.63 |    68.29 |     100 |   76.63 | ...48,493-499,560 
  ...rSetupFlow.ts |   44.61 |    33.33 |      50 |   44.61 | ...57-378,395-438 
 src/ui/commands   |   70.24 |     79.6 |   80.45 |   70.24 |                   
  aboutCommand.ts  |     100 |    85.71 |     100 |     100 | 36                
  agentsCommand.ts |   83.78 |      100 |      60 |   83.78 | 30-32,42-44       
  ...odeCommand.ts |     100 |      100 |     100 |     100 |                   
  arenaCommand.ts  |   62.81 |    58.73 |   65.21 |   62.81 | ...91-596,681-689 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  branchCommand.ts |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |   95.59 |    71.42 |     100 |   95.59 | 72,154-159        
  bugCommand.ts    |   81.13 |    71.42 |     100 |   81.13 | 60-69             
  clearCommand.ts  |   92.94 |       75 |     100 |   92.94 | 45-46,74-75,93-94 
  ...essCommand.ts |    64.7 |       50 |      75 |    64.7 | ...48-149,163-166 
  ...extCommand.ts |   34.78 |    22.22 |   45.45 |   34.78 | ...86-521,532-533 
  copyCommand.ts   |   98.28 |    94.89 |     100 |   98.28 | ...80,280,321,327 
  deleteCommand.ts |     100 |      100 |     100 |     100 |                   
  diffCommand.ts   |   99.02 |    86.11 |     100 |   99.02 | 222,226           
  ...ryCommand.tsx |   68.09 |    77.77 |   77.77 |   68.09 | ...56-261,315-323 
  docsCommand.ts   |     100 |    88.88 |     100 |     100 | 25                
  doctorCommand.ts |     100 |    93.33 |     100 |     100 | 21                
  dreamCommand.ts  |      75 |    66.66 |   66.66 |      75 | 22-27,44-47       
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |      60 |    92.85 |   77.77 |      60 | 176-317           
  ...onsCommand.ts |   48.66 |     90.9 |   63.63 |   48.66 | ...05-109,159-211 
  forgetCommand.ts |   26.82 |      100 |      50 |   26.82 | 18-51             
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |    20.4 |       40 |      40 |    20.4 | ...48-180,204-205 
  ideCommand.ts    |   60.75 |    64.28 |   41.17 |   60.75 | ...05-306,310-324 
  initCommand.ts   |   84.33 |    72.72 |     100 |   84.33 | 68,82-87,89-94    
  ...ghtCommand.ts |   74.56 |    68.42 |     100 |   74.56 | ...31-245,250-273 
  ...ageCommand.ts |   85.76 |    82.82 |     100 |   85.76 | ...51-658,687-694 
  ...elsCommand.ts |     100 |      100 |     100 |     100 |                   
  mcpCommand.ts    |     100 |      100 |     100 |     100 |                   
  memoryCommand.ts |     100 |      100 |     100 |     100 |                   
  modelCommand.ts  |   74.56 |    79.06 |   71.42 |   74.56 | ...91-200,223-228 
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  planCommand.ts   |   78.82 |    76.92 |     100 |   78.82 | 30-35,51-56,68-73 
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  recapCommand.ts  |   21.81 |      100 |      50 |   21.81 | 24-73             
  ...berCommand.ts |   32.43 |      100 |      50 |   32.43 | 23-57             
  renameCommand.ts |   85.61 |    78.18 |     100 |   85.61 | ...15-322,329-334 
  ...oreCommand.ts |    92.3 |    87.87 |     100 |    92.3 | ...,83-88,129-130 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |      80 |      100 |      50 |      80 | 19-21             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   81.43 |    65.21 |      80 |   81.43 | ...70-173,176-179 
  skillsCommand.ts |   15.04 |      100 |      25 |   15.04 | ...90-106,109-136 
  statsCommand.ts  |   88.19 |    84.21 |     100 |   88.19 | ...,58-61,143-146 
  ...ineCommand.ts |     100 |      100 |     100 |     100 |                   
  ...aryCommand.ts |    6.51 |      100 |      50 |    6.51 | 28-323            
  tasksCommand.ts  |   77.45 |    73.43 |     100 |   77.45 | ...55-159,181-186 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  vimCommand.ts    |   54.54 |      100 |      50 |   54.54 | 19-29             
 src/ui/components |   61.15 |    75.56 |   66.66 |   61.15 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |   65.57 |      100 |      50 |   65.57 | 69-90             
  ApiKeyInput.tsx  |       0 |        0 |       0 |       0 | 1-97              
  AppHeader.tsx    |   89.39 |       75 |     100 |   89.39 | 35,37-42,44       
  ...odeDialog.tsx |     9.7 |      100 |       0 |     9.7 | 35-47,50-182      
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   14.63 |      100 |       0 |   14.63 | 18-56             
  ...TextInput.tsx |   77.01 |       76 |     100 |   77.01 | ...20,234-236,263 
  Composer.tsx     |   79.48 |    57.14 |     100 |   79.48 | ...-77,95,134,147 
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   68.42 |    57.14 |     100 |   68.42 | 16-17,31-32,42-50 
  ...ification.tsx |   28.57 |      100 |       0 |   28.57 | 16-36             
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |   12.53 |      100 |       0 |   12.53 | 63-470            
  ...ngsDialog.tsx |    8.44 |      100 |       0 |    8.44 | 37-195            
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...hProgress.tsx |    87.8 |    33.33 |     100 |    87.8 | 28-31,56          
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   79.67 |    58.06 |     100 |   79.67 | ...98-102,104-108 
  ...ngSpinner.tsx |   68.42 |       80 |      50 |   68.42 | 35-52,73,80-81    
  Header.tsx       |   98.62 |    94.28 |     100 |   98.62 | 162,164           
  Help.tsx         |   98.32 |    89.88 |     100 |   98.32 | ...24,381,447-448 
  ...emDisplay.tsx |   63.27 |    36.73 |     100 |   63.27 | ...29-338,341,344 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   82.25 |    77.43 |   83.33 |   82.25 | ...1347,1412,1462 
  ...Shortcuts.tsx |   20.87 |      100 |       0 |   20.87 | ...6,49-51,67-125 
  ...Indicator.tsx |     100 |    91.42 |     100 |     100 | 65,74             
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   81.75 |       75 |     100 |   81.75 | ...70-274,282-286 
  ...elsDialog.tsx |   16.07 |    89.18 |      50 |   16.07 | ...58-159,162-648 
  MemoryDialog.tsx |   53.21 |    51.21 |   57.14 |   53.21 | ...54,366,379-381 
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   76.31 |    54.94 |     100 |   76.31 | ...05-521,578-582 
  ...tsDisplay.tsx |     100 |    96.96 |     100 |     100 | 234               
  ...fications.tsx |   18.18 |      100 |       0 |   18.18 | 15-58             
  ...onsDialog.tsx |    2.13 |      100 |       0 |    2.13 | 62-133,148-1004   
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   88.14 |    83.87 |     100 |   88.14 | ...01-105,133-138 
  PrepareLabel.tsx |   91.66 |    77.27 |     100 |   91.66 | 73-75,77-79,110   
  ...atePrompt.tsx |    8.57 |      100 |       0 |    8.57 | 24-55,58-134      
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |   21.42 |      100 |       0 |   21.42 | 13-39             
  ...hProgress.tsx |   85.25 |    88.46 |     100 |   85.25 | 121-147           
  ...dSelector.tsx |    4.45 |      100 |       0 |    4.45 | 28-92,100-328     
  ...ionPicker.tsx |      86 |    81.25 |     100 |      86 | ...98-310,344-346 
  ...onPreview.tsx |   92.42 |    84.37 |     100 |   92.42 | ...,70-71,143-145 
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...ngsDialog.tsx |   66.88 |    73.52 |     100 |   66.88 | ...11-819,825-826 
  ...ionDialog.tsx |    87.8 |      100 |   33.33 |    87.8 | 36-39,44-51       
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   57.14 |      100 |       0 |   57.14 | 12-15             
  ...MoreLines.tsx |      28 |      100 |       0 |      28 | 18-40             
  ...ionPicker.tsx |   17.59 |      100 |       0 |   17.59 | 55-172            
  StatsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...yTodoList.tsx |   94.17 |       80 |     100 |   94.17 | 56-57,131-134     
  ...nsDisplay.tsx |   87.25 |       64 |     100 |   87.25 | ...45-147,154-156 
  ThemeDialog.tsx  |   89.95 |    46.15 |      75 |   89.95 | ...71-173,243-245 
  Tips.tsx         |   93.54 |       75 |     100 |   93.54 | 39-40             
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  TrustDialog.tsx  |     100 |    81.81 |     100 |     100 | 71-86             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...ackDialog.tsx |    7.84 |      100 |       0 |    7.84 | 24-134            
 ...nts/agent-view |    25.2 |       90 |      10 |    25.2 |                   
  ...atContent.tsx |    8.79 |      100 |       0 |    8.79 | 53-265,271-273    
  ...tChatView.tsx |   21.05 |      100 |       0 |   21.05 | 21-39             
  ...tComposer.tsx |    9.95 |      100 |       0 |    9.95 | 57-308            
  AgentFooter.tsx  |   17.07 |      100 |       0 |   17.07 | 28-66             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    8.13 |      100 |       0 |    8.13 | 39-59,64-187      
  ...oryAdapter.ts |     100 |    91.83 |     100 |     100 | 103,109-110,138   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |   45.72 |    70.53 |   60.86 |   45.72 |                   
  ArenaCards.tsx   |   73.06 |    71.79 |   85.71 |   73.06 | ...83-185,321-326 
  ...ectDialog.tsx |   83.48 |    69.86 |   88.88 |   83.48 | ...88-392,409-410 
  ...artDialog.tsx |   10.15 |      100 |       0 |   10.15 | 27-161            
  ...tusDialog.tsx |    5.63 |      100 |       0 |    5.63 | 33-75,80-288      
  ...topDialog.tsx |    6.17 |      100 |       0 |    6.17 | 33-213            
 ...ackground-view |   75.44 |     83.7 |   85.29 |   75.44 |                   
  ...sksDialog.tsx |   70.05 |     79.2 |   76.19 |   70.05 | ...1119,1195-1197 
  ...TasksPill.tsx |   70.83 |    86.95 |     100 |   70.83 | 44,84-96,104-112  
  ...gentPanel.tsx |   99.52 |    93.18 |     100 |   99.52 | 123               
 ...nts/extensions |   45.28 |    33.33 |      60 |   45.28 |                   
  ...gerDialog.tsx |   44.31 |    34.14 |      75 |   44.31 | ...71-480,483-488 
  index.ts         |       0 |        0 |       0 |       0 | 1-9               
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   54.77 |    94.23 |   66.66 |   54.77 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |    6.18 |      100 |       0 |    6.18 | 17-128            
  ...nListStep.tsx |   88.35 |    94.73 |      80 |   88.35 | 51-52,58-71,105   
  ...electStep.tsx |   13.46 |      100 |       0 |   13.46 | 20-70             
  ...nfirmStep.tsx |   19.56 |      100 |       0 |   19.56 | 23-65             
  index.ts         |     100 |      100 |     100 |     100 |                   
 ...mponents/hooks |   72.24 |    70.52 |      80 |   72.24 |                   
  ...etailStep.tsx |   96.52 |       75 |     100 |   96.52 | 33,37,50,59       
  ...etailStep.tsx |   93.27 |    73.68 |     100 |   93.27 | 41-42,99-104,110  
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   36.09 |    47.05 |      50 |   36.09 | ...49,453-466,470 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   20.83 |    83.72 |   83.33 |   20.83 |                   
  ...ealthPill.tsx |   68.42 |    85.71 |     100 |   68.42 | 40-46             
  ...entDialog.tsx |    3.64 |      100 |       0 |    3.64 | 41-717            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-30              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   94.79 |    85.71 |     100 |   94.79 | 16,20,35,109-110  
 ...ents/mcp/steps |    6.65 |      100 |       0 |    6.65 |                   
  ...icateStep.tsx |     5.1 |      100 |       0 |     5.1 | 34-95,98-334      
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |    5.26 |      100 |       0 |    5.26 | 31-247            
  ...rListStep.tsx |    5.88 |      100 |       0 |    5.88 | 20-176            
  ...etailStep.tsx |   10.41 |      100 |       0 |   10.41 | ...1,67-79,82-139 
  ToolListStep.tsx |    7.14 |      100 |       0 |    7.14 | 16-146            
 ...nents/messages |   82.15 |    80.23 |   72.85 |   82.15 |                   
  ...ionDialog.tsx |   77.35 |    74.54 |    62.5 |   77.35 | ...90,508,526-528 
  BtwMessage.tsx   |     100 |      100 |     100 |     100 |                   
  ...upDisplay.tsx |   97.67 |    83.72 |     100 |   97.67 | 119,142,150       
  ...onMessage.tsx |   91.93 |    82.35 |     100 |   91.93 | 57-59,61,63       
  ...nMessages.tsx |   79.06 |      100 |      70 |   79.06 | ...51-264,268-280 
  DiffRenderer.tsx |   93.19 |    86.17 |     100 |   93.19 | ...09,237-238,304 
  ...tsDisplay.tsx |   97.82 |    77.27 |     100 |   97.82 | 87,89             
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...edMessage.tsx |   16.66 |      100 |       0 |   16.66 | 22-38             
  ...sMessages.tsx |   55.67 |       40 |   28.57 |   55.67 | ...20-125,133-145 
  ...ryMessage.tsx |   14.28 |      100 |       0 |   14.28 | 23-62             
  ...onMessage.tsx |   81.02 |    69.23 |   33.33 |   81.02 | ...24-426,433-435 
  ...upMessage.tsx |      84 |    93.61 |     100 |      84 | ...56-383,405-420 
  ToolMessage.tsx  |   88.84 |    75.71 |    92.3 |   88.84 | ...44-749,776-778 
 ...ponents/shared |   82.37 |    77.36 |   92.75 |   82.37 |                   
  ...ctionList.tsx |   99.03 |    95.65 |     100 |   99.03 | 85                
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  MaxSizedBox.tsx  |   83.01 |    86.25 |   88.88 |   83.01 | ...12-513,618-619 
  MultiSelect.tsx  |    6.29 |      100 |       0 |    6.29 | 35-42,45-176      
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  TextInput.tsx    |   72.98 |    55.55 |      80 |   72.98 | ...08-212,224-230 
  ...apsedTime.tsx |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  text-buffer.ts   |   83.62 |    75.62 |   97.61 |   83.62 | ...2272,2300,2368 
  ...er-actions.ts |   86.71 |    67.79 |     100 |   86.71 | ...07-608,809-811 
 ...ents/subagents |   30.87 |        0 |       0 |   30.87 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-11              
  reducers.tsx     |    12.1 |      100 |       0 |    12.1 | 33-190            
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   10.95 |      100 |       0 |   10.95 | ...1,56-57,60-102 
 ...bagents/create |    9.13 |      100 |       0 |    9.13 |                   
  ...ionWizard.tsx |    7.28 |      100 |       0 |    7.28 | 34-299            
  ...rSelector.tsx |   14.75 |      100 |       0 |   14.75 | 26-85             
  ...onSummary.tsx |    4.26 |      100 |       0 |    4.26 | 27-331            
  ...tionInput.tsx |    8.63 |      100 |       0 |    8.63 | 23-177            
  ...dSelector.tsx |   33.33 |      100 |       0 |   33.33 | 20-21,26-27,36-63 
  ...nSelector.tsx |    37.5 |      100 |       0 |    37.5 | 20-21,26-27,36-58 
  ...EntryStep.tsx |   12.76 |      100 |       0 |   12.76 | 34-78             
  ToolSelector.tsx |    4.16 |      100 |       0 |    4.16 | 31-253            
 ...bagents/manage |    8.39 |      100 |       0 |    8.39 |                   
  ...ctionStep.tsx |   10.25 |      100 |       0 |   10.25 | 21-103            
  ...eleteStep.tsx |   20.93 |      100 |       0 |   20.93 | 23-62             
  ...tEditStep.tsx |   25.53 |      100 |       0 |   25.53 | ...2,37-38,51-124 
  ...ctionStep.tsx |    2.29 |      100 |       0 |    2.29 | 28-449            
  ...iewerStep.tsx |   13.72 |      100 |       0 |   13.72 | 18-73             
  ...gerDialog.tsx |    6.74 |      100 |       0 |    6.74 | 35-341            
 ...mponents/views |   42.16 |    69.23 |   21.42 |   42.16 |                   
  ContextUsage.tsx |     4.7 |      100 |       0 |     4.7 | ...52-167,170-456 
  DoctorReport.tsx |     9.8 |      100 |       0 |     9.8 | 25-54,57-131      
  ...sionsList.tsx |   87.69 |    73.68 |     100 |   87.69 | 65-72             
  McpStatus.tsx    |   89.53 |    60.52 |     100 |   89.53 | ...72,175-177,262 
  SkillsList.tsx   |   27.27 |      100 |       0 |   27.27 | 18-35             
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   77.05 |    78.24 |   82.14 |   77.05 |                   
  ...ewContext.tsx |   65.77 |      100 |      75 |   65.77 | ...22-225,231-241 
  AppContext.tsx   |      80 |       50 |     100 |      80 | 19-20             
  ...ewContext.tsx |   93.37 |    68.57 |      50 |   93.37 | ...94-195,222-226 
  ...deContext.tsx |     100 |      100 |     100 |     100 |                   
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   81.88 |    82.26 |     100 |   81.88 | ...1153,1159-1161 
  ...owContext.tsx |   89.28 |       80 |   66.66 |   89.28 | 34,47-48,60-62    
  ...deContext.tsx |     100 |      100 |      50 |     100 |                   
  ...onContext.tsx |   43.28 |     62.5 |    62.5 |   43.28 | ...56-259,263-266 
  ...gsContext.tsx |   83.33 |       50 |     100 |   83.33 | 17-18             
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...utContext.tsx |   85.71 |      100 |   66.66 |   85.71 | 13-14             
  ...nsContext.tsx |   88.23 |       50 |     100 |   88.23 | 108-109           
  ...teContext.tsx |   86.66 |       50 |     100 |   86.66 | 173-174           
  ...deContext.tsx |   76.08 |    72.72 |     100 |   76.08 | 47-48,52-59,77-78 
 src/ui/editors    |   93.33 |    85.71 |   66.66 |   93.33 |                   
  ...ngsManager.ts |   93.33 |    85.71 |   66.66 |   93.33 | 49,63-64          
 src/ui/hooks      |   81.33 |    81.11 |   86.47 |   81.33 |                   
  ...dProcessor.ts |   83.12 |    82.56 |     100 |   83.12 | ...88-389,408-435 
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...dProcessor.ts |    94.8 |    70.58 |     100 |    94.8 | ...76-277,282-283 
  ...dProcessor.ts |    75.9 |    63.44 |   61.53 |    75.9 | ...84,908,927-931 
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-158            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...ationFrame.ts |      32 |       60 |     100 |      32 | 42-44,51-90       
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   19.81 |    66.66 |      25 |   19.81 | 57-175            
  ...Completion.ts |   92.77 |    89.09 |     100 |   92.77 | ...86-187,220-223 
  ...ifications.ts |   92.07 |    96.29 |     100 |   92.07 | 116-124           
  ...tIndicator.ts |     100 |    93.75 |     100 |     100 | 63                
  ...waySummary.ts |   96.22 |    69.69 |     100 |   96.22 | 125-127,169       
  ...ndTaskView.ts |   94.11 |    76.92 |     100 |   94.11 | 119-123,216,222   
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-37             
  ...nchCommand.ts |   93.75 |    73.17 |     100 |   93.75 | ...68-169,221-222 
  ...ompletion.tsx |   95.95 |    82.75 |     100 |   95.95 | ...22-223,225-226 
  ...dMigration.ts |   90.62 |       75 |     100 |   90.62 | 38-40             
  useCompletion.ts |    92.4 |     87.5 |     100 |    92.4 | 68-69,93-94,98-99 
  ...nitMessage.ts |     100 |      100 |     100 |     100 |                   
  ...extualTips.ts |   76.92 |       50 |     100 |   76.92 | 55,68,71-75,88-96 
  ...eteCommand.ts |   33.33 |       50 |     100 |   33.33 | 30,34,41-90       
  ...ialogClose.ts |   16.66 |      100 |     100 |   16.66 | 79-139            
  ...oublePress.ts |   53.12 |       75 |     100 |   53.12 | 33-35,41-54       
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...Completion.ts |   99.12 |     97.7 |     100 |   99.12 | 182-183           
  ...ionUpdates.ts |   93.45 |     92.3 |     100 |   93.45 | ...83-287,300-306 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |   54.47 |       50 |   33.33 |   54.47 | ...69-171,193-194 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |      100 |     100 |     100 |                   
  ...ggestions.tsx |   89.15 |     62.5 |      50 |   89.15 | ...22-124,149-150 
  ...miniStream.ts |   75.92 |    72.95 |   91.66 |   75.92 | ...2300,2313-2321 
  ...BranchName.ts |    90.9 |     92.3 |     100 |    90.9 | 19-20,55-58       
  ...oryManager.ts |   93.15 |    93.75 |     100 |   93.15 | 44,107-110        
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |    9.67 |      100 |       0 |    9.67 | 11-32,39-90       
  ...gIndicator.ts |     100 |      100 |     100 |     100 |                   
  useLogger.ts     |   21.05 |      100 |       0 |   21.05 | 15-37             
  useMCPHealth.ts  |   63.15 |       75 |      50 |   63.15 | 42-52,64-67       
  ...elsCommand.ts |     100 |      100 |     100 |     100 |                   
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...moryDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...delCommand.ts |     100 |       75 |     100 |     100 | 22                
  ...raseCycler.ts |   84.74 |    76.47 |     100 |   84.74 | ...49,52-53,69-71 
  ...derUpdates.ts |   86.38 |    77.19 |     100 |   86.38 | ...22,281-293,341 
  useQwenAuth.ts   |     100 |      100 |     100 |     100 |                   
  ...lScheduler.ts |    84.7 |    93.33 |     100 |    84.7 | ...71-276,372-382 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   97.24 |    76.92 |     100 |   97.24 | 104-105,145       
  ...ompletion.tsx |   90.59 |    83.33 |     100 |   90.59 | ...01,104,137-140 
  ...ectionList.ts |   96.96 |    95.69 |     100 |   96.96 | ...82-183,237-240 
  ...sionPicker.ts |   79.79 |    61.19 |     100 |   79.79 | ...02-404,413-415 
  ...earchInput.ts |     100 |      100 |     100 |     100 |                   
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   91.74 |    79.41 |     100 |   91.74 | ...74,122-123,133 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-73              
  ...Completion.ts |   82.67 |    85.41 |   94.73 |   82.67 | ...68-670,678-714 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  useStatusLine.ts |     100 |    98.79 |     100 |     100 | 257               
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...tification.ts |     100 |    85.71 |     100 |     100 | 47                
  ...alProgress.ts |   53.06 |       50 |   66.66 |   53.06 | ...53,61-68,79-85 
  ...rminalSize.ts |   76.19 |      100 |      50 |   76.19 | 21-25             
  ...emeCommand.ts |   67.01 |    29.41 |     100 |   67.01 | ...10-111,115-116 
  useTimer.ts      |   88.09 |    85.71 |     100 |   88.09 | 44-45,51-53       
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |      100 |     100 |     100 |                   
  ...elcomeBack.ts |   87.36 |     90.9 |     100 |   87.36 | ...,94-96,114-115 
  vim.ts           |   83.77 |    80.31 |     100 |   83.77 | ...55,759-767,776 
 src/ui/layouts    |   89.72 |     87.5 |     100 |   89.72 |                   
  ...AppLayout.tsx |   89.88 |     87.5 |     100 |   89.88 | 51-53,93-98       
  ...AppLayout.tsx |   89.47 |     87.5 |     100 |   89.47 | 58-63             
 ...i/manageModels |   93.61 |       48 |     100 |   93.61 |                   
  manageModels.ts  |   93.61 |       48 |     100 |   93.61 | ...63-166,179,209 
 src/ui/models     |   80.24 |    79.16 |   71.42 |   80.24 |                   
  ...ableModels.ts |   80.24 |    79.16 |   71.42 |   80.24 | ...,61-71,123-125 
 ...noninteractive |     100 |      100 |    7.14 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    7.14 |     100 |                   
 src/ui/state      |   94.91 |    81.81 |     100 |   94.91 |                   
  extensions.ts    |   94.91 |    81.81 |     100 |   94.91 | 68-69,88          
 src/ui/themes     |   98.53 |    70.58 |     100 |   98.53 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |     100 |      100 |     100 |     100 |                   
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  ...inal-theme.ts |   88.59 |    85.96 |     100 |   88.59 | ...57-261,266-270 
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   87.98 |    82.89 |     100 |   87.98 | ...48-357,362-363 
  theme.ts         |     100 |    38.02 |     100 |     100 | ...34-449,457-461 
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   83.03 |    81.98 |   91.82 |   83.03 |                   
  ...Colorizer.tsx |   82.78 |    88.23 |     100 |   82.78 | ...10-111,197-223 
  ...nRenderer.tsx |   57.89 |    55.31 |      50 |   57.89 | ...86-188,208-227 
  ...wnDisplay.tsx |   86.01 |    87.41 |     100 |   86.01 | ...87,704,729-754 
  ...idDiagram.tsx |   87.79 |    95.34 |     100 |   87.79 | 156-179           
  ...eRenderer.tsx |   94.74 |    82.22 |   94.11 |   94.74 | ...91,503,506-509 
  ...dWorkUtils.ts |     100 |      100 |     100 |     100 |                   
  ...boardUtils.ts |   59.61 |    58.82 |     100 |   59.61 | ...,86-88,107-149 
  commandUtils.ts  |    95.9 |    88.29 |     100 |    95.9 | ...62,164-165,289 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  customBanner.ts  |   90.68 |    91.22 |     100 |   90.68 | ...13,324-327,334 
  displayUtils.ts  |   88.37 |    72.22 |     100 |   88.37 | 23,25,29,31,33    
  formatters.ts    |   95.23 |    98.27 |     100 |   95.23 | 117-120           
  gradientUtils.ts |     100 |      100 |     100 |     100 |                   
  highlight.ts     |     100 |      100 |     100 |     100 |                   
  ...oryMapping.ts |     100 |    94.28 |     100 |     100 | 29,51             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |    8.23 |      100 |       0 |    8.23 | ...31-132,135-136 
  latexRenderer.ts |   94.95 |     73.8 |     100 |   94.95 | ...76-178,184-187 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  ...nUtilities.ts |   69.84 |    85.71 |     100 |   69.84 | 75-91,100-101     
  ...ToolGroups.ts |   98.66 |    96.77 |     100 |   98.66 | 48-49             
  ...geRenderer.ts |   86.23 |    69.06 |   95.12 |   86.23 | ...1284,1324-1330 
  ...alRenderer.ts |   86.69 |     71.9 |     100 |   86.69 | ...1476,1513-1519 
  ...lsBySource.ts |     100 |    95.23 |     100 |     100 | 84                
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   61.06 |    69.62 |      90 |   61.06 | ...64,412,417-439 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  ...izedOutput.ts |   94.94 |      100 |   88.88 |   94.94 | 112-117           
  ...wOptimizer.ts |     100 |    96.77 |     100 |     100 | 69                
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   97.35 |    94.38 |   91.66 |   97.35 | ...50-251,386-387 
  todoSnapshot.ts  |   89.11 |    93.33 |     100 |   89.11 | ...,66-78,180-181 
  updateCheck.ts   |     100 |    80.95 |     100 |     100 | 30-42             
 ...i/utils/export |   56.77 |     40.8 |   79.41 |   56.77 |                   
  collect.ts       |   55.92 |    50.58 |   86.36 |   55.92 | ...25-640,642-647 
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |   57.47 |    20.51 |      80 |   57.47 | ...09-310,324-359 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |      40 |      100 |       0 |      40 | 11-13             
 ...ort/formatters |    3.38 |      100 |       0 |    3.38 |                   
  html.ts          |    9.61 |      100 |       0 |    9.61 | ...28,34-76,82-84 
  json.ts          |      50 |      100 |       0 |      50 | 14-15             
  jsonl.ts         |     3.5 |      100 |       0 |     3.5 | 14-76             
  markdown.ts      |    0.94 |      100 |       0 |    0.94 | 13-295            
 src/utils         |   73.31 |       90 |   93.68 |   73.31 |                   
  acpModelUtils.ts |     100 |      100 |     100 |     100 |                   
  apiPreconnect.ts |   96.52 |    97.05 |     100 |   96.52 | 164-167           
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  cleanup.ts       |   84.12 |    93.33 |      80 |   84.12 | 75,106-115        
  commands.ts      |     100 |      100 |     100 |     100 |                   
  commentJson.ts   |   87.17 |    90.47 |     100 |   87.17 | 64-73             
  ...Calculator.ts |     100 |      100 |     100 |     100 |                   
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  doctorChecks.ts  |   71.06 |       75 |     100 |   71.06 | ...95-301,325-341 
  ...putCapture.ts |   90.65 |    86.17 |     100 |   90.65 | ...72,370,372-373 
  ...arResolver.ts |   94.28 |       88 |     100 |   94.28 | 28-29,125-126     
  errors.ts        |   98.67 |    96.36 |     100 |   98.67 | 67-68             
  events.ts        |     100 |      100 |     100 |     100 |                   
  gitUtils.ts      |   91.91 |    84.61 |     100 |   91.91 | 78-81,124-127     
  ...AutoUpdate.ts |   90.76 |    93.33 |   88.88 |   90.76 | 103-114           
  ...lationInfo.ts |     100 |      100 |     100 |     100 |                   
  languageUtils.ts |   97.89 |    96.42 |     100 |   97.89 | 132-133           
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...onfigUtils.ts |     100 |      100 |     100 |     100 |                   
  ...iveHelpers.ts |   96.82 |    93.28 |     100 |   96.82 | ...84-485,583,596 
  osc.ts           |    97.5 |      100 |   88.88 |    97.5 | 195-196           
  package.ts       |   88.88 |       80 |     100 |   88.88 | 33-34             
  processUtils.ts  |     100 |      100 |     100 |     100 |                   
  readStdin.ts     |   79.62 |       90 |      80 |   79.62 | 33-40,52-54       
  relaunch.ts      |   98.07 |    76.92 |     100 |   98.07 | 70                
  resolvePath.ts   |   66.66 |       25 |     100 |   66.66 | 12-13,16,18-19    
  sandbox.ts       |       0 |        0 |       0 |       0 | 1-1047            
  settingsUtils.ts |   82.89 |    90.67 |   89.47 |   82.89 | ...52-663,670-678 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...upProfiler.ts |     100 |       96 |     100 |     100 | 110               
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       60 |     100 |     100 | 23,32             
  systemInfo.ts    |   92.52 |     90.9 |   83.33 |   92.52 | 63-69,184         
  ...InfoFields.ts |    87.5 |     64.1 |     100 |    87.5 | ...21-122,143-144 
  ...iffPreview.ts |   94.11 |    83.33 |     100 |   94.11 | 13                
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   91.17 |    82.35 |     100 |   91.17 | 67-68,73-74,77-78 
  version.ts       |     100 |       50 |     100 |     100 | 11                
  windowTitle.ts   |     100 |      100 |     100 |     100 |                   
  ...WithBackup.ts |   63.15 |    81.25 |     100 |   63.15 | 93,118-157        
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   77.66 |    82.64 |   80.42 |   77.66 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |   86.11 |    76.88 |   91.66 |   86.11 |                   
  ...transcript.ts |   88.92 |    76.66 |     100 |   88.92 | ...82,306-307,438 
  ...ent-resume.ts |   81.23 |    69.89 |   77.41 |   81.23 | ...1021,1024-1026 
  ...ound-tasks.ts |   95.13 |    86.61 |     100 |   95.13 | ...06-707,733-734 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/agents/arena  |    76.9 |    66.66 |   78.94 |    76.9 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |   75.84 |     62.9 |   78.57 |   75.84 | ...1889,1895-1896 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  diff-summary.ts  |    87.5 |    73.46 |     100 |    87.5 | ...32-133,137-138 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   76.29 |    86.15 |   73.04 |   76.29 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   91.25 |    90.62 |   86.66 |   91.25 | ...94,249-269,328 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   81.13 |     76.7 |   71.42 |   81.13 |                   
  agent-context.ts |     100 |      100 |     100 |     100 |                   
  agent-core.ts    |   76.45 |    72.35 |   60.86 |   76.45 | ...1604,1631-1677 
  agent-events.ts  |     100 |      100 |     100 |     100 |                   
  ...t-headless.ts |   81.19 |    71.73 |   60.86 |   81.19 | ...98-399,402-403 
  ...nteractive.ts |   79.71 |    79.62 |      75 |   79.71 | ...54,456,458,461 
  ...statistics.ts |   98.19 |    82.35 |     100 |   98.19 | 127,151,192,225   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/config        |   74.66 |    77.87 |   61.41 |   74.66 |                   
  config.ts        |   72.63 |    75.62 |   56.65 |   72.63 | ...3090,3101-3113 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   92.11 |    93.22 |   86.84 |   92.11 | ...66-267,270-271 
 ...nfirmation-bus |   98.29 |    97.14 |     100 |   98.29 |                   
  message-bus.ts   |   98.14 |    97.05 |     100 |   98.14 | 42-43             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   84.32 |    82.81 |   89.11 |   84.32 |                   
  baseLlmClient.ts |   96.77 |    96.42 |      80 |   96.77 | 123-126           
  client.ts        |   79.39 |    79.52 |   87.09 |   79.39 | ...1472,1495-1498 
  ...tGenerator.ts |    72.1 |    61.11 |     100 |    72.1 | ...63,365,372-375 
  ...lScheduler.ts |   81.13 |    82.25 |   93.33 |   81.13 | ...2332,2384-2388 
  geminiChat.ts    |   88.81 |    84.36 |    87.5 |   88.81 | ...1304,1371-1372 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  ...htProtocol.ts |    9.09 |      100 |       0 |    9.09 | 34-42,45-49,52-87 
  logger.ts        |   82.25 |    81.81 |     100 |   82.25 | ...57-361,407-421 
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   92.59 |       75 |      50 |   92.59 | 41-42             
  ...on-helpers.ts |   85.71 |    70.58 |     100 |   85.71 | ...90-191,205-214 
  ...issionFlow.ts |   98.59 |    94.73 |     100 |   98.59 | 93                
  prompts.ts       |   89.16 |    86.41 |   76.92 |   89.16 | ...-965,1168-1169 
  tokenLimits.ts   |     100 |    89.47 |     100 |     100 | 51-52             
  ...okTriggers.ts |   99.31 |    90.41 |     100 |   99.31 | 124,135           
  turn.ts          |   96.42 |    88.88 |     100 |   96.42 | ...00,413-414,462 
 ...ntentGenerator |   95.12 |    81.91 |   93.61 |   95.12 |                   
  ...tGenerator.ts |   97.13 |    83.58 |    92.3 |   97.13 | ...22,714,870,926 
  converter.ts     |   94.51 |    80.62 |     100 |   94.51 | ...06-607,617,816 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
 ...ntentGenerator |   91.53 |    71.64 |   93.33 |   91.53 |                   
  ...tGenerator.ts |      90 |    70.96 |   92.85 |      90 | ...80-286,304-305 
  index.ts         |     100 |       80 |     100 |     100 | 50                
 ...ntentGenerator |      94 |    84.23 |      90 |      94 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   93.98 |    84.23 |      90 |   93.98 | ...88,798-799,827 
 ...ntentGenerator |    79.7 |       84 |   89.47 |    79.7 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   74.92 |    80.85 |   86.95 |   74.92 | ...1410,1431-1437 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |   52.38 |    44.44 |      50 |   52.38 | ...77,81-85,89-93 
  ...tGenerator.ts |   48.78 |    91.66 |   77.77 |   48.78 | ...10-163,166-167 
  pipeline.ts      |   93.65 |     84.9 |     100 |   93.65 | ...79-480,488,553 
  ...ureContext.ts |     100 |      100 |     100 |     100 |                   
  ...ingOptions.ts |       0 |        0 |       0 |       0 | 1                 
  ...CallParser.ts |   90.66 |     88.4 |     100 |   90.66 | ...15-319,349-350 
  ...kingParser.ts |     100 |    96.87 |     100 |     100 | 42                
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...rator/provider |   96.62 |     88.3 |   95.45 |   96.62 |                   
  dashscope.ts     |   97.22 |    87.69 |   93.33 |   97.22 | ...10-211,287-288 
  deepseek.ts      |   95.55 |    90.56 |     100 |   95.55 | ...31-132,145-146 
  default.ts       |   94.62 |    86.36 |   85.71 |   94.62 | 85-86,156-158     
  index.ts         |     100 |      100 |     100 |     100 |                   
  minimax.ts       |     100 |      100 |     100 |     100 |                   
  mistral.ts       |   96.07 |    73.33 |     100 |   96.07 | 32-33             
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
 src/extension     |   60.56 |    79.46 |    78.4 |   60.56 |                   
  ...-converter.ts |   62.35 |    47.82 |      90 |   62.35 | ...90-791,800-832 
  ...ionManager.ts |   47.04 |    82.06 |    65.9 |   47.04 | ...1398,1408-1427 
  ...onSettings.ts |   93.46 |    93.05 |     100 |   93.46 | ...17-221,228-232 
  ...-converter.ts |   54.88 |    94.44 |      60 |   54.88 | ...35-146,158-192 
  github.ts        |   44.94 |    88.52 |      60 |   44.94 | ...53-359,398-451 
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   97.29 |    93.75 |     100 |   97.29 | ...64,184-185,274 
  npm.ts           |   48.66 |    76.08 |      75 |   48.66 | ...18-420,427-431 
  override.ts      |   94.11 |    88.88 |     100 |   94.11 | 63-64,81-82       
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-108,143-149    
  storage.ts       |     100 |      100 |     100 |     100 |                   
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.75 |    83.33 |     100 |   88.75 | ...28-231,234-237 
 src/followup      |   46.35 |     92.3 |   71.87 |   46.35 |                   
  followupState.ts |      96 |    89.74 |     100 |      96 | 159-161,218-219   
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   95.06 |       84 |     100 |   95.06 | 78,108,122,133    
  speculation.ts   |   13.22 |      100 |   16.66 |   13.22 | 88-458,518-568    
  ...onToolGate.ts |     100 |    96.29 |     100 |     100 | 93                
  ...nGenerator.ts |   36.67 |    95.12 |   33.33 |   36.67 | ...24-326,361-391 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/hooks         |   80.63 |    84.35 |   84.16 |   80.63 |                   
  ...okRegistry.ts |   86.48 |    77.08 |     100 |   86.48 | ...41-344,362-369 
  ...bortSignal.ts |     100 |      100 |     100 |     100 |                   
  ...terpolator.ts |   96.66 |    93.33 |     100 |   96.66 | 66-67             
  ...HookRunner.ts |   96.68 |    87.23 |     100 |   96.68 | 110-112,231-233   
  ...Aggregator.ts |   96.37 |    90.54 |     100 |   96.37 | ...89,291-292,365 
  ...entHandler.ts |   95.58 |    84.37 |   92.59 |   95.58 | ...29,682-683,693 
  hookPlanner.ts   |   84.13 |    76.59 |      90 |   84.13 | ...38,144,162-173 
  hookRegistry.ts  |   88.83 |    86.36 |     100 |   88.83 | ...21,326,330,334 
  hookRunner.ts    |   53.94 |     72.6 |   61.11 |   53.94 | ...27-728,737-738 
  hookSystem.ts    |   75.47 |      100 |   56.41 |   75.47 | ...75-576,582-583 
  ...HookRunner.ts |   75.51 |     61.9 |      80 |   75.51 | ...05-406,424-425 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...SkillHooks.ts |   78.75 |       75 |   66.66 |   78.75 | 62-66,137-152     
  ...oksManager.ts |    96.5 |     91.8 |     100 |    96.5 | ...90,209-210,223 
  ssrfGuard.ts     |   77.22 |    85.36 |     100 |   77.22 | ...57,261-267,273 
  trustedHooks.ts  |       0 |        0 |       0 |       0 | 1-124             
  types.ts         |   90.18 |    90.78 |   85.18 |   90.18 | ...91-392,452-456 
  urlValidator.ts  |     100 |      100 |     100 |     100 |                   
 src/ide           |   74.28 |    83.39 |   78.33 |   74.28 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |    64.2 |    81.48 |   66.66 |    64.2 | ...9-970,999-1007 
  ide-installer.ts |   89.06 |    79.31 |     100 |   89.06 | ...36,143-147,160 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   33.92 |    44.97 |   45.76 |   33.92 |                   
  ...nfigLoader.ts |   70.27 |    35.89 |   94.73 |   70.27 | ...20-422,426-432 
  ...ionFactory.ts |    4.29 |        0 |       0 |    4.29 | ...20-371,377-394 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   13.52 |    81.25 |   29.16 |   13.52 | ...75-694,700-730 
  ...eLspClient.ts |   17.89 |      100 |       0 |   17.89 | ...37-244,254-258 
  ...LspService.ts |   45.87 |    62.13 |   66.66 |   45.87 | ...1282,1299-1309 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |   78.69 |    75.34 |   75.92 |   78.69 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   73.82 |    53.92 |     100 |   73.82 | ...88-895,902-904 
  ...en-storage.ts |   98.62 |    97.72 |     100 |   98.62 | 87-88             
  oauth-utils.ts   |   70.58 |    85.29 |    90.9 |   70.58 | ...70-290,315-344 
  ...n-provider.ts |   89.83 |    95.83 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   79.52 |    86.66 |   86.36 |   79.52 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   82.87 |    82.35 |   92.85 |   82.87 | ...63-173,181-182 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   59.01 |     75.8 |   63.12 |   59.01 |                   
  const.ts         |     100 |      100 |     100 |     100 |                   
  dream.ts         |   65.65 |    73.33 |      50 |   65.65 | 50,107-148        
  ...entPlanner.ts |   57.84 |    72.72 |   33.33 |   57.84 | ...35,140-147,152 
  entries.ts       |   59.84 |       70 |      50 |   59.84 | ...72-180,183-189 
  extract.ts       |    95.2 |    79.16 |     100 |    95.2 | 81-86,125         
  ...entPlanner.ts |   63.08 |    65.71 |   41.17 |   63.08 | ...17,222-223,332 
  ...ionPlanner.ts |       0 |        0 |       0 |       0 | 1                 
  forget.ts        |    8.04 |      100 |       0 |    8.04 | 67-342            
  governance.ts    |       0 |        0 |       0 |       0 | 1-352             
  indexer.ts       |   83.87 |    45.45 |     100 |   83.87 | ...50,56-57,69-70 
  manager.ts       |   75.31 |    81.04 |    75.6 |   75.31 | ...1278,1291-1293 
  memoryAge.ts     |   90.47 |    77.77 |     100 |   90.47 | 50-51             
  paths.ts         |   55.47 |    89.47 |   85.71 |   55.47 | ...,89-90,106-114 
  prompt.ts        |   93.36 |    71.42 |     100 |   93.36 | ...58,161,228-229 
  recall.ts        |   79.56 |    69.38 |   88.88 |   79.56 | ...40-245,269-280 
  ...ceSelector.ts |   91.95 |    77.27 |     100 |   91.95 | ...08,110-111,119 
  scan.ts          |   87.91 |    68.42 |     100 |   87.91 | ...47-48,58,82-87 
  ...entPlanner.ts |    11.5 |      100 |       0 |    11.5 | ...57-192,210-298 
  status.ts        |   10.52 |      100 |       0 |   10.52 | 41-98             
  store.ts         |   94.44 |    83.33 |     100 |   94.44 | 56-57,92-93       
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   89.31 |    85.47 |    87.5 |   89.31 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...tor-config.ts |   90.24 |    91.42 |     100 |   90.24 | 142,148,151-160   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |       44 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |   98.63 |    92.53 |     100 |   98.63 | 161,323,329       
  modelRegistry.ts |     100 |    98.59 |     100 |     100 | 222               
  modelsConfig.ts  |   84.57 |    81.92 |   81.57 |   84.57 | ...1223,1252-1253 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   71.18 |    88.73 |   48.57 |   71.18 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   81.42 |    86.66 |      80 |   81.42 | ...29-830,837-846 
  rule-parser.ts   |   95.99 |    93.18 |     100 |   95.99 | ...-864,1013-1015 
  ...-semantics.ts |   58.28 |    85.27 |    30.2 |   58.28 | ...1604-1614,1643 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/prompts       |   83.63 |      100 |    87.5 |   83.63 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |     100 |      100 |     100 |     100 |                   
 src/qwen          |   86.01 |    79.48 |   97.18 |   86.01 |                   
  ...tGenerator.ts |   98.64 |    98.18 |     100 |   98.64 | 105-106           
  qwenOAuth2.ts    |   84.99 |    74.81 |   93.33 |   84.99 | ...,985-1001,1031 
  ...kenManager.ts |   83.76 |    76.22 |     100 |   83.76 | ...62-767,788-793 
 src/services      |   86.75 |    84.84 |   90.06 |   86.75 |                   
  ...ionTrailer.ts |     100 |      100 |     100 |     100 |                   
  ...llRegistry.ts |   97.82 |    94.73 |     100 |   97.82 | 172-173           
  ...ionService.ts |   95.52 |    94.33 |     100 |   95.52 | ...92,350,352-356 
  ...ingService.ts |    84.1 |    84.35 |   82.85 |    84.1 | ...1240,1257-1258 
  ...ttribution.ts |   91.73 |    87.71 |      90 |   91.73 | ...80-685,826-827 
  cronScheduler.ts |   97.56 |    92.98 |     100 |   97.56 | 62-63,77,155      
  ...eryService.ts |   80.43 |    95.45 |      75 |   80.43 | ...19-134,140-141 
  fileReadCache.ts |     100 |      100 |     100 |     100 |                   
  ...temService.ts |   89.76 |     85.1 |   88.88 |   89.76 | ...89,191,266-273 
  ...ratedFiles.ts |      96 |    88.23 |     100 |      96 | 119-120,146-147   
  gitInit.ts       |     100 |      100 |     100 |     100 |                   
  gitService.ts    |   68.75 |     92.3 |   55.55 |   68.75 | ...12-122,125-129 
  ...reeService.ts |   71.83 |    68.47 |    91.3 |   71.83 | ...89-790,806,822 
  ...ionService.ts |   98.13 |     97.8 |   95.45 |   98.13 | ...32-333,380-381 
  ...orRegistry.ts |   96.34 |    91.66 |     100 |   96.34 | ...90-391,542-543 
  sessionRecap.ts  |   10.71 |      100 |       0 |   10.71 | 48-161            
  ...ionService.ts |   89.42 |     78.1 |   96.42 |   89.42 | ...1221,1225-1226 
  sessionTitle.ts  |   93.95 |    70.37 |     100 |   93.95 | ...36-239,270-271 
  ...ionService.ts |   83.01 |    78.66 |   87.75 |   83.01 | ...1482,1488-1493 
  ...UseSummary.ts |    94.7 |    88.67 |     100 |    94.7 | ...69-171,221-222 
 ...icrocompaction |   98.62 |    86.44 |     100 |   98.62 |                   
  microcompact.ts  |   98.62 |    86.44 |     100 |   98.62 | 138,142           
 src/skills        |    87.5 |     83.8 |   94.23 |    87.5 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...activation.ts |     100 |     93.1 |     100 |     100 | 93,112            
  skill-load.ts    |   92.94 |    81.63 |     100 |   92.94 | ...06,226,238-240 
  skill-manager.ts |   83.31 |    79.66 |   90.32 |   83.31 | ...1115,1122-1126 
  skill-paths.ts   |   86.74 |    77.77 |     100 |   86.74 | ...00-101,106-107 
  symlinkScope.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/subagents     |   82.84 |    79.74 |   95.23 |   82.84 |                   
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...-selection.ts |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |   76.74 |    71.42 |   92.85 |   76.74 | ...1155,1177-1178 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.46 |    95.18 |     100 |   92.46 | 51-56,69-74,78-83 
 src/telemetry     |   72.18 |    85.28 |   76.49 |   72.18 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...-exporters.ts |   46.37 |      100 |   44.44 |   46.37 | ...85,88-89,92-93 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...-processor.ts |   93.89 |    90.21 |   94.11 |   93.89 | ...70-275,294-295 
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |    51.9 |       64 |   57.77 |    51.9 | ...1214,1231-1251 
  metrics.ts       |    74.9 |    82.95 |   74.54 |    74.9 | ...58-978,981-992 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  sdk.ts           |   90.35 |    83.33 |   76.92 |   90.35 | ...15-316,335-339 
  ...on-context.ts |     100 |      100 |     100 |     100 |                   
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  ...e-id-utils.ts |     100 |      100 |     100 |     100 |                   
  tracer.ts        |   99.24 |    88.88 |     100 |   99.24 | 53                
  types.ts         |   79.17 |    85.83 |   83.33 |   79.17 | ...1149,1152-1181 
  uiTelemetry.ts   |   92.97 |    96.96 |   81.25 |   92.97 | ...93-194,200-207 
 ...ry/qwen-logger |   68.24 |    79.56 |   64.91 |   68.24 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |   68.24 |    79.34 |   64.28 |   68.24 | ...1055,1093-1094 
 src/test-utils    |   93.16 |    95.83 |   73.52 |   93.16 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...st-helpers.ts |   94.11 |       90 |     100 |   94.11 | 69-70             
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   91.19 |    97.05 |   68.96 |   91.19 | ...38,202-203,216 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |    76.5 |    81.34 |   84.43 |    76.5 |                   
  ...erQuestion.ts |   89.01 |    76.74 |    90.9 |   89.01 | ...41-342,349-350 
  cron-create.ts   |   97.75 |    88.88 |   83.33 |   97.75 | 30-31             
  cron-delete.ts   |   96.82 |      100 |   83.33 |   96.82 | 26-27             
  cron-list.ts     |   96.66 |      100 |   83.33 |   96.66 | 25-26             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |   78.01 |    84.76 |   73.33 |   78.01 | ...86-687,774-824 
  exitPlanMode.ts  |   85.09 |    85.71 |     100 |   85.09 | ...60-163,177-189 
  glob.ts          |   90.63 |    88.33 |   84.61 |   90.63 | ...28,171,302,305 
  grep.ts          |   79.19 |    85.71 |   78.94 |   79.19 | ...20,560,569-576 
  ls.ts            |   96.74 |    90.27 |     100 |   96.74 | 176-181,212,216   
  lsp.ts           |   72.77 |    60.09 |   90.32 |   72.77 | ...1211,1213-1214 
  ...nt-manager.ts |   51.95 |     65.9 |   47.36 |   51.95 | ...03-525,528-565 
  mcp-client.ts    |   32.44 |    75.28 |   63.63 |   32.44 | ...1462,1466-1469 
  mcp-tool.ts      |   90.98 |    88.88 |   96.42 |   90.98 | ...95-596,646-647 
  memory-config.ts |       0 |        0 |       0 |       0 | 1-47              
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 102,109           
  monitor.ts       |   92.27 |    83.94 |      92 |   92.27 | ...18,547-550,563 
  ...nforcement.ts |   82.44 |       90 |     100 |   82.44 | 174-185,234-247   
  read-file.ts     |   95.07 |     88.6 |      90 |   95.07 | ...99,290-293,296 
  ripGrep.ts       |   94.59 |    85.71 |   93.33 |   94.59 | ...60,463,541-542 
  ...-transport.ts |    6.34 |      100 |       0 |    6.34 | 47-145            
  send-message.ts  |   89.32 |    91.66 |   83.33 |   89.32 | 44-45,68-76       
  shell.ts         |   72.18 |    80.23 |   89.65 |   72.18 | ...3659,3708-3714 
  skill-utils.ts   |     100 |      100 |     100 |     100 |                   
  skill.ts         |   88.11 |    91.17 |   84.61 |   88.11 | ...95,399,422-444 
  ...eticOutput.ts |   95.12 |      100 |      80 |   95.12 | 87-88             
  task-stop.ts     |   93.14 |    96.15 |   85.71 |   93.14 | 39-40,54-64       
  todoWrite.ts     |   85.42 |    84.09 |   84.61 |   85.42 | ...05-410,432-433 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   74.64 |    75.24 |      80 |   74.64 | ...82-783,791-792 
  tool-search.ts   |   95.19 |    86.48 |    92.3 |   95.19 | ...47-153,208-213 
  tools.ts         |   87.76 |       90 |   88.23 |   87.76 | ...50-451,467-473 
  web-fetch.ts     |   88.69 |    76.92 |    92.3 |   88.69 | ...10-311,313-314 
  write-file.ts    |    79.2 |    79.26 |   83.33 |    79.2 | ...39-642,654-689 
 src/tools/agent   |   83.39 |    84.95 |   83.92 |   83.39 |                   
  agent.ts         |   83.69 |    85.38 |   84.31 |   83.69 | ...1668,1677-1681 
  fork-subagent.ts |   78.26 |    71.42 |      80 |   78.26 | 54-72,104-105     
 src/utils         |   88.55 |    87.01 |   93.11 |   88.55 |                   
  LruCache.ts      |       0 |        0 |       0 |       0 | 1-41              
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   76.08 |    44.44 |     100 |   76.08 | 61-70,72          
  bareMode.ts      |   27.27 |      100 |       0 |   27.27 | 9-15,18-19        
  browser.ts       |    7.69 |      100 |       0 |    7.69 | 17-56             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  ...engthError.ts |   89.11 |    86.66 |     100 |   89.11 | ...28-129,132-133 
  cronDisplay.ts   |   42.85 |    23.07 |     100 |   42.85 | 26-31,33-45,47-54 
  cronParser.ts    |   89.74 |    85.71 |     100 |   89.74 | ...,63-64,183-186 
  debugLogger.ts   |    95.9 |    93.84 |   94.73 |    95.9 | 106-107,214-218   
  editHelper.ts    |   93.63 |    83.52 |     100 |   93.63 | ...28-429,463-464 
  editor.ts        |   97.61 |    95.71 |     100 |   97.61 | ...70-271,273-274 
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |     100 |    95.45 |     100 |     100 | 83                
  errorParsing.ts  |    97.7 |    97.05 |     100 |    97.7 | 72-73             
  ...rReporting.ts |   88.46 |       90 |     100 |   88.46 | 69-74             
  errors.ts        |   70.92 |    79.59 |   53.33 |   70.92 | ...03-219,223-229 
  fetch.ts         |   70.18 |    71.42 |   71.42 |   70.18 | ...42,148,161,186 
  fileUtils.ts     |   91.41 |    86.13 |      95 |   91.41 | ...1182,1186-1192 
  forkedAgent.ts   |    78.5 |    70.73 |   85.71 |    78.5 | ...30-436,441-447 
  formatters.ts    |   54.54 |       50 |     100 |   54.54 | 12-16             
  ...eUtilities.ts |   89.21 |    86.66 |     100 |   89.21 | 16-17,49-55,65-66 
  ...rStructure.ts |   94.36 |    94.28 |     100 |   94.36 | ...17-120,330-335 
  getPty.ts        |    12.5 |      100 |       0 |    12.5 | 21-34             
  gitDiff.ts       |   92.36 |    79.53 |     100 |   92.36 | ...55-856,928-929 
  ...noreParser.ts |    92.3 |    89.36 |     100 |    92.3 | ...15-116,186-187 
  gitUtils.ts      |   56.66 |    85.71 |      75 |   56.66 | ...2,72-73,97-148 
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...ionManager.ts |     100 |     90.9 |     100 |     100 | 26                
  ...lPromptIds.ts |     100 |      100 |     100 |     100 |                   
  jsonl-utils.ts   |    74.1 |    90.76 |   58.33 |    74.1 | ...23-326,336-342 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...yDiscovery.ts |    83.9 |    79.36 |     100 |    83.9 | ...16,319,411-414 
  ...tProcessor.ts |   93.63 |       90 |     100 |   93.63 | ...96-302,384-385 
  ...Inspectors.ts |   61.53 |      100 |      50 |   61.53 | 18-23             
  ...kerChecker.ts |   82.55 |    78.57 |     100 |   82.55 | 68-69,79-84,92-98 
  notebook.ts      |   94.35 |    84.78 |     100 |   94.35 | ...10,122,174-176 
  openaiLogger.ts  |   86.27 |    82.14 |     100 |   86.27 | ...05-107,130-135 
  partUtils.ts     |     100 |      100 |     100 |     100 |                   
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   93.21 |    91.86 |     100 |   93.21 | ...89-390,392-394 
  pdf.ts           |   93.68 |    87.05 |     100 |   93.68 | ...96-297,321-325 
  projectPath.ts   |     100 |      100 |     100 |     100 |                   
  ...ectSummary.ts |   89.39 |    72.41 |     100 |   89.39 | ...37-142,193-196 
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  proxyUtils.ts    |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   58.57 |       76 |     100 |   58.57 | ...4,88-89,95-100 
  ...noreParser.ts |   85.45 |    85.18 |     100 |   85.45 | ...59,65-66,72-73 
  rateLimit.ts     |   92.55 |    85.92 |     100 |   92.55 | ...70-272,309-310 
  readManyFiles.ts |   87.96 |    86.95 |     100 |   87.96 | ...05-207,223-234 
  retry.ts         |   89.81 |    88.05 |     100 |   89.81 | ...29,350,357-358 
  ripgrepUtils.ts  |   46.53 |    84.37 |   66.66 |   46.53 | ...32-233,245-322 
  ...sDiscovery.ts |   97.42 |    92.85 |     100 |   97.42 | ...04,182-183,202 
  ...tchOptions.ts |   63.85 |    64.28 |   83.33 |   63.85 | ...29-130,187-188 
  runtimeStatus.ts |   83.47 |    78.04 |     100 |   83.47 | ...87,242-248,250 
  safeJsonParse.ts |   74.07 |    83.33 |     100 |   74.07 | 40-46             
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   90.78 |    88.23 |     100 |   90.78 | ...41-42,93,95-96 
  ...aValidator.ts |   94.57 |    80.26 |     100 |   94.57 | ...04,213-216,270 
  ...r-launcher.ts |   76.92 |     91.3 |   66.66 |   76.92 | ...34,136,157-195 
  ...orageUtils.ts |   96.89 |    85.84 |     100 |   96.89 | ...51,367,447,466 
  shell-utils.ts   |   82.93 |    89.55 |     100 |   82.93 | ...1522,1529-1533 
  ...lAstParser.ts |   95.58 |    85.79 |     100 |   95.58 | ...1059-1061,1071 
  ...nlyChecker.ts |   95.75 |    92.39 |     100 |   95.75 | ...00-301,313-314 
  sideQuery.ts     |     100 |    92.85 |     100 |     100 | 43                
  ...tGenerator.ts |     100 |      100 |     100 |     100 |                   
  ...ameContext.ts |     100 |      100 |     100 |     100 |                   
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  terminalSafe.ts  |     100 |      100 |     100 |     100 |                   
  ...Serializer.ts |   98.72 |       90 |     100 |   98.72 | 42-43,134,201-203 
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  textUtils.ts     |      60 |      100 |   66.66 |      60 | 36-55             
  thoughtUtils.ts  |     100 |    92.85 |     100 |     100 | 71                
  ...-converter.ts |   94.59 |    85.71 |     100 |   94.59 | 35-36             
  tool-utils.ts    |    93.6 |     91.3 |     100 |    93.6 | ...58-159,162-163 
  truncation.ts    |     100 |       92 |     100 |     100 | 52,71             
  windowsPath.ts   |   89.47 |    79.31 |     100 |   89.47 | ...57-58,62,90-91 
  ...aceContext.ts |   93.71 |    89.28 |   93.33 |   93.71 | ...24-225,249-251 
  xml.ts           |     100 |      100 |     100 |     100 |                   
  yaml-parser.ts   |      92 |    84.31 |     100 |      92 | 49-53,65-69       
 ...ils/filesearch |   96.34 |    91.66 |     100 |   96.34 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   96.87 |    94.44 |     100 |   96.87 | 83-84             
  fileSearch.ts    |   93.29 |    86.76 |     100 |   93.29 | ...40-241,243-244 
  ignore.ts        |     100 |      100 |     100 |     100 |                   
  result-cache.ts  |     100 |     92.3 |     100 |     100 | 46                
 ...uest-tokenizer |   56.63 |    74.52 |   74.19 |   56.63 |                   
  ...eTokenizer.ts |   41.86 |    76.47 |   69.23 |   41.86 | ...70-443,453-507 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |      76 |      100 |   33.33 |      76 | 45-48,55-56       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

For detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run.

…rompt cache scope

- Use authToken instead of apiKey to send Authorization: Bearer header,
  avoiding dual-header conflicts with IdeaLab-style proxies
- Set User-Agent to claude-cli format and add x-app header for proxy
  Team rule compatibility
- Add adaptive thinking support for Claude 4.6+ models
- Enable prompt-caching-scope-2026-01-05 beta header and scope: global
  on system prompt cache_control to improve cross-session cache hit rates
@wenshao wenshao force-pushed the feat/anthropic-proxy-compat-and-cache-scope branch from 5327ad5 to 05a9c6e Compare May 10, 2026 10:59

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Request Changes to Comment: self-PR; CI failing (Test macos-latest, Test ubuntu-latest).

9 existing tests are broken by this PR — User-Agent, beta header, and cache_control scope assertions need updating.

Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/converter.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/converter.ts Outdated

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Request changes to Comment: self-PR; CI failing.

Review found 7 Critical and 9 Suggestion issues across 524 files (+74,929/-10,117 lines). Key Critical findings:

  1. modelSupportsAdaptiveThinking regex only matches single-digit versions [6-9]claude-opus-4-10 and beyond will not match
  2. User-approved command silently rewritten before execution — getConfirmationDetails shows raw command but execute() runs rewritten version; error messages actively hide the rewrite
  3. Synchronous execFileSync blocks event loop in commit attribution — getGitHeadSync + N+1 validateAgainst calls block 10-50ms+ each
  4. Promoted shell orphan zombie — no exit listener; registry stays running forever; PID recycling risk
  5. isAmendCommit / findAttributableCommitSegment mismatch — compound git commit && git commit --amend injects trailer on wrong segment
  6. hookRunner silently downgrades deny→allow — non-zero hook exits that previously blocked are now allowed with warning
  7. 172 tsc type errors — 164 TS4111 (index signature access), plus unused vars, missing return, missing types

Other Suggestion findings: beta header unconditional, User-Agent spoofed as claude-cli, Mistral provider false positive, shell.ts duplication (3725 lines), qwen-home-bootstrap.js sync hazard, priorReadEnforcement no dedicated test, chatCompressionService double JSON.stringify, WeChat detectImageMime incomplete WebP validation.

See inline comments for details.

Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
wenshao added 2 commits May 10, 2026 19:20
Address review feedback on PR #4020 by narrowing each workaround to where
it actually applies, instead of shipping it globally.

- Gate `Authorization: Bearer` (`authToken`), `claude-cli` User-Agent, and
  `x-app: cli` to non-Anthropic-native baseURLs. Direct `api.anthropic.com`
  users keep the SDK-default `x-api-key` (`apiKey`) auth and a truthful
  `QwenCode` User-Agent so usage isn't misattributed in Anthropic's
  logs/quotas, and so a stricter Anthropic backend doesn't 401 on a
  `Bearer`-shaped header.
- Gate the `prompt-caching-scope-2026-01-05` beta on `enableCacheControl`.
  When the converter isn't attaching `cache_control` to the body the beta
  is dead weight and risks 4xx responses from anthropic-compatible
  backends that don't recognize it. Restores the `betas.length === 0`
  early-return for the all-disabled case.
- Detect adaptive-thinking models with numeric major/minor compare instead
  of `[6-9]`. The character class missed `claude-haiku-4-6` entirely and
  would silently fall through to `budget_tokens` on `claude-opus-4-10` /
  `claude-opus-5-1` once those ship — tripping HTTP 400 with a shape the
  server no longer accepts.
- Honor explicit `reasoning.budget_tokens` before the adaptive branch.
  Adaptive omits `budget_tokens` from the wire shape, so checking it
  second silently dropped a user-supplied escape-hatch budget on Claude
  4.6+ models.
- Add `scope: 'global'` on the tool `cache_control` entry so the largest,
  slowest-changing prefix actually participates in cross-session caching
  under the new beta — the system-only attachment was capturing maybe
  half the available hit-rate improvement.
- Replace the misleading `as { type: 'ephemeral' }` cast on the system
  block (which erased `scope` from the type while leaving it on the
  wire) with a `AnthropicTextBlockParam` type that mirrors the existing
  `AnthropicToolParam` widening, so types match the runtime shape.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — deepseek-v4-pro

4 files, +322/−27. Build passes, all 89 tests green. Previous review comments all addressed.

Suggestion

**1. may diverge between generator and converter after hot **
,

The generator reads at request time (new code at line 316), but the converter captures it once at construction time (). If hot-switches mid-session, the beta header and body can disagree:

  • : beta header dropped but body still carries
  • : beta header sent but body has no

Suggested fix: have the converter read from the shared config object at convert time instead of caching at construction.

**2. Streaming and per-request beta tests don't assert **

Two existing tests use (where defaults to ) and verify / but not the new cache-scope beta flag. Both use so they pass even if the flag is accidentally removed.

Suggested fix: add at both locations.

Needs Human Review

  • Cache-scope beta () is gated only by , not by . Non-Anthropic backends may 4xx on unknown beta flags. Mitigation exists: set .
  • has two uncovered branches ( subdomain matching, URL parse failure catch).

Verdict

Comment — no Critical issues. All determinations pre-checked: self-PR, CI has Agent failure (unrelated to this diff).

— deepseek-v4-pro via Qwen Code /review

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — deepseek-v4-pro

4 files, +322/−27. Build passes, all 89 tests green. Previous review comments all addressed.

Suggestion

1. enableCacheControl may diverge between generator and converter after hot setModel()
packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts:316, converter.ts:91-94

The generator reads this.contentGeneratorConfig.enableCacheControl at request time (new code at line 316), but the converter captures it once at construction time (converter.ts:91-94). If Config.setModel() hot-switches enableCacheControl mid-session, the beta header and body cache_control can disagree:

  • true → false: beta header dropped but body still carries scope: 'global'
  • false → true: beta header sent but body has no cache_control

Suggested fix: have the converter read from the shared config object at convert time instead of caching at construction.

2. Streaming and per-request beta tests don't assert prompt-caching-scope-2026-01-05
packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.test.ts:463, 495

Two existing tests use baseConfig (where enableCacheControl defaults to true) and verify interleaved-thinking-2025-05-14 / effort-2025-11-24 but not the new cache-scope beta flag. Both use toContain so they pass even if the flag is accidentally removed.

Suggested fix: add expect(headers['anthropic-beta']).toContain('prompt-caching-scope-2026-01-05') at both locations.

Needs Human Review

  • Cache-scope beta (prompt-caching-scope-2026-01-05) is gated only by enableCacheControl, not by isAnthropicNativeBaseUrl. Non-Anthropic backends may 4xx on unknown beta flags. Mitigation exists: set enableCacheControl: false.
  • isAnthropicNativeBaseUrl has two uncovered branches (.anthropic.com subdomain matching, URL parse failure catch).

Verdict

Comment — no Critical issues. All determinations pre-checked: self-PR, CI has Agent failure (unrelated to this diff).

— deepseek-v4-pro via Qwen Code /review

Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Follow-up on PR #4020 review: `Config.setModel()` mutates
`enableCacheControl` in place (it's in `MODEL_GENERATION_CONFIG_FIELDS`),
but the converter captured it once at construction. On a hot flip the
generator's per-request `prompt-caching-scope-2026-01-05` beta gate would
sample the new value while the converter still emitted the old body-side
`cache_control` — beta-header and body could disagree.

- Thread the live `contentGeneratorConfig.enableCacheControl` into the
  converter via a per-call options override on both
  `convertGeminiRequestToAnthropic` and `convertGeminiToolsToAnthropic`,
  falling back to the constructor-time default when the caller doesn't
  pass one. The generator samples the value once per `buildRequest` and
  forwards it to both convert calls so the body and beta header always
  agree within a request, even across `setModel` flips.
- Regression test: hot-flip `enableCacheControl` from `true` to `false`
  on a live generator, verify the 2nd request drops both the beta header
  AND the body-side `cache_control` in lockstep.
- Tighten two existing beta-header tests that used `toContain` only on
  `interleaved-thinking` / `effort` — they now also assert
  `prompt-caching-scope-2026-01-05` is present (per-request keep-default
  and streaming paths), so accidental removal trips the test.
- Add coverage for the two previously-uncovered branches of
  `isAnthropicNativeBaseUrl`: `*.anthropic.com` subdomains
  (Anthropic-native) and a malformed baseURL (URL parse failure → proxy
  fallthrough). Also add an `anthropic.com.evil.com` hostname-spoof case
  mirroring the existing DeepSeek spoof test.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

…e cases

Follow-up on PR #4020 review:

- Extract `AnthropicThinkingParam` type alias. The thinking union
  `{ type: 'enabled'; budget_tokens } | { type: 'adaptive' }` was repeated
  verbatim in three places: the `MessageCreateParamsWithThinking` field,
  the streaming-request intersection, and `buildThinkingConfig`'s return
  type. Once a third shape ships, forgetting one site would silently
  narrow a runtime value — single alias keeps them locked.
- Compute `useProxyIdentity` once in the constructor and pass it into
  `buildHeaders`. Previously `useBearerAuth` and `useProxyIdentity` named
  the same predicate at two call sites; collapsing them clarifies that
  Bearer auth + `claude-cli` UA + `x-app: cli` are one bundle that
  should never be split.
- Document that `modelSupportsAdaptiveThinking`'s regex is intentionally
  unanchored so reseller-prefixed names (`bedrock/claude-opus-4-7`,
  `vertex_ai/claude-sonnet-4-6@…`, `idealab:claude-opus-4-6`, …) keep
  matching. Tightening to `^claude-` would silently regress those.
- Soften the `prompt-caching-scope` beta comment so it describes what
  the code enforces (gate on the `enableCacheControl` flag) rather than
  promising a stronger "only ship when cache_control is on the body"
  invariant — the converter still skips `cache_control` on niche shapes
  (e.g. no system text, no tools, last user block isn't text). The
  looser gate is intentional; Anthropic-native ignores unused betas.
- Pin the wire shape for the `reasoning: undefined` + 4.6+ model corner.
  `resolveEffectiveEffort` returns undefined on `reasoning === undefined`,
  so `buildThinkingConfig` ships `{ type: 'adaptive' }` with no
  `output_config` and no `effort-2025-11-24` beta. If Anthropic ever
  starts requiring `output_config.effort` alongside adaptive, this test
  will fail at CI rather than at runtime as a server 400.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Comment to Comment: self-PR. Additional findings that cannot be mapped to specific diff lines:

  1. addCacheControlToMessages missing scope: 'global'converter.ts addCacheControlToMessages (L~789) still writes { type: 'ephemeral' } without scope: 'global', inconsistent with system/tool blocks which both added scope: 'global' in this PR. User messages change per-request so cross-session caching here has lower value, but no comment explains the intentional omission — future maintainers may mistake it for a bug.

  2. Converter per-call enableCacheControl override untestedconverter.test.ts has no tests passing { enableCacheControl: false/true } to convertGeminiRequestToAnthropic or convertGeminiToolsToAnthropic. The ?? fallback path that enables hot Config.setModel() flips is never verified at the converter level.

  3. Hot flip test doesn't verify tool pathanthropicContentGenerator.test.ts "hot enableCacheControl flips" test only asserts system output, not tool cache_control from convertGeminiToolsToAnthropic.

— DeepSeek/deepseek-v4-pro via Qwen Code /review

…gate

Follow-up on PR #4020 review: the `prompt-caching-scope-2026-01-05` beta
header and the body-side `scope: 'global'` field together comprise an
Anthropic-only wire-shape extension. Shipping them to non-Anthropic
backends (DeepSeek, IdeaLab) leaned on "unknown betas are ignored" —
true on Anthropic-native, but unverified for proxies and silently
inconsistent with the auth/identity gate, which already uses
`isAnthropicNativeBaseUrl` to bind Bearer / claude-cli / x-app to the
proxy path only.

- Add `useGlobalCacheScope` predicate on the generator. True iff
  `enableCacheControl !== false` AND the resolved baseURL is
  Anthropic-native. Plumbed per-request into both
  `convertGeminiRequestToAnthropic` and `convertGeminiToolsToAnthropic`;
  the same predicate also gates the `prompt-caching-scope-2026-01-05`
  beta in `buildPerRequestHeaders` so beta + scope field always travel
  together.
- Converter emits `cache_control: { type: 'ephemeral' }` (per-session)
  when scope is off and `{ type: 'ephemeral', scope: 'global' }` when on.
  Non-Anthropic baseURLs go back to their pre-PR per-session caching
  shape; existing prompt caching keeps working with no new beta.
- Document the intentional `scope: 'global'` omission on
  `addCacheControlToMessages`. The last user message changes every
  turn (live prompt + immediate tool_results), so cross-session reuse
  has effectively zero hit rate; cross-session caching is concentrated
  on system + tool prefixes only.

Tests:
- DeepSeek baseURL pins the proxy auth/identity path
  (`authToken` / claude-cli UA / `x-app: cli`). Documents the
  contract assumption that DeepSeek's anthropic-compatible endpoint
  accepts `Authorization: Bearer` — any future deviation surfaces
  here rather than at runtime for users.
- Non-Anthropic baseURL strips the cache-scope beta AND
  `scope: 'global'` from the wire shape, while keeping per-session
  `cache_control: { type: 'ephemeral' }` on system / tools.
- Hot-flip test extended to assert tool `cache_control` flips alongside
  system / user / beta header.
- Converter-level tests for per-call `enableCacheControl` and
  `useGlobalCacheScope` overrides — both directions of the constructor
  default (true→false, false→true) and the scope-independent-of-source
  case (cache on, scope off → per-session shape).
- baseConfig in the per-request anthropic-beta block now targets
  `api.anthropic.com` so cache-scope assertions remain meaningful; the
  proxy-baseURL behavior is covered separately.
@wenshao wenshao requested a review from Copilot May 11, 2026 09:44
@wenshao

wenshao commented May 11, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for catching this — confirmed the credential-leak path and fixed in ea4ce13df.

What changed

The leak (your scenario): SDK destructures with defaults (apiKey = readEnv('ANTHROPIC_API_KEY') ?? null); defaults fire only for undefined. The proxy branch spread { authToken: <key> } and omitted apiKey, so ANTHROPIC_API_KEY back-filled it, and the SDK's auth resolver preferred apiKey over authToken. A user with ANTHROPIC_API_KEY=sk-ant-… exported plus an IdeaLab baseUrl would ship the real Anthropic key as X-Api-Key to the third-party proxy.

Fix: explicit null on the unused auth field on both branches.

...(useProxyIdentity
  ? { authToken: contentGeneratorConfig.apiKey, apiKey: null }
  : { apiKey: contentGeneratorConfig.apiKey, authToken: null }),

Destructuring default no longer fires; env back-fill is dead.

Inverse direction (you flagged it alongside): isAnthropicNativeBaseUrl only read config.baseUrl, so a user configuring the proxy purely through ANTHROPIC_BASE_URL (with baseUrl unset) would route to the proxy but ship native auth + UA + cache-scope. Added resolveEffectiveBaseUrl that mirrors the SDK's own resolution (config → ANTHROPIC_BASE_URL env → SDK default) and threads it through the predicate.

Tests

Five new regression tests in the env-poison suite — all assert the exact constructor args:

  • ANTHROPIC_API_KEY env + proxy baseURL → ctor receives apiKey: null (pins the leak fix).
  • ANTHROPIC_AUTH_TOKEN env + Anthropic-native baseURL → ctor receives authToken: null.
  • ANTHROPIC_BASE_URL env points to proxy, baseUrl unset → proxy identity bundle applies.
  • ANTHROPIC_BASE_URL unset → SDK default stays Anthropic-native.
  • config.baseUrl wins over ANTHROPIC_BASE_URL.

Also updated the existing 7 identity tests from toBeUndefined() to toBeNull() to match the explicit-suppression contract.

Re-requesting review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
Comment thread packages/core/src/core/anthropicContentGenerator/converter.ts Outdated
tanzhenxin
tanzhenxin previously approved these changes May 11, 2026

@tanzhenxin tanzhenxin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Both code-level findings from the prior round are closed. The Bearer-auth env back-fill is fixed at the right place — passing apiKey: null (and the symmetric authToken: null on the native branch) suppresses the SDK's destructuring default, since defaults fire only for undefined. The new regression test does the right thing: stubs the env, asserts the explicit-null contract rather than toBeUndefined(), and would fail under the pre-fix code. The ANTHROPIC_BASE_URL classification fix mirrors the SDK's resolution order precisely (config → env → default), and the cache-scope gate inherits the env-aware predicate automatically, so identity and cache-scope stay paired.

Verdict

APPROVE — solid follow-up. The fix is minimal, the tests exercise the real failure mode rather than mocking it away, and the symmetric ANTHROPIC_AUTH_TOKEN guard is a nice defensive add even though it wasn't strictly requested.

…icate

#4020 review (Copilot): the comment promised "beta and body-side
scope: 'global' field always ship together" but the gate was just
`useGlobalCacheScope()`. In the degenerate case where the predicate is
true but the request body has no system text AND no tools, the beta
would still ship without any matching `cache_control.scope: 'global'`
on the wire — overstating the contract and shipping dead weight.

- New `hasGlobalCacheScopeOnWire(req)` scans the assembled request body
  (system block when shaped as `TextBlockParam[]`, tools array) for any
  `cache_control: { …, scope: 'global' }` entry. `buildPerRequestHeaders`
  gates the `prompt-caching-scope-2026-01-05` beta on this scan, so the
  beta and the body field share a single source of truth. No window
  between sampling the predicate and emitting the body where the two
  could diverge.
- `useGlobalCacheScope()` is still sampled once per `buildRequest` and
  threaded into the converter to decide whether to ATTACH
  `scope: 'global'` to the body. The body-scan downstream then derives
  the beta from what actually landed.

Tests:
- New: empty systemInstruction + no tools + Anthropic-native + cache on
  → beta NOT shipped (degenerate body-scan case).
- New: empty systemInstruction + non-empty tools → beta shipped
  (tool scope:'global' triggers the scan).
- Existing per-request beta tests now include a `systemInstruction` so
  the body has the scope field; degenerate case is covered by the new
  dedicated test.

Also tightened two stale comments (#3217834451, #3217834505) that
claimed `Config.setModel()` mutates both `enableCacheControl` and
`baseUrl` in place — only `enableCacheControl` is hot-mutated (qwen-oauth
path); non-qwen-oauth providers recreate the generator on refresh, so
`baseUrl` is captured fresh at construct time. Comments now describe the
real in-place mutation and note the qwen-oauth boundary.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

Comment thread packages/core/src/core/anthropicContentGenerator/anthropicContentGenerator.ts Outdated
#4020 review (Copilot): two low-stakes follow-ups on 491a441.

- `resolveEffectiveBaseUrl` trimmed `ANTHROPIC_BASE_URL` env but
  returned `contentGeneratorConfig.baseUrl` as-is. A copy-pasted baseURL
  with leading/trailing whitespace would trip `new URL(...)` in
  `isAnthropicNativeBaseUrl` and fall through the catch branch to the
  proxy identity bundle — meaning real api.anthropic.com would receive
  Bearer auth + claude-cli UA and 401. Apply the same trim() +
  empty-as-missing normalization on the config side. New regression
  test pins the contract with `'  https://api.anthropic.com  '`.
- `buildHeaders` docstring said constructor headers carry only
  User-Agent + customHeaders (excluding anthropic-beta). The PR also
  added `x-app: cli` on the proxy path; updated the comment so a future
  maintainer reading the "no duplicate headers" rationale doesn't
  miss the x-app addition.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

// half of the bundle without the other.
const useProxyIdentity = !isAnthropicNativeBaseUrl(contentGeneratorConfig);
const defaultHeaders = this.buildHeaders(useProxyIdentity);
const baseURL = contentGeneratorConfig.baseUrl;
Comment on lines +85 to +107
/**
* Resolve the baseURL the Anthropic SDK will actually use, mirroring the
* SDK's own destructuring-default order: explicit config first, then
* `ANTHROPIC_BASE_URL` env, then the SDK default. Returns the SDK default
* literal when nothing is configured so callers can do hostname matching
* without a special case for the empty path.
*
* Both inputs get the SDK's `readEnv`-style normalization
* (whitespace-trim + empty-as-missing). Trimming the config side too
* prevents a copy-pasted baseURL with stray whitespace from tripping
* `new URL(...)` in `isAnthropicNativeBaseUrl`, which would otherwise
* fall through the catch branch to proxy identity and ship Bearer auth
* against the real Anthropic API.
*/
function resolveEffectiveBaseUrl(
contentGeneratorConfig: ContentGeneratorConfig,
): string {
const fromConfig = contentGeneratorConfig.baseUrl?.trim();
if (fromConfig) return fromConfig;
const fromEnv = process.env['ANTHROPIC_BASE_URL']?.trim();
if (fromEnv) return fromEnv;
return 'https://api.anthropic.com';
}
@wenshao wenshao requested a review from tanzhenxin May 11, 2026 10:54

@tanzhenxin tanzhenxin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Re-reviewed the two follow-up commits since the dismissed approve. The cache-scope refactor is the substantive one — it replaces the predicate-based gate on prompt-caching-scope-2026-01-05 with a scan of the assembled request body, so the header now ships iff a block actually carries scope: 'global' on the wire. Single source of truth, locked in by tests on both the degenerate path (empty system + no tools → no beta) and the tools-only path. The baseUrl trim commit is small but adds parity with the SDK's readEnv whitespace handling and a regression test for whitespace-wrapped native URLs.

The minor observations from the prior round are unchanged or only partially closed (whitespace-only config now resolves correctly; strict baseUrl: '' still routes differently between the predicate and the SDK constructor; the PR description framing on the type widening still doesn't match what was on main). None of them gate merge — no caller passes an empty string, and the predicate/constructor divergence would require a mid-stack process.env mutation that doesn't happen in practice. One small commit-message nit on the trim commit: it says whitespace-wrapped URLs "trip new URL(...)", but Node's URL constructor tolerates leading/trailing whitespace fine — the trim is still useful for parity and normalization, just not for the failure mode the message describes.

Verdict

APPROVE — both new commits hold up; the body-scan refactor is structurally tighter than the predicate-only gate it replaces.

@pomelo-nwu pomelo-nwu merged commit bdd5b60 into main May 11, 2026
12 checks passed

@wenshao wenshao left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Downgraded from Comment to Comment: self-PR.

Additional findings not mapped to specific diff lines:

[Suggestion] Missing test: ANTHROPIC_BASE_URL env-side whitespace trimresolveEffectiveBaseUrl trims both config and env inputs, but only config-side whitespace has a direct test. An env value like ' https://api.anthropic.com ' going untrimmed would misclassify as proxy identity.

[Suggestion] Missing test: empty-string / whitespace-only baseUrlresolveEffectiveBaseUrl treats '' and ' ' as missing (falls through to env/default). No test covers these edge cases.

[Suggestion] No diagnostic logging for auth path selection — The constructor makes an important security decision (apiKey vs authToken) silently. A debugLogger.debug line for the selected auth path + resolved baseURL would aid 401/403 incident debugging.

// half of the bundle without the other.
const useProxyIdentity = !isAnthropicNativeBaseUrl(contentGeneratorConfig);
const defaultHeaders = this.buildHeaders(useProxyIdentity);
const baseURL = contentGeneratorConfig.baseUrl;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] SDK receives untrimmed baseURL while classification uses trimmed value. resolveEffectiveBaseUrl() trims whitespace and resolves env fallback for classification, but this line passes the raw contentGeneratorConfig.baseUrl to the SDK constructor. A copy-pasted URL like ' https://api.anthropic.com ' classifies correctly as Anthropic-native (correct auth/identity) but the SDK receives the whitespace-padded string — which may cause TypeError or connection failures.

Suggested change
const baseURL = contentGeneratorConfig.baseUrl;
const baseURL = resolveEffectiveBaseUrl(contentGeneratorConfig);

— glm-5.1 via Qwen Code /review

this.client = new Anthropic({
apiKey: contentGeneratorConfig.apiKey,
...(useProxyIdentity
? { authToken: contentGeneratorConfig.apiKey, apiKey: null }

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] SDK null auth contract lacks regression protection. Passing null to suppress env back-fill is correct and well-documented, but all tests mock the SDK. If a future @anthropic-ai/sdk version normalizes null to undefined in its constructor, the credential leak silently returns — ANTHROPIC_API_KEY env would back-fill the "unused" field, shipping the real key to a third-party proxy. Consider adding an integration test that runs against the real SDK (not a mock) with ANTHROPIC_API_KEY set, verifying the suppressed field remains unset.

— glm-5.1 via Qwen Code /review

wenshao added a commit that referenced this pull request May 17, 2026
…rompt cache scope (#4020)

* feat(core): improve Anthropic proxy compatibility and enable global prompt cache scope

- Use authToken instead of apiKey to send Authorization: Bearer header,
  avoiding dual-header conflicts with IdeaLab-style proxies
- Set User-Agent to claude-cli format and add x-app header for proxy
  Team rule compatibility
- Add adaptive thinking support for Claude 4.6+ models
- Enable prompt-caching-scope-2026-01-05 beta header and scope: global
  on system prompt cache_control to improve cross-session cache hit rates

* test: update tests for User-Agent, beta header, and cache_control changes

* fix(core): scope anthropic proxy workarounds to non-native baseURLs only

Address review feedback on PR #4020 by narrowing each workaround to where
it actually applies, instead of shipping it globally.

- Gate `Authorization: Bearer` (`authToken`), `claude-cli` User-Agent, and
  `x-app: cli` to non-Anthropic-native baseURLs. Direct `api.anthropic.com`
  users keep the SDK-default `x-api-key` (`apiKey`) auth and a truthful
  `QwenCode` User-Agent so usage isn't misattributed in Anthropic's
  logs/quotas, and so a stricter Anthropic backend doesn't 401 on a
  `Bearer`-shaped header.
- Gate the `prompt-caching-scope-2026-01-05` beta on `enableCacheControl`.
  When the converter isn't attaching `cache_control` to the body the beta
  is dead weight and risks 4xx responses from anthropic-compatible
  backends that don't recognize it. Restores the `betas.length === 0`
  early-return for the all-disabled case.
- Detect adaptive-thinking models with numeric major/minor compare instead
  of `[6-9]`. The character class missed `claude-haiku-4-6` entirely and
  would silently fall through to `budget_tokens` on `claude-opus-4-10` /
  `claude-opus-5-1` once those ship — tripping HTTP 400 with a shape the
  server no longer accepts.
- Honor explicit `reasoning.budget_tokens` before the adaptive branch.
  Adaptive omits `budget_tokens` from the wire shape, so checking it
  second silently dropped a user-supplied escape-hatch budget on Claude
  4.6+ models.
- Add `scope: 'global'` on the tool `cache_control` entry so the largest,
  slowest-changing prefix actually participates in cross-session caching
  under the new beta — the system-only attachment was capturing maybe
  half the available hit-rate improvement.
- Replace the misleading `as { type: 'ephemeral' }` cast on the system
  block (which erased `scope` from the type while leaving it on the
  wire) with a `AnthropicTextBlockParam` type that mirrors the existing
  `AnthropicToolParam` widening, so types match the runtime shape.

* fix(core): keep enableCacheControl live in the converter

Follow-up on PR #4020 review: `Config.setModel()` mutates
`enableCacheControl` in place (it's in `MODEL_GENERATION_CONFIG_FIELDS`),
but the converter captured it once at construction. On a hot flip the
generator's per-request `prompt-caching-scope-2026-01-05` beta gate would
sample the new value while the converter still emitted the old body-side
`cache_control` — beta-header and body could disagree.

- Thread the live `contentGeneratorConfig.enableCacheControl` into the
  converter via a per-call options override on both
  `convertGeminiRequestToAnthropic` and `convertGeminiToolsToAnthropic`,
  falling back to the constructor-time default when the caller doesn't
  pass one. The generator samples the value once per `buildRequest` and
  forwards it to both convert calls so the body and beta header always
  agree within a request, even across `setModel` flips.
- Regression test: hot-flip `enableCacheControl` from `true` to `false`
  on a live generator, verify the 2nd request drops both the beta header
  AND the body-side `cache_control` in lockstep.
- Tighten two existing beta-header tests that used `toContain` only on
  `interleaved-thinking` / `effort` — they now also assert
  `prompt-caching-scope-2026-01-05` is present (per-request keep-default
  and streaming paths), so accidental removal trips the test.
- Add coverage for the two previously-uncovered branches of
  `isAnthropicNativeBaseUrl`: `*.anthropic.com` subdomains
  (Anthropic-native) and a malformed baseURL (URL parse failure → proxy
  fallthrough). Also add an `anthropic.com.evil.com` hostname-spoof case
  mirroring the existing DeepSeek spoof test.

* refactor(core): consolidate anthropic generator shapes & document edge cases

Follow-up on PR #4020 review:

- Extract `AnthropicThinkingParam` type alias. The thinking union
  `{ type: 'enabled'; budget_tokens } | { type: 'adaptive' }` was repeated
  verbatim in three places: the `MessageCreateParamsWithThinking` field,
  the streaming-request intersection, and `buildThinkingConfig`'s return
  type. Once a third shape ships, forgetting one site would silently
  narrow a runtime value — single alias keeps them locked.
- Compute `useProxyIdentity` once in the constructor and pass it into
  `buildHeaders`. Previously `useBearerAuth` and `useProxyIdentity` named
  the same predicate at two call sites; collapsing them clarifies that
  Bearer auth + `claude-cli` UA + `x-app: cli` are one bundle that
  should never be split.
- Document that `modelSupportsAdaptiveThinking`'s regex is intentionally
  unanchored so reseller-prefixed names (`bedrock/claude-opus-4-7`,
  `vertex_ai/claude-sonnet-4-6@…`, `idealab:claude-opus-4-6`, …) keep
  matching. Tightening to `^claude-` would silently regress those.
- Soften the `prompt-caching-scope` beta comment so it describes what
  the code enforces (gate on the `enableCacheControl` flag) rather than
  promising a stronger "only ship when cache_control is on the body"
  invariant — the converter still skips `cache_control` on niche shapes
  (e.g. no system text, no tools, last user block isn't text). The
  looser gate is intentional; Anthropic-native ignores unused betas.
- Pin the wire shape for the `reasoning: undefined` + 4.6+ model corner.
  `resolveEffectiveEffort` returns undefined on `reasoning === undefined`,
  so `buildThinkingConfig` ships `{ type: 'adaptive' }` with no
  `output_config` and no `effort-2025-11-24` beta. If Anthropic ever
  starts requiring `output_config.effort` alongside adaptive, this test
  will fail at CI rather than at runtime as a server 400.

* fix(core): gate cache-scope on Anthropic-native baseURL, mirror auth gate

Follow-up on PR #4020 review: the `prompt-caching-scope-2026-01-05` beta
header and the body-side `scope: 'global'` field together comprise an
Anthropic-only wire-shape extension. Shipping them to non-Anthropic
backends (DeepSeek, IdeaLab) leaned on "unknown betas are ignored" —
true on Anthropic-native, but unverified for proxies and silently
inconsistent with the auth/identity gate, which already uses
`isAnthropicNativeBaseUrl` to bind Bearer / claude-cli / x-app to the
proxy path only.

- Add `useGlobalCacheScope` predicate on the generator. True iff
  `enableCacheControl !== false` AND the resolved baseURL is
  Anthropic-native. Plumbed per-request into both
  `convertGeminiRequestToAnthropic` and `convertGeminiToolsToAnthropic`;
  the same predicate also gates the `prompt-caching-scope-2026-01-05`
  beta in `buildPerRequestHeaders` so beta + scope field always travel
  together.
- Converter emits `cache_control: { type: 'ephemeral' }` (per-session)
  when scope is off and `{ type: 'ephemeral', scope: 'global' }` when on.
  Non-Anthropic baseURLs go back to their pre-PR per-session caching
  shape; existing prompt caching keeps working with no new beta.
- Document the intentional `scope: 'global'` omission on
  `addCacheControlToMessages`. The last user message changes every
  turn (live prompt + immediate tool_results), so cross-session reuse
  has effectively zero hit rate; cross-session caching is concentrated
  on system + tool prefixes only.

Tests:
- DeepSeek baseURL pins the proxy auth/identity path
  (`authToken` / claude-cli UA / `x-app: cli`). Documents the
  contract assumption that DeepSeek's anthropic-compatible endpoint
  accepts `Authorization: Bearer` — any future deviation surfaces
  here rather than at runtime for users.
- Non-Anthropic baseURL strips the cache-scope beta AND
  `scope: 'global'` from the wire shape, while keeping per-session
  `cache_control: { type: 'ephemeral' }` on system / tools.
- Hot-flip test extended to assert tool `cache_control` flips alongside
  system / user / beta header.
- Converter-level tests for per-call `enableCacheControl` and
  `useGlobalCacheScope` overrides — both directions of the constructor
  default (true→false, false→true) and the scope-independent-of-source
  case (cache on, scope off → per-session shape).
- baseConfig in the per-request anthropic-beta block now targets
  `api.anthropic.com` so cache-scope assertions remain meaningful; the
  proxy-baseURL behavior is covered separately.

* docs(core): tighten useGlobalCacheScope JSDoc — baseUrl is NOT hot-mutated

#4020 review: the JSDoc claimed `Config.setModel()` mutates both
`enableCacheControl` AND `baseUrl` in place. Per the current Config
implementation, only the qwen-oauth hot-update path mutates
`enableCacheControl` in place; non-qwen-oauth providers go through
the refresh path which recreates the ContentGenerator (so `baseUrl`
is captured fresh at construct time, not mutated).

Tightened the wording to reflect actual behavior + kept the
read-both-each-request defense (cheap and avoids stale-cache
surprises if the hot-update list ever expands).

* fix(core)!: suppress env back-fill so proxy auth doesn't leak real Anthropic key

#4020 review (tanzhenxin, severity high): the IdeaLab-proxy branch
spread `{ authToken: <key> }` and omitted `apiKey` entirely. The
Anthropic SDK constructor destructures with defaults
(`apiKey = readEnv('ANTHROPIC_API_KEY') ?? null`), and destructuring
defaults only fire for `undefined` — so an omitted `apiKey` lets
`ANTHROPIC_API_KEY` back-fill it. The SDK's auth resolver then prefers
`apiKey` over `authToken`, shipping `X-Api-Key` (not
`Authorization: Bearer`) on the wire. Concrete impact: a user with
`ANTHROPIC_API_KEY=sk-ant-…` exported (normal for anyone also running
Claude Code in the same shell) configuring qwen-code with an IdeaLab
proxy plus an IdeaLab token would leak their real Anthropic key as
`X-Api-Key` to the third-party proxy endpoint.

- Pass `apiKey: null` explicitly on the proxy branch and `authToken: null`
  on the Anthropic-native branch. Explicit `null` suppresses the
  destructuring default; the env back-fill no longer fires.
- New helper `resolveEffectiveBaseUrl` mirrors the SDK's own
  destructuring order (config → `ANTHROPIC_BASE_URL` env → SDK default).
  `isAnthropicNativeBaseUrl` now consults the env too, so a user
  configuring the proxy purely through `ANTHROPIC_BASE_URL` (qwen-code
  `baseUrl` unset) gets the proxy identity bundle instead of silently
  shipping native auth + UA + cache-scope beta to the proxy.

Tests:
- ANTHROPIC_API_KEY env + proxy baseURL → ctor receives `apiKey: null`
  and `authToken: our-key`. Locks in the credential-leak fix.
- ANTHROPIC_AUTH_TOKEN env + Anthropic-native baseURL → ctor receives
  `authToken: null` and `apiKey: our-key`. Symmetric guard for the
  inverse direction.
- ANTHROPIC_BASE_URL env points to proxy, config.baseUrl unset → proxy
  identity bundle (claude-cli UA, x-app, Bearer auth) applies.
- ANTHROPIC_BASE_URL unset → SDK default api.anthropic.com path keeps
  native identity (predicate doesn't misclassify the SDK default as a
  proxy).
- config.baseUrl wins over ANTHROPIC_BASE_URL — mirrors the SDK's own
  resolution order.
- Existing 7 identity tests updated from `toBeUndefined()` to
  `toBeNull()` to match the new explicit-suppression contract.

* refactor(core): gate cache-scope beta on body presence, not just predicate

#4020 review (Copilot): the comment promised "beta and body-side
scope: 'global' field always ship together" but the gate was just
`useGlobalCacheScope()`. In the degenerate case where the predicate is
true but the request body has no system text AND no tools, the beta
would still ship without any matching `cache_control.scope: 'global'`
on the wire — overstating the contract and shipping dead weight.

- New `hasGlobalCacheScopeOnWire(req)` scans the assembled request body
  (system block when shaped as `TextBlockParam[]`, tools array) for any
  `cache_control: { …, scope: 'global' }` entry. `buildPerRequestHeaders`
  gates the `prompt-caching-scope-2026-01-05` beta on this scan, so the
  beta and the body field share a single source of truth. No window
  between sampling the predicate and emitting the body where the two
  could diverge.
- `useGlobalCacheScope()` is still sampled once per `buildRequest` and
  threaded into the converter to decide whether to ATTACH
  `scope: 'global'` to the body. The body-scan downstream then derives
  the beta from what actually landed.

Tests:
- New: empty systemInstruction + no tools + Anthropic-native + cache on
  → beta NOT shipped (degenerate body-scan case).
- New: empty systemInstruction + non-empty tools → beta shipped
  (tool scope:'global' triggers the scan).
- Existing per-request beta tests now include a `systemInstruction` so
  the body has the scope field; degenerate case is covered by the new
  dedicated test.

Also tightened two stale comments (#3217834451, #3217834505) that
claimed `Config.setModel()` mutates both `enableCacheControl` and
`baseUrl` in place — only `enableCacheControl` is hot-mutated (qwen-oauth
path); non-qwen-oauth providers recreate the generator on refresh, so
`baseUrl` is captured fresh at construct time. Comments now describe the
real in-place mutation and note the qwen-oauth boundary.

* fix(core): trim config.baseUrl and document x-app in buildHeaders

#4020 review (Copilot): two low-stakes follow-ups on 491a441.

- `resolveEffectiveBaseUrl` trimmed `ANTHROPIC_BASE_URL` env but
  returned `contentGeneratorConfig.baseUrl` as-is. A copy-pasted baseURL
  with leading/trailing whitespace would trip `new URL(...)` in
  `isAnthropicNativeBaseUrl` and fall through the catch branch to the
  proxy identity bundle — meaning real api.anthropic.com would receive
  Bearer auth + claude-cli UA and 401. Apply the same trim() +
  empty-as-missing normalization on the config side. New regression
  test pins the contract with `'  https://api.anthropic.com  '`.
- `buildHeaders` docstring said constructor headers carry only
  User-Agent + customHeaders (excluding anthropic-beta). The PR also
  added `x-app: cli` on the proxy path; updated the comment so a future
  maintainer reading the "no duplicate headers" rationale doesn't
  miss the x-app addition.
LaZzyMan added a commit that referenced this pull request May 20, 2026
#4323)

On the IdeaLab-style proxy branch, the Anthropic SDK is constructed with
`authToken: <key>, apiKey: null` so it emits `Authorization: Bearer <key>`
and suppresses the ANTHROPIC_API_KEY env back-fill (the #4020 leak fix).
That covers IdeaLab and CherryStudio-style proxies, but standards-
compliant Anthropic-compatible servers (OpenCode-Go, Claude proxy
products) authenticate only on the canonical `x-api-key` header and
reject the request with "Missing API key" even though the bearer token
is present.

Inject `x-api-key: <key>` into `defaultHeaders` on the proxy branch
(post-`buildHeaders`, so customHeaders cannot override it). The value
is the user's already-configured `apiKey` — never an env-resolved one —
so the #4020 env-leak vector stays closed. The Anthropic-native branch
is untouched: the SDK's apiKey path already emits the header, and
duplicating it via defaultHeaders would risk stale-value drift.

Verified:
- new unit test pins `x-api-key: <key>` on every proxy-branch case
  (config-baseUrl, malformed baseUrl, DeepSeek anthropic-compat,
  ANTHROPIC_BASE_URL env-pointed-at-proxy); a negative test pins that
  the native branch does NOT add the header.
- E2E: spun up a local `http.createServer`, pointed the SDK at it the
  same way `AnthropicContentGenerator` does, and dumped the captured
  wire headers — `Authorization: Bearer` and `x-api-key` both arrive
  alongside the existing X-Stainless-* / x-app / claude-cli UA trio.

Fixes #4323
pomelo-nwu pushed a commit that referenced this pull request May 21, 2026
#4323) (#4342)

* fix(core): set x-api-key alongside Authorization on Anthropic outbound (#4323)

On the IdeaLab-style proxy branch, the Anthropic SDK is constructed with
`authToken: <key>, apiKey: null` so it emits `Authorization: Bearer <key>`
and suppresses the ANTHROPIC_API_KEY env back-fill (the #4020 leak fix).
That covers IdeaLab and CherryStudio-style proxies, but standards-
compliant Anthropic-compatible servers (OpenCode-Go, Claude proxy
products) authenticate only on the canonical `x-api-key` header and
reject the request with "Missing API key" even though the bearer token
is present.

Inject `x-api-key: <key>` into `defaultHeaders` on the proxy branch
(post-`buildHeaders`, so customHeaders cannot override it). The value
is the user's already-configured `apiKey` — never an env-resolved one —
so the #4020 env-leak vector stays closed. The Anthropic-native branch
is untouched: the SDK's apiKey path already emits the header, and
duplicating it via defaultHeaders would risk stale-value drift.

Verified:
- new unit test pins `x-api-key: <key>` on every proxy-branch case
  (config-baseUrl, malformed baseUrl, DeepSeek anthropic-compat,
  ANTHROPIC_BASE_URL env-pointed-at-proxy); a negative test pins that
  the native branch does NOT add the header.
- E2E: spun up a local `http.createServer`, pointed the SDK at it the
  same way `AnthropicContentGenerator` does, and dumped the captured
  wire headers — `Authorization: Bearer` and `x-api-key` both arrive
  alongside the existing X-Stainless-* / x-app / claude-cli UA trio.

Fixes #4323

* fix(core): clarify x-api-key comment + cover guard branch & customHeaders ordering (#4323)

Address review feedback on #4342:

- Source comment claimed the apiKey value was "never an env-resolved
  one"; that's wrong — `resolveCredentialField` in
  content-generator-config.ts:178 falls through to env vars when the
  explicit and inherited values are unset. The security reasoning
  doesn't actually depend on that claim (the same value already ships
  as `Authorization: Bearer` via `authToken` on the same request), so
  re-anchor the comment on that fact and drop the misleading "never
  env-resolved" framing.

- Add test pinning the `&& contentGeneratorConfig.apiKey` guard: a
  falsy apiKey on the proxy branch must NOT inject `x-api-key:` (empty
  string would otherwise ship a meaningless header). The TypeScript
  signature `apiKey?: string` keeps the guard needed at the type level,
  but a future loosen-the-type refactor would silently re-enable the
  empty ship; the test catches that.

- Add test pinning the post-buildHeaders ordering: a user-supplied
  `customHeaders: { 'x-api-key': … }` must NOT win against the
  canonical key. The source comment promises this invariant but no
  test pinned it; a refactor that moved the injection above the
  customHeaders merge would silently let user config swap the auth
  header, defeating the dual-auth contract.

Declined two suggestions:
- Bot suggested extracting the 3-line injection into a `buildApiKeyHeader()`
  helper for consistency. Declined: adds indirection without abstraction
  win, and the inline form keeps the post-buildHeaders ordering visible
  at the call site (the ordering IS the invariant the comment promises).
- Bot suggested asserting `Authorization` is absent from `defaultHeaders`
  on the native path. Declined: the constructor-options pins
  (`apiKey: 'test-key'`, `authToken: null`) already document the
  SDK-driven auth mode; asserting on the absence of a header we never
  set in defaultHeaders is redundant given the existing assertions.

68 tests pass (66 + 2 new). tsc + eslint clean.
LaZzyMan added a commit that referenced this pull request May 21, 2026
… outbound (#4323) (#4342)" (#4385)

This reverts commit 4b25f9c.

PR #4342 unconditionally injected `x-api-key` alongside `Authorization:
Bearer` on every proxy-branch request. This broke IdeaLab-style proxies
(e.g. `idealab.alibaba-inc.com/api/anthropic`) which reject requests
carrying both headers with HTTP 401:

  鉴权header, x-api-key和Authorization不可以同时存在
  (auth header: x-api-key and Authorization cannot coexist)

The two proxy families have mutually exclusive header contracts —
OpenCode-Go-style servers want `x-api-key` only, IdeaLab-style servers
want `Authorization` only — so a one-size-fits-all default cannot
satisfy both at once.

Reverting restores the pre-#4342 default (Bearer only) so IdeaLab users
are unblocked. OpenCode-Go-style users can opt in via `customHeaders`:

  {
    "customHeaders": {
      "x-api-key": "<key>"
    }
  }

`buildHeaders` already merges customHeaders into defaultHeaders (only
`anthropic-beta` is reserved for per-request handling), and on the
proxy branch the SDK is constructed with `apiKey: null` so it does
not emit its own `x-api-key` — the value on the wire comes solely
from the user's explicit customHeaders entry, preserving the #4020
env-leak guard.

Reopens #4323.
DragonnZhang pushed a commit that referenced this pull request May 21, 2026
… outbound (#4323) (#4342)" (#4385)

This reverts commit 4b25f9c.

PR #4342 unconditionally injected `x-api-key` alongside `Authorization:
Bearer` on every proxy-branch request. This broke IdeaLab-style proxies
(e.g. `idealab.alibaba-inc.com/api/anthropic`) which reject requests
carrying both headers with HTTP 401:

  鉴权header, x-api-key和Authorization不可以同时存在
  (auth header: x-api-key and Authorization cannot coexist)

The two proxy families have mutually exclusive header contracts —
OpenCode-Go-style servers want `x-api-key` only, IdeaLab-style servers
want `Authorization` only — so a one-size-fits-all default cannot
satisfy both at once.

Reverting restores the pre-#4342 default (Bearer only) so IdeaLab users
are unblocked. OpenCode-Go-style users can opt in via `customHeaders`:

  {
    "customHeaders": {
      "x-api-key": "<key>"
    }
  }

`buildHeaders` already merges customHeaders into defaultHeaders (only
`anthropic-beta` is reserved for per-request handling), and on the
proxy branch the SDK is constructed with `apiKey: null` so it does
not emit its own `x-api-key` — the value on the wire comes solely
from the user's explicit customHeaders entry, preserving the #4020
env-leak guard.

Reopens #4323.
DragonnZhang added a commit that referenced this pull request May 25, 2026
…ompatibility

Restore the x-api-key header alongside Authorization: Bearer for
non-Anthropic-native baseURLs. Some Anthropic-compatible servers
(OpenCode-Go, Claude proxy products — see #4323) authenticate only on
the canonical x-api-key header, not Authorization: Bearer.

The dual-header approach ships both authentication shapes side-by-side
so either family of proxies accepts us. This doesn't widen the credential
leak surface from #4020 because contentGeneratorConfig.apiKey is already
shipped as Authorization: Bearer via authToken on the same request.

Resolves review thread: PRRT_kwDOPB-92c6EdXgl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/feature-request New feature or enhancement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants