From d01acc648b5d8b5da666e5cb6f949a254ad6fcf5 Mon Sep 17 00:00:00 2001 From: Eason Liang Date: Sun, 16 Aug 2026 19:38:07 +0800 Subject: [PATCH 1/2] feat(webview): surface inline-subtask transitions as distinct chat banners --- packages/types/src/message.ts | 4 + src/core/tools/NewTaskTool.ts | 10 ++ .../__tests__/newTaskInlineFlatten.spec.ts | 10 ++ webview-ui/src/components/chat/ChatRow.tsx | 63 ++++++++ .../__tests__/ChatRow.inline-subtask.spec.tsx | 144 ++++++++++++++++++ webview-ui/src/i18n/locales/ca/chat.json | 5 +- webview-ui/src/i18n/locales/de/chat.json | 5 +- webview-ui/src/i18n/locales/en/chat.json | 5 +- webview-ui/src/i18n/locales/es/chat.json | 5 +- webview-ui/src/i18n/locales/fr/chat.json | 5 +- webview-ui/src/i18n/locales/hi/chat.json | 5 +- webview-ui/src/i18n/locales/id/chat.json | 5 +- webview-ui/src/i18n/locales/it/chat.json | 5 +- webview-ui/src/i18n/locales/ja/chat.json | 5 +- webview-ui/src/i18n/locales/ko/chat.json | 5 +- webview-ui/src/i18n/locales/nl/chat.json | 5 +- webview-ui/src/i18n/locales/pl/chat.json | 5 +- webview-ui/src/i18n/locales/pt-BR/chat.json | 5 +- webview-ui/src/i18n/locales/ru/chat.json | 5 +- webview-ui/src/i18n/locales/tr/chat.json | 5 +- webview-ui/src/i18n/locales/vi/chat.json | 5 +- webview-ui/src/i18n/locales/zh-CN/chat.json | 5 +- webview-ui/src/i18n/locales/zh-TW/chat.json | 5 +- .../src/utils/chatBatchingPredicates.ts | 2 + 24 files changed, 305 insertions(+), 18 deletions(-) create mode 100644 webview-ui/src/components/chat/__tests__/ChatRow.inline-subtask.spec.tsx diff --git a/packages/types/src/message.ts b/packages/types/src/message.ts index 28d5af82ac..7d6a835e67 100644 --- a/packages/types/src/message.ts +++ b/packages/types/src/message.ts @@ -140,6 +140,8 @@ export function isNonBlockingAsk(ask: ClineAsk): ask is NonBlockingAsk { * - `condense_context_error`: Error occurred during context condensation * - `codebase_search_result`: Results from searching the codebase * - `too_many_tools_warning`: Warning that too many MCP tools are enabled, which may confuse the LLM + * - `inline_subtask_started`: A subtask was auto-flattened and is now executing inline in this conversation + * - `inline_subtask_rejected`: A nested new_task call was rejected (an inline phase is already active) */ export const clineSays = [ "error", @@ -161,6 +163,8 @@ export const clineSays = [ "mcp_server_request_started", "mcp_server_response", "subtask_result", + "inline_subtask_started", + "inline_subtask_rejected", "checkpoint_saved", "rooignore_error", "diff_error", diff --git a/src/core/tools/NewTaskTool.ts b/src/core/tools/NewTaskTool.ts index b5716f70d8..b41dba0495 100644 --- a/src/core/tools/NewTaskTool.ts +++ b/src/core/tools/NewTaskTool.ts @@ -114,6 +114,8 @@ export class NewTaskTool extends BaseTool<"new_task"> { }) if (decision.action === "reject-nested") { + // Surface the rejection in the UI as well — tool results are not rendered. + await task.say("inline_subtask_rejected", decision.message) pushToolResult(formatResponse.toolError(decision.message)) return } @@ -121,11 +123,19 @@ export class NewTaskTool extends BaseTool<"new_task"> { if (decision.action === "flatten") { // Set the phase marker and let the tool_result double as the inline prompt. task.inlineSubtask = { message: unescapedMessage, todos: todoItems } + // Surface the auto-flatten in the UI — the model sees it via the tool result, + // but without this the user has no indication that a subtask now runs inline. + await task.say( + "inline_subtask_started", + `Nesting limit ${maxNestingDepth} reached — subtask flattened and executing inline in this conversation.`, + ) pushToolResult(decision.directive) return } if (decision.action === "reject-limit") { + // Surface the rejection in the UI as well — tool results are not rendered. + await task.say("inline_subtask_rejected", decision.message) pushToolResult(formatResponse.toolError(decision.message)) return } diff --git a/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts b/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts index 3c960966a9..268e5079de 100644 --- a/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts +++ b/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts @@ -37,6 +37,7 @@ function makeTask(opts: { depth?: number; inlineSubtask?: InlineSubtask; provide didToolFailInCurrentTurn: false, recordToolError: vi.fn(), sayAndCreateMissingParamError: vi.fn().mockResolvedValue("missing param"), + say: vi.fn().mockResolvedValue(undefined), providerRef: { deref: () => opts.provider }, } return task as unknown as Task @@ -91,6 +92,9 @@ describe("NewTaskTool auto-flatten inline", () => { const pushed = pushToolResult.mock.calls[0][0] as string expect(pushed).toContain("auto-flattened") expect(pushed).toContain("do X") + // The auto-flatten is surfaced to the UI via a say message (tool results are not rendered). + const say = (task as unknown as { say: ReturnType }).say + expect(say).toHaveBeenCalledWith("inline_subtask_started", expect.stringContaining("Nesting limit 2 reached")) }) it("rejects when over the limit and autoFlattenOnLimit is false (error result, no marker)", async () => { @@ -109,6 +113,9 @@ describe("NewTaskTool auto-flatten inline", () => { expect(task.inlineSubtask).toBeUndefined() const pushed = pushToolResult.mock.calls[0][0] as string expect(pushed.toLowerCase()).toContain("error") + // The rejection is surfaced to the UI via a say message. + const say = (task as unknown as { say: ReturnType }).say + expect(say).toHaveBeenCalledWith("inline_subtask_rejected", expect.stringContaining("auto-flatten is disabled")) }) it("rejects a nested new_task while an inline phase is already active", async () => { @@ -128,6 +135,9 @@ describe("NewTaskTool auto-flatten inline", () => { expect(task.inlineSubtask?.message).toBe("outer") const pushed = pushToolResult.mock.calls[0][0] as string expect(pushed.toLowerCase()).toContain("error") + // The rejection is surfaced to the UI via a say message. + const say = (task as unknown as { say: ReturnType }).say + expect(say).toHaveBeenCalledWith("inline_subtask_rejected", expect.stringContaining("already in progress")) }) }) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 3c48b2fdd1..dbb4c0b076 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -73,6 +73,7 @@ import { ArrowRight, Check, OctagonX, + Settings, } from "lucide-react" import { cn } from "@/lib/utils" import { PathTooltip } from "../ui/PathTooltip" @@ -1067,6 +1068,68 @@ export const ChatRowContent = ({ )} ) + case "inline_subtask_started": + // A subtask was auto-flattened and now runs inline in this conversation. + return ( +
+
+ + + {t("chat:subtasks.inlineStarted")} + +
+ +
+ ) + case "inline_subtask_rejected": + // A nested new_task was rejected because an inline phase is already active. + return ( +
+
+ + + {t("chat:subtasks.inlineRejected")} + +
+ +
+ ) case "reasoning": return ( ({ + vscode: { + postMessage: (msg: unknown) => mockPostMessage(msg), + }, +})) + +// Mock i18n — the two inline-subtask banner titles plus a fallback to the key itself. +vi.mock("react-i18next", () => ({ + useTranslation: () => ({ + t: (key: string) => { + const map: Record = { + "chat:subtasks.inlineStarted": "Subtask flattened to inline", + "chat:subtasks.inlineRejected": "Nested subtask rejected", + "chat:subtasks.inlineConfigure": "Adjust task tree settings", + } + return map[key] ?? key + }, + i18n: { exists: () => true }, + }), + Trans: ({ children }: { children?: React.ReactNode }) => <>{children}, + initReactI18next: { type: "3rdParty", init: () => {} }, +})) + +// Mock extension state context +vi.mock("@src/context/ExtensionStateContext", () => ({ + useExtensionState: () => ({ + mcpServers: [], + alwaysAllowMcp: false, + currentCheckpoint: null, + mode: "code", + apiConfiguration: {}, + clineMessages: [] as ClineMessage[], + currentTaskItem: undefined, + }), +})) + +// Mock useSelectedModel hook +vi.mock("@src/components/ui/hooks/useSelectedModel", () => ({ + useSelectedModel: () => ({ info: { supportsImages: true } }), +})) + +function renderChatRow(message: ClineMessage) { + return render( + {}} + onSuggestionClick={() => {}} + onBatchFileResponse={() => {}} + onFollowUpUnmount={() => {}} + isFollowUpAnswered={false} + />, + ) +} + +describe("ChatRow - inline subtask banners", () => { + it("renders a distinct banner when a subtask is auto-flattened to inline", () => { + const message: ClineMessage = { + ts: Date.now(), + type: "say" as const, + say: "inline_subtask_started" as const, + text: "Nesting limit 2 reached — subtask flattened and executing inline in this conversation.", + } + + renderChatRow(message) + + // Banner title (i18n) is present… + expect(screen.getByText("Subtask flattened to inline")).toBeInTheDocument() + // …and the detail text from message.text renders below it. + expect( + screen.getByText("Nesting limit 2 reached — subtask flattened and executing inline in this conversation."), + ).toBeInTheDocument() + }) + + it("renders a distinct banner when a nested new_task is rejected", () => { + const message: ClineMessage = { + ts: Date.now(), + type: "say" as const, + say: "inline_subtask_rejected" as const, + text: "Cannot start a nested subtask while an inline subtask is already in progress.", + } + + renderChatRow(message) + + expect(screen.getByText("Nested subtask rejected")).toBeInTheDocument() + expect( + screen.getByText("Cannot start a nested subtask while an inline subtask is already in progress."), + ).toBeInTheDocument() + }) + + describe("settings hint link", () => { + beforeEach(() => { + mockPostMessage.mockClear() + }) + + it.each(["inline_subtask_started", "inline_subtask_rejected"] as const)( + "deep-links the %s banner into the task-tree settings section", + (say) => { + const message: ClineMessage = { + ts: Date.now(), + type: "say" as const, + say, + text: "detail", + } + + renderChatRow(message) + + // The banner renders its settings-hint link… + const link = screen.getByText("Adjust task tree settings") + expect(link).toBeInTheDocument() + // …and clicking it switches to the settings tab, deep-linked to contextManagement. + fireEvent.click(link) + expect(mockPostMessage).toHaveBeenCalledWith({ + type: "switchTab", + tab: "settings", + values: { section: "contextManagement" }, + }) + }, + ) + }) + + it("does not render the banners for unrelated say types", () => { + const message: ClineMessage = { + ts: Date.now(), + type: "say" as const, + say: "text" as const, + text: "ordinary model text", + } + + renderChatRow(message) + + expect(screen.queryByText("Subtask flattened to inline")).not.toBeInTheDocument() + expect(screen.queryByText("Nested subtask rejected")).not.toBeInTheDocument() + }) +}) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index d5b63ea886..3ad82e5308 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -270,7 +270,10 @@ "resultContent": "Resultats de la subtasca", "defaultResult": "Si us plau, continua amb la següent tasca.", "completionInstructions": "Subtasca completada! Pots revisar els resultats i suggerir correccions o següents passos. Si tot sembla correcte, confirma per tornar el resultat a la tasca principal.", - "goToSubtask": "Veure tasca" + "goToSubtask": "Veure tasca", + "inlineStarted": "Subtarea aplanada en línia", + "inlineRejected": "Subtarea niuada rebutjada", + "inlineConfigure": "Ajusta la configuració de l'arbre de tasques" }, "questions": { "hasQuestion": "Zoo té una pregunta" diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index ad94856234..b0ff25b292 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -270,7 +270,10 @@ "resultContent": "Teilaufgabenergebnisse", "defaultResult": "Bitte fahre mit der nächsten Aufgabe fort.", "completionInstructions": "Teilaufgabe abgeschlossen! Du kannst die Ergebnisse überprüfen und Korrekturen oder nächste Schritte vorschlagen. Wenn alles gut aussieht, bestätige, um das Ergebnis an die übergeordnete Aufgabe zurückzugeben.", - "goToSubtask": "Aufgabe anzeigen" + "goToSubtask": "Aufgabe anzeigen", + "inlineStarted": "Unteraufgabe inline ausgeführt", + "inlineRejected": "Verschachtelte Unteraufgabe abgelehnt", + "inlineConfigure": "Aufgabenbaum-Einstellungen anpassen" }, "questions": { "hasQuestion": "Zoo hat eine Frage" diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 89f6c2f488..ebeb28d511 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -312,7 +312,10 @@ "resultContent": "Subtask completed", "defaultResult": "Please continue to the next task.", "completionInstructions": "You can review the results and suggest any corrections or next steps. If everything looks good, confirm to return the result to the parent task.", - "goToSubtask": "View task" + "goToSubtask": "View task", + "inlineStarted": "Subtask flattened to inline", + "inlineRejected": "Nested subtask rejected", + "inlineConfigure": "Adjust task tree settings" }, "questions": { "hasQuestion": "Zoo has a question" diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 7876845932..b84ba93a3c 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -270,7 +270,10 @@ "resultContent": "Resultados de la subtarea", "defaultResult": "Por favor, continúa con la siguiente tarea.", "completionInstructions": "¡Subtarea completada! Puedes revisar los resultados y sugerir correcciones o próximos pasos. Si todo se ve bien, confirma para devolver el resultado a la tarea principal.", - "goToSubtask": "Ver tarea" + "goToSubtask": "Ver tarea", + "inlineStarted": "Subtarea aplanada en línea", + "inlineRejected": "Subtarea anidada rechazada", + "inlineConfigure": "Ajustar configuración del árbol de tareas" }, "questions": { "hasQuestion": "Zoo tiene una pregunta" diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 032d43ce27..edc9193e6f 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -270,7 +270,10 @@ "resultContent": "Résultats de la sous-tâche", "defaultResult": "Veuillez continuer avec la tâche suivante.", "completionInstructions": "Sous-tâche terminée ! Vous pouvez examiner les résultats et suggérer des corrections ou les prochaines étapes. Si tout semble bon, confirmez pour retourner le résultat à la tâche parente.", - "goToSubtask": "Afficher la tâche" + "goToSubtask": "Afficher la tâche", + "inlineStarted": "Sous-tâche aplatie en ligne", + "inlineRejected": "Sous-tâche imbriquée rejetée", + "inlineConfigure": "Ajuster les paramètres de l'arborescence des tâches" }, "questions": { "hasQuestion": "Zoo a une question" diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 94a805f328..418e43b677 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -270,7 +270,10 @@ "resultContent": "उपकार्य परिणाम", "defaultResult": "कृपया अगले कार्य पर जारी रखें।", "completionInstructions": "उपकार्य पूर्ण! आप परिणामों की समीक्षा कर सकते हैं और सुधार या अगले चरण सुझा सकते हैं। यदि सब कुछ ठीक लगता है, तो मुख्य कार्य को परिणाम वापस करने के लिए पुष्टि करें।", - "goToSubtask": "कार्य देखें" + "goToSubtask": "कार्य देखें", + "inlineStarted": "उप-कार्य इनलाइन में सपाट किया गया", + "inlineRejected": "नेस्टेड उप-कार्य अस्वीकृत", + "inlineConfigure": "टास्क ट्री सेटिंग्स समायोजित करें" }, "questions": { "hasQuestion": "Zoo का एक प्रश्न है" diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index d58d80db00..763eb1422f 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -321,7 +321,10 @@ "resultContent": "Hasil Subtugas", "defaultResult": "Silakan lanjutkan ke tugas berikutnya.", "completionInstructions": "Subtugas selesai! Kamu bisa meninjau hasilnya dan menyarankan koreksi atau langkah selanjutnya. Jika semuanya terlihat baik, konfirmasi untuk mengembalikan hasil ke tugas induk.", - "goToSubtask": "Lihat tugas" + "goToSubtask": "Lihat tugas", + "inlineStarted": "Subtugas diratakan inline", + "inlineRejected": "Subtugas bersarang ditolak", + "inlineConfigure": "Atur pengaturan pohon tugas" }, "questions": { "hasQuestion": "Zoo punya pertanyaan" diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 7c4c657b35..b4ac4b01cf 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -270,7 +270,10 @@ "resultContent": "Risultati sottoattività", "defaultResult": "Per favore continua con la prossima attività.", "completionInstructions": "Sottoattività completata! Puoi rivedere i risultati e suggerire correzioni o prossimi passi. Se tutto sembra a posto, conferma per restituire il risultato all'attività principale.", - "goToSubtask": "Visualizza attività" + "goToSubtask": "Visualizza attività", + "inlineStarted": "Compito secondario appiattito in linea", + "inlineRejected": "Compito secondario annidato rifiutato", + "inlineConfigure": "Regola le impostazioni dell'albero dei compiti" }, "questions": { "hasQuestion": "Zoo ha una domanda" diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index f2f17b3fa5..f7f261fce0 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -270,7 +270,10 @@ "resultContent": "サブタスク結果", "defaultResult": "次のタスクに進んでください。", "completionInstructions": "サブタスク完了!結果を確認し、修正や次のステップを提案できます。問題なければ、親タスクに結果を返すために確認してください。", - "goToSubtask": "タスクを表示" + "goToSubtask": "タスクを表示", + "inlineStarted": "サブタスクをインラインにフラット化しました", + "inlineRejected": "ネストしたサブタスクを拒否しました", + "inlineConfigure": "タスクツリー設定を調整する" }, "questions": { "hasQuestion": "Zooは質問があります" diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 090bb1a706..cac8368899 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -270,7 +270,10 @@ "resultContent": "하위 작업 결과", "defaultResult": "다음 작업을 계속 진행해주세요.", "completionInstructions": "하위 작업 완료! 결과를 검토하고 수정 사항이나 다음 단계를 제안할 수 있습니다. 모든 것이 괜찮아 보이면, 부모 작업에 결과를 반환하기 위해 확인해주세요.", - "goToSubtask": "작업 보기" + "goToSubtask": "작업 보기", + "inlineStarted": "서브태스크를 인라인으로 평탄화했습니다", + "inlineRejected": "중첩 서브태스크가 거부되었습니다", + "inlineConfigure": "작업 트리 설정 조정" }, "questions": { "hasQuestion": "Zoo에게 질문이 있습니다" diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 0f1ce14084..3f91bc5757 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -265,7 +265,10 @@ "resultContent": "Subtaakresultaten", "defaultResult": "Ga verder met de volgende taak.", "completionInstructions": "Subtaak voltooid! Je kunt de resultaten bekijken en eventuele correcties of volgende stappen voorstellen. Als alles goed is, bevestig dan om het resultaat terug te sturen naar de hoofdtaak.", - "goToSubtask": "Taak weergeven" + "goToSubtask": "Taak weergeven", + "inlineStarted": "Onderopdracht inline afgevlakt", + "inlineRejected": "Geneste onderopdracht afgewezen", + "inlineConfigure": "Instellingen van de taakboom aanpassen" }, "questions": { "hasQuestion": "Zoo heeft een vraag" diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 53ae2013e1..7dd59f29a4 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -270,7 +270,10 @@ "resultContent": "Wyniki podzadania", "defaultResult": "Proszę kontynuować następne zadanie.", "completionInstructions": "Podzadanie zakończone! Możesz przejrzeć wyniki i zasugerować poprawki lub następne kroki. Jeśli wszystko wygląda dobrze, potwierdź, aby zwrócić wynik do zadania nadrzędnego.", - "goToSubtask": "Wyświetl zadanie" + "goToSubtask": "Wyświetl zadanie", + "inlineStarted": "Zadanie podrzędne spłaszczone do inline", + "inlineRejected": "Zagnieżdżone zadanie odrzucone", + "inlineConfigure": "Dostosuj ustawienia drzewa zadań" }, "questions": { "hasQuestion": "Zoo ma pytanie" diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 4769341a7b..3a5c9e6707 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -270,7 +270,10 @@ "resultContent": "Resultados da subtarefa", "defaultResult": "Por favor, continue com a próxima tarefa.", "completionInstructions": "Subtarefa concluída! Você pode revisar os resultados e sugerir correções ou próximos passos. Se tudo parecer bom, confirme para retornar o resultado à tarefa principal.", - "goToSubtask": "Ver tarefa" + "goToSubtask": "Ver tarefa", + "inlineStarted": "Subtarefa achatada em linha", + "inlineRejected": "Subtarefa aninhada rejeitada", + "inlineConfigure": "Ajustar configurações da árvore de tarefas" }, "questions": { "hasQuestion": "Zoo tem uma pergunta" diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index de34a0e0b8..2c6d51e451 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -266,7 +266,10 @@ "resultContent": "Результаты подзадачи", "defaultResult": "Пожалуйста, переходите к следующей задаче.", "completionInstructions": "Подзадача завершена! Вы можете просмотреть результаты и предложить исправления или следующие шаги. Если всё в порядке, подтвердите для возврата результата в родительскую задачу.", - "goToSubtask": "Просмотреть задачу" + "goToSubtask": "Просмотреть задачу", + "inlineStarted": "Подзадача выровнена в inline", + "inlineRejected": "Вложенная подзадача отклонена", + "inlineConfigure": "Настроить параметры дерева задач" }, "questions": { "hasQuestion": "У Zoo есть вопрос" diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 752e5bff9f..cf77f45887 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -271,7 +271,10 @@ "resultContent": "Alt Görev Sonuçları", "defaultResult": "Lütfen sonraki göreve devam edin.", "completionInstructions": "Alt görev tamamlandı! Sonuçları inceleyebilir ve düzeltmeler veya sonraki adımlar önerebilirsiniz. Her şey iyi görünüyorsa, sonucu üst göreve döndürmek için onaylayın.", - "goToSubtask": "Görevi görüntüle" + "goToSubtask": "Görevi görüntüle", + "inlineStarted": "Alt görev içine düzleştirildi", + "inlineRejected": "İç içe alt görev reddedildi", + "inlineConfigure": "Görev ağacı ayarlarını düzenle" }, "questions": { "hasQuestion": "Zoo'nun bir sorusu var" diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 3caa0e8d3d..8b5b286ca9 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -271,7 +271,10 @@ "resultContent": "Kết quả nhiệm vụ phụ", "defaultResult": "Vui lòng tiếp tục với nhiệm vụ tiếp theo.", "completionInstructions": "Nhiệm vụ phụ đã hoàn thành! Bạn có thể xem lại kết quả và đề xuất các sửa đổi hoặc bước tiếp theo. Nếu mọi thứ có vẻ tốt, hãy xác nhận để trả kết quả về nhiệm vụ chính.", - "goToSubtask": "Xem nhiệm vụ" + "goToSubtask": "Xem nhiệm vụ", + "inlineStarted": "Nhiệm vụ con đã được làm phẳng inline", + "inlineRejected": "Từ chối nhiệm vụ con lồng nhau", + "inlineConfigure": "Điều chỉnh cài đặt cây nhiệm vụ" }, "questions": { "hasQuestion": "Zoo có một câu hỏi" diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 76989eb473..68add3f165 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -271,7 +271,10 @@ "resultContent": "子任务结果", "defaultResult": "请继续下一个任务。", "completionInstructions": "子任务已完成!您可以查看结果并提出修改或下一步建议。如果一切正常,请确认以将结果返回给主任务。", - "goToSubtask": "查看任务" + "goToSubtask": "查看任务", + "inlineStarted": "子任务已扁平化为内联执行", + "inlineRejected": "嵌套子任务被拒绝", + "inlineConfigure": "调整任务树设置" }, "questions": { "hasQuestion": "Zoo有一个问题" diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index e096c27af4..da4cfa0074 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -315,7 +315,10 @@ "resultContent": "子任務結果", "defaultResult": "請繼續下一個工作。", "completionInstructions": "子任務已完成!您可以檢閱結果並提出修正或後續步驟。如果一切順利,請確認以將結果回傳給主任務。", - "goToSubtask": "查看工作" + "goToSubtask": "查看工作", + "inlineStarted": "子任務已扁平化為內聯執行", + "inlineRejected": "巢狀子任務被拒絕", + "inlineConfigure": "調整任務樹設定" }, "questions": { "hasQuestion": "Zoo 有一個問題" diff --git a/webview-ui/src/utils/chatBatchingPredicates.ts b/webview-ui/src/utils/chatBatchingPredicates.ts index 9fe65a98fa..00d406ae5d 100644 --- a/webview-ui/src/utils/chatBatchingPredicates.ts +++ b/webview-ui/src/utils/chatBatchingPredicates.ts @@ -25,6 +25,8 @@ export const isBoundary = (msg: BatchableMessage): boolean => { (msg.say === "text" && !!msg.text?.trim()) || msg.say === "completion_result" || msg.say === "checkpoint_saved" || + msg.say === "inline_subtask_started" || + msg.say === "inline_subtask_rejected" || msg.say === "error" || msg.say === "condense_context" || msg.say === "codebase_search_result" From 4f0642feab50c1a119ce2ac93b80f040807e6df6 Mon Sep 17 00:00:00 2001 From: Eason Liang Date: Sun, 16 Aug 2026 20:10:45 +0800 Subject: [PATCH 2/2] fix(webview): localize inline-subtask banner details and task-tree settings keys --- src/core/tools/NewTaskTool.ts | 15 ++++---- .../__tests__/newTaskInlineFlatten.spec.ts | 12 +++---- webview-ui/src/components/chat/ChatRow.tsx | 21 ++++++++--- .../__tests__/ChatRow.inline-subtask.spec.tsx | 36 ++++++++++++++----- .../settings/ContextManagementSettings.tsx | 14 ++++---- .../ContextManagementSettings.spec.tsx | 10 ++++++ webview-ui/src/i18n/locales/ca/chat.json | 5 ++- webview-ui/src/i18n/locales/de/chat.json | 5 ++- webview-ui/src/i18n/locales/en/chat.json | 5 ++- webview-ui/src/i18n/locales/es/chat.json | 5 ++- webview-ui/src/i18n/locales/fr/chat.json | 5 ++- webview-ui/src/i18n/locales/hi/chat.json | 5 ++- webview-ui/src/i18n/locales/id/chat.json | 5 ++- webview-ui/src/i18n/locales/it/chat.json | 5 ++- webview-ui/src/i18n/locales/ja/chat.json | 5 ++- webview-ui/src/i18n/locales/ko/chat.json | 5 ++- webview-ui/src/i18n/locales/nl/chat.json | 5 ++- webview-ui/src/i18n/locales/pl/chat.json | 5 ++- webview-ui/src/i18n/locales/pt-BR/chat.json | 5 ++- webview-ui/src/i18n/locales/ru/chat.json | 5 ++- webview-ui/src/i18n/locales/tr/chat.json | 5 ++- webview-ui/src/i18n/locales/vi/chat.json | 5 ++- webview-ui/src/i18n/locales/zh-CN/chat.json | 5 ++- webview-ui/src/i18n/locales/zh-TW/chat.json | 5 ++- 24 files changed, 148 insertions(+), 50 deletions(-) diff --git a/src/core/tools/NewTaskTool.ts b/src/core/tools/NewTaskTool.ts index b41dba0495..68240bb21d 100644 --- a/src/core/tools/NewTaskTool.ts +++ b/src/core/tools/NewTaskTool.ts @@ -115,7 +115,8 @@ export class NewTaskTool extends BaseTool<"new_task"> { if (decision.action === "reject-nested") { // Surface the rejection in the UI as well — tool results are not rendered. - await task.say("inline_subtask_rejected", decision.message) + // Structured payload so the webview can localize the detail text. + await task.say("inline_subtask_rejected", JSON.stringify({ reason: "nested" })) pushToolResult(formatResponse.toolError(decision.message)) return } @@ -125,17 +126,19 @@ export class NewTaskTool extends BaseTool<"new_task"> { task.inlineSubtask = { message: unescapedMessage, todos: todoItems } // Surface the auto-flatten in the UI — the model sees it via the tool result, // but without this the user has no indication that a subtask now runs inline. - await task.say( - "inline_subtask_started", - `Nesting limit ${maxNestingDepth} reached — subtask flattened and executing inline in this conversation.`, - ) + // Structured payload so the webview can localize the detail text. + await task.say("inline_subtask_started", JSON.stringify({ maxDepth: maxNestingDepth })) pushToolResult(decision.directive) return } if (decision.action === "reject-limit") { // Surface the rejection in the UI as well — tool results are not rendered. - await task.say("inline_subtask_rejected", decision.message) + // Structured payload so the webview can localize the detail text. + await task.say( + "inline_subtask_rejected", + JSON.stringify({ reason: "limit", maxDepth: maxNestingDepth }), + ) pushToolResult(formatResponse.toolError(decision.message)) return } diff --git a/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts b/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts index 268e5079de..890fe1bbaf 100644 --- a/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts +++ b/src/core/tools/__tests__/newTaskInlineFlatten.spec.ts @@ -92,9 +92,9 @@ describe("NewTaskTool auto-flatten inline", () => { const pushed = pushToolResult.mock.calls[0][0] as string expect(pushed).toContain("auto-flattened") expect(pushed).toContain("do X") - // The auto-flatten is surfaced to the UI via a say message (tool results are not rendered). + // The auto-flatten is surfaced to the UI via a structured say payload (tool results are not rendered). const say = (task as unknown as { say: ReturnType }).say - expect(say).toHaveBeenCalledWith("inline_subtask_started", expect.stringContaining("Nesting limit 2 reached")) + expect(say).toHaveBeenCalledWith("inline_subtask_started", JSON.stringify({ maxDepth: 2 })) }) it("rejects when over the limit and autoFlattenOnLimit is false (error result, no marker)", async () => { @@ -113,9 +113,9 @@ describe("NewTaskTool auto-flatten inline", () => { expect(task.inlineSubtask).toBeUndefined() const pushed = pushToolResult.mock.calls[0][0] as string expect(pushed.toLowerCase()).toContain("error") - // The rejection is surfaced to the UI via a say message. + // The rejection is surfaced to the UI via a structured say payload. const say = (task as unknown as { say: ReturnType }).say - expect(say).toHaveBeenCalledWith("inline_subtask_rejected", expect.stringContaining("auto-flatten is disabled")) + expect(say).toHaveBeenCalledWith("inline_subtask_rejected", JSON.stringify({ reason: "limit", maxDepth: 2 })) }) it("rejects a nested new_task while an inline phase is already active", async () => { @@ -135,9 +135,9 @@ describe("NewTaskTool auto-flatten inline", () => { expect(task.inlineSubtask?.message).toBe("outer") const pushed = pushToolResult.mock.calls[0][0] as string expect(pushed.toLowerCase()).toContain("error") - // The rejection is surfaced to the UI via a say message. + // The rejection is surfaced to the UI via a structured say payload. const say = (task as unknown as { say: ReturnType }).say - expect(say).toHaveBeenCalledWith("inline_subtask_rejected", expect.stringContaining("already in progress")) + expect(say).toHaveBeenCalledWith("inline_subtask_rejected", JSON.stringify({ reason: "nested" })) }) }) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index dbb4c0b076..a360ffe18f 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -1068,8 +1068,9 @@ export const ChatRowContent = ({ )} ) - case "inline_subtask_started": + case "inline_subtask_started": { // A subtask was auto-flattened and now runs inline in this conversation. + const started = safeJsonParse<{ maxDepth?: number }>(message.text) return (
@@ -1080,7 +1081,9 @@ export const ChatRowContent = ({

- {message.text} + {started?.maxDepth != null + ? t("chat:subtasks.inlineStartedDetail", { maxDepth: started.maxDepth }) + : message.text}

) - case "inline_subtask_rejected": - // A nested new_task was rejected because an inline phase is already active. + } + case "inline_subtask_rejected": { + // A nested new_task was rejected (an inline phase is already active, or the + // nesting limit was hit with auto-flatten disabled). + const rejected = safeJsonParse<{ reason?: string; maxDepth?: number }>(message.text) return (
@@ -1111,7 +1117,11 @@ export const ChatRowContent = ({
) + } case "reasoning": return ( ({ // Mock i18n — the two inline-subtask banner titles plus a fallback to the key itself. vi.mock("react-i18next", () => ({ useTranslation: () => ({ - t: (key: string) => { + t: (key: string, options?: Record) => { const map: Record = { "chat:subtasks.inlineStarted": "Subtask flattened to inline", "chat:subtasks.inlineRejected": "Nested subtask rejected", "chat:subtasks.inlineConfigure": "Adjust task tree settings", + "chat:subtasks.inlineStartedDetail": + "Nesting limit {{maxDepth}} reached — subtask flattened and executing inline in this conversation.", + "chat:subtasks.inlineRejectedLimitDetail": + "Nesting limit {{maxDepth}} reached and auto-flatten is disabled. Continue working directly in the current conversation instead of delegating.", + "chat:subtasks.inlineRejectedNestedDetail": + "Cannot start a nested subtask while an inline subtask is already in progress. Complete the current inline subtask with attempt_completion first.", } - return map[key] ?? key + const raw = map[key] ?? key + if (!options) return raw + // Substitute {{var}} placeholders from the options object. + return raw.replace(/\{\{(\w+)\}\}/g, (_, name: string) => String(options[name] ?? `{{${name}}}`)) }, i18n: { exists: () => true }, }), @@ -68,33 +77,42 @@ describe("ChatRow - inline subtask banners", () => { ts: Date.now(), type: "say" as const, say: "inline_subtask_started" as const, - text: "Nesting limit 2 reached — subtask flattened and executing inline in this conversation.", + text: JSON.stringify({ maxDepth: 2 }), } renderChatRow(message) // Banner title (i18n) is present… expect(screen.getByText("Subtask flattened to inline")).toBeInTheDocument() - // …and the detail text from message.text renders below it. + // …and the localized detail text renders below it. expect( screen.getByText("Nesting limit 2 reached — subtask flattened and executing inline in this conversation."), ).toBeInTheDocument() }) - it("renders a distinct banner when a nested new_task is rejected", () => { + it.each([ + [ + "nested", + JSON.stringify({ reason: "nested" }), + "Cannot start a nested subtask while an inline subtask is already in progress. Complete the current inline subtask with attempt_completion first.", + ], + [ + "limit", + JSON.stringify({ reason: "limit", maxDepth: 2 }), + "Nesting limit 2 reached and auto-flatten is disabled. Continue working directly in the current conversation instead of delegating.", + ], + ] as const)("renders a distinct banner when a new_task is rejected (%s)", (_reason, text, detail) => { const message: ClineMessage = { ts: Date.now(), type: "say" as const, say: "inline_subtask_rejected" as const, - text: "Cannot start a nested subtask while an inline subtask is already in progress.", + text, } renderChatRow(message) expect(screen.getByText("Nested subtask rejected")).toBeInTheDocument() - expect( - screen.getByText("Cannot start a nested subtask while an inline subtask is already in progress."), - ).toBeInTheDocument() + expect(screen.getByText(detail)).toBeInTheDocument() }) describe("settings hint link", () => { diff --git a/webview-ui/src/components/settings/ContextManagementSettings.tsx b/webview-ui/src/components/settings/ContextManagementSettings.tsx index cf0f09e313..54aa1a05d6 100644 --- a/webview-ui/src/components/settings/ContextManagementSettings.tsx +++ b/webview-ui/src/components/settings/ContextManagementSettings.tsx @@ -442,8 +442,10 @@ export const ContextManagementSettings = ({ - {t("settings:taskTree.maxNestingDepth.label")} + label={t("settings:contextManagement.taskTree.maxNestingDepth.label")}> + + {t("settings:contextManagement.taskTree.maxNestingDepth.label")} +
{maxNestingDepth ?? DEFAULT_MAX_NESTING_DEPTH}
- {t("settings:taskTree.maxNestingDepth.description")} + {t("settings:contextManagement.taskTree.maxNestingDepth.description")}
+ label={t("settings:contextManagement.taskTree.autoFlattenOnLimit.label")}> setCachedStateField("autoFlattenOnLimit", e.target.checked)} data-testid="auto-flatten-on-limit-checkbox">
- {t("settings:taskTree.autoFlattenOnLimit.description")} + {t("settings:contextManagement.taskTree.autoFlattenOnLimit.description")}
diff --git a/webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx b/webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx index b7fae7802b..e5a3519e96 100644 --- a/webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx @@ -531,6 +531,16 @@ describe("ContextManagementSettings", () => { }) describe("taskTree settings", () => { + // Regression: the task-tree controls must resolve their i18n keys under + // contextManagement.taskTree.* (where the translations live), not a top-level + // taskTree.* — otherwise the raw key is rendered in the UI. + it("resolves task-tree labels via the nested contextManagement.taskTree path", () => { + render() + + expect(screen.getByText("settings:contextManagement.taskTree.maxNestingDepth.label")).toBeInTheDocument() + expect(screen.queryByText("settings:taskTree.maxNestingDepth.label")).not.toBeInTheDocument() + }) + it("renders max nesting depth slider with default value when unset", () => { render() diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 3ad82e5308..fcb0131432 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Veure tasca", "inlineStarted": "Subtarea aplanada en línia", "inlineRejected": "Subtarea niuada rebutjada", - "inlineConfigure": "Ajusta la configuració de l'arbre de tasques" + "inlineConfigure": "Ajusta la configuració de l'arbre de tasques", + "inlineStartedDetail": "S'ha assolit el límit d'anidament {{maxDepth}} — la subtasca s'ha aplanat i s'executa en línia en aquesta conversa.", + "inlineRejectedLimitDetail": "S'ha assolit el límit d'anidament {{maxDepth}} i l'aplanament automàtic està desactivat. Continua treballant directament en la conversa actual en lloc de delegar.", + "inlineRejectedNestedDetail": "No es pot iniciar una subtasca anidada mentre n'hi ha una d'en línia en curs. Completa primer la subtasca en línia amb attempt_completion." }, "questions": { "hasQuestion": "Zoo té una pregunta" diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index b0ff25b292..f5efad9f3c 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Aufgabe anzeigen", "inlineStarted": "Unteraufgabe inline ausgeführt", "inlineRejected": "Verschachtelte Unteraufgabe abgelehnt", - "inlineConfigure": "Aufgabenbaum-Einstellungen anpassen" + "inlineConfigure": "Aufgabenbaum-Einstellungen anpassen", + "inlineStartedDetail": "Nestigungsgrenze {{maxDepth}} erreicht — Unteraufgabe wurde eingeebnet und wird inline in diesem Gespräch ausgeführt.", + "inlineRejectedLimitDetail": "Nestigungsgrenze {{maxDepth}} erreicht und Auto-Einbiegen ist deaktiviert. Führe die Arbeit direkt in der aktuellen Konversation fort, statt zu delegieren.", + "inlineRejectedNestedDetail": "Während eine Inline-Unteraufgabe läuft, kann keine verschachtelte Unteraufgabe gestartet werden. Schließe zuerst die aktuelle Inline-Unteraufgabe mit attempt_completion ab." }, "questions": { "hasQuestion": "Zoo hat eine Frage" diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index ebeb28d511..325c18988f 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -315,7 +315,10 @@ "goToSubtask": "View task", "inlineStarted": "Subtask flattened to inline", "inlineRejected": "Nested subtask rejected", - "inlineConfigure": "Adjust task tree settings" + "inlineConfigure": "Adjust task tree settings", + "inlineStartedDetail": "Nesting limit {{maxDepth}} reached — subtask flattened and executing inline in this conversation.", + "inlineRejectedLimitDetail": "Nesting limit {{maxDepth}} reached and auto-flatten is disabled. Continue working directly in the current conversation instead of delegating.", + "inlineRejectedNestedDetail": "Cannot start a nested subtask while an inline subtask is already in progress. Complete the current inline subtask with attempt_completion first." }, "questions": { "hasQuestion": "Zoo has a question" diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index b84ba93a3c..ef0b0b66ec 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Ver tarea", "inlineStarted": "Subtarea aplanada en línea", "inlineRejected": "Subtarea anidada rechazada", - "inlineConfigure": "Ajustar configuración del árbol de tareas" + "inlineConfigure": "Ajustar configuración del árbol de tareas", + "inlineStartedDetail": "Se alcanzó el límite de anidamiento {{maxDepth}} — la subtarea se aplanó y se ejecuta en línea en esta conversación.", + "inlineRejectedLimitDetail": "Se alcanzó el límite de anidamiento {{maxDepth}} y el aplanado automático está desactivado. Continúa trabajando directamente en la conversación actual en lugar de delegar.", + "inlineRejectedNestedDetail": "No se puede iniciar una subtarea anidada mientras hay una subtarea en línea en curso. Completa primero la subtarea en línea con attempt_completion." }, "questions": { "hasQuestion": "Zoo tiene una pregunta" diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index edc9193e6f..d9106944e4 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Afficher la tâche", "inlineStarted": "Sous-tâche aplatie en ligne", "inlineRejected": "Sous-tâche imbriquée rejetée", - "inlineConfigure": "Ajuster les paramètres de l'arborescence des tâches" + "inlineConfigure": "Ajuster les paramètres de l'arborescence des tâches", + "inlineStartedDetail": "Limite d'imbrication {{maxDepth}} atteinte — la sous-tâche a été aplatie et s'exécute en ligne dans cette conversation.", + "inlineRejectedLimitDetail": "Limite d'imbrication {{maxDepth}} atteinte et l'aplatissement automatique est désactivé. Continuez à travailler directement dans la conversation actuelle au lieu de déléguer.", + "inlineRejectedNestedDetail": "Impossible de démarrer une sous-tâche imbriquée pendant qu'une sous-tâche en ligne est en cours. Terminez d'abord la sous-tâche en ligne avec attempt_completion." }, "questions": { "hasQuestion": "Zoo a une question" diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 418e43b677..a13b1de0fd 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "कार्य देखें", "inlineStarted": "उप-कार्य इनलाइन में सपाट किया गया", "inlineRejected": "नेस्टेड उप-कार्य अस्वीकृत", - "inlineConfigure": "टास्क ट्री सेटिंग्स समायोजित करें" + "inlineConfigure": "टास्क ट्री सेटिंग्स समायोजित करें", + "inlineStartedDetail": "नेस्टिंग सीमा {{maxDepth}} पहुँची — उप-कार्य सपाट कर दिया गया और इस संवाद में इनलाइन चलाया जा रहा है।", + "inlineRejectedLimitDetail": "नेस्टिंग सीमा {{maxDepth}} पहुँची और ऑटो-फ्लैटन बंद है। डेलीगेट करने के बजाय वर्तमान संवाद में सीधे काम जारी रखें।", + "inlineRejectedNestedDetail": "जब एक इनलाइन उप-कार्य प्रगति पर हो, तब एक नेस्टेड उप-कार्य शुरू नहीं किया जा सकता। पहले attempt_completion से वर्तमान इनलाइन उप-कार्य पूर्ण करें।" }, "questions": { "hasQuestion": "Zoo का एक प्रश्न है" diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 763eb1422f..70128776cd 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -324,7 +324,10 @@ "goToSubtask": "Lihat tugas", "inlineStarted": "Subtugas diratakan inline", "inlineRejected": "Subtugas bersarang ditolak", - "inlineConfigure": "Atur pengaturan pohon tugas" + "inlineConfigure": "Atur pengaturan pohon tugas", + "inlineStartedDetail": "Batas penempaan {{maxDepth}} tercapai — sub-tugas diratakan dan dijalankan inline dalam percakapan ini.", + "inlineRejectedLimitDetail": "Batas penempaan {{maxDepth}} tercapai dan auto-flatten nonaktif. Terus bekerja langsung di percakapan saat ini alih-alih mendelegasikan.", + "inlineRejectedNestedDetail": "Tidak dapat memulai sub-tugas bersarang saat sub-tugas inline sedang berjalan. Selesaikan dulu sub-tugas inline dengan attempt_completion." }, "questions": { "hasQuestion": "Zoo punya pertanyaan" diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index b4ac4b01cf..222435f640 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Visualizza attività", "inlineStarted": "Compito secondario appiattito in linea", "inlineRejected": "Compito secondario annidato rifiutato", - "inlineConfigure": "Regola le impostazioni dell'albero dei compiti" + "inlineConfigure": "Regola le impostazioni dell'albero dei compiti", + "inlineStartedDetail": "Limite di annidamento {{maxDepth}} raggiunto — il sotto-compito è stato appiattito e viene eseguito in linea in questa conversazione.", + "inlineRejectedLimitDetail": "Limite di annidamento {{maxDepth}} raggiunto e l'appiattimento automatico è disattivato. Continua a lavorare direttamente nella conversazione attuale invece di delegare.", + "inlineRejectedNestedDetail": "Non è possibile avviare un sotto-compito annidato mentre ne è in corso uno in linea. Completa prima il sotto-compito in linea con attempt_completion." }, "questions": { "hasQuestion": "Zoo ha una domanda" diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index f7f261fce0..ae6cb095c1 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "タスクを表示", "inlineStarted": "サブタスクをインラインにフラット化しました", "inlineRejected": "ネストしたサブタスクを拒否しました", - "inlineConfigure": "タスクツリー設定を調整する" + "inlineConfigure": "タスクツリー設定を調整する", + "inlineStartedDetail": "ネスト上限 {{maxDepth}} に到達 — サブタスクはフラット化され、この会話でインライン実行されています。", + "inlineRejectedLimitDetail": "ネスト上限 {{maxDepth}} に到達し、自動フラット化が無効です。委任する代わりに現在の会話で直接作業を続けてください。", + "inlineRejectedNestedDetail": "インラインサブタスクが進行中の間は、ネストしたサブタスクを開始できません。まず attempt_completion で現在のインラインサブタスクを完了してください。" }, "questions": { "hasQuestion": "Zooは質問があります" diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index cac8368899..a981a61632 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "작업 보기", "inlineStarted": "서브태스크를 인라인으로 평탄화했습니다", "inlineRejected": "중첩 서브태스크가 거부되었습니다", - "inlineConfigure": "작업 트리 설정 조정" + "inlineConfigure": "작업 트리 설정 조정", + "inlineStartedDetail": "네스팅 한도 {{maxDepth}} 도달 — 하위 작업이 평탄화되어 이 대화에서 인라인으로 실행 중입니다.", + "inlineRejectedLimitDetail": "네스팅 한도 {{maxDepth}}에 도달했으며 자동 평탄화가 비활성화되었습니다. 위임 대신 현재 대화에서 직접 작업을 계속하세요.", + "inlineRejectedNestedDetail": "인라인 하위 작업이 진행 중인 동안 중첩된 하위 작업을 시작할 수 없습니다. 먼저 attempt_completion으로 현재 인라인 하위 작업을 완료하세요." }, "questions": { "hasQuestion": "Zoo에게 질문이 있습니다" diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 3f91bc5757..218576fca2 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -268,7 +268,10 @@ "goToSubtask": "Taak weergeven", "inlineStarted": "Onderopdracht inline afgevlakt", "inlineRejected": "Geneste onderopdracht afgewezen", - "inlineConfigure": "Instellingen van de taakboom aanpassen" + "inlineConfigure": "Instellingen van de taakboom aanpassen", + "inlineStartedDetail": "Nestingslimiet {{maxDepth}} bereikt — de subtaak is afgevlakt en wordt inline in dit gesprek uitgevoerd.", + "inlineRejectedLimitDetail": "Nestingslimiet {{maxDepth}} bereikt en automatisch afvlakken is uitgeschakeld. Ga door met direct werken in het huidige gesprek in plaats van delegeren.", + "inlineRejectedNestedDetail": "Een geneste subtaak kan niet gestart worden terwijl een inline-subtaak bezig is. Voltooi eerst de huidige inline-subtaak met attempt_completion." }, "questions": { "hasQuestion": "Zoo heeft een vraag" diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 7dd59f29a4..6349118413 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Wyświetl zadanie", "inlineStarted": "Zadanie podrzędne spłaszczone do inline", "inlineRejected": "Zagnieżdżone zadanie odrzucone", - "inlineConfigure": "Dostosuj ustawienia drzewa zadań" + "inlineConfigure": "Dostosuj ustawienia drzewa zadań", + "inlineStartedDetail": "Osiągnięto limit zagnieżdżania {{maxDepth}} — podzadanie zostało spłaszczone i jest wykonywane inline w tej rozmowie.", + "inlineRejectedLimitDetail": "Osiągnięto limit zagnieżdżania {{maxDepth}}, a automatyczne spłaszczanie jest wyłączone. Kontynuuj pracę bezpośrednio w bieżącej rozmowie zamiast delegować.", + "inlineRejectedNestedDetail": "Nie można uruchomić zagnieżdżonego podzadania, gdy trwa podzadanie inline. Najpierw zakończ bieżące podzadanie inline za pomocą attempt_completion." }, "questions": { "hasQuestion": "Zoo ma pytanie" diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 3a5c9e6707..b645bef1cc 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -273,7 +273,10 @@ "goToSubtask": "Ver tarefa", "inlineStarted": "Subtarefa achatada em linha", "inlineRejected": "Subtarefa aninhada rejeitada", - "inlineConfigure": "Ajustar configurações da árvore de tarefas" + "inlineConfigure": "Ajustar configurações da árvore de tarefas", + "inlineStartedDetail": "Limite de aninhamento {{maxDepth}} atingido — a subtarefa foi achatada e está sendo executada em linha nesta conversa.", + "inlineRejectedLimitDetail": "Limite de aninhamento {{maxDepth}} atingido e o achatamento automático está desativado. Continue trabalhando diretamente na conversa atual em vez de delegar.", + "inlineRejectedNestedDetail": "Não é possível iniciar uma subtarefa aninhada enquanto há uma subtarefa em linha em andamento. Conclua primeiro a subtarefa em linha com attempt_completion." }, "questions": { "hasQuestion": "Zoo tem uma pergunta" diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 2c6d51e451..3d366bf9b7 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -269,7 +269,10 @@ "goToSubtask": "Просмотреть задачу", "inlineStarted": "Подзадача выровнена в inline", "inlineRejected": "Вложенная подзадача отклонена", - "inlineConfigure": "Настроить параметры дерева задач" + "inlineConfigure": "Настроить параметры дерева задач", + "inlineStartedDetail": "Достигнут предел вложенности {{maxDepth}} — подзадача выровнена и выполняется inline в этом диалоге.", + "inlineRejectedLimitDetail": "Достигнут предел вложенности {{maxDepth}}, а автовыравнивание отключено. Продолжайте работать непосредственно в текущем диалоге вместо делегирования.", + "inlineRejectedNestedDetail": "Нельзя запустить вложенную подзадачу, пока выполняется inline-подзадача. Сначала завершите текущую inline-подзадачу с помощью attempt_completion." }, "questions": { "hasQuestion": "У Zoo есть вопрос" diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index cf77f45887..dc9d864587 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -274,7 +274,10 @@ "goToSubtask": "Görevi görüntüle", "inlineStarted": "Alt görev içine düzleştirildi", "inlineRejected": "İç içe alt görev reddedildi", - "inlineConfigure": "Görev ağacı ayarlarını düzenle" + "inlineConfigure": "Görev ağacı ayarlarını düzenle", + "inlineStartedDetail": "Yiyeşleme sınırı {{maxDepth}}'e ulaşıldı — alt görev düzleştirildi ve bu sohbette satır içi olarak çalıştırılıyor.", + "inlineRejectedLimitDetail": "Yiyeşleme sınırı {{maxDepth}}'e ulaşıldı ve otomatik düzleştirme kapalı. Devretmek yerine mevcut sohbette doğrudan çalışmaya devam edin.", + "inlineRejectedNestedDetail": "Satır içi bir alt görev sürerken iç içe geçmiş bir alt görev başlatılamaz. Önce attempt_completion ile mevcut satır içi alt görevi tamamlayın." }, "questions": { "hasQuestion": "Zoo'nun bir sorusu var" diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 8b5b286ca9..230ba46987 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -274,7 +274,10 @@ "goToSubtask": "Xem nhiệm vụ", "inlineStarted": "Nhiệm vụ con đã được làm phẳng inline", "inlineRejected": "Từ chối nhiệm vụ con lồng nhau", - "inlineConfigure": "Điều chỉnh cài đặt cây nhiệm vụ" + "inlineConfigure": "Điều chỉnh cài đặt cây nhiệm vụ", + "inlineStartedDetail": "Đã đạt giới hạn lồng nhau {{maxDepth}} — tác vụ con đã được làm phẳng và chạy inline trong cuộc trò chuyện này.", + "inlineRejectedLimitDetail": "Đã đạt giới hạn lồng nhau {{maxDepth}} và tự động làm phẳng đang tắt. Tiếp tục làm việc trực tiếp trong cuộc trò chuyện hiện tại thay vì ủy quyền.", + "inlineRejectedNestedDetail": "Không thể bắt đầu tác vụ con lồng nhau khi một tác vụ con inline đang chạy. Hãy hoàn thành trước tác vụ inline hiện tại bằng attempt_completion." }, "questions": { "hasQuestion": "Zoo có một câu hỏi" diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 68add3f165..d6181bce17 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -274,7 +274,10 @@ "goToSubtask": "查看任务", "inlineStarted": "子任务已扁平化为内联执行", "inlineRejected": "嵌套子任务被拒绝", - "inlineConfigure": "调整任务树设置" + "inlineConfigure": "调整任务树设置", + "inlineStartedDetail": "已达到嵌套上限 {{maxDepth}} — 子任务已扁平化,正在本对话中内联执行。", + "inlineRejectedLimitDetail": "已达到嵌套上限 {{maxDepth}},且自动扁平化已关闭。请直接在当前对话中继续工作,而非委派。", + "inlineRejectedNestedDetail": "当一个内联子任务正在进行时,无法启动嵌套的子任务。请先用 attempt_completion 完成当前的内联子任务。" }, "questions": { "hasQuestion": "Zoo有一个问题" diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index da4cfa0074..4ce131819b 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -318,7 +318,10 @@ "goToSubtask": "查看工作", "inlineStarted": "子任務已扁平化為內聯執行", "inlineRejected": "巢狀子任務被拒絕", - "inlineConfigure": "調整任務樹設定" + "inlineConfigure": "調整任務樹設定", + "inlineStartedDetail": "已達到巢狀上限 {{maxDepth}} — 子任務已扁平化,正在本對話中內聯執行。", + "inlineRejectedLimitDetail": "已達到巢狀上限 {{maxDepth}},且自動扁平化已關閉。請直接在目前對話中繼續工作,而非委派。", + "inlineRejectedNestedDetail": "當一個內聯子任務進行中時,無法啟動巢狀的子任務。請先用 attempt_completion 完成目前的內聯子任務。" }, "questions": { "hasQuestion": "Zoo 有一個問題"