diff --git a/.changeset/estimate-code-context-at-plan-exit.md b/.changeset/estimate-code-context-at-plan-exit.md new file mode 100644 index 00000000000..85a904ac171 --- /dev/null +++ b/.changeset/estimate-code-context-at-plan-exit.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Show the estimated Code-mode context usage and recommend a fresh session when continuing a plan is near automatic compaction. diff --git a/packages/kilo-i18n/src/ar.ts b/packages/kilo-i18n/src/ar.ts index 13170b89c6d..9ee1e2736e8 100644 --- a/packages/kilo-i18n/src/ar.ts +++ b/packages/kilo-i18n/src/ar.ts @@ -110,8 +110,10 @@ export const dict = { "plan.followup.question": "جاهز للتنفيذ؟", "plan.followup.answer.newSession": "بدء جلسة جديدة", "plan.followup.answer.newSession.description": "نفّذ في جلسة جديدة بسياق نظيف", + "plan.followup.answer.newSession.recommended.description": "نفّذ في جلسة جديدة بسياق نظيف (موصى به)", "plan.followup.answer.continue": "المتابعة هنا", "plan.followup.answer.continue.description": "نفّذ الخطة في هذه الجلسة", + "plan.followup.answer.continue.estimated.description": "نفّذ الخطة في هذه الجلسة (باستخدام {{0}}٪ من سياق وضع البرمجة)", "plan.followup.answer.keepRefining": "واصل التحسين", "plan.followup.answer.keepRefining.description": "واصل التخطيط دون التنفيذ الآن", diff --git a/packages/kilo-i18n/src/br.ts b/packages/kilo-i18n/src/br.ts index 3e91b3d765e..1c16c4c89e6 100644 --- a/packages/kilo-i18n/src/br.ts +++ b/packages/kilo-i18n/src/br.ts @@ -111,8 +111,10 @@ export const dict = { "plan.followup.question": "Pronto para implementar?", "plan.followup.answer.newSession": "Iniciar nova sessão", "plan.followup.answer.newSession.description": "Implementar em uma nova sessão com contexto limpo", + "plan.followup.answer.newSession.recommended.description": "Implementar em uma nova sessão com contexto limpo (Recomendado)", "plan.followup.answer.continue": "Continuar aqui", "plan.followup.answer.continue.description": "Implementar o plano nesta sessão", + "plan.followup.answer.continue.estimated.description": "Implementar o plano nesta sessão (usando {{0}}% do contexto do modo de código)", "plan.followup.answer.keepRefining": "Continuar refinando", "plan.followup.answer.keepRefining.description": "Continuar planejando sem implementar ainda", diff --git a/packages/kilo-i18n/src/bs.ts b/packages/kilo-i18n/src/bs.ts index d1aece561ee..8031b84a15a 100644 --- a/packages/kilo-i18n/src/bs.ts +++ b/packages/kilo-i18n/src/bs.ts @@ -116,8 +116,10 @@ export const dict = { "plan.followup.question": "Spreman za implementaciju?", "plan.followup.answer.newSession": "Pokreni novu sesiju", "plan.followup.answer.newSession.description": "Implementiraj u novoj sesiji s čistim kontekstom", + "plan.followup.answer.newSession.recommended.description": "Implementiraj u novoj sesiji s čistim kontekstom (Preporučeno)", "plan.followup.answer.continue": "Nastavi ovdje", "plan.followup.answer.continue.description": "Implementiraj plan u ovoj sesiji", + "plan.followup.answer.continue.estimated.description": "Implementiraj plan u ovoj sesiji (koristi {{0}}% konteksta režima koda)", "plan.followup.answer.keepRefining": "Nastavi dorađivati", "plan.followup.answer.keepRefining.description": "Nastavi planirati bez implementacije za sada", diff --git a/packages/kilo-i18n/src/da.ts b/packages/kilo-i18n/src/da.ts index 3147ec1eee1..c536cebc348 100644 --- a/packages/kilo-i18n/src/da.ts +++ b/packages/kilo-i18n/src/da.ts @@ -111,8 +111,10 @@ export const dict = { "plan.followup.question": "Klar til at implementere?", "plan.followup.answer.newSession": "Start ny session", "plan.followup.answer.newSession.description": "Implementér i en ny session med ren kontekst", + "plan.followup.answer.newSession.recommended.description": "Implementér i en ny session med ren kontekst (Anbefalet)", "plan.followup.answer.continue": "Fortsæt her", "plan.followup.answer.continue.description": "Implementér planen i denne session", + "plan.followup.answer.continue.estimated.description": "Implementér planen i denne session (bruger {{0}}% af konteksten i kodetilstand)", "plan.followup.answer.keepRefining": "Fortsæt med at finpudse", "plan.followup.answer.keepRefining.description": "Fortsæt planlægningen uden at implementere endnu", diff --git a/packages/kilo-i18n/src/de.ts b/packages/kilo-i18n/src/de.ts index 8e4fe468a5c..4883a410b98 100644 --- a/packages/kilo-i18n/src/de.ts +++ b/packages/kilo-i18n/src/de.ts @@ -113,8 +113,10 @@ export const dict = { "plan.followup.question": "Bereit zur Umsetzung?", "plan.followup.answer.newSession": "Neue Sitzung starten", "plan.followup.answer.newSession.description": "In einer neuen Sitzung mit leerem Kontext umsetzen", + "plan.followup.answer.newSession.recommended.description": "In einer neuen Sitzung mit leerem Kontext umsetzen (Empfohlen)", "plan.followup.answer.continue": "Hier fortfahren", "plan.followup.answer.continue.description": "Den Plan in dieser Sitzung umsetzen", + "plan.followup.answer.continue.estimated.description": "Den Plan in dieser Sitzung umsetzen ({{0}}% des Code-Kontextes verwendet)", "plan.followup.answer.keepRefining": "Weiter verfeinern", "plan.followup.answer.keepRefining.description": "Weiter planen, ohne jetzt zu implementieren", diff --git a/packages/kilo-i18n/src/en.ts b/packages/kilo-i18n/src/en.ts index 9eb679e3a03..505c6de94ba 100644 --- a/packages/kilo-i18n/src/en.ts +++ b/packages/kilo-i18n/src/en.ts @@ -113,8 +113,10 @@ export const dict = { "plan.followup.question": "Ready to implement?", "plan.followup.answer.newSession": "Start new session", "plan.followup.answer.newSession.description": "Implement in a fresh session with a clean context", + "plan.followup.answer.newSession.recommended.description": "Implement in a fresh session with a clean context (Recommended)", "plan.followup.answer.continue": "Continue here", "plan.followup.answer.continue.description": "Implement the plan in this session", + "plan.followup.answer.continue.estimated.description": "Implement the plan in this session (using {{0}}% of Code mode context)", "plan.followup.answer.keepRefining": "Keep refining", "plan.followup.answer.keepRefining.description": "Keep planning without implementing yet", diff --git a/packages/kilo-i18n/src/es.ts b/packages/kilo-i18n/src/es.ts index a72ba48094c..a79eac45299 100644 --- a/packages/kilo-i18n/src/es.ts +++ b/packages/kilo-i18n/src/es.ts @@ -112,8 +112,10 @@ export const dict = { "plan.followup.question": "¿Listo para implementar?", "plan.followup.answer.newSession": "Iniciar nueva sesión", "plan.followup.answer.newSession.description": "Implementar en una sesión nueva con contexto limpio", + "plan.followup.answer.newSession.recommended.description": "Implementar en una sesión nueva con contexto limpio (Recomendado)", "plan.followup.answer.continue": "Continuar aquí", "plan.followup.answer.continue.description": "Implementar el plan en esta sesión", + "plan.followup.answer.continue.estimated.description": "Implementar el plan en esta sesión (usando {{0}}% del contexto del modo Código)", "plan.followup.answer.keepRefining": "Seguir refinando", "plan.followup.answer.keepRefining.description": "Seguir planificando sin implementar todavía", diff --git a/packages/kilo-i18n/src/fr.ts b/packages/kilo-i18n/src/fr.ts index 6f654770827..bc7d7600d9a 100644 --- a/packages/kilo-i18n/src/fr.ts +++ b/packages/kilo-i18n/src/fr.ts @@ -113,8 +113,10 @@ export const dict = { "plan.followup.question": "Prêt à implémenter ?", "plan.followup.answer.newSession": "Démarrer une nouvelle session", "plan.followup.answer.newSession.description": "Implémenter dans une nouvelle session avec un contexte vierge", + "plan.followup.answer.newSession.recommended.description": "Implémenter dans une nouvelle session avec un contexte vierge (Recommandé)", "plan.followup.answer.continue": "Continuer ici", "plan.followup.answer.continue.description": "Implémenter le plan dans cette session", + "plan.followup.answer.continue.estimated.description": "Implémenter le plan dans cette session (utilise {{0}} % du contexte du mode Code)", "plan.followup.answer.keepRefining": "Continuer à affiner", "plan.followup.answer.keepRefining.description": "Continuer à planifier sans implémenter pour l'instant", diff --git a/packages/kilo-i18n/src/it.ts b/packages/kilo-i18n/src/it.ts index 229be83c14a..ad22e3ddebd 100644 --- a/packages/kilo-i18n/src/it.ts +++ b/packages/kilo-i18n/src/it.ts @@ -113,8 +113,10 @@ export const dict = { "plan.followup.question": "Pronto per implementare?", "plan.followup.answer.newSession": "Avvia una nuova sessione", "plan.followup.answer.newSession.description": "Implementa in una nuova sessione con contesto vuoto", + "plan.followup.answer.newSession.recommended.description": "Implementa in una nuova sessione con contesto vuoto (Raccomandato)", "plan.followup.answer.continue": "Continua qui", "plan.followup.answer.continue.description": "Implementa il piano in questa sessione", + "plan.followup.answer.continue.estimated.description": "Implementa il piano in questa sessione (usa il {{0}}% del contesto della modalità Codice)", "plan.followup.answer.keepRefining": "Continua a rifinire", "plan.followup.answer.keepRefining.description": "Continua a pianificare senza implementare per ora", diff --git a/packages/kilo-i18n/src/ja.ts b/packages/kilo-i18n/src/ja.ts index c1699834b6d..1b010a2c5d6 100644 --- a/packages/kilo-i18n/src/ja.ts +++ b/packages/kilo-i18n/src/ja.ts @@ -110,8 +110,10 @@ export const dict = { "plan.followup.question": "実装する準備はできましたか?", "plan.followup.answer.newSession": "新しいセッションを開始", "plan.followup.answer.newSession.description": "クリーンなコンテキストの新しいセッションで実装する", + "plan.followup.answer.newSession.recommended.description": "クリーンなコンテキストの新しいセッションで実装する(推奨)", "plan.followup.answer.continue": "ここで続行", "plan.followup.answer.continue.description": "このセッションで計画を実装する", + "plan.followup.answer.continue.estimated.description": "このセッションで計画を実装する(Code モードのコンテキストを {{0}}% 使用)", "plan.followup.answer.keepRefining": "さらに調整する", "plan.followup.answer.keepRefining.description": "まだ実装せずに計画を続ける", diff --git a/packages/kilo-i18n/src/ko.ts b/packages/kilo-i18n/src/ko.ts index a0e760dd541..4ff6a2f4996 100644 --- a/packages/kilo-i18n/src/ko.ts +++ b/packages/kilo-i18n/src/ko.ts @@ -110,8 +110,10 @@ export const dict = { "plan.followup.question": "구현할 준비가 되셨나요?", "plan.followup.answer.newSession": "새 세션 시작", "plan.followup.answer.newSession.description": "깨끗한 컨텍스트의 새 세션에서 구현", + "plan.followup.answer.newSession.recommended.description": "깨끗한 컨텍스트의 새 세션에서 구현 (권장)", "plan.followup.answer.continue": "여기서 계속하기", "plan.followup.answer.continue.description": "이 세션에서 계획 구현", + "plan.followup.answer.continue.estimated.description": "이 세션에서 계획 구현 (Code 모드 컨텍스트의 {{0}}% 사용)", "plan.followup.answer.keepRefining": "계속 다듬기", "plan.followup.answer.keepRefining.description": "아직 구현하지 않고 계획을 계속 진행", diff --git a/packages/kilo-i18n/src/nl.ts b/packages/kilo-i18n/src/nl.ts index bf4f116fd47..8b14ca5835d 100644 --- a/packages/kilo-i18n/src/nl.ts +++ b/packages/kilo-i18n/src/nl.ts @@ -114,8 +114,10 @@ export const dict = { "plan.followup.question": "Klaar om te implementeren?", "plan.followup.answer.newSession": "Nieuwe sessie starten", "plan.followup.answer.newSession.description": "Implementeren in een nieuwe sessie met een lege context", + "plan.followup.answer.newSession.recommended.description": "Implementeren in een nieuwe sessie met een lege context (Aanbevolen)", "plan.followup.answer.continue": "Hier doorgaan", "plan.followup.answer.continue.description": "Het plan in deze sessie implementeren", + "plan.followup.answer.continue.estimated.description": "Het plan in deze sessie implementeren (gebruikt {{0}}% van de Code-moduscontext)", "plan.followup.answer.keepRefining": "Blijven verfijnen", "plan.followup.answer.keepRefining.description": "Blijven plannen zonder nu te implementeren", diff --git a/packages/kilo-i18n/src/no.ts b/packages/kilo-i18n/src/no.ts index c28bfb16cda..fcb13033ca0 100644 --- a/packages/kilo-i18n/src/no.ts +++ b/packages/kilo-i18n/src/no.ts @@ -111,8 +111,10 @@ export const dict = { "plan.followup.question": "Klar til å implementere?", "plan.followup.answer.newSession": "Start ny økt", "plan.followup.answer.newSession.description": "Implementer i en ny økt med ren kontekst", + "plan.followup.answer.newSession.recommended.description": "Implementer i en ny økt med ren kontekst (Anbefalt)", "plan.followup.answer.continue": "Fortsett her", "plan.followup.answer.continue.description": "Implementer planen i denne økten", + "plan.followup.answer.continue.estimated.description": "Implementer planen i denne økten (bruker {{0}}% av konteksten i kodemodus)", "plan.followup.answer.keepRefining": "Fortsett å finpusse", "plan.followup.answer.keepRefining.description": "Fortsett planleggingen uten å implementere ennå", diff --git a/packages/kilo-i18n/src/pl.ts b/packages/kilo-i18n/src/pl.ts index 6764a61f265..b1d0d814739 100644 --- a/packages/kilo-i18n/src/pl.ts +++ b/packages/kilo-i18n/src/pl.ts @@ -112,8 +112,10 @@ export const dict = { "plan.followup.question": "Gotowy do wdrożenia?", "plan.followup.answer.newSession": "Rozpocznij nową sesję", "plan.followup.answer.newSession.description": "Wdróż w nowej sesji z czystym kontekstem", + "plan.followup.answer.newSession.recommended.description": "Wdróż w nowej sesji z czystym kontekstem (Zalecane)", "plan.followup.answer.continue": "Kontynuuj tutaj", "plan.followup.answer.continue.description": "Wdróż plan w tej sesji", + "plan.followup.answer.continue.estimated.description": "Wdróż plan w tej sesji (wykorzystując {{0}}% kontekstu trybu kodu)", "plan.followup.answer.keepRefining": "Dalej dopracowuj", "plan.followup.answer.keepRefining.description": "Kontynuuj planowanie bez wdrażania na razie", diff --git a/packages/kilo-i18n/src/ru.ts b/packages/kilo-i18n/src/ru.ts index d426d1c0f1f..f3f3b2197e3 100644 --- a/packages/kilo-i18n/src/ru.ts +++ b/packages/kilo-i18n/src/ru.ts @@ -113,8 +113,10 @@ export const dict = { "plan.followup.question": "Готовы реализовать?", "plan.followup.answer.newSession": "Начать новую сессию", "plan.followup.answer.newSession.description": "Реализовать в новой сессии с чистым контекстом", + "plan.followup.answer.newSession.recommended.description": "Реализовать в новой сессии с чистым контекстом (Рекомендуется)", "plan.followup.answer.continue": "Продолжить здесь", "plan.followup.answer.continue.description": "Реализовать план в этой сессии", + "plan.followup.answer.continue.estimated.description": "Реализовать план в этой сессии (используя {{0}}% контекста режима кода)", "plan.followup.answer.keepRefining": "Продолжить уточнение", "plan.followup.answer.keepRefining.description": "Продолжить планирование без реализации пока что", diff --git a/packages/kilo-i18n/src/th.ts b/packages/kilo-i18n/src/th.ts index 11a2f317c9a..0f938db2233 100644 --- a/packages/kilo-i18n/src/th.ts +++ b/packages/kilo-i18n/src/th.ts @@ -111,8 +111,10 @@ export const dict = { "plan.followup.question": "พร้อมดำเนินการหรือยัง?", "plan.followup.answer.newSession": "เริ่มเซสชันใหม่", "plan.followup.answer.newSession.description": "ดำเนินการในเซสชันใหม่ที่มีบริบทว่างเปล่า", + "plan.followup.answer.newSession.recommended.description": "ดำเนินการในเซสชันใหม่ที่มีบริบทว่างเปล่า (แนะนำ)", "plan.followup.answer.continue": "ดำเนินการต่อที่นี่", "plan.followup.answer.continue.description": "ดำเนินการตามแผนในเซสชันนี้", + "plan.followup.answer.continue.estimated.description": "ดำเนินการตามแผนในเซสชันนี้ (ใช้บริบทโหมดโค้ด {{0}}%)", "plan.followup.answer.keepRefining": "ปรับแผนต่อ", "plan.followup.answer.keepRefining.description": "วางแผนต่อโดยยังไม่ดำเนินการ", diff --git a/packages/kilo-i18n/src/tr.ts b/packages/kilo-i18n/src/tr.ts index a787e69f62c..cb9661ab42f 100644 --- a/packages/kilo-i18n/src/tr.ts +++ b/packages/kilo-i18n/src/tr.ts @@ -112,8 +112,10 @@ export const dict = { "plan.followup.question": "Uygulamaya hazır mısın?", "plan.followup.answer.newSession": "Yeni oturum başlat", "plan.followup.answer.newSession.description": "Temiz bir bağlamla yeni bir oturumda uygula", + "plan.followup.answer.newSession.recommended.description": "Temiz bir bağlamla yeni bir oturumda uygula (Önerilen)", "plan.followup.answer.continue": "Burada devam et", "plan.followup.answer.continue.description": "Planı bu oturumda uygula", + "plan.followup.answer.continue.estimated.description": "Planı bu oturumda uygula (Kod modu bağlamının {{0}}% kadarı kullanılıyor)", "plan.followup.answer.keepRefining": "İyileştirmeye devam et", "plan.followup.answer.keepRefining.description": "Henüz uygulamadan planlamaya devam et", diff --git a/packages/kilo-i18n/src/uk.ts b/packages/kilo-i18n/src/uk.ts index b95a8240da7..2c54f408ce2 100644 --- a/packages/kilo-i18n/src/uk.ts +++ b/packages/kilo-i18n/src/uk.ts @@ -113,8 +113,10 @@ export const dict = { "plan.followup.question": "Готові реалізувати?", "plan.followup.answer.newSession": "Почати нову сесію", "plan.followup.answer.newSession.description": "Реалізувати в новій сесії з чистим контекстом", + "plan.followup.answer.newSession.recommended.description": "Реалізувати в новій сесії з чистим контекстом (Рекомендовано)", "plan.followup.answer.continue": "Продовжити тут", "plan.followup.answer.continue.description": "Реалізувати план у цій сесії", + "plan.followup.answer.continue.estimated.description": "Реалізувати план у цій сесії (використовуючи {{0}}% контексту режиму коду)", "plan.followup.answer.keepRefining": "Продовжити уточнення", "plan.followup.answer.keepRefining.description": "Продовжити планування без реалізації наразі", diff --git a/packages/kilo-i18n/src/zh.ts b/packages/kilo-i18n/src/zh.ts index 8baddc98f38..673a864a3e9 100644 --- a/packages/kilo-i18n/src/zh.ts +++ b/packages/kilo-i18n/src/zh.ts @@ -106,8 +106,10 @@ export const dict = { "plan.followup.question": "准备好实现了吗?", "plan.followup.answer.newSession": "开启新会话", "plan.followup.answer.newSession.description": "在具有干净上下文的新会话中实现", + "plan.followup.answer.newSession.recommended.description": "在具有干净上下文的新会话中实现(推荐)", "plan.followup.answer.continue": "在此继续", "plan.followup.answer.continue.description": "在本会话中实现计划", + "plan.followup.answer.continue.estimated.description": "在本会话中实现计划(使用 {{0}}% 的代码模式上下文)", "plan.followup.answer.keepRefining": "继续完善", "plan.followup.answer.keepRefining.description": "继续规划,暂不实现", diff --git a/packages/kilo-i18n/src/zht.ts b/packages/kilo-i18n/src/zht.ts index fdb58ffcaf7..5246588d2ad 100644 --- a/packages/kilo-i18n/src/zht.ts +++ b/packages/kilo-i18n/src/zht.ts @@ -106,8 +106,10 @@ export const dict = { "plan.followup.question": "準備好實作了嗎?", "plan.followup.answer.newSession": "開啟新工作階段", "plan.followup.answer.newSession.description": "在具有乾淨上下文的新工作階段中實作", + "plan.followup.answer.newSession.recommended.description": "在具有乾淨上下文的新工作階段中實作(建議)", "plan.followup.answer.continue": "在此繼續", "plan.followup.answer.continue.description": "在本工作階段中實作計畫", + "plan.followup.answer.continue.estimated.description": "在本工作階段中實作計畫(使用 {{0}}% 的程式碼模式上下文)", "plan.followup.answer.keepRefining": "繼續完善", "plan.followup.answer.keepRefining.description": "繼續規劃,暫不實作", diff --git a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloCliDataParser.kt b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloCliDataParser.kt index fee794849bc..5d70ae0a10e 100644 --- a/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloCliDataParser.kt +++ b/packages/kilo-jetbrains/backend/src/main/kotlin/ai/kilocode/backend/cli/KiloCliDataParser.kt @@ -1193,6 +1193,7 @@ object KiloCliDataParser { description = oo.str("description") ?: "", labelKey = oo.str("labelKey"), descriptionKey = oo.str("descriptionKey"), + descriptionArgs = oo["descriptionArgs"]?.arr()?.mapNotNull { it.jsonPrimitive.contentOrNull } ?: emptyList(), mode = oo.str("mode"), ) } ?: emptyList() diff --git a/packages/kilo-jetbrains/backend/src/test/kotlin/ai/kilocode/backend/cli/KiloCliDataParserTest.kt b/packages/kilo-jetbrains/backend/src/test/kotlin/ai/kilocode/backend/cli/KiloCliDataParserTest.kt index 74479094e7a..bf4404124e6 100644 --- a/packages/kilo-jetbrains/backend/src/test/kotlin/ai/kilocode/backend/cli/KiloCliDataParserTest.kt +++ b/packages/kilo-jetbrains/backend/src/test/kotlin/ai/kilocode/backend/cli/KiloCliDataParserTest.kt @@ -911,6 +911,7 @@ class KiloCliDataParserTest { "labelKey": "plan.followup.answer.continue", "description": "Implement the plan in this session", "descriptionKey": "plan.followup.answer.continue.description", + "descriptionArgs": ["75"], "mode": "code" }] }], @@ -930,6 +931,7 @@ class KiloCliDataParserTest { val opt = item.options.single() assertEquals("plan.followup.answer.continue", opt.labelKey) assertEquals("plan.followup.answer.continue.description", opt.descriptionKey) + assertEquals(listOf("75"), opt.descriptionArgs) assertEquals("code", opt.mode) } diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/plugin/KiloBundle.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/plugin/KiloBundle.kt index 26efda9948d..f00628708e8 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/plugin/KiloBundle.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/plugin/KiloBundle.kt @@ -10,8 +10,8 @@ object KiloBundle : DynamicBundle(BUNDLE) { return getMessage(key, *params) } - fun optional(key: String): String? { + fun optional(key: String, vararg params: Any): String? { if (!containsKey(key)) return null - return getMessage(key) + return getMessage(key, *params) } } diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/controller/SessionController.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/controller/SessionController.kt index 21827b7f53a..7cbec0a4bd2 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/controller/SessionController.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/controller/SessionController.kt @@ -2469,6 +2469,7 @@ private fun toQuestion(dto: QuestionRequestDto): Question { description = opt.description, labelKey = opt.labelKey, descriptionKey = opt.descriptionKey, + descriptionArgs = opt.descriptionArgs, mode = opt.mode, ) }, diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/model/Question.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/model/Question.kt index aba1b54b6b4..0ea5cd8e6c1 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/model/Question.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/model/Question.kt @@ -25,5 +25,6 @@ data class QuestionOption( val description: String, val labelKey: String? = null, val descriptionKey: String? = null, + val descriptionArgs: List = emptyList(), val mode: String? = null, ) diff --git a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/question/QuestionView.kt b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/question/QuestionView.kt index 6cd19df3aa2..35c41f4130d 100644 --- a/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/question/QuestionView.kt +++ b/packages/kilo-jetbrains/frontend/src/main/kotlin/ai/kilocode/client/session/views/question/QuestionView.kt @@ -631,10 +631,13 @@ class QuestionView( @RequiresEdt private fun optionRow(toggle: AbstractButton, opt: QuestionOption): JPanel { + val description = opt.descriptionKey?.let { key -> + KiloBundle.optional(key, *opt.descriptionArgs.toTypedArray()) + } ?: opt.description val row = JPanel(BorderLayout()).apply { isOpaque = false border = JBUI.Borders.emptyBottom(UiStyle.Gap.lg()) - toolTipText = opt.description.ifBlank { null } + toolTipText = description.ifBlank { null } alignmentX = Component.LEFT_ALIGNMENT } val press = object : MouseAdapter() { @@ -642,7 +645,7 @@ class QuestionView( if (toggle.isEnabled) toggle.doClick() } } - val center = opt.description.isBlank() + val center = description.isBlank() val icon = JPanel(if (center) GridBagLayout() else BorderLayout()).apply { isOpaque = false border = JBUI.Borders.emptyRight(UiStyle.Gap.sm()) @@ -659,8 +662,8 @@ class QuestionView( label.addMouseListener(press) col.add(label) - if (opt.description.isNotBlank()) { - val desc = text(opt.description, UiStyle.Colors.weak()) + if (description.isNotBlank()) { + val desc = text(description, UiStyle.Colors.weak()) desc.alignmentX = Component.LEFT_ALIGNMENT desc.addMouseListener(press) col.add(desc) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle.properties index fa800d28d14..21c60e6b43b 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle.properties @@ -591,3 +591,7 @@ migration.button.migrate=Migrate Settings migration.button.migrating=Migrating... migration.button.done=Done migration.button.continue=Continue +plan.followup.answer.newSession.description=Implement in a fresh session with a clean context +plan.followup.answer.newSession.recommended.description=Implement in a fresh session with a clean context (Recommended) +plan.followup.answer.continue.description=Implement the plan in this session +plan.followup.answer.continue.estimated.description=Implement the plan in this session (using {0}% of Code mode context) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties index 30e9d4c84b9..40a0805a05a 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ar.properties @@ -371,3 +371,7 @@ revert.banner.redo=إعادة revert.banner.redo.all=إعادة الكل revert.banner.hint=يمكنك إعادة هذه التغييرات حتى ترسل رسالة جديدة revert.message.rollback=العودة إلى هذه الرسالة +plan.followup.answer.newSession.description=نفّذ في جلسة جديدة بسياق نظيف +plan.followup.answer.newSession.recommended.description=نفّذ في جلسة جديدة بسياق نظيف (موصى به) +plan.followup.answer.continue.description=نفّذ الخطة في هذه الجلسة +plan.followup.answer.continue.estimated.description=نفّذ الخطة في هذه الجلسة (باستخدام {0}% من سياق وضع البرمجة) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties index f6307333565..8df7b3697d7 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_bs.properties @@ -371,3 +371,7 @@ revert.banner.redo=Ponovi revert.banner.redo.all=Ponovi sve revert.banner.hint=Možete ponoviti ove promjene dok ne pošaljete novu poruku revert.message.rollback=Vrati na ovu poruku +plan.followup.answer.newSession.description=Implementiraj u novoj sesiji s čistim kontekstom +plan.followup.answer.newSession.recommended.description=Implementiraj u novoj sesiji s čistim kontekstom (Preporučeno) +plan.followup.answer.continue.description=Implementiraj plan u ovoj sesiji +plan.followup.answer.continue.estimated.description=Implementiraj plan u ovoj sesiji (koristi {0}% konteksta režima koda) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties index 42f4f8d5c71..f4384f8089a 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_da.properties @@ -371,3 +371,7 @@ revert.banner.redo=Gentag revert.banner.redo.all=Gentag alle revert.banner.hint=Du kan gentage disse ændringer, indtil du sender en ny besked revert.message.rollback=Rul tilbage til denne besked +plan.followup.answer.newSession.description=Implementér i en ny session med ren kontekst +plan.followup.answer.newSession.recommended.description=Implementér i en ny session med ren kontekst (Anbefalet) +plan.followup.answer.continue.description=Implementér planen i denne session +plan.followup.answer.continue.estimated.description=Implementér planen i denne session (bruger {0}% af konteksten i kodetilstand) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties index 3341e43e9fa..ec50280dbe6 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_de.properties @@ -371,3 +371,7 @@ revert.banner.redo=Wiederholen revert.banner.redo.all=Alle wiederholen revert.banner.hint=Du kannst diese Änderungen wiederholen, bis du eine neue Nachricht sendest revert.message.rollback=Auf diese Nachricht zurücksetzen +plan.followup.answer.newSession.description=In einer neuen Sitzung mit leerem Kontext umsetzen +plan.followup.answer.newSession.recommended.description=In einer neuen Sitzung mit leerem Kontext umsetzen (Empfohlen) +plan.followup.answer.continue.description=Den Plan in dieser Sitzung umsetzen +plan.followup.answer.continue.estimated.description=Den Plan in dieser Sitzung umsetzen ({0}% des Code-Kontextes verwendet) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties index 4cbbeea651f..9cdb40f2cf2 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_es.properties @@ -371,3 +371,7 @@ revert.banner.redo=Rehacer revert.banner.redo.all=Rehacer todo revert.banner.hint=Puedes rehacer estos cambios hasta que envíes un mensaje nuevo revert.message.rollback=Revertir a este mensaje +plan.followup.answer.newSession.description=Implementar en una sesión nueva con contexto limpio +plan.followup.answer.newSession.recommended.description=Implementar en una sesión nueva con contexto limpio (Recomendado) +plan.followup.answer.continue.description=Implementar el plan en esta sesión +plan.followup.answer.continue.estimated.description=Implementar el plan en esta sesión (usando {0}% del contexto del modo Código) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties index 5806ba574fe..d8564ed3940 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_fr.properties @@ -371,3 +371,7 @@ revert.banner.redo=Rétablir revert.banner.redo.all=Tout rétablir revert.banner.hint=Vous pouvez rétablir ces modifications jusqu'à l'envoi d'un nouveau message revert.message.rollback=Revenir à ce message +plan.followup.answer.newSession.description=Implémenter dans une nouvelle session avec un contexte vierge +plan.followup.answer.newSession.recommended.description=Implémenter dans une nouvelle session avec un contexte vierge (Recommandé) +plan.followup.answer.continue.description=Implémenter le plan dans cette session +plan.followup.answer.continue.estimated.description=Implémenter le plan dans cette session (utilise {0} % du contexte du mode Code) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties index 27f540e0c03..26a00801b95 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ja.properties @@ -371,3 +371,7 @@ revert.banner.redo=やり直し revert.banner.redo.all=すべてやり直し revert.banner.hint=新しいメッセージを送信するまで、これらの変更をやり直せます revert.message.rollback=このメッセージまでロールバック +plan.followup.answer.newSession.description=クリーンなコンテキストの新しいセッションで実装する +plan.followup.answer.newSession.recommended.description=クリーンなコンテキストの新しいセッションで実装する(推奨) +plan.followup.answer.continue.description=このセッションで計画を実装する +plan.followup.answer.continue.estimated.description=このセッションで計画を実装する(Code モードのコンテキストを {0}% 使用) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties index 7919395ec49..c7c214606df 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ko.properties @@ -371,3 +371,7 @@ revert.banner.redo=다시 실행 revert.banner.redo.all=모두 다시 실행 revert.banner.hint=새 메시지를 보내기 전까지 이 변경 사항을 다시 실행할 수 있습니다 revert.message.rollback=이 메시지로 롤백 +plan.followup.answer.newSession.description=깨끗한 컨텍스트의 새 세션에서 구현 +plan.followup.answer.newSession.recommended.description=깨끗한 컨텍스트의 새 세션에서 구현 (권장) +plan.followup.answer.continue.description=이 세션에서 계획 구현 +plan.followup.answer.continue.estimated.description=이 세션에서 계획 구현 (Code 모드 컨텍스트의 {0}% 사용) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties index df32ed67cc9..82415b66d30 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_nl.properties @@ -371,3 +371,7 @@ revert.banner.redo=Opnieuw uitvoeren revert.banner.redo.all=Alles opnieuw uitvoeren revert.banner.hint=Je kunt deze wijzigingen opnieuw uitvoeren totdat je een nieuw bericht verstuurt revert.message.rollback=Terugdraaien naar dit bericht +plan.followup.answer.newSession.description=Implementeren in een nieuwe sessie met een lege context +plan.followup.answer.newSession.recommended.description=Implementeren in een nieuwe sessie met een lege context (Aanbevolen) +plan.followup.answer.continue.description=Het plan in deze sessie implementeren +plan.followup.answer.continue.estimated.description=Het plan in deze sessie implementeren (gebruikt {0}% van de Code-moduscontext) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties index c454886532c..f0a3c80c25b 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_no.properties @@ -371,3 +371,7 @@ revert.banner.redo=Gjør om revert.banner.redo.all=Gjør om alle revert.banner.hint=Du kan gjøre om disse endringene til du sender en ny melding revert.message.rollback=Rull tilbake til denne meldingen +plan.followup.answer.newSession.description=Implementer i en ny økt med ren kontekst +plan.followup.answer.newSession.recommended.description=Implementer i en ny økt med ren kontekst (Anbefalt) +plan.followup.answer.continue.description=Implementer planen i denne økten +plan.followup.answer.continue.estimated.description=Implementer planen i denne økten (bruker {0}% av konteksten i kodemodus) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties index 473faaebe39..e495bc3fe88 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pl.properties @@ -371,3 +371,7 @@ revert.banner.redo=Ponów revert.banner.redo.all=Ponów wszystko revert.banner.hint=Możesz ponowić te zmiany, dopóki nie wyślesz nowej wiadomości revert.message.rollback=Cofnij do tej wiadomości +plan.followup.answer.newSession.description=Wdróż w nowej sesji z czystym kontekstem +plan.followup.answer.newSession.recommended.description=Wdróż w nowej sesji z czystym kontekstem (Zalecane) +plan.followup.answer.continue.description=Wdróż plan w tej sesji +plan.followup.answer.continue.estimated.description=Wdróż plan w tej sesji (wykorzystując {0}% kontekstu trybu kodu) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties index 3d6ee039719..15ce6d0d155 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_pt_BR.properties @@ -371,3 +371,7 @@ revert.banner.redo=Refazer revert.banner.redo.all=Refazer tudo revert.banner.hint=Você pode refazer essas alterações até enviar uma nova mensagem revert.message.rollback=Reverter para esta mensagem +plan.followup.answer.newSession.description=Implementar em uma nova sessão com contexto limpo +plan.followup.answer.newSession.recommended.description=Implementar em uma nova sessão com contexto limpo (Recomendado) +plan.followup.answer.continue.description=Implementar o plano nesta sessão +plan.followup.answer.continue.estimated.description=Implementar o plano nesta sessão (usando {0}% do contexto do modo de código) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties index 411bb6d9df7..882a0bf38ac 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_ru.properties @@ -371,3 +371,7 @@ revert.banner.redo=Повторить revert.banner.redo.all=Повторить все revert.banner.hint=Эти изменения можно повторить до отправки нового сообщения revert.message.rollback=Откатиться к этому сообщению +plan.followup.answer.newSession.description=Реализовать в новой сессии с чистым контекстом +plan.followup.answer.newSession.recommended.description=Реализовать в новой сессии с чистым контекстом (Рекомендуется) +plan.followup.answer.continue.description=Реализовать план в этой сессии +plan.followup.answer.continue.estimated.description=Реализовать план в этой сессии (используя {0}% контекста режима кода) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties index 433dfc32f5d..f4178316f88 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_th.properties @@ -371,3 +371,7 @@ revert.banner.redo=ทำซ้ำ revert.banner.redo.all=ทำซ้ำทั้งหมด revert.banner.hint=คุณสามารถทำซ้ำการเปลี่ยนแปลงเหล่านี้ได้จนกว่าจะส่งข้อความใหม่ revert.message.rollback=ย้อนกลับไปยังข้อความนี้ +plan.followup.answer.newSession.description=ดำเนินการในเซสชันใหม่ที่มีบริบทว่างเปล่า +plan.followup.answer.newSession.recommended.description=ดำเนินการในเซสชันใหม่ที่มีบริบทว่างเปล่า (แนะนำ) +plan.followup.answer.continue.description=ดำเนินการตามแผนในเซสชันนี้ +plan.followup.answer.continue.estimated.description=ดำเนินการตามแผนในเซสชันนี้ (ใช้บริบทโหมดโค้ด {0}%) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties index 77056728b65..e37470114b7 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_tr.properties @@ -371,3 +371,7 @@ revert.banner.redo=Yinele revert.banner.redo.all=Tümünü yinele revert.banner.hint=Yeni bir mesaj gönderene kadar bu değişiklikleri yineleyebilirsiniz revert.message.rollback=Bu mesaja geri dön +plan.followup.answer.newSession.description=Temiz bir bağlamla yeni bir oturumda uygula +plan.followup.answer.newSession.recommended.description=Temiz bir bağlamla yeni bir oturumda uygula (Önerilen) +plan.followup.answer.continue.description=Planı bu oturumda uygula +plan.followup.answer.continue.estimated.description=Planı bu oturumda uygula (Kod modu bağlamının {0}% kadarı kullanılıyor) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties index dcddefa7fcd..ce996288d94 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_uk.properties @@ -371,3 +371,7 @@ revert.banner.redo=Повторити revert.banner.redo.all=Повторити все revert.banner.hint=Ці зміни можна повторити, доки ви не надішлете нове повідомлення revert.message.rollback=Відкотитися до цього повідомлення +plan.followup.answer.newSession.description=Реалізувати в новій сесії з чистим контекстом +plan.followup.answer.newSession.recommended.description=Реалізувати в новій сесії з чистим контекстом (Рекомендовано) +plan.followup.answer.continue.description=Реалізувати план у цій сесії +plan.followup.answer.continue.estimated.description=Реалізувати план у цій сесії (використовуючи {0}% контексту режиму коду) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties index 6c209630d49..2a81700976e 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_CN.properties @@ -371,3 +371,7 @@ revert.banner.redo=重做 revert.banner.redo.all=全部重做 revert.banner.hint=在发送新消息之前,你可以重做这些更改 revert.message.rollback=回滚到此消息 +plan.followup.answer.newSession.description=在具有干净上下文的新会话中实现 +plan.followup.answer.newSession.recommended.description=在具有干净上下文的新会话中实现(推荐) +plan.followup.answer.continue.description=在本会话中实现计划 +plan.followup.answer.continue.estimated.description=在本会话中实现计划(使用 {0}% 的代码模式上下文) diff --git a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties index 6159d4b16ab..2ebcd29225e 100644 --- a/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties +++ b/packages/kilo-jetbrains/frontend/src/main/resources/messages/KiloBundle_zh_TW.properties @@ -371,3 +371,7 @@ revert.banner.redo=重做 revert.banner.redo.all=全部重做 revert.banner.hint=在傳送新訊息之前,你可以重做這些變更 revert.message.rollback=回復到此訊息 +plan.followup.answer.newSession.description=在具有乾淨上下文的新工作階段中實作 +plan.followup.answer.newSession.recommended.description=在具有乾淨上下文的新工作階段中實作(建議) +plan.followup.answer.continue.description=在本工作階段中實作計畫 +plan.followup.answer.continue.estimated.description=在本工作階段中實作計畫(使用 {0}% 的程式碼模式上下文) diff --git a/packages/kilo-jetbrains/shared/src/main/kotlin/ai/kilocode/rpc/dto/ChatDto.kt b/packages/kilo-jetbrains/shared/src/main/kotlin/ai/kilocode/rpc/dto/ChatDto.kt index cfc0ef47774..ff01cca61aa 100644 --- a/packages/kilo-jetbrains/shared/src/main/kotlin/ai/kilocode/rpc/dto/ChatDto.kt +++ b/packages/kilo-jetbrains/shared/src/main/kotlin/ai/kilocode/rpc/dto/ChatDto.kt @@ -349,6 +349,7 @@ data class QuestionOptionDto( val description: String, val labelKey: String? = null, val descriptionKey: String? = null, + val descriptionArgs: List = emptyList(), val mode: String? = null, ) diff --git a/packages/kilo-vscode/tests/unit/plan-followup-locale-keys.test.ts b/packages/kilo-vscode/tests/unit/plan-followup-locale-keys.test.ts index 86b4ef96dd4..0e9fc3e50e9 100644 --- a/packages/kilo-vscode/tests/unit/plan-followup-locale-keys.test.ts +++ b/packages/kilo-vscode/tests/unit/plan-followup-locale-keys.test.ts @@ -48,8 +48,10 @@ const keys = [ "plan.followup.question", "plan.followup.answer.newSession", "plan.followup.answer.newSession.description", + "plan.followup.answer.newSession.recommended.description", "plan.followup.answer.continue", "plan.followup.answer.continue.description", + "plan.followup.answer.continue.estimated.description", "plan.followup.answer.keepRefining", "plan.followup.answer.keepRefining.description", ] diff --git a/packages/kilo-vscode/tests/unit/question-dock-utils.test.ts b/packages/kilo-vscode/tests/unit/question-dock-utils.test.ts index 9b882d03957..965663615c3 100644 --- a/packages/kilo-vscode/tests/unit/question-dock-utils.test.ts +++ b/packages/kilo-vscode/tests/unit/question-dock-utils.test.ts @@ -241,4 +241,10 @@ describe("tr", () => { const t = (key: string) => dict[key] ?? key expect(tr(t, "plan.followup.question", "")).toBe("Prêt à implémenter ?") }) + + it("passes positional description arguments to the translator", () => { + const t = (key: string, params?: Record) => + key === "plan.followup.answer.continue.description" ? `Continue (${params?.[0]}%)` : key + expect(tr(t, "plan.followup.answer.continue.description", "Continue here", [75])).toBe("Continue (75%)") + }) }) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx b/packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx index 15695ecd04c..43989cd8dea 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/chat/QuestionDock.tsx @@ -87,9 +87,11 @@ export const QuestionDock: Component<{ request: QuestionRequest }> = (props) => description?: string labelKey?: string descriptionKey?: string + descriptionArgs?: string[] }) => ({ label: () => tr(language.t, opt.labelKey, opt.label), - description: () => (opt.description ? tr(language.t, opt.descriptionKey, opt.description) : ""), + description: () => + opt.description ? tr(language.t, opt.descriptionKey, opt.description, opt.descriptionArgs) : "", }) const focusPrompt = () => requestAnimationFrame(() => window.dispatchEvent(new Event("focusPrompt"))) diff --git a/packages/kilo-vscode/webview-ui/src/components/chat/question-dock-utils.ts b/packages/kilo-vscode/webview-ui/src/components/chat/question-dock-utils.ts index 615aa02fb3d..e6fd7e91d7b 100644 --- a/packages/kilo-vscode/webview-ui/src/components/chat/question-dock-utils.ts +++ b/packages/kilo-vscode/webview-ui/src/components/chat/question-dock-utils.ts @@ -1,4 +1,5 @@ import type { QuestionOption } from "../../types/messages" +import type { UiI18nParams } from "@opencode-ai/ui/context/i18n" /** * Translate a backend-provided i18n key, falling back to the canonical label when no key is @@ -13,9 +14,18 @@ import type { QuestionOption } from "../../types/messages" * helper would falsely fall back to the English label. Namespaced keys (`plan.followup.*`) * make this practically impossible, but keep it in mind before picking ambiguous key names. */ -export function tr(translate: (key: string) => string, key: string | undefined, fallback: string): string { +export function tr( + translate: (key: string, params?: UiI18nParams) => string, + key: string | undefined, + fallback: string, + args?: string[], +): string { if (!key) return fallback - const result = translate(key) + const params = args?.reduce((result, value, index) => { + result[index] = value + return result + }, {}) + const result = translate(key, params) if (result === key) return fallback return result } diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/questions.ts b/packages/kilo-vscode/webview-ui/src/types/messages/questions.ts index a829646bd18..a0fa91286be 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/questions.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/questions.ts @@ -14,6 +14,7 @@ export interface QuestionOption { // The canonical English `label` stays on the reply wire, so server-side matching is unaffected. labelKey?: string descriptionKey?: string + descriptionArgs?: string[] } export interface QuestionInfo { diff --git a/packages/opencode/src/kilocode/plan-followup.ts b/packages/opencode/src/kilocode/plan-followup.ts index e65c4cfc1a7..f7b94dc600c 100644 --- a/packages/opencode/src/kilocode/plan-followup.ts +++ b/packages/opencode/src/kilocode/plan-followup.ts @@ -7,13 +7,17 @@ import { Global } from "@opencode-ai/core/global" import { Identifier } from "@/id/id" import { Instance } from "@/kilocode/instance" import { Provider } from "@/provider/provider" -import { ProviderID, ModelID } from "@/provider/schema" +import { ProviderV2 } from "@opencode-ai/core/provider" +import { ModelV2 } from "@opencode-ai/core/model" +import { Config } from "@/config/config" import { Question } from "@/question" import { Session } from "@/session/session" import { SessionID, MessageID, PartID } from "@/session/schema" import { LLM } from "@/session/llm" import { KiloLLM } from "@/kilocode/session/llm" +import { KiloSessionOverflow } from "@/kilocode/session/overflow" import { MessageV2 } from "@/session/message-v2" +import { usable } from "@/session/overflow" import { SessionStatus } from "@/session/status" import { Todo } from "@/session/todo" import { makeRuntime } from "@/effect/run-service" @@ -27,6 +31,7 @@ import { PlanFile } from "@/kilocode/plan-file" const agents = lazy(() => makeRuntime(Agent.Service, Agent.defaultLayer)) const providers = lazy(() => makeRuntime(Provider.Service, Provider.defaultLayer)) +const configs = lazy(() => makeRuntime(Config.Service, Config.defaultLayer)) const todo = lazy(() => makeRuntime(Todo.Service, Todo.defaultLayer)) const llm = lazy(() => makeRuntime(LLM.Service, LLM.defaultLayer)) const pending = new Map() @@ -35,9 +40,12 @@ export const PlanFollowupRuntime = { agent(name: string): Promise { return agents().runPromise((svc) => svc.get(name)) }, - model(providerID: ProviderID, modelID: ModelID): Promise { + model(providerID: ProviderV2.ID, modelID: ModelV2.ID): Promise { return providers().runPromise((svc) => svc.getModel(providerID, modelID)) }, + config(): Promise { + return configs().runPromise((svc) => svc.get()) + }, todo: { get(sessionID: SessionID) { return todo().runPromise((svc) => svc.get(sessionID)) @@ -182,8 +190,8 @@ export namespace PlanFollowup { .record( z.string(), z.object({ - providerID: z.custom(Schema.is(ProviderID)), - modelID: z.custom(Schema.is(ModelID)), + providerID: z.custom(Schema.is(ProviderV2.ID)), + modelID: z.custom(Schema.is(ModelV2.ID)), }), ) .optional(), @@ -207,20 +215,48 @@ export namespace PlanFollowup { const key = `${saved.providerID}/${saved.modelID}` return { model: { ...saved, variant: resolveVariant(state?.variant?.[key], full) }, + full, } } } - const entry = await PlanFollowupRuntime.agent("code") + const entry = await PlanFollowupRuntime.agent("code").catch(() => undefined) if (entry?.model) { const full = await PlanFollowupRuntime.model(entry.model.providerID, entry.model.modelID).catch(() => undefined) if (full) { return { model: { ...entry.model, variant: resolveVariant(entry.variant, full) }, + full, } } } - return input + return { + model: input.model, + full: await PlanFollowupRuntime.model(input.model.providerID, input.model.modelID).catch(() => undefined), + } + } + + async function estimate(input: { assistant: MessageV2.WithParts; model?: Provider.Model }) { + if (!input.model || input.model.limit.context === 0 || input.assistant.info.role !== "assistant") return + const tokens = KiloSessionOverflow.count(input.assistant.info.tokens) + if (!tokens) return + + const context = input.model.limit.input || input.model.limit.context + if (context === 0) return + const percent = Math.round((tokens / context) * 100) + const cfg = await PlanFollowupRuntime.config().catch(() => undefined) + if (!cfg) return { percent, recommended: false } + return { + percent, + recommended: + cfg.compaction?.auto !== false && + tokens >= + KiloSessionOverflow.limit({ + cfg, + model: input.model, + usable: usable({ cfg, model: input.model }), + }), + } } async function locatePlan(sessionID: SessionID, messages: MessageV2.WithParts[]) { @@ -302,7 +338,12 @@ export namespace PlanFollowup { reject: (requestID: Parameters[0]) => Promise } - function prompt(input: { sessionID: SessionID; abort: AbortSignal; question: QuestionRuntime }) { + function prompt(input: { + sessionID: SessionID + abort: AbortSignal + question: QuestionRuntime + estimate?: { percent: number; recommended: boolean } + }) { if (input.abort.aborted) return Promise.resolve(undefined) const promise = input.question.ask({ sessionID: input.sessionID, @@ -322,14 +363,23 @@ export namespace PlanFollowup { { label: ANSWER_NEW_SESSION, labelKey: "plan.followup.answer.newSession", - description: "Implement in a fresh session with a clean context", - descriptionKey: "plan.followup.answer.newSession.description", + description: input.estimate?.recommended + ? "Implement in a fresh session with a clean context (Recommended)" + : "Implement in a fresh session with a clean context", + descriptionKey: input.estimate?.recommended + ? "plan.followup.answer.newSession.recommended.description" + : "plan.followup.answer.newSession.description", }, { label: ANSWER_CONTINUE, labelKey: "plan.followup.answer.continue", - description: "Implement the plan in this session", - descriptionKey: "plan.followup.answer.continue.description", + description: input.estimate + ? `Implement the plan in this session (using ${input.estimate.percent}% of Code mode context)` + : "Implement the plan in this session", + descriptionKey: input.estimate + ? "plan.followup.answer.continue.estimated.description" + : "plan.followup.answer.continue.description", + descriptionArgs: input.estimate ? [String(input.estimate.percent)] : undefined, mode: "code", }, { @@ -518,7 +568,14 @@ export namespace PlanFollowup { const user = latest.find((msg) => msg.info.role === "user")?.info if (!user || user.role !== "user" || !user.model) return "break" - const answers = await prompt({ sessionID: input.sessionID, abort: input.abort, question: input.question }) + const code = await resolveCodeModel({ model: user.model }) + const context = await estimate({ assistant, model: code.full }) + const answers = await prompt({ + sessionID: input.sessionID, + abort: input.abort, + question: input.question, + estimate: context, + }) if (!answers) { Telemetry.trackPlanFollowup(input.sessionID, "dismissed") return "break" @@ -546,9 +603,6 @@ export namespace PlanFollowup { if (answer === ANSWER_CONTINUE) { Telemetry.trackPlanFollowup(input.sessionID, "continue") - const code = await resolveCodeModel({ - model: user.model, - }) const msg = await inject({ sessionID: input.sessionID, agent: "code", diff --git a/packages/opencode/src/question/index.ts b/packages/opencode/src/question/index.ts index ed473ea7cd6..c3b7845b0c2 100644 --- a/packages/opencode/src/question/index.ts +++ b/packages/opencode/src/question/index.ts @@ -29,6 +29,9 @@ export const Option = Schema.Struct({ descriptionKey: Schema.optional(Schema.String).annotate({ description: "Optional i18n key for the description", }), + descriptionArgs: Schema.optional(Schema.Array(Schema.String)).annotate({ + description: "Optional positional arguments for the description i18n key", + }), // kilocode_change end // kilocode_change start - hint to UI clients to switch the active agent/mode picker // when this option is selected (before the reply is confirmed by the server). diff --git a/packages/opencode/test/kilocode/plan-followup.test.ts b/packages/opencode/test/kilocode/plan-followup.test.ts index f0142d82570..4054ee5fb8b 100644 --- a/packages/opencode/test/kilocode/plan-followup.test.ts +++ b/packages/opencode/test/kilocode/plan-followup.test.ts @@ -106,6 +106,7 @@ async function withInstance(fn: () => Promise) { async function seed(input: { text: string variant?: string + tokens?: MessageV2.Assistant["tokens"] tools?: Array<{ tool: string; input: Record; output: string }> }) { const session = await store.create({}) @@ -144,7 +145,7 @@ async function seed(input: { root: Instance.worktree, }, cost: 0, - tokens: { + tokens: input.tokens ?? { total: 0, input: 0, output: 0, @@ -424,6 +425,131 @@ describe("plan follow-up", () => { await expect(pending).resolves.toBe("break") })) + test("ask - estimates Code context and recommends a fresh session at the compaction threshold", () => + withInstance(async () => { + const configSpy = spyOn(PlanFollowupRuntime, "config").mockResolvedValue({ + compaction: { threshold_percent: 80 }, + } as any) + const modelSpy = spyOn(PlanFollowupRuntime, "model").mockResolvedValue(fakeModel) + const seeded = await seed({ + text: "1. Build", + tokens: { + total: 110_000, + input: 110_000, + output: 0, + reasoning: 0, + cache: { read: 0, write: 0 }, + }, + }) + const pending = PlanFollowup.ask({ + question, + sessionID: seeded.sessionID, + messages: seeded.messages, + abort: AbortSignal.any([]), + }) + + const item = await waitQuestion(seeded.sessionID) + expect(item).toBeDefined() + if (!item) return + const q = item.questions[0] + expect(q).toBeDefined() + if (!q) return + + const fresh = q.options.find((o) => o.label === PlanFollowup.ANSWER_NEW_SESSION) + const cont = q.options.find((o) => o.label === PlanFollowup.ANSWER_CONTINUE) + expect(fresh?.description).toContain("(Recommended)") + expect(cont?.description).toContain("using 86% of Code mode context") + expect(fresh?.descriptionKey).toBe("plan.followup.answer.newSession.recommended.description") + expect(cont?.descriptionKey).toBe("plan.followup.answer.continue.estimated.description") + expect(cont?.descriptionArgs).toEqual(["86"]) + expect(configSpy).toHaveBeenCalled() + + await question.reject(item.id) + await expect(pending).resolves.toBe("break") + configSpy.mockRestore() + modelSpy.mockRestore() + })) + + test("ask - uses the model input limit for the displayed percentage", () => + withInstance(async () => { + const configSpy = spyOn(PlanFollowupRuntime, "config").mockResolvedValue({ + compaction: { threshold_percent: 75 }, + } as any) + const modelSpy = spyOn(PlanFollowupRuntime, "model").mockResolvedValue({ + ...fakeModel, + limit: { context: 400_000, input: 200_000 }, + } as Provider.Model) + const seeded = await seed({ + text: "1. Build", + tokens: { + total: 150_000, + input: 150_000, + output: 0, + reasoning: 0, + cache: { read: 0, write: 0 }, + }, + }) + const pending = PlanFollowup.ask({ + question, + sessionID: seeded.sessionID, + messages: seeded.messages, + abort: AbortSignal.any([]), + }) + + const item = await waitQuestion(seeded.sessionID) + expect(item).toBeDefined() + if (!item) return + const q = item.questions[0] + expect(q).toBeDefined() + if (!q) return + + const cont = q.options.find((o) => o.label === PlanFollowup.ANSWER_CONTINUE) + expect(cont?.description).toContain("using 75% of Code mode context") + expect(cont?.descriptionArgs).toEqual(["75"]) + + await question.reject(item.id) + await expect(pending).resolves.toBe("break") + configSpy.mockRestore() + modelSpy.mockRestore() + })) + + test("ask - recommends a fresh session at the default usable limit", () => + withInstance(async () => { + const configSpy = spyOn(PlanFollowupRuntime, "config").mockResolvedValue({} as any) + const modelSpy = spyOn(PlanFollowupRuntime, "model").mockResolvedValue(fakeModel) + const seeded = await seed({ + text: "1. Build", + tokens: { + total: 108_000, + input: 108_000, + output: 0, + reasoning: 0, + cache: { read: 0, write: 0 }, + }, + }) + const pending = PlanFollowup.ask({ + question, + sessionID: seeded.sessionID, + messages: seeded.messages, + abort: AbortSignal.any([]), + }) + + const item = await waitQuestion(seeded.sessionID) + expect(item).toBeDefined() + if (!item) return + const q = item.questions[0] + expect(q).toBeDefined() + if (!q) return + + const fresh = q.options.find((o) => o.label === PlanFollowup.ANSWER_NEW_SESSION) + expect(fresh?.descriptionKey).toBe("plan.followup.answer.newSession.recommended.description") + + await question.reject(item.id) + await expect(pending).resolves.toBe("break") + configSpy.mockRestore() + modelSpy.mockRestore() + })) + test("ask - returns continue and creates code message on Continue here", () => withInstance(async () => { const get = spyOn(PlanFollowupRuntime, "agent").mockImplementation(async (name: string) => { diff --git a/packages/opencode/test/kilocode/question-option-schema.test.ts b/packages/opencode/test/kilocode/question-option-schema.test.ts index 939dec436b4..0b9b6d54733 100644 --- a/packages/opencode/test/kilocode/question-option-schema.test.ts +++ b/packages/opencode/test/kilocode/question-option-schema.test.ts @@ -7,7 +7,8 @@ * * 1. labelKey / descriptionKey — lost during the opencode v1.3.x * effectify refactor (cec1255b36), restored in PR #9246. - * 2. mode — lost in the same merge cycle (c37f85386f + 5bb42b6bdb), + * 2. descriptionArgs — added for dynamic localized descriptions. + * 3. mode — lost in the same merge cycle (c37f85386f + 5bb42b6bdb), * restored in the ionized-emmental branch. * * The plan follow-up "Continue here" option relies on `mode: "code"` being @@ -52,6 +53,17 @@ describe("QuestionOption schema — Kilo-specific field contract", () => { expect(decoded.descriptionKey).toBe("plan.followup.answer.continue.description") }) + test("Option class accepts and round-trips descriptionArgs", () => { + const raw = { + label: "Continue here", + description: "Implement the plan in this session (using 75% of Code mode context)", + descriptionKey: "plan.followup.answer.continue.description", + descriptionArgs: ["75"], + } + const decoded = Schema.decodeUnknownSync(Option)(raw) + expect(decoded.descriptionArgs).toEqual(["75"]) + }) + // Static source checks — guard the kilocode_change markers so a conflict // resolution that drops the fields is caught immediately. test("source declares mode as an optional field inside a kilocode_change block", () => { @@ -66,5 +78,6 @@ describe("QuestionOption schema — Kilo-specific field contract", () => { expect(src).toMatch(/kilocode_change start[^\n]*i18n keys/) expect(src).toMatch(/labelKey:\s*Schema\.optional\(Schema\.String\)/) expect(src).toMatch(/descriptionKey:\s*Schema\.optional\(Schema\.String\)/) + expect(src).toMatch(/descriptionArgs:\s*Schema\.optional\(Schema\.Array\(Schema\.String\)\)/) }) }) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 9d391eebe24..0c1573c2fe9 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -287,6 +287,7 @@ export type QuestionOption = { description: string labelKey?: string descriptionKey?: string + descriptionArgs?: Array mode?: string } diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index 8b11d68b1b7..e1e549b7dcb 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -21049,6 +21049,12 @@ "descriptionKey": { "type": "string" }, + "descriptionArgs": { + "type": "array", + "items": { + "type": "string" + } + }, "mode": { "type": "string" }