diff --git a/.changeset/manual-compact-limit.md b/.changeset/manual-compact-limit.md new file mode 100644 index 00000000000..c4d823ca617 --- /dev/null +++ b/.changeset/manual-compact-limit.md @@ -0,0 +1,7 @@ +--- +"@kilocode/cli": minor +"@kilocode/sdk": minor +"kilo-code": minor +--- + +Support setting an auto-compaction threshold percentage so long sessions can compact before the context window is full. diff --git a/packages/kilo-docs/pages/customize/context/context-condensing.md b/packages/kilo-docs/pages/customize/context/context-condensing.md index 9993b4bcca3..c5b173a3e09 100644 --- a/packages/kilo-docs/pages/customize/context/context-condensing.md +++ b/packages/kilo-docs/pages/customize/context/context-condensing.md @@ -36,10 +36,12 @@ This summary replaces older conversation history while Kilo keeps the most recen ### Automatic trigger -Kilo tracks the total token count for the session — input, output, and cached reads and writes — and compares it to the model's context window. Compaction runs when the total fills the window minus a reserved buffer of headroom kept free for the next turn. +Kilo tracks the total token count for the session: input, output, and cached reads and writes. Compaction runs when token usage reaches `compaction.threshold_percent`, or when the remaining window hits the reserved safety buffer, whichever happens first. How the buffer is chosen depends on what the model declares. When the model advertises a separate input limit, the buffer defaults to 20,000 tokens (or the model's maximum output size, whichever is smaller). When the model only declares a single context window, Kilo instead reserves the model's full output cap — up to 32,000 tokens. +`compaction.threshold_percent` is optional. Set it from `1` to `100` to compact at that percentage of the model input or context window. + Custom models that do not declare a context window are not tracked, and auto-compaction does not run for them. ### Context Pruning @@ -59,10 +61,11 @@ You can trigger compaction at any time: | Setting | Default | Effect | |---|---|---| | `compaction.auto` | `true` | Automatically compact when the usable window is reached | +| `compaction.threshold_percent` | unset | Compact when token usage reaches this percentage of the model window | | `compaction.prune` | `true` | Clear old tool outputs beyond the 40K recency window | | `compaction.tail_turns` | `2` | Keep the most recent user turns and their responses verbatim when possible | | `compaction.preserve_recent_tokens` | 25% of usable context, clamped between 2,000 and 8,000 tokens | Token budget for the verbatim recent tail | -| `compaction.reserved` | `min(20,000, model_max_output_tokens)` | Token headroom kept free for the next turn — also defines the compaction trigger point | +| `compaction.reserved` | `min(20,000, model_max_output_tokens)` | Token headroom kept free for the next turn, and a safety trigger if reached before the threshold | ## Configuration @@ -72,6 +75,7 @@ Compaction is configured in your `kilo.jsonc` file: { "compaction": { "auto": true, // Enable or disable automatic compaction + "threshold_percent": 80, // Optional trigger at 80% of the model window "prune": true, // Enable pruning of old tool outputs beyond the recency window "tail_turns": 2, // Recent user turns to keep verbatim during compaction "preserve_recent_tokens": 8000, // Maximum token budget for the recent tail @@ -83,6 +87,7 @@ Compaction is configured in your `kilo.jsonc` file: | Option | Type | Default | Description | |---|---|---|---| | `compaction.auto` | boolean | `true` | Enable or disable automatic compaction when the usable window is reached | +| `compaction.threshold_percent` | number | unset | Optional percentage from 1 to 100. Auto-compaction runs when token usage reaches this share of the model input or context window, unless the reserved safety buffer triggers first. | | `compaction.prune` | boolean | `true` | Enable pruning of old tool outputs outside the 40K token recency window | | `compaction.tail_turns` | number | `2` | Number of recent user turns, including following assistant and tool responses, to keep verbatim during compaction | | `compaction.preserve_recent_tokens` | number | 25% of usable context, clamped between 2,000 and 8,000 tokens | Maximum token budget for recent turns kept verbatim after compaction | @@ -131,10 +136,12 @@ This summary replaces older conversation history while Kilo keeps the most recen ### Automatic trigger -Kilo tracks the total token count for the session — input, output, and cached reads and writes — and compares it to the model's context window. Compaction runs when the total fills the window minus a reserved buffer of headroom kept free for the next turn. +Kilo tracks the total token count for the session: input, output, and cached reads and writes. Compaction runs when token usage reaches `compaction.threshold_percent`, or when the remaining window hits the reserved safety buffer, whichever happens first. How the buffer is chosen depends on what the model declares. When the model advertises a separate input limit, the buffer defaults to 20,000 tokens (or the model's maximum output size, whichever is smaller). When the model only declares a single context window, Kilo instead reserves the model's full output cap — up to 32,000 tokens. +`compaction.threshold_percent` is optional. Set it from `1` to `100` to compact at that percentage of the model input or context window. + [Custom models](/docs/code-with-ai/agents/custom-models) that do not declare a context window are not tracked, and auto-compaction does not run for them. ### Context Pruning @@ -153,10 +160,11 @@ You can trigger compaction at any time: | Setting | Default | Effect | |---|---|---| | `compaction.auto` | `true` | Automatically compact when the usable window is reached | +| `compaction.threshold_percent` | unset | Compact when token usage reaches this percentage of the model window | | `compaction.prune` | `true` | Clear old tool outputs beyond the 40K recency window | | `compaction.tail_turns` | `2` | Keep the most recent user turns and their responses verbatim when possible | | `compaction.preserve_recent_tokens` | 25% of usable context, clamped between 2,000 and 8,000 tokens | Token budget for the verbatim recent tail | -| `compaction.reserved` | `min(20,000, model_max_output_tokens)` | Token headroom kept free for the next turn — also defines the compaction trigger point | +| `compaction.reserved` | `min(20,000, model_max_output_tokens)` | Token headroom kept free for the next turn, and a safety trigger if reached before the threshold | ## Configuration @@ -166,6 +174,7 @@ Compaction is configured in your `kilo.jsonc` file: { "compaction": { "auto": true, // Enable or disable automatic compaction + "threshold_percent": 80, // Optional trigger at 80% of the model window "prune": true, // Enable pruning of old tool outputs beyond the recency window "tail_turns": 2, // Recent user turns to keep verbatim during compaction "preserve_recent_tokens": 8000, // Maximum token budget for the recent tail @@ -177,6 +186,7 @@ Compaction is configured in your `kilo.jsonc` file: | Option | Type | Default | Description | |---|---|---|---| | `compaction.auto` | boolean | `true` | Enable or disable automatic compaction when the usable window is reached | +| `compaction.threshold_percent` | number | unset | Optional percentage from 1 to 100. Auto-compaction runs when token usage reaches this share of the model input or context window, unless the reserved safety buffer triggers first. | | `compaction.prune` | boolean | `true` | Enable pruning of old tool outputs outside the 40K token recency window | | `compaction.tail_turns` | number | `2` | Number of recent user turns, including following assistant and tool responses, to keep verbatim during compaction | | `compaction.preserve_recent_tokens` | number | 25% of usable context, clamped between 2,000 and 8,000 tokens | Maximum token budget for recent turns kept verbatim after compaction | @@ -284,7 +294,11 @@ If the condensed summary doesn't capture important details: - **Before major transitions**: When switching to a different aspect of your project - **When approaching limits**: Run `/compact` manually before hitting the automatic trigger if you want control over _when_ the summary is produced -### Tuning `compaction.reserved` +### Tuning compaction triggers + +Use `compaction.threshold_percent` when you want compaction to happen at a predictable share of the model window, such as `80` for earlier summaries on long tasks. + +The reserved safety buffer still applies and can trigger compaction earlier than the percentage threshold. On models that advertise a separate input limit, the `reserved` value is a trade-off: diff --git a/packages/kilo-vscode/package.json b/packages/kilo-vscode/package.json index 25b4536daee..686adb943fc 100644 --- a/packages/kilo-vscode/package.json +++ b/packages/kilo-vscode/package.json @@ -886,7 +886,7 @@ "format": "prettier --write .", "format:check": "prettier --check .", "knip": "knip", - "check-kilocode-change": "! grep -rn 'kilocode_change' . ../kilo-ui/ --exclude='package.json' --exclude='*.md' --exclude-dir='node_modules' --exclude-dir='dist' | grep -v '`kilocode_change`'", + "check-kilocode-change": "! grep -rIn 'kilocode_change' . ../kilo-ui/ --exclude='package.json' --exclude='*.md' --exclude-dir='node_modules' --exclude-dir='dist' | grep -v '`kilocode_change`'", "lint": "eslint src webview-ui", "test": "vscode-test", "test:unit": "bun test tests/unit/", diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ContextTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ContextTab.tsx index 10d99c2a64b..878d260e398 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ContextTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ContextTab.tsx @@ -15,6 +15,23 @@ const ContextTab: Component = () => { const [newPattern, setNewPattern] = createSignal("") const patterns = () => config().watcher?.ignore ?? [] + const limit = () => { + const value = config().compaction?.threshold_percent + return value === null || value === undefined ? "" : String(value) + } + + const saveLimit = (value: string) => { + const raw = value.trim() + if (!raw) { + updateConfig({ compaction: { ...config().compaction, threshold_percent: null } }) + return + } + + const percent = Number(raw) + if (!Number.isFinite(percent)) return + const next = Math.min(100, Math.max(1, percent)) + updateConfig({ compaction: { ...config().compaction, threshold_percent: next } }) + } const addPattern = () => { const value = newPattern().trim() @@ -42,20 +59,39 @@ const ContextTab: Component = () => { description={language.t("settings.context.autoCompaction.description")} > updateConfig({ compaction: { ...config().compaction, auto: checked } })} hideLabel > {language.t("settings.context.autoCompaction.title")} + +
+ + % +
+
updateConfig({ compaction: { ...config().compaction, prune: checked } })} hideLabel > diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index cb292f16288..5e5a7986ad1 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -1378,7 +1378,10 @@ export const dict = { "settings.checkpoints.enable.title": "تمكين اللقطات", "settings.checkpoints.enable.description": "إنشاء نقاط فحص قبل تحرير الملفات", "settings.context.autoCompaction.title": "ضغط تلقائي", - "settings.context.autoCompaction.description": "ضغط السياق تلقائياً عند امتلائه", + "settings.context.autoCompaction.description": "ضغط السياق تلقائياً قبل أن يصل إلى الحد", + "settings.context.compactionLimit.title": "حد الضغط التلقائي", + "settings.context.compactionLimit.description": + "اضغط عندما يصل السياق إلى هذه النسبة المئوية من نافذة النموذج. اتركه فارغاً لاستخدام هامش الأمان فقط.", "settings.context.prune.title": "تقليم المخرجات القديمة", "settings.context.prune.description": "إزالة مخرجات الأدوات القديمة أثناء الضغط", "settings.context.watcherPatterns": "أنماط تجاهل مراقب الملفات", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index c7dd24dc01c..a07f8ee6645 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -1419,7 +1419,10 @@ export const dict = { "settings.checkpoints.enable.title": "Ativar snapshots", "settings.checkpoints.enable.description": "Criar pontos de verificação antes de editar arquivos", "settings.context.autoCompaction.title": "Compactação automática", - "settings.context.autoCompaction.description": "Compactar automaticamente o contexto quando estiver cheio", + "settings.context.autoCompaction.description": "Compactar automaticamente o contexto antes que atinja o limite", + "settings.context.compactionLimit.title": "Limite de compactação automática", + "settings.context.compactionLimit.description": + "Compacte quando o contexto atingir esta porcentagem da janela do modelo. Deixe em branco para usar apenas a margem de segurança.", "settings.context.prune.title": "Remover saídas antigas", "settings.context.prune.description": "Remover saídas antigas de ferramentas durante a compactação", "settings.context.watcherPatterns": "Padrões de ignorar do observador", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 461584d1240..9efd0465abd 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -1416,7 +1416,10 @@ export const dict = { "settings.checkpoints.enable.title": "Omogući snimke", "settings.checkpoints.enable.description": "Kreiraj kontrolne točke prije uređivanja datoteka", "settings.context.autoCompaction.title": "Automatska kompresija", - "settings.context.autoCompaction.description": "Automatski komprimiraj kontekst kada je pun", + "settings.context.autoCompaction.description": "Automatski komprimiraj kontekst prije nego dostigne limit", + "settings.context.compactionLimit.title": "Limit automatske kompresije", + "settings.context.compactionLimit.description": + "Komprimiraj kada kontekst dostigne ovaj procenat prozora modela. Ostavite prazno da koristite samo sigurnosnu rezervu.", "settings.context.prune.title": "Očisti stare izlaze", "settings.context.prune.description": "Ukloni stare izlaze alata tokom kompresije", "settings.context.watcherPatterns": "Uzorci ignoriranja za promatrač datoteka", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index 77996e22001..20433ae49e7 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -1405,7 +1405,10 @@ export const dict = { "settings.checkpoints.enable.title": "Aktiver snapshots", "settings.checkpoints.enable.description": "Opret kontrolpunkter før filredigeringer", "settings.context.autoCompaction.title": "Automatisk komprimering", - "settings.context.autoCompaction.description": "Komprimér automatisk kontekst, når den er fuld", + "settings.context.autoCompaction.description": "Komprimér automatisk kontekst, før den når grænsen", + "settings.context.compactionLimit.title": "Grænse for automatisk komprimering", + "settings.context.compactionLimit.description": + "Komprimér, når konteksten når denne procentdel af modelvinduet. Lad feltet være tomt for kun at bruge sikkerhedsbufferen.", "settings.context.prune.title": "Fjern gamle output", "settings.context.prune.description": "Fjern gamle værktøjsoutput under komprimering", "settings.context.watcherPatterns": "Filvagt-ignormønstre", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index 231bab9d25a..2753c763c31 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -1434,7 +1434,10 @@ export const dict = { "settings.checkpoints.enable.description": "Prüfpunkte vor Dateibearbeitungen erstellen, um vorherige Zustände wiederherstellen zu können", "settings.context.autoCompaction.title": "Automatische Komprimierung", - "settings.context.autoCompaction.description": "Kontext automatisch komprimieren, wenn er voll ist", + "settings.context.autoCompaction.description": "Kontext automatisch komprimieren, bevor er das Limit erreicht", + "settings.context.compactionLimit.title": "Limit für automatische Komprimierung", + "settings.context.compactionLimit.description": + "Komprimieren, wenn der Kontext diesen Prozentsatz des Modellfensters erreicht. Leer lassen, um nur den Sicherheitspuffer zu verwenden.", "settings.context.prune.title": "Alte Ausgaben bereinigen", "settings.context.prune.description": "Alte Werkzeugausgaben während der Komprimierung entfernen", "settings.context.watcherPatterns": "Datei-Watcher-Ignorierungsmuster", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 9770f4753e4..807482293f0 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1396,7 +1396,10 @@ export const dict = { "settings.checkpoints.enable.description": "Create checkpoints before file edits so you can restore previous states", "settings.context.autoCompaction.title": "Auto Compaction", - "settings.context.autoCompaction.description": "Automatically compact context when it's full", + "settings.context.autoCompaction.description": "Automatically compact context before it reaches the limit", + "settings.context.compactionLimit.title": "Auto Compaction Limit", + "settings.context.compactionLimit.description": + "Compact when context reaches this percentage of the model window. Leave blank to use the safety buffer only.", "settings.context.prune.title": "Prune Old Outputs", "settings.context.prune.description": "Remove old tool outputs during compaction", "settings.context.watcherPatterns": "File Watcher Ignore Patterns", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index 626627dadfa..ffb8cddae5a 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -1426,7 +1426,10 @@ export const dict = { "settings.checkpoints.enable.title": "Habilitar instantáneas", "settings.checkpoints.enable.description": "Crear puntos de control antes de editar archivos", "settings.context.autoCompaction.title": "Compactación automática", - "settings.context.autoCompaction.description": "Compactar automáticamente el contexto cuando está lleno", + "settings.context.autoCompaction.description": "Compactar automáticamente el contexto antes de que alcance el límite", + "settings.context.compactionLimit.title": "Límite de compactación automática", + "settings.context.compactionLimit.description": + "Compactar cuando el contexto alcance este porcentaje de la ventana del modelo. Déjalo en blanco para usar solo el búfer de seguridad.", "settings.context.prune.title": "Eliminar salidas antiguas", "settings.context.prune.description": "Eliminar salidas de herramientas antiguas durante la compactación", "settings.context.watcherPatterns": "Patrones de ignorar del observador", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 159e32340c2..f557dbc72c6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -1441,7 +1441,11 @@ export const dict = { "settings.checkpoints.enable.title": "Activer les instantanés", "settings.checkpoints.enable.description": "Créer des points de contrôle avant les modifications de fichiers", "settings.context.autoCompaction.title": "Compaction automatique", - "settings.context.autoCompaction.description": "Compacter automatiquement le contexte lorsqu'il est plein", + "settings.context.autoCompaction.description": + "Compacter automatiquement le contexte avant qu'il n'atteigne la limite", + "settings.context.compactionLimit.title": "Limite de compactage automatique", + "settings.context.compactionLimit.description": + "Compacter lorsque le contexte atteint ce pourcentage de la fenêtre du modèle. Laissez vide pour utiliser uniquement la marge de sécurité.", "settings.context.prune.title": "Élaguer les anciennes sorties", "settings.context.prune.description": "Supprimer les anciennes sorties d'outils pendant la compaction", "settings.context.watcherPatterns": "Motifs d'ignorance de l'observateur", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index a6a13784a65..8354dc6dd07 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -1401,7 +1401,10 @@ export const dict = { "settings.checkpoints.enable.title": "スナップショットを有効にする", "settings.checkpoints.enable.description": "ファイル編集前にチェックポイントを作成して以前の状態を復元可能にする", "settings.context.autoCompaction.title": "自動圧縮", - "settings.context.autoCompaction.description": "コンテキストが満杯のとき自動的に圧縮", + "settings.context.autoCompaction.description": "コンテキストが上限に達する前に自動的に圧縮", + "settings.context.compactionLimit.title": "自動圧縮の上限", + "settings.context.compactionLimit.description": + "コンテキストがモデルウィンドウのこの割合に達したら圧縮します。安全バッファーのみを使用するには空欄のままにしてください。", "settings.context.prune.title": "古い出力を削除", "settings.context.prune.description": "圧縮時に古いツール出力を削除", "settings.context.watcherPatterns": "ファイルウォッチャー無視パターン", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index 2367e50cc87..01e5ece527b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -1386,7 +1386,10 @@ export const dict = { "settings.checkpoints.enable.title": "스냅샷 활성화", "settings.checkpoints.enable.description": "파일 편집 전 체크포인트를 생성하여 이전 상태를 복원할 수 있습니다", "settings.context.autoCompaction.title": "자동 압축", - "settings.context.autoCompaction.description": "컨텍스트가 가득 차면 자동으로 압축", + "settings.context.autoCompaction.description": "컨텍스트가 한도에 도달하기 전에 자동으로 압축", + "settings.context.compactionLimit.title": "자동 압축 한도", + "settings.context.compactionLimit.description": + "컨텍스트가 모델 창의 이 비율에 도달하면 압축합니다. 안전 버퍼만 사용하려면 비워 두세요.", "settings.context.prune.title": "이전 출력 정리", "settings.context.prune.description": "압축 중 이전 도구 출력 제거", "settings.context.watcherPatterns": "파일 감시자 무시 패턴", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 6c93dc790a1..19f2d8c8351 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1385,7 +1385,10 @@ export const dict = { "Maak checkpoints aan voor het bewerken van bestanden zodat je eerdere staten kunt herstellen", "settings.context.autoCompaction.title": "Automatische Compactie", - "settings.context.autoCompaction.description": "Context automatisch compacteren wanneer deze vol is", + "settings.context.autoCompaction.description": "Context automatisch compacteren voordat deze de limiet bereikt", + "settings.context.compactionLimit.title": "Limiet voor automatisch compacteren", + "settings.context.compactionLimit.description": + "Compacteer wanneer de context dit percentage van het modelvenster bereikt. Laat leeg om alleen de veiligheidsbuffer te gebruiken.", "settings.context.prune.title": "Oude Uitvoer Opschonen", "settings.context.prune.description": "Verwijder oude tool uitvoer tijdens compactie", "settings.context.watcherPatterns": "File Watcher Negeer Patronen", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index a7b08921e48..0c2be64ddc6 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -1404,7 +1404,10 @@ export const dict = { "settings.checkpoints.enable.title": "Aktiver øyeblikksbilder", "settings.checkpoints.enable.description": "Opprett kontrollpunkter før filredigeringer", "settings.context.autoCompaction.title": "Automatisk komprimering", - "settings.context.autoCompaction.description": "Komprimer automatisk kontekst når den er full", + "settings.context.autoCompaction.description": "Komprimer automatisk kontekst før den når grensen", + "settings.context.compactionLimit.title": "Grense for automatisk komprimering", + "settings.context.compactionLimit.description": + "Komprimer når konteksten når denne prosentandelen av modellvinduet. La stå tomt for å bare bruke sikkerhetsbufferen.", "settings.context.prune.title": "Fjern gamle utdata", "settings.context.prune.description": "Fjern gamle verktøyutdata under komprimering", "settings.context.watcherPatterns": "Filvakt-ignormønstre", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 84550227de4..63289102089 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -1411,7 +1411,10 @@ export const dict = { "settings.checkpoints.enable.title": "Włącz migawki", "settings.checkpoints.enable.description": "Twórz punkty kontrolne przed edycją plików", "settings.context.autoCompaction.title": "Automatyczna kompakcja", - "settings.context.autoCompaction.description": "Automatycznie kompaktuj kontekst, gdy jest pełny", + "settings.context.autoCompaction.description": "Automatycznie kompaktuj kontekst, zanim osiągnie limit", + "settings.context.compactionLimit.title": "Limit automatycznego kompaktowania", + "settings.context.compactionLimit.description": + "Kompaktuj, gdy kontekst osiągnie ten procent okna modelu. Pozostaw puste, aby używać tylko bufora bezpieczeństwa.", "settings.context.prune.title": "Przytnij stare wyjścia", "settings.context.prune.description": "Usuń stare wyjścia narzędzi podczas kompakcji", "settings.context.watcherPatterns": "Wzorce ignorowania obserwatora plików", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index baf9174e0d4..ae20ef5057f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -1411,7 +1411,10 @@ export const dict = { "settings.checkpoints.enable.title": "Включить снимки", "settings.checkpoints.enable.description": "Создавать контрольные точки перед редактированием файлов", "settings.context.autoCompaction.title": "Автоматическое сжатие", - "settings.context.autoCompaction.description": "Автоматически сжимать контекст при заполнении", + "settings.context.autoCompaction.description": "Автоматически сжимать контекст до достижения лимита", + "settings.context.compactionLimit.title": "Лимит автоматического сжатия", + "settings.context.compactionLimit.description": + "Сжимать, когда контекст достигает этого процента окна модели. Оставьте пустым, чтобы использовать только буфер безопасности.", "settings.context.prune.title": "Очистить старые выходные данные", "settings.context.prune.description": "Удалить старые выходные данные инструментов при сжатии", "settings.context.watcherPatterns": "Шаблоны игнорирования наблюдателя файлов", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index 5438042d7ee..c29a61c2b27 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -1384,7 +1384,10 @@ export const dict = { "settings.checkpoints.enable.title": "เปิดใช้งานสแนปชอต", "settings.checkpoints.enable.description": "สร้างจุดตรวจก่อนแก้ไขไฟล์", "settings.context.autoCompaction.title": "การบีบอัดอัตโนมัติ", - "settings.context.autoCompaction.description": "บีบอัดบริบทอัตโนมัติเมื่อเต็ม", + "settings.context.autoCompaction.description": "บีบอัดบริบทอัตโนมัติก่อนถึงขีดจำกัด", + "settings.context.compactionLimit.title": "ขีดจำกัดการบีบอัดอัตโนมัติ", + "settings.context.compactionLimit.description": + "บีบอัดเมื่อบริบทถึงเปอร์เซ็นต์นี้ของหน้าต่างโมเดล เว้นว่างไว้เพื่อใช้เฉพาะบัฟเฟอร์ความปลอดภัย", "settings.context.prune.title": "ตัดผลลัพธ์เก่า", "settings.context.prune.description": "ลบผลลัพธ์เครื่องมือเก่าระหว่างการบีบอัด", "settings.context.watcherPatterns": "รูปแบบการละเว้นตัวเฝ้าดูไฟล์", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 8a7d0c756ae..de26b4a0573 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1374,7 +1374,10 @@ export const dict = { "Dosya düzenlemelerinden önce kontrol noktaları oluştur, böylece önceki durumları geri yükleyebilirsiniz", "settings.context.autoCompaction.title": "Otomatik Sıkıştırma", - "settings.context.autoCompaction.description": "Bağlam dolduğunda otomatik olarak sıkıştır", + "settings.context.autoCompaction.description": "Bağlam sınıra ulaşmadan önce otomatik olarak sıkıştır", + "settings.context.compactionLimit.title": "Otomatik sıkıştırma sınırı", + "settings.context.compactionLimit.description": + "Bağlam model penceresinin bu yüzdesine ulaştığında sıkıştır. Yalnızca güvenlik tamponunu kullanmak için boş bırakın.", "settings.context.prune.title": "Eski Çıktıları Temizle", "settings.context.prune.description": "Sıkıştırma sırasında eski araç çıktılarını kaldır", "settings.context.watcherPatterns": "Dosya İzleyici Yok Sayma Kalıpları", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index e2f36ebc4a3..bcfe2046569 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -1373,7 +1373,10 @@ export const dict = { "Створювати контрольні точки перед редагуванням файлів, щоб мати можливість відновити попередні стани", "settings.context.autoCompaction.title": "Автоматичне стиснення", - "settings.context.autoCompaction.description": "Автоматично стискати при заповненні контексту", + "settings.context.autoCompaction.description": "Автоматично стискати контекст до досягнення ліміту", + "settings.context.compactionLimit.title": "Ліміт автоматичного стискання", + "settings.context.compactionLimit.description": + "Стискати, коли контекст досягає цього відсотка вікна моделі. Залиште порожнім, щоб використовувати лише буфер безпеки.", "settings.context.prune.title": "Очищати старі виводи", "settings.context.prune.description": "Видаляти старі виводи інструментів під час стиснення", "settings.context.watcherPatterns": "Шаблони ігнорування спостерігача файлів", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 9d55d18cfa9..0aa747f2a36 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -1352,7 +1352,9 @@ export const dict = { "settings.checkpoints.enable.title": "启用快照", "settings.checkpoints.enable.description": "在文件编辑前创建检查点,以便恢复之前的状态", "settings.context.autoCompaction.title": "自动压缩", - "settings.context.autoCompaction.description": "上下文满时自动压缩", + "settings.context.autoCompaction.description": "在上下文达到限制前自动压缩", + "settings.context.compactionLimit.title": "自动压缩限制", + "settings.context.compactionLimit.description": "当上下文达到模型窗口的此百分比时进行压缩。留空则仅使用安全缓冲区。", "settings.context.prune.title": "修剪旧输出", "settings.context.prune.description": "压缩期间移除旧的工具输出", "settings.context.watcherPatterns": "文件监视器忽略模式", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index 4cddda95852..2f28047d674 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -1323,7 +1323,9 @@ export const dict = { "settings.checkpoints.enable.title": "啟用快照", "settings.checkpoints.enable.description": "在檔案編輯前建立檢查點,以便恢復之前的狀態", "settings.context.autoCompaction.title": "自動壓縮", - "settings.context.autoCompaction.description": "上下文滿時自動壓縮", + "settings.context.autoCompaction.description": "在上下文達到限制前自動壓縮", + "settings.context.compactionLimit.title": "自動壓縮限制", + "settings.context.compactionLimit.description": "當上下文達到模型視窗的此百分比時進行壓縮。留空則僅使用安全緩衝區。", "settings.context.prune.title": "修剪舊輸出", "settings.context.prune.description": "壓縮期間移除舊的工具輸出", "settings.context.watcherPatterns": "檔案監視器忽略模式", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/config.ts b/packages/kilo-vscode/webview-ui/src/types/messages/config.ts index ca0c91c3d39..fef81e37362 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/config.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/config.ts @@ -29,6 +29,7 @@ export interface SkillsConfig { export interface CompactionConfig { auto?: boolean + threshold_percent?: number | null prune?: boolean } diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index bc2a2d5122b..3b3fc94a330 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -115,6 +115,7 @@ const LogLevelRef = Schema.Literals(["DEBUG", "INFO", "WARN", "ERROR"]).annotate identifier: "LogLevel", description: "Log level", }) +const Percent = Schema.Number.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)) // kilocode_change // kilocode_change - KiloIndexingConfig is still a Zod schema; bridge via ZodOverride const IndexingRef = Schema.Any.annotate({ [ZodOverride]: KiloIndexingConfig }) @@ -277,6 +278,12 @@ export const Info = Schema.Struct({ auto: Schema.optional(Schema.Boolean).annotate({ description: "Enable automatic compaction when context is full (default: true)", }), + // kilocode_change start + threshold_percent: Schema.optional(Schema.NullOr(Percent)).annotate({ + description: + "Percentage of the model input/context window that triggers automatic compaction. The reserved safety buffer still applies if it would compact sooner.", + }), + // kilocode_change end prune: Schema.optional(Schema.Boolean).annotate({ description: "Enable pruning of old tool outputs (default: true)", }), diff --git a/packages/opencode/src/kilocode/session/overflow.ts b/packages/opencode/src/kilocode/session/overflow.ts new file mode 100644 index 00000000000..270259176f3 --- /dev/null +++ b/packages/opencode/src/kilocode/session/overflow.ts @@ -0,0 +1,15 @@ +import type { Config } from "@/config/config" +import type { Provider } from "@/provider/provider" + +export namespace KiloSessionOverflow { + export function limit(input: { cfg: Config.Info; model: Provider.Model; usable: number }) { + const percent = input.cfg.compaction?.threshold_percent + if (typeof percent !== "number") return input.usable + + const context = input.model.limit.input || input.model.limit.context + if (context === 0) return input.usable + + const cap = Math.floor(context * (percent / 100)) + return Math.min(input.usable, cap) + } +} diff --git a/packages/opencode/src/session/overflow.ts b/packages/opencode/src/session/overflow.ts index 6485950dcc8..e6eb566ef1c 100644 --- a/packages/opencode/src/session/overflow.ts +++ b/packages/opencode/src/session/overflow.ts @@ -2,6 +2,7 @@ import type { Config } from "@/config/config" import type { Provider } from "@/provider/provider" import { ProviderTransform } from "@/provider/transform" import type { MessageV2 } from "./message-v2" +import { KiloSessionOverflow } from "@/kilocode/session/overflow" // kilocode_change const COMPACTION_BUFFER = 20_000 @@ -22,5 +23,8 @@ export function isOverflow(input: { cfg: Config.Info; tokens: MessageV2.Assistan const count = input.tokens.total || input.tokens.input + input.tokens.output + input.tokens.cache.read + input.tokens.cache.write - return count >= usable(input) + // kilocode_change start + const cap = KiloSessionOverflow.limit({ cfg: input.cfg, model: input.model, usable: usable(input) }) + return count >= cap + // kilocode_change end } diff --git a/packages/opencode/test/kilocode/session-overflow.test.ts b/packages/opencode/test/kilocode/session-overflow.test.ts new file mode 100644 index 00000000000..83890141bb4 --- /dev/null +++ b/packages/opencode/test/kilocode/session-overflow.test.ts @@ -0,0 +1,78 @@ +import { describe, expect, test } from "bun:test" +import { Config } from "@/config/config" +import type { Provider } from "@/provider/provider" +import type { MessageV2 } from "@/session/message-v2" +import { isOverflow } from "@/session/overflow" + +function cfg(compaction?: Config.Info["compaction"]) { + return Config.Info.zod.parse({ compaction }) +} + +function model(opts: { context: number; output: number; input?: number }): Provider.Model { + return { + id: "test-model", + providerID: "test", + name: "Test", + limit: { + context: opts.context, + input: opts.input, + output: opts.output, + }, + cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, + capabilities: { + toolcall: true, + attachment: false, + reasoning: false, + temperature: true, + input: { text: true, image: false, audio: false, video: false }, + output: { text: true, image: false, audio: false, video: false }, + }, + api: { npm: "@ai-sdk/anthropic" }, + options: {}, + } as Provider.Model +} + +function tokens(count: number): MessageV2.Assistant["tokens"] { + return { input: count, output: 0, reasoning: 0, cache: { read: 0, write: 0 } } +} + +describe("Kilo auto-compaction threshold", () => { + test("triggers at the configured context percentage", () => { + const conf = cfg({ threshold_percent: 75 }) + const mdl = model({ context: 200_000, output: 32_000 }) + + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(149_999) })).toBe(false) + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(150_000) })).toBe(true) + }) + + test("keeps the reserved safety trigger when it is lower", () => { + const conf = cfg({ threshold_percent: 95 }) + const mdl = model({ context: 200_000, output: 32_000 }) + + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(167_999) })).toBe(false) + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(168_000) })).toBe(true) + }) + + test("uses a model input limit when present", () => { + const conf = cfg({ threshold_percent: 75 }) + const mdl = model({ context: 400_000, input: 200_000, output: 32_000 }) + + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(149_999) })).toBe(false) + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(150_000) })).toBe(true) + }) + + test("ignores a cleared threshold", () => { + const conf = cfg({ threshold_percent: null }) + const mdl = model({ context: 200_000, output: 32_000 }) + + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(150_000) })).toBe(false) + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(168_000) })).toBe(true) + }) + + test("still respects disabled auto-compaction", () => { + const conf = cfg({ auto: false, threshold_percent: 75 }) + const mdl = model({ context: 200_000, output: 32_000 }) + + expect(isOverflow({ cfg: conf, model: mdl, tokens: tokens(150_000) })).toBe(false) + }) +}) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index a5aed799518..ce8f77317e9 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -2048,6 +2048,10 @@ export type Config = { * Enable automatic compaction when context is full (default: true) */ auto?: boolean + /** + * Percentage of the model input/context window that triggers automatic compaction. The reserved safety buffer still applies if it would compact sooner. + */ + threshold_percent?: number | null /** * Enable pruning of old tool outputs (default: true) */ diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 65600b7db7b..33c1727634a 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -16413,6 +16413,19 @@ "description": "Enable automatic compaction when context is full (default: true)", "type": "boolean" }, + "threshold_percent": { + "description": "Percentage of the model input/context window that triggers automatic compaction. The reserved safety buffer still applies if it would compact sooner.", + "anyOf": [ + { + "type": "number", + "exclusiveMinimum": 0, + "maximum": 100 + }, + { + "type": "null" + } + ] + }, "prune": { "description": "Enable pruning of old tool outputs (default: true)", "type": "boolean"