|
| 1 | +import chalk from 'chalk' |
| 2 | +import type { Command } from '@commands' |
| 3 | +import { getGlobalConfig, saveGlobalConfig } from '@utils/config' |
| 4 | +import { |
| 5 | + AUTO_COMPACT_THRESHOLD_RATIO, |
| 6 | + getAutoCompactThresholdRatio, |
| 7 | + isValidAutoCompactThresholdRatio, |
| 8 | +} from '@utils/session/autoCompactThreshold' |
| 9 | + |
| 10 | +const HELP_ARGS = new Set(['help', '-h', '--help', '?']) |
| 11 | +const RESET_ARGS = new Set(['reset', 'default']) |
| 12 | + |
| 13 | +function parseThresholdInput(raw: string): number | null { |
| 14 | + const trimmed = raw.trim() |
| 15 | + if (!trimmed) return null |
| 16 | + |
| 17 | + let valueText = trimmed |
| 18 | + let isPercent = false |
| 19 | + |
| 20 | + if (valueText.endsWith('%')) { |
| 21 | + isPercent = true |
| 22 | + valueText = valueText.slice(0, -1).trim() |
| 23 | + } |
| 24 | + |
| 25 | + if (!valueText) return null |
| 26 | + |
| 27 | + const value = Number(valueText) |
| 28 | + if (!Number.isFinite(value)) return null |
| 29 | + |
| 30 | + let ratio = value |
| 31 | + // Treat bare values >1 as percentages (85 => 0.85) while still allowing ratios like 0.85. |
| 32 | + if (isPercent || (value > 1 && value <= 100)) { |
| 33 | + ratio = value / 100 |
| 34 | + } |
| 35 | + |
| 36 | + return isValidAutoCompactThresholdRatio(ratio) ? ratio : null |
| 37 | +} |
| 38 | + |
| 39 | +function formatRatio(ratio: number): string { |
| 40 | + const percent = Math.round(ratio * 100) |
| 41 | + return `${ratio} (${percent}%)` |
| 42 | +} |
| 43 | + |
| 44 | +const compactThreshold = { |
| 45 | + type: 'local', |
| 46 | + name: 'compact-threshold', |
| 47 | + description: 'View or set the auto-compact threshold ratio', |
| 48 | + isEnabled: true, |
| 49 | + isHidden: false, |
| 50 | + argumentHint: '[ratio]', |
| 51 | + userFacingName() { |
| 52 | + return 'compact-threshold' |
| 53 | + }, |
| 54 | + async call(args) { |
| 55 | + const raw = args.trim() |
| 56 | + |
| 57 | + if (!raw || HELP_ARGS.has(raw)) { |
| 58 | + const configured = getGlobalConfig().autoCompactThreshold |
| 59 | + const isCustom = isValidAutoCompactThresholdRatio(configured) |
| 60 | + const ratio = getAutoCompactThresholdRatio() |
| 61 | + const defaultNote = isCustom ? '' : ' (default)' |
| 62 | + |
| 63 | + return [ |
| 64 | + `Auto-compact threshold: ${formatRatio(ratio)}${defaultNote}`, |
| 65 | + 'Usage: /compact-threshold 0.85', |
| 66 | + 'Tip: You can also use percentages, e.g. /compact-threshold 85%', |
| 67 | + ].join('\n') |
| 68 | + } |
| 69 | + |
| 70 | + if (RESET_ARGS.has(raw)) { |
| 71 | + const nextConfig = { ...getGlobalConfig() } |
| 72 | + delete nextConfig.autoCompactThreshold |
| 73 | + saveGlobalConfig(nextConfig) |
| 74 | + return `Auto-compact threshold reset to default (${AUTO_COMPACT_THRESHOLD_RATIO}).` |
| 75 | + } |
| 76 | + |
| 77 | + const parsed = parseThresholdInput(raw) |
| 78 | + if (!parsed) { |
| 79 | + return [ |
| 80 | + `Invalid threshold: ${chalk.bold(raw)}`, |
| 81 | + 'Provide a ratio greater than 0 and less than 1 (e.g. 0.85 or 85%).', |
| 82 | + ].join('\n') |
| 83 | + } |
| 84 | + |
| 85 | + const config = getGlobalConfig() |
| 86 | + saveGlobalConfig({ ...config, autoCompactThreshold: parsed }) |
| 87 | + return `Auto-compact threshold set to ${formatRatio(parsed)}.` |
| 88 | + }, |
| 89 | +} satisfies Command |
| 90 | + |
| 91 | +export default compactThreshold |
0 commit comments