mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-22 14:30:53 +08:00
fix(server): preserve context estimates for empty usage #1063
This commit is contained in:
parent
71dc2fd4cf
commit
8995f56d1f
@ -891,6 +891,76 @@ describe('ConversationService', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should fall back to transcript estimates when provider usage is empty or zero', async () => {
|
||||||
|
const previousConfigDir = process.env.CLAUDE_CONFIG_DIR
|
||||||
|
const previousNodeEnv = process.env.NODE_ENV
|
||||||
|
const tmpConfigDir = await fs.mkdtemp(path.join(os.tmpdir(), 'claude-transcript-zero-usage-'))
|
||||||
|
const workDir = await fs.mkdtemp(path.join(os.tmpdir(), 'claude-workdir-zero-usage-'))
|
||||||
|
process.env.CLAUDE_CONFIG_DIR = tmpConfigDir
|
||||||
|
process.env.NODE_ENV = 'development'
|
||||||
|
|
||||||
|
try {
|
||||||
|
const svc = new SessionService()
|
||||||
|
|
||||||
|
for (const usage of [
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
input_tokens: 0,
|
||||||
|
output_tokens: 0,
|
||||||
|
cache_read_input_tokens: 0,
|
||||||
|
cache_creation_input_tokens: 0,
|
||||||
|
},
|
||||||
|
]) {
|
||||||
|
const { sessionId } = await svc.createSession(workDir)
|
||||||
|
const found = await svc.findSessionFile(sessionId)
|
||||||
|
expect(found).not.toBeNull()
|
||||||
|
|
||||||
|
await fs.appendFile(found!.filePath, JSON.stringify({
|
||||||
|
type: 'user',
|
||||||
|
uuid: crypto.randomUUID(),
|
||||||
|
timestamp: '2026-07-20T12:00:00.000Z',
|
||||||
|
cwd: workDir,
|
||||||
|
message: {
|
||||||
|
role: 'user',
|
||||||
|
content: [{ type: 'text', text: 'Estimate this transcript even when the provider does not report token counts.' }],
|
||||||
|
},
|
||||||
|
}) + '\n')
|
||||||
|
await fs.appendFile(found!.filePath, JSON.stringify({
|
||||||
|
type: 'assistant',
|
||||||
|
uuid: crypto.randomUUID(),
|
||||||
|
timestamp: '2026-07-20T12:00:01.000Z',
|
||||||
|
cwd: workDir,
|
||||||
|
message: {
|
||||||
|
role: 'assistant',
|
||||||
|
model: 'claude-sonnet-4-6',
|
||||||
|
content: [{ type: 'text', text: 'The local transcript estimate should remain available.' }],
|
||||||
|
usage,
|
||||||
|
},
|
||||||
|
}) + '\n')
|
||||||
|
|
||||||
|
const contextEstimate = await svc.getTranscriptContextEstimate(sessionId)
|
||||||
|
const inspectionSnapshot = await svc.getInspectionTranscriptSnapshot(sessionId)
|
||||||
|
|
||||||
|
expect(contextEstimate?.model).toBe('claude-sonnet-4-6')
|
||||||
|
expect(contextEstimate?.totalTokens).toBeGreaterThan(0)
|
||||||
|
expect(inspectionSnapshot?.contextEstimate).toEqual(contextEstimate)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (previousConfigDir === undefined) {
|
||||||
|
delete process.env.CLAUDE_CONFIG_DIR
|
||||||
|
} else {
|
||||||
|
process.env.CLAUDE_CONFIG_DIR = previousConfigDir
|
||||||
|
}
|
||||||
|
if (previousNodeEnv === undefined) {
|
||||||
|
delete process.env.NODE_ENV
|
||||||
|
} else {
|
||||||
|
process.env.NODE_ENV = previousNodeEnv
|
||||||
|
}
|
||||||
|
await fs.rm(tmpConfigDir, { recursive: true, force: true })
|
||||||
|
await fs.rm(workDir, { recursive: true, force: true })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('should use active provider model context windows for transcript estimates', async () => {
|
it('should use active provider model context windows for transcript estimates', async () => {
|
||||||
const previousConfigDir = process.env.CLAUDE_CONFIG_DIR
|
const previousConfigDir = process.env.CLAUDE_CONFIG_DIR
|
||||||
const previousNodeEnv = process.env.NODE_ENV
|
const previousNodeEnv = process.env.NODE_ENV
|
||||||
|
|||||||
@ -2504,8 +2504,6 @@ export class SessionService {
|
|||||||
const outputTokens = typeof usage.output_tokens === 'number' ? usage.output_tokens : 0
|
const outputTokens = typeof usage.output_tokens === 'number' ? usage.output_tokens : 0
|
||||||
const cacheReadInputTokens = typeof usage.cache_read_input_tokens === 'number' ? usage.cache_read_input_tokens : 0
|
const cacheReadInputTokens = typeof usage.cache_read_input_tokens === 'number' ? usage.cache_read_input_tokens : 0
|
||||||
const cacheCreationInputTokens = typeof usage.cache_creation_input_tokens === 'number' ? usage.cache_creation_input_tokens : 0
|
const cacheCreationInputTokens = typeof usage.cache_creation_input_tokens === 'number' ? usage.cache_creation_input_tokens : 0
|
||||||
const promptTokens = inputTokens + cacheReadInputTokens + cacheCreationInputTokens
|
|
||||||
if (promptTokens === 0 && outputTokens === 0) continue
|
|
||||||
|
|
||||||
latest = {
|
latest = {
|
||||||
model,
|
model,
|
||||||
@ -2774,16 +2772,13 @@ export class SessionService {
|
|||||||
const webSearchRequests = typeof usage.server_tool_use?.web_search_requests === 'number'
|
const webSearchRequests = typeof usage.server_tool_use?.web_search_requests === 'number'
|
||||||
? usage.server_tool_use.web_search_requests
|
? usage.server_tool_use.web_search_requests
|
||||||
: 0
|
: 0
|
||||||
const promptTokens = inputTokens + cacheReadInputTokens + cacheCreationInputTokens
|
|
||||||
|
|
||||||
if (promptTokens !== 0 || outputTokens !== 0) {
|
latestContextUsage = {
|
||||||
latestContextUsage = {
|
model,
|
||||||
model,
|
inputTokens,
|
||||||
inputTokens,
|
outputTokens,
|
||||||
outputTokens,
|
cacheReadInputTokens,
|
||||||
cacheReadInputTokens,
|
cacheCreationInputTokens,
|
||||||
cacheCreationInputTokens,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user