/** * Human-facing `/compact` command over the backend-independent compaction seam. * @module @deepseek-ai/dsh-command-compact */ import type { Context } from 'cordis' import { ManualCompactionError } from '@deepseek-ai/dsh-compact' import type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands' export const name = 'command-compact' export const inject = ['commands', 'compact'] const USAGE = 'Usage: /compact (no arguments)' /** Fail loudly if a locally closed union gains an unhandled member. */ /* v8 ignore start -- closed-union backstop is unreachable without violating the TypeScript contract */ function assertNever(value: never): never { throw new TypeError(`unknown manual compaction error code: ${String(value)}`) } /* v8 ignore stop */ /** Convert expected capability failures into concise human-only outcomes. */ function expectedFailure(error: ManualCompactionError): CommandResult { switch (error.code) { case 'busy': return { kind: 'error', text: 'Compaction is unavailable because this process has an active compaction, or the agent is not idle.', } case 'changed': return { kind: 'error', text: 'The history selected for compaction changed before it could be replaced. The conversation is unchanged; the attempt is recorded in the session log.', } case 'summary': return { kind: 'error', text: 'Compaction could not produce a useful summary. The conversation is unchanged; the attempt is recorded in the session log.', } case 'commit': return { kind: 'error', text: 'Compaction did not finish cleanly; some session history may have changed. Inspect the current session state before retrying.', } case 'persistence': return { kind: 'error', text: 'Compaction finished, but the session could not be saved.', } /* v8 ignore next 2 -- ManualCompactionErrorCode is closed and every member is handled above */ default: return assertNever(error.code) } } /** Execute one argument-free manual compaction request. */ async function executeCompact( ctx: Context, invocation: CommandInvocation, ): Promise { if (invocation.rawInput.trim().length > 0) { return { kind: 'error', text: USAGE } } try { const result = await ctx.compact.compactNow(invocation.agent, invocation.signal) if (result === null) return { kind: 'success', text: 'No compactable history yet.' } return { kind: 'success', text: `Compacted ${result.shadowedSeqs.length} history items (~${result.shadowedTokenCount} tokens).`, } } catch (error: unknown) { if (invocation.signal.aborted) return { kind: 'error', text: 'Compaction cancelled.' } if (error instanceof ManualCompactionError) return expectedFailure(error) throw error } } /** * Register `/compact` for every composed human-command adapter. * @param ctx - context carrying the command registry and the compaction seam. */ export function apply(ctx: Context): void { ctx.commands.register({ name: 'compact', description: 'Compact older conversation history', handler: invocation => executeCompact(ctx, invocation), }) }