Skip to content

Commit 0e3c232

Browse files
authored
Merge branch 'main' into main
2 parents 4d13822 + 2cc9a7d commit 0e3c232

12 files changed

Lines changed: 127 additions & 19 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "claude-code-best",
3-
"version": "2.4.3",
3+
"version": "2.4.4",
44
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
55
"type": "module",
66
"author": "claude-code-best <claude-code-best@proton.me>",

packages/@ant/model-provider/src/providers/gemini/streamAdapter.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ export async function* adaptGeminiStreamToAnthropic(
1616
let finishReason: string | undefined
1717
let inputTokens = 0
1818
let outputTokens = 0
19+
let cachedReadTokens = 0
1920

2021
for await (const chunk of stream) {
2122
const usage = chunk.usageMetadata
2223
if (usage) {
2324
inputTokens = usage.promptTokenCount ?? inputTokens
2425
outputTokens =
2526
(usage.candidatesTokenCount ?? 0) + (usage.thoughtsTokenCount ?? 0)
27+
cachedReadTokens = usage.cachedContentTokenCount ?? cachedReadTokens
2628
}
2729

2830
if (!started) {
@@ -41,7 +43,7 @@ export async function* adaptGeminiStreamToAnthropic(
4143
input_tokens: inputTokens,
4244
output_tokens: 0,
4345
cache_creation_input_tokens: 0,
44-
cache_read_input_tokens: 0,
46+
cache_read_input_tokens: cachedReadTokens,
4547
},
4648
},
4749
} as unknown as BetaRawMessageStreamEvent
@@ -204,7 +206,10 @@ export async function* adaptGeminiStreamToAnthropic(
204206
stop_sequence: null,
205207
},
206208
usage: {
209+
input_tokens: inputTokens,
207210
output_tokens: outputTokens,
211+
cache_creation_input_tokens: 0,
212+
cache_read_input_tokens: cachedReadTokens,
208213
},
209214
} as BetaRawMessageStreamEvent
210215

packages/@ant/model-provider/src/providers/gemini/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export type GeminiUsageMetadata = {
6868
candidatesTokenCount?: number
6969
thoughtsTokenCount?: number
7070
totalTokenCount?: number
71+
cachedContentTokenCount?: number
7172
}
7273

7374
export type GeminiCandidate = {

packages/builtin-tools/src/tools/ExecuteTool/ExecuteTool.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,29 @@ export const ExecuteTool = buildTool({
121121
}
122122
}
123123

124+
// Validate input before delegating — prevents crashes when the model
125+
// omits required params (e.g. TeamCreate without team_name →
126+
// sanitizeName(undefined).replace() TypeError).
127+
if (targetTool.validateInput) {
128+
const validation = await targetTool.validateInput(
129+
input.params as Record<string, unknown>,
130+
context,
131+
)
132+
if (!validation.result) {
133+
return {
134+
data: {
135+
result: null,
136+
tool_name: input.tool_name,
137+
},
138+
newMessages: [
139+
createUserMessage({
140+
content: `Invalid parameters for tool "${input.tool_name}": ${validation.message}`,
141+
}),
142+
],
143+
}
144+
}
145+
}
146+
124147
// Check permissions on the target tool
125148
const permResult = await targetTool.checkPermissions?.(
126149
input.params as Record<string, unknown>,
@@ -164,7 +187,7 @@ export const ExecuteTool = buildTool({
164187
}
165188
},
166189
renderToolUseMessage(input) {
167-
return `Executing ${input.tool_name}...`
190+
return `${input.tool_name}`
168191
},
169192
userFacingName() {
170193
return 'ExecuteExtraTool'

src/commands/autofix-pr/__tests__/AutofixProgress.test.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,12 @@ import * as React from 'react';
88
import { renderToString } from '../../../utils/staticRender.js';
99
import { AutofixProgress } from '../AutofixProgress.js';
1010

11-
describe('AutofixProgress', () => {
12-
test(
13-
'renders target in header',
14-
async () => {
15-
const out = await renderToString(<AutofixProgress phase="detecting" target="acme/myrepo#42" />);
16-
expect(out).toContain('acme/myrepo#42');
17-
expect(out).toContain('Autofix PR');
18-
},
19-
{ timeout: 10000 },
20-
);
11+
describe.skipIf(!!process.env.CI)('AutofixProgress', () => {
12+
test('renders target in header', async () => {
13+
const out = await renderToString(<AutofixProgress phase="detecting" target="acme/myrepo#42" />);
14+
expect(out).toContain('acme/myrepo#42');
15+
expect(out).toContain('Autofix PR');
16+
});
2117

2218
test(
2319
'detecting phase shows arrow on detecting step',

src/constants/tools.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const ASYNC_AGENT_ALLOWED_TOOLS = new Set([
8282
SKILL_TOOL_NAME,
8383
SYNTHETIC_OUTPUT_TOOL_NAME,
8484
SEARCH_EXTRA_TOOLS_TOOL_NAME,
85+
EXECUTE_TOOL_NAME,
8586
ENTER_WORKTREE_TOOL_NAME,
8687
EXIT_WORKTREE_TOOL_NAME,
8788
])

src/services/api/grok/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
ChatCompletionCreateParamsStreaming,
1313
} from 'openai/resources/chat/completions/completions.mjs'
1414
import { getGrokClient } from './client.js'
15+
import { updateOpenAIUsage } from '../openai/openaiShared.js'
1516
import {
1617
anthropicMessagesToOpenAI,
1718
anthropicToolsToOpenAI,
@@ -136,7 +137,7 @@ export async function* queryModelGrok(
136137
partialMessage = (event as any).message
137138
ttftMs = Date.now() - start
138139
if ((event as any).message?.usage) {
139-
usage = { ...usage, ...(event as any).message.usage }
140+
usage = updateOpenAIUsage(usage, (event as any).message.usage)
140141
}
141142
break
142143
}
@@ -192,7 +193,7 @@ export async function* queryModelGrok(
192193
case 'message_delta': {
193194
const deltaUsage = (event as any).usage
194195
if (deltaUsage) {
195-
usage = { ...usage, ...deltaUsage }
196+
usage = updateOpenAIUsage(usage, deltaUsage)
196197
}
197198
break
198199
}

src/services/api/openai/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010
import type { AgentId } from '../../../types/ids.js'
1111
import type { Tools } from '../../../Tool.js'
1212
import { getOpenAIClient } from './client.js'
13+
import { updateOpenAIUsage } from './openaiShared.js'
1314
import {
1415
anthropicMessagesToOpenAI,
1516
resolveOpenAIModel,
@@ -454,7 +455,7 @@ export async function* queryModelOpenAI(
454455
case 'message_delta': {
455456
const deltaUsage = (event as any).usage
456457
if (deltaUsage) {
457-
usage = { ...usage, ...deltaUsage }
458+
usage = updateOpenAIUsage(usage, deltaUsage)
458459
}
459460
if ((event as any).delta?.stop_reason != null) {
460461
stopReason = (event as any).delta.stop_reason
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Shared utilities for OpenAI-compatible API paths.
3+
*
4+
* Both the OpenAI path (queryModelOpenAI) and Grok path (queryModelGrok) use
5+
* the same adapters (openaiStreamAdapter, openaiConvertMessages), so the event
6+
* processing logic should be shared rather than duplicated.
7+
*/
8+
9+
/**
10+
* Merge a delta usage into the accumulated usage, preserving cache-related
11+
* fields from previous values when the delta carries explicit zeroes or
12+
* undefined values.
13+
*
14+
* Mirrors updateUsage() in claude.ts: a future adapter change that omits
15+
* cache fields from certain streaming events should not silently zero the
16+
* accumulated counters.
17+
*/
18+
export function updateOpenAIUsage(
19+
current: {
20+
input_tokens: number
21+
output_tokens: number
22+
cache_creation_input_tokens: number
23+
cache_read_input_tokens: number
24+
},
25+
delta: {
26+
input_tokens?: number
27+
output_tokens?: number
28+
cache_creation_input_tokens?: number
29+
cache_read_input_tokens?: number
30+
},
31+
): typeof current {
32+
return {
33+
input_tokens: delta.input_tokens ?? current.input_tokens,
34+
output_tokens: delta.output_tokens ?? current.output_tokens,
35+
cache_creation_input_tokens:
36+
delta.cache_creation_input_tokens !== undefined &&
37+
delta.cache_creation_input_tokens > 0
38+
? delta.cache_creation_input_tokens
39+
: current.cache_creation_input_tokens,
40+
cache_read_input_tokens:
41+
delta.cache_read_input_tokens !== undefined &&
42+
delta.cache_read_input_tokens > 0
43+
? delta.cache_read_input_tokens
44+
: current.cache_read_input_tokens,
45+
}
46+
}

src/services/api/openai/requestBody.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ export function isOpenAIThinkingEnabled(model: string): boolean {
2323
if (isEnvDefinedFalsy(process.env.OPENAI_ENABLE_THINKING)) return false
2424
// Explicit enable
2525
if (isEnvTruthy(process.env.OPENAI_ENABLE_THINKING)) return true
26-
// Auto-detect from model name (DeepSeek and MiMo models support thinking mode)
26+
// Auto-detect from model name (DeepSeek and MiMo models support thinking mode).
27+
// Grok is intentionally excluded — Grok reasoning models reason automatically
28+
// and do NOT require thinking/enable_thinking request body parameters.
2729
const modelLower = model.toLowerCase()
2830
return modelLower.includes('deepseek') || modelLower.includes('mimo')
2931
}

0 commit comments

Comments
 (0)