diff --git a/packages/compact/compact-basic/src/index.ts b/packages/compact/compact-basic/src/index.ts index b77ebebc76..5d325d57ba 100644 --- a/packages/compact/compact-basic/src/index.ts +++ b/packages/compact/compact-basic/src/index.ts @@ -9,7 +9,7 @@ import z from 'schemastery' import { CompactService } from '@deepseek-ai/dsh-compact' import type { CompactionResult, CompactionTrigger } from '@deepseek-ai/dsh-compact' import type { Session } from '@deepseek-ai/dsh-session' -import { CONTEXT_WINDOW_EXCEEDED_CODE } from '@deepseek-ai/dsh-llm' +import { CONTEXT_WINDOW_EXCEEDED_CODE, assertNever } from '@deepseek-ai/dsh-llm' import type { ContentBlock } from '@deepseek-ai/dsh-llm' import type { Agent } from '@deepseek-ai/dsh-agent' import { resolveConfig } from './config.ts' @@ -152,11 +152,18 @@ export class BasicCompactService extends CompactService { const model = routedModel(agent.session) if (model === undefined) return null const meter = this.ctx.tokenMeter - if (trigger === 'context-overflow') { - const measurement = meter.measure(agent.session) - const range = selectCompactableRange(agent.session, measurement, 0) - if (range === null) return null - return this.compactRegion(range.start, range.end, agent, signal) + switch (trigger) { + case 'context-overflow': { + const measurement = meter.measure(agent.session) + const range = selectCompactableRange(agent.session, measurement, 0) + if (range === null) return null + return this.compactRegion(range.start, range.end, agent, signal) + } + case 'pressure': + break + /* v8 ignore next -- closed-union exhaustiveness guard */ + default: + assertNever(trigger, 'compaction trigger') } const threshold = Math.floor(meter.contextWindow * this.config.thresholdRatio) diff --git a/packages/core/agent-loop/src/loop.ts b/packages/core/agent-loop/src/loop.ts index 54cbbc6bdd..08c1ab9412 100644 --- a/packages/core/agent-loop/src/loop.ts +++ b/packages/core/agent-loop/src/loop.ts @@ -8,7 +8,7 @@ import type { Context } from 'cordis' import type { ContentBlock, FinishReason, GenerateOptions, LlmCallConfig, Message } from '@deepseek-ai/dsh-llm' import { isDeepStrictEqual } from 'node:util' -import { BlockAssembler, HarnessError, deepFreeze, isLlmAdapterFailure } from '@deepseek-ai/dsh-llm' +import { BlockAssembler, HarnessError, assertNever, deepFreeze, isLlmAdapterFailure } from '@deepseek-ai/dsh-llm' import { agentEvents, assembleContextFor } from '@deepseek-ai/dsh-agent' import type { AgentEventDispatch, ContinuationDecision, HookContext, PromptDecision, RequestError, RequestErrorDecision } from '@deepseek-ai/dsh-agent' import { canonicalHeader } from '@deepseek-ai/dsh-session' @@ -392,11 +392,17 @@ async function runTurn( : { kind: 'aborted', reason: String(abort.signal.reason) } break } - if (recoveryDecision.action === 'retry') { - requestRetryAttempt += 1 - continue + switch (recoveryDecision.action) { + case 'retry': + requestRetryAttempt += 1 + continue + case 'fail': + failTurn(stepOutcome.requestError) + break + /* v8 ignore next -- closed-union exhaustiveness guard */ + default: + assertNever(recoveryDecision, 'agent request-error decision') } - failTurn(stepOutcome.requestError) break }