From d59fa64cfd0b10bac221bc72d793216fe6b8c27a Mon Sep 17 00:00:00 2001
From: TDFSE <77169190+TDFSE@users.noreply.github.com>
Date: Fri, 10 Apr 2026 13:01:33 -0400
Subject: [PATCH 1/4] Add advisor functionality and tests
---
packages/types/src/model.ts | 1 +
packages/types/src/provider-settings.ts | 3 +
packages/types/src/providers/anthropic.ts | 3 +
src/api/providers/__tests__/anthropic.spec.ts | 135 ++++++++++++++++++
src/api/providers/anthropic.ts | 24 +++-
.../settings/providers/Anthropic.tsx | 48 +++++++
webview-ui/src/i18n/locales/en/settings.json | 4 +
7 files changed, 217 insertions(+), 1 deletion(-)
diff --git a/packages/types/src/model.ts b/packages/types/src/model.ts
index 926f29a0a1a..98fb3961886 100644
--- a/packages/types/src/model.ts
+++ b/packages/types/src/model.ts
@@ -98,6 +98,7 @@ export const modelInfoSchema = z.object({
outputPrice: z.number().optional(),
cacheWritesPrice: z.number().optional(),
cacheReadsPrice: z.number().optional(),
+ supportsAdvisorTool: z.boolean().optional(),
longContextPricing: z
.object({
thresholdTokens: z.number(),
diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts
index 43135577e16..1500ab81d40 100644
--- a/packages/types/src/provider-settings.ts
+++ b/packages/types/src/provider-settings.ts
@@ -207,6 +207,9 @@ const anthropicSchema = apiModelIdProviderModelSchema.extend({
anthropicBaseUrl: z.string().optional(),
anthropicUseAuthToken: z.boolean().optional(),
anthropicBeta1MContext: z.boolean().optional(), // Enable 'context-1m-2025-08-07' beta for 1M context window.
+ anthropicAdvisorEnabled: z.boolean().optional(),
+ anthropicAdvisorModel: z.string().optional(),
+ anthropicAdvisorMaxUses: z.number().int().min(1).optional(),
})
const openRouterSchema = baseProviderSettingsSchema.extend({
diff --git a/packages/types/src/providers/anthropic.ts b/packages/types/src/providers/anthropic.ts
index 40a3d885d84..72ad88ea576 100644
--- a/packages/types/src/providers/anthropic.ts
+++ b/packages/types/src/providers/anthropic.ts
@@ -17,6 +17,7 @@ export const anthropicModels = {
cacheWritesPrice: 3.75, // $3.75 per million tokens
cacheReadsPrice: 0.3, // $0.30 per million tokens
supportsReasoningBudget: true,
+ supportsAdvisorTool: true,
// Tiered pricing for extended context (requires beta flag 'context-1m-2025-08-07')
tiers: [
{
@@ -80,6 +81,7 @@ export const anthropicModels = {
cacheWritesPrice: 6.25, // $6.25 per million tokens
cacheReadsPrice: 0.5, // $0.50 per million tokens
supportsReasoningBudget: true,
+ supportsAdvisorTool: true,
// Tiered pricing for extended context (requires beta flag)
tiers: [
{
@@ -196,6 +198,7 @@ export const anthropicModels = {
cacheWritesPrice: 1.25,
cacheReadsPrice: 0.1,
supportsReasoningBudget: true,
+ supportsAdvisorTool: true,
description:
"Claude Haiku 4.5 delivers near-frontier intelligence at lightning speeds with extended thinking, vision, and multilingual support.",
},
diff --git a/src/api/providers/__tests__/anthropic.spec.ts b/src/api/providers/__tests__/anthropic.spec.ts
index 3731f3a068b..7dbad50dcd7 100644
--- a/src/api/providers/__tests__/anthropic.spec.ts
+++ b/src/api/providers/__tests__/anthropic.spec.ts
@@ -209,6 +209,141 @@ describe("AnthropicHandler", () => {
const requestOptions = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[1]
expect(requestOptions?.headers?.["anthropic-beta"]).toContain("context-1m-2025-08-07")
})
+
+ describe("advisor tool feature", () => {
+ const systemPrompt = "You are a helpful assistant."
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "user",
+ content: [{ type: "text" as const, text: "Hello" }],
+ },
+ ]
+
+ it("should include advisor tool beta header when advisor tool is enabled", async () => {
+ const advisorHandler = new AnthropicHandler({
+ apiKey: "test-api-key",
+ apiModelId: "claude-sonnet-4-6",
+ anthropicAdvisorEnabled: true,
+ })
+
+ const stream = advisorHandler.createMessage(systemPrompt, messages)
+
+ for await (const _chunk of stream) {
+ // Consume stream
+ }
+
+ const requestOptions = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[1]
+ expect(requestOptions?.headers?.["anthropic-beta"]).toContain("advisor-tool-2026-03-01")
+ })
+
+ it("should inject advisor tool definition when advisor tool is enabled", async () => {
+ const advisorHandler = new AnthropicHandler({
+ apiKey: "test-api-key",
+ apiModelId: "claude-sonnet-4-6",
+ anthropicAdvisorEnabled: true,
+ })
+
+ const stream = advisorHandler.createMessage(systemPrompt, messages)
+
+ for await (const _chunk of stream) {
+ // Consume stream
+ }
+
+ const callArgs = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[0]
+ expect(callArgs?.tools).toBeDefined()
+ expect(callArgs?.tools).toEqual(
+ expect.arrayContaining([
+ expect.objectContaining({
+ type: "advisor_20260301",
+ name: "advisor",
+ model: "claude-opus-4-6",
+ }),
+ ]),
+ )
+ })
+
+ it("should include max_uses in advisor tool definition when configured", async () => {
+ const customMaxUses = 5
+ const advisorHandler = new AnthropicHandler({
+ apiKey: "test-api-key",
+ apiModelId: "claude-sonnet-4-6",
+ anthropicAdvisorEnabled: true,
+ anthropicAdvisorMaxUses: customMaxUses,
+ })
+
+ const stream = advisorHandler.createMessage(systemPrompt, messages)
+
+ for await (const _chunk of stream) {
+ // Consume stream
+ }
+
+ const callArgs = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[0]
+ const advisorTool = callArgs?.tools?.find((tool: any) => tool.type === "advisor_20260301")
+ expect(advisorTool).toBeDefined()
+ expect(advisorTool?.max_uses).toBe(customMaxUses)
+ })
+
+ it("should use custom advisor model when configured", async () => {
+ const customModel = "claude-opus-4-5-20251101"
+ const advisorHandler = new AnthropicHandler({
+ apiKey: "test-api-key",
+ apiModelId: "claude-sonnet-4-6",
+ anthropicAdvisorEnabled: true,
+ anthropicAdvisorModel: customModel,
+ })
+
+ const stream = advisorHandler.createMessage(systemPrompt, messages)
+
+ for await (const _chunk of stream) {
+ // Consume stream
+ }
+
+ const callArgs = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[0]
+ const advisorTool = callArgs?.tools?.find((tool: any) => tool.type === "advisor_20260301")
+ expect(advisorTool).toBeDefined()
+ expect(advisorTool?.model).toBe(customModel)
+ })
+
+ it("should not include advisor tool when advisor tool is disabled", async () => {
+ const stream = handler.createMessage(systemPrompt, messages)
+
+ for await (const _chunk of stream) {
+ // Consume stream
+ }
+
+ const callArgs = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[0]
+ const advisorTool = callArgs?.tools?.find((tool: any) => tool.type === "advisor_20260301")
+ expect(advisorTool).toBeUndefined()
+
+ // Also verify beta header is not present
+ const requestOptions = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[1]
+ const betaHeader = requestOptions?.headers?.["anthropic-beta"]
+ if (betaHeader && typeof betaHeader === "string") {
+ expect(betaHeader).not.toContain("advisor-tool-2026-03-01")
+ }
+ })
+
+ it("should use default advisor model and max_uses when not configured", async () => {
+ const advisorHandler = new AnthropicHandler({
+ apiKey: "test-api-key",
+ apiModelId: "claude-sonnet-4-6",
+ anthropicAdvisorEnabled: true,
+ // No anthropicAdvisorModel or anthropicAdvisorMaxUses provided
+ })
+
+ const stream = advisorHandler.createMessage(systemPrompt, messages)
+
+ for await (const _chunk of stream) {
+ // Consume stream
+ }
+
+ const callArgs = mockCreate.mock.calls[mockCreate.mock.calls.length - 1]?.[0]
+ const advisorTool = callArgs?.tools?.find((tool: any) => tool.type === "advisor_20260301")
+ expect(advisorTool).toBeDefined()
+ expect(advisorTool?.model).toBe("claude-opus-4-6") // default
+ expect(advisorTool?.max_uses).toBe(3) // default
+ })
+ })
})
describe("completePrompt", () => {
diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts
index 1786a105a5e..010d0df38d0 100644
--- a/src/api/providers/anthropic.ts
+++ b/src/api/providers/anthropic.ts
@@ -75,8 +75,30 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
betas.push("context-1m-2025-08-07")
}
+ // Add advisor tool beta flag if enabled
+ if (this.options.anthropicAdvisorEnabled) {
+ betas.push("advisor-tool-2026-03-01")
+ }
+
+ let tools = convertOpenAIToolsToAnthropic(metadata?.tools ?? [])
+
+ // Add advisor tool if enabled
+ if (this.options.anthropicAdvisorEnabled) {
+ const advisorModel = this.options.anthropicAdvisorModel ?? "claude-opus-4-6"
+ const maxUses = this.options.anthropicAdvisorMaxUses ?? 3
+ const advisorToolDef: { type: string; name: string; model: string; max_uses?: number } = {
+ type: "advisor_20260301",
+ name: "advisor",
+ model: advisorModel,
+ }
+ if (maxUses >= 1) {
+ advisorToolDef.max_uses = maxUses
+ }
+ tools.push(advisorToolDef as unknown as Anthropic.Tool)
+ }
+
const nativeToolParams = {
- tools: convertOpenAIToolsToAnthropic(metadata?.tools ?? []),
+ tools,
tool_choice: convertOpenAIToolChoiceToAnthropic(metadata?.tool_choice, metadata?.parallelToolCalls),
}
diff --git a/webview-ui/src/components/settings/providers/Anthropic.tsx b/webview-ui/src/components/settings/providers/Anthropic.tsx
index 6417e34b8be..a766914ebb7 100644
--- a/webview-ui/src/components/settings/providers/Anthropic.tsx
+++ b/webview-ui/src/components/settings/providers/Anthropic.tsx
@@ -19,6 +19,7 @@ type AnthropicProps = {
export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: AnthropicProps) => {
const { t } = useAppTranslation()
const selectedModel = useSelectedModel(apiConfiguration)
+ const modelInfo = selectedModel?.info
const [anthropicBaseUrlSelected, setAnthropicBaseUrlSelected] = useState(!!apiConfiguration?.anthropicBaseUrl)
@@ -103,6 +104,53 @@ export const Anthropic = ({ apiConfiguration, setApiConfigurationField }: Anthro
)}
+ {modelInfo?.supportsAdvisorTool && (
+
+
{
+ setApiConfigurationField("anthropicAdvisorEnabled", checked)
+ }}>
+ {t("settings:providers.anthropicAdvisorToolLabel")}
+
+ {apiConfiguration?.anthropicAdvisorEnabled && (
+
+
+
+ {t("settings:providers.anthropicAdvisorModelLabel")}
+
+ {
+ setApiConfigurationField("anthropicAdvisorModel", event.target.value)
+ }}
+ className="w-full px-2 py-1 rounded border border-vscode-input-border bg-vscode-input-background text-vscode-foreground">
+ claude-opus-4-6
+
+
+
+
+ {t("settings:providers.anthropicAdvisorMaxUsesLabel")}
+
+ {
+ const value = event.target.value
+ setApiConfigurationField(
+ "anthropicAdvisorMaxUses",
+ value === "" ? undefined : parseInt(value, 10),
+ )
+ }}
+ placeholder={t("settings:providers.anthropicAdvisorMaxUsesPlaceholder")}
+ className="w-full px-2 py-1 rounded border border-vscode-input-border bg-vscode-input-background text-vscode-foreground"
+ />
+
+
+ )}
+
+ )}
>
)
}
diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json
index 183cd663e31..5a6b24aeb10 100644
--- a/webview-ui/src/i18n/locales/en/settings.json
+++ b/webview-ui/src/i18n/locales/en/settings.json
@@ -437,6 +437,10 @@
"anthropicUseAuthToken": "Pass Anthropic API Key as Authorization header instead of X-Api-Key",
"anthropic1MContextBetaLabel": "Enable 1M context window (Beta)",
"anthropic1MContextBetaDescription": "Extends context window to 1 million tokens for Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Enable Advisor Tool (Beta)",
+ "anthropicAdvisorModelLabel": "Advisor Model",
+ "anthropicAdvisorMaxUsesLabel": "Max Uses",
+ "anthropicAdvisorMaxUsesPlaceholder": "No limit",
"awsBedrock1MContextBetaLabel": "Enable 1M context window (Beta)",
"awsBedrock1MContextBetaDescription": "Extends context window to 1 million tokens for Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Enable 1M context window (Beta)",
From 32a8d58725aeccb7352557ddbd1f5fb0086174e0 Mon Sep 17 00:00:00 2001
From: TDFSE <77169190+TDFSE@users.noreply.github.com>
Date: Fri, 10 Apr 2026 14:02:00 -0400
Subject: [PATCH 2/4] Add tool use/result to VALID_ANTHROPIC_BLOCK_TYPES
---
.../__tests__/anthropic-filter.spec.ts | 61 +++++++++++++++++++
src/api/transform/anthropic-filter.ts | 2 +
2 files changed, 63 insertions(+)
diff --git a/src/api/transform/__tests__/anthropic-filter.spec.ts b/src/api/transform/__tests__/anthropic-filter.spec.ts
index 46ad1a19526..ceb0fdb34d9 100644
--- a/src/api/transform/__tests__/anthropic-filter.spec.ts
+++ b/src/api/transform/__tests__/anthropic-filter.spec.ts
@@ -12,6 +12,13 @@ describe("anthropic-filter", () => {
expect(VALID_ANTHROPIC_BLOCK_TYPES.has("thinking")).toBe(true)
expect(VALID_ANTHROPIC_BLOCK_TYPES.has("redacted_thinking")).toBe(true)
expect(VALID_ANTHROPIC_BLOCK_TYPES.has("document")).toBe(true)
+ expect(VALID_ANTHROPIC_BLOCK_TYPES.has("server_tool_use")).toBe(true)
+ expect(VALID_ANTHROPIC_BLOCK_TYPES.has("advisor_tool_result")).toBe(true)
+ })
+
+ it("should contain server_tool_use and advisor_tool_result", () => {
+ expect(VALID_ANTHROPIC_BLOCK_TYPES.has("server_tool_use")).toBe(true)
+ expect(VALID_ANTHROPIC_BLOCK_TYPES.has("advisor_tool_result")).toBe(true)
})
it("should not contain internal or provider-specific types", () => {
@@ -140,5 +147,59 @@ describe("anthropic-filter", () => {
expect(result).toHaveLength(1)
expect(result[0].content).toEqual([{ type: "text", text: "Valid text" }])
})
+
+ it("should preserve server_tool_use blocks in assistant turns", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ { role: "user", content: "Hello" },
+ {
+ role: "assistant",
+ content: [
+ { type: "server_tool_use" as any, id: "srvtoolu_abc123", name: "advisor", input: {} },
+ { type: "text", text: "Response" },
+ ],
+ },
+ ]
+ const result = filterNonAnthropicBlocks(messages)
+ expect(result).toHaveLength(2)
+ expect(result[1].content).toHaveLength(2)
+ expect((result[1].content as any[])[0].type).toBe("server_tool_use")
+ })
+
+ it("should preserve advisor_tool_result blocks in assistant turns", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ { role: "user", content: "Hello" },
+ {
+ role: "assistant",
+ content: [
+ {
+ type: "advisor_tool_result" as any,
+ tool_use_id: "srvtoolu_abc123",
+ content: "Advisor says hi",
+ },
+ { type: "text", text: "Response" },
+ ],
+ },
+ ]
+ const result = filterNonAnthropicBlocks(messages)
+ expect(result).toHaveLength(2)
+ expect(result[1].content).toHaveLength(2)
+ expect((result[1].content as any[])[0].type).toBe("advisor_tool_result")
+ })
+
+ it("should preserve both server_tool_use and advisor_tool_result block types alongside text blocks", () => {
+ const messages: Anthropic.Messages.MessageParam[] = [
+ {
+ role: "assistant",
+ content: [
+ { type: "server_tool_use" as any, id: "srvtoolu_abc123", name: "advisor", input: {} },
+ { type: "advisor_tool_result" as any, tool_use_id: "srvtoolu_abc123", content: "ok" },
+ { type: "text", text: "Final answer" },
+ ],
+ },
+ ]
+ const result = filterNonAnthropicBlocks(messages)
+ expect(result).toHaveLength(1)
+ expect(result[0].content).toHaveLength(3)
+ })
})
})
diff --git a/src/api/transform/anthropic-filter.ts b/src/api/transform/anthropic-filter.ts
index 2bfc6dccfd0..c82634995fd 100644
--- a/src/api/transform/anthropic-filter.ts
+++ b/src/api/transform/anthropic-filter.ts
@@ -13,6 +13,8 @@ export const VALID_ANTHROPIC_BLOCK_TYPES = new Set([
"thinking",
"redacted_thinking",
"document",
+ "server_tool_use",
+ "advisor_tool_result",
])
/**
From 33bb838f1108f4cbd0fd2e71dc3fb1db9411ab69 Mon Sep 17 00:00:00 2001
From: TDFSE <77169190+TDFSE@users.noreply.github.com>
Date: Fri, 10 Apr 2026 20:55:20 -0400
Subject: [PATCH 3/4] Add translations
---
webview-ui/src/i18n/locales/ca/settings.json | 4 ++++
webview-ui/src/i18n/locales/de/settings.json | 4 ++++
webview-ui/src/i18n/locales/es/settings.json | 4 ++++
webview-ui/src/i18n/locales/fr/settings.json | 4 ++++
webview-ui/src/i18n/locales/hi/settings.json | 4 ++++
webview-ui/src/i18n/locales/id/settings.json | 4 ++++
webview-ui/src/i18n/locales/it/settings.json | 4 ++++
webview-ui/src/i18n/locales/ja/settings.json | 4 ++++
webview-ui/src/i18n/locales/ko/settings.json | 4 ++++
webview-ui/src/i18n/locales/nl/settings.json | 4 ++++
webview-ui/src/i18n/locales/pl/settings.json | 4 ++++
webview-ui/src/i18n/locales/pt-BR/settings.json | 4 ++++
webview-ui/src/i18n/locales/ru/settings.json | 4 ++++
webview-ui/src/i18n/locales/tr/settings.json | 4 ++++
webview-ui/src/i18n/locales/vi/settings.json | 4 ++++
webview-ui/src/i18n/locales/zh-CN/settings.json | 4 ++++
webview-ui/src/i18n/locales/zh-TW/settings.json | 4 ++++
17 files changed, 68 insertions(+)
diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json
index 4bd1b8ef33d..901734c181b 100644
--- a/webview-ui/src/i18n/locales/ca/settings.json
+++ b/webview-ui/src/i18n/locales/ca/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Passar la clau API d'Anthropic com a capçalera d'autorització en lloc de X-Api-Key",
"anthropic1MContextBetaLabel": "Activa la finestra de context d'1M (Beta)",
"anthropic1MContextBetaDescription": "Amplia la finestra de context a 1 milió de tokens per a Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Activa l'eina Advisor (Beta)",
+ "anthropicAdvisorModelLabel": "Model Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Usos Màxims",
+ "anthropicAdvisorMaxUsesPlaceholder": "Sense límit",
"awsBedrock1MContextBetaLabel": "Activa la finestra de context d'1M (Beta)",
"awsBedrock1MContextBetaDescription": "Amplia la finestra de context a 1 milió de tokens per a Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Activa la finestra de context d'1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json
index c524ffb4627..76d845e2ddb 100644
--- a/webview-ui/src/i18n/locales/de/settings.json
+++ b/webview-ui/src/i18n/locales/de/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Anthropic API-Schlüssel als Authorization-Header anstelle von X-Api-Key übergeben",
"anthropic1MContextBetaLabel": "1M Kontextfenster aktivieren (Beta)",
"anthropic1MContextBetaDescription": "Erweitert das Kontextfenster für Claude Sonnet 4.x / Claude Opus 4.6 auf 1 Million Token",
+ "anthropicAdvisorToolLabel": "Advisor-Tool aktivieren (Beta)",
+ "anthropicAdvisorModelLabel": "Advisor-Modell",
+ "anthropicAdvisorMaxUsesLabel": "Maximale Nutzungen",
+ "anthropicAdvisorMaxUsesPlaceholder": "Unbegrenzt",
"awsBedrock1MContextBetaLabel": "1M Kontextfenster aktivieren (Beta)",
"awsBedrock1MContextBetaDescription": "Erweitert das Kontextfenster für Claude Sonnet 4.x / Claude Opus 4.6 auf 1 Million Token",
"vertex1MContextBetaLabel": "1M Kontextfenster aktivieren (Beta)",
diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json
index dc2634b7186..88f0384b62b 100644
--- a/webview-ui/src/i18n/locales/es/settings.json
+++ b/webview-ui/src/i18n/locales/es/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Pasar la clave API de Anthropic como encabezado de autorización en lugar de X-Api-Key",
"anthropic1MContextBetaLabel": "Habilitar ventana de contexto de 1M (Beta)",
"anthropic1MContextBetaDescription": "Amplía la ventana de contexto a 1 millón de tokens para Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Habilitar herramienta Advisor (Beta)",
+ "anthropicAdvisorModelLabel": "Modelo Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Usos Máximos",
+ "anthropicAdvisorMaxUsesPlaceholder": "Sin límite",
"awsBedrock1MContextBetaLabel": "Habilitar ventana de contexto de 1M (Beta)",
"awsBedrock1MContextBetaDescription": "Amplía la ventana de contexto a 1 millón de tokens para Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Habilitar ventana de contexto de 1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json
index ceed03755ce..8e236903500 100644
--- a/webview-ui/src/i18n/locales/fr/settings.json
+++ b/webview-ui/src/i18n/locales/fr/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Passer la clé API Anthropic comme en-tête d'autorisation au lieu de X-Api-Key",
"anthropic1MContextBetaLabel": "Activer la fenêtre de contexte de 1M (Bêta)",
"anthropic1MContextBetaDescription": "Étend la fenêtre de contexte à 1 million de tokens pour Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Activer l'outil Advisor (Bêta)",
+ "anthropicAdvisorModelLabel": "Modèle Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Utilisations Maximales",
+ "anthropicAdvisorMaxUsesPlaceholder": "Illimité",
"awsBedrock1MContextBetaLabel": "Activer la fenêtre de contexte de 1M (Bêta)",
"awsBedrock1MContextBetaDescription": "Étend la fenêtre de contexte à 1 million de tokens pour Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Activer la fenêtre de contexte de 1M (Bêta)",
diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json
index a9e778e4a7d..41d7bb403b8 100644
--- a/webview-ui/src/i18n/locales/hi/settings.json
+++ b/webview-ui/src/i18n/locales/hi/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "X-Api-Key के बजाय Anthropic API कुंजी को Authorization हेडर के रूप में पास करें",
"anthropic1MContextBetaLabel": "1M संदर्भ विंडो सक्षम करें (बीटा)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6 के लिए संदर्भ विंडो को 1 मिलियन टोकन तक बढ़ाता है",
+ "anthropicAdvisorToolLabel": "Advisor Tool सक्षम करें (Beta)",
+ "anthropicAdvisorModelLabel": "Advisor मॉडल",
+ "anthropicAdvisorMaxUsesLabel": "अधिकतम उपयोग",
+ "anthropicAdvisorMaxUsesPlaceholder": "कोई सीमा नहीं",
"awsBedrock1MContextBetaLabel": "1M संदर्भ विंडो सक्षम करें (बीटा)",
"awsBedrock1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6 के लिए संदर्भ विंडो को 1 मिलियन टोकन तक बढ़ाता है",
"vertex1MContextBetaLabel": "1M संदर्भ विंडो सक्षम करें (बीटा)",
diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json
index 36c0f6799f4..badeeece121 100644
--- a/webview-ui/src/i18n/locales/id/settings.json
+++ b/webview-ui/src/i18n/locales/id/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Kirim Anthropic API Key sebagai Authorization header alih-alih X-Api-Key",
"anthropic1MContextBetaLabel": "Aktifkan jendela konteks 1M (Beta)",
"anthropic1MContextBetaDescription": "Memperluas jendela konteks menjadi 1 juta token untuk Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Aktifkan Advisor Tool (Beta)",
+ "anthropicAdvisorModelLabel": "Model Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Penggunaan Maksimal",
+ "anthropicAdvisorMaxUsesPlaceholder": "Tanpa batas",
"awsBedrock1MContextBetaLabel": "Aktifkan jendela konteks 1M (Beta)",
"awsBedrock1MContextBetaDescription": "Memperluas jendela konteks menjadi 1 juta token untuk Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Aktifkan jendela konteks 1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json
index 970752b16b4..fa5bfa44c48 100644
--- a/webview-ui/src/i18n/locales/it/settings.json
+++ b/webview-ui/src/i18n/locales/it/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Passa la chiave API Anthropic come header di autorizzazione invece di X-Api-Key",
"anthropic1MContextBetaLabel": "Abilita finestra di contesto da 1M (Beta)",
"anthropic1MContextBetaDescription": "Estende la finestra di contesto a 1 milione di token per Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Abilita Advisor Tool (Beta)",
+ "anthropicAdvisorModelLabel": "Modello Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Utilizzi Massimi",
+ "anthropicAdvisorMaxUsesPlaceholder": "Senza limite",
"awsBedrock1MContextBetaLabel": "Abilita finestra di contesto da 1M (Beta)",
"awsBedrock1MContextBetaDescription": "Estende la finestra di contesto a 1 milione di token per Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Abilita finestra di contesto da 1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json
index 1b2a125600e..353871fe881 100644
--- a/webview-ui/src/i18n/locales/ja/settings.json
+++ b/webview-ui/src/i18n/locales/ja/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Anthropic APIキーをX-Api-Keyの代わりにAuthorizationヘッダーとして渡す",
"anthropic1MContextBetaLabel": "1Mコンテキストウィンドウを有効にする(ベータ版)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6のコンテキストウィンドウを100万トークンに拡張します",
+ "anthropicAdvisorToolLabel": "Advisor ツールを有効にする (ベータ版)",
+ "anthropicAdvisorModelLabel": "Advisor モデル",
+ "anthropicAdvisorMaxUsesLabel": "最大使用回数",
+ "anthropicAdvisorMaxUsesPlaceholder": "無制限",
"awsBedrock1MContextBetaLabel": "1Mコンテキストウィンドウを有効にする(ベータ版)",
"awsBedrock1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6のコンテキストウィンドウを100万トークンに拡張します",
"vertex1MContextBetaLabel": "1Mコンテキストウィンドウを有効にする(ベータ版)",
diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json
index e35ab51e3b9..2b09fbeb517 100644
--- a/webview-ui/src/i18n/locales/ko/settings.json
+++ b/webview-ui/src/i18n/locales/ko/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "X-Api-Key 대신 Authorization 헤더로 Anthropic API 키 전달",
"anthropic1MContextBetaLabel": "1M 컨텍스트 창 활성화 (베타)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6의 컨텍스트 창을 100만 토큰으로 확장",
+ "anthropicAdvisorToolLabel": "Advisor 도구 활성화 (베타)",
+ "anthropicAdvisorModelLabel": "Advisor 모델",
+ "anthropicAdvisorMaxUsesLabel": "최대 사용 횟수",
+ "anthropicAdvisorMaxUsesPlaceholder": "제한 없음",
"awsBedrock1MContextBetaLabel": "1M 컨텍스트 창 활성화 (베타)",
"awsBedrock1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6의 컨텍스트 창을 100만 토큰으로 확장",
"vertex1MContextBetaLabel": "1M 컨텍스트 창 활성화 (베타)",
diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json
index 9ec6a91df90..b9f83b626e7 100644
--- a/webview-ui/src/i18n/locales/nl/settings.json
+++ b/webview-ui/src/i18n/locales/nl/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Anthropic API-sleutel als Authorization-header doorgeven in plaats van X-Api-Key",
"anthropic1MContextBetaLabel": "1M contextvenster inschakelen (bèta)",
"anthropic1MContextBetaDescription": "Breidt het contextvenster uit tot 1 miljoen tokens voor Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Advisor Tool inschakelen (bèta)",
+ "anthropicAdvisorModelLabel": "Advisor Model",
+ "anthropicAdvisorMaxUsesLabel": "Maximale Toepassingen",
+ "anthropicAdvisorMaxUsesPlaceholder": "Onbeperkt",
"awsBedrock1MContextBetaLabel": "1M contextvenster inschakelen (bèta)",
"awsBedrock1MContextBetaDescription": "Breidt het contextvenster uit tot 1 miljoen tokens voor Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "1M contextvenster inschakelen (bèta)",
diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json
index 45570384f1c..754fa4b00a1 100644
--- a/webview-ui/src/i18n/locales/pl/settings.json
+++ b/webview-ui/src/i18n/locales/pl/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Przekaż klucz API Anthropic jako nagłówek Authorization zamiast X-Api-Key",
"anthropic1MContextBetaLabel": "Włącz okno kontekstowe 1M (Beta)",
"anthropic1MContextBetaDescription": "Rozszerza okno kontekstowe do 1 miliona tokenów dla Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Włącz narzędzie Advisor (Beta)",
+ "anthropicAdvisorModelLabel": "Model Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Maksymalne Użycia",
+ "anthropicAdvisorMaxUsesPlaceholder": "Bez limitu",
"awsBedrock1MContextBetaLabel": "Włącz okno kontekstowe 1M (Beta)",
"awsBedrock1MContextBetaDescription": "Rozszerza okno kontekstowe do 1 miliona tokenów dla Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Włącz okno kontekstowe 1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json
index cebf1c5cd23..5d392bf9fe2 100644
--- a/webview-ui/src/i18n/locales/pt-BR/settings.json
+++ b/webview-ui/src/i18n/locales/pt-BR/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Passar a chave de API Anthropic como cabeçalho Authorization em vez de X-Api-Key",
"anthropic1MContextBetaLabel": "Ativar janela de contexto de 1M (Beta)",
"anthropic1MContextBetaDescription": "Estende a janela de contexto para 1 milhão de tokens para o Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Ativar Advisor Tool (Beta)",
+ "anthropicAdvisorModelLabel": "Modelo Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Usos Máximos",
+ "anthropicAdvisorMaxUsesPlaceholder": "Sem limite",
"awsBedrock1MContextBetaLabel": "Ativar janela de contexto de 1M (Beta)",
"awsBedrock1MContextBetaDescription": "Estende a janela de contexto para 1 milhão de tokens para o Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Ativar janela de contexto de 1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json
index 698ae4c4038..93d81dce925 100644
--- a/webview-ui/src/i18n/locales/ru/settings.json
+++ b/webview-ui/src/i18n/locales/ru/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Передавать Anthropic API-ключ как Authorization-заголовок вместо X-Api-Key",
"anthropic1MContextBetaLabel": "Включить контекстное окно 1M (бета)",
"anthropic1MContextBetaDescription": "Расширяет контекстное окно до 1 миллиона токенов для Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Включить инструмент Advisor (бета)",
+ "anthropicAdvisorModelLabel": "Модель Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Максимум использований",
+ "anthropicAdvisorMaxUsesPlaceholder": "Без ограничений",
"awsBedrock1MContextBetaLabel": "Включить контекстное окно 1M (бета)",
"awsBedrock1MContextBetaDescription": "Расширяет контекстное окно до 1 миллиона токенов для Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Включить контекстное окно 1M (бета)",
diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json
index 55ba2ece655..2bee477f005 100644
--- a/webview-ui/src/i18n/locales/tr/settings.json
+++ b/webview-ui/src/i18n/locales/tr/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Anthropic API Anahtarını X-Api-Key yerine Authorization başlığı olarak geçir",
"anthropic1MContextBetaLabel": "1M bağlam penceresini etkinleştir (Beta)",
"anthropic1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6 için bağlam penceresini 1 milyon token'a genişletir",
+ "anthropicAdvisorToolLabel": "Advisor Aracını Etkinleştir (Beta)",
+ "anthropicAdvisorModelLabel": "Advisor Modeli",
+ "anthropicAdvisorMaxUsesLabel": "Maksimum Kullanım",
+ "anthropicAdvisorMaxUsesPlaceholder": "Sınır Yok",
"awsBedrock1MContextBetaLabel": "1M bağlam penceresini etkinleştir (Beta)",
"awsBedrock1MContextBetaDescription": "Claude Sonnet 4.x / Claude Opus 4.6 için bağlam penceresini 1 milyon token'a genişletir",
"vertex1MContextBetaLabel": "1M bağlam penceresini etkinleştir (Beta)",
diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json
index 9d77fbc5705..3422d5221ee 100644
--- a/webview-ui/src/i18n/locales/vi/settings.json
+++ b/webview-ui/src/i18n/locales/vi/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "Truyền khóa API Anthropic dưới dạng tiêu đề Authorization thay vì X-Api-Key",
"anthropic1MContextBetaLabel": "Bật cửa sổ ngữ cảnh 1M (Beta)",
"anthropic1MContextBetaDescription": "Mở rộng cửa sổ ngữ cảnh lên 1 triệu token cho Claude Sonnet 4.x / Claude Opus 4.6",
+ "anthropicAdvisorToolLabel": "Bật Advisor Tool (Beta)",
+ "anthropicAdvisorModelLabel": "Mô hình Advisor",
+ "anthropicAdvisorMaxUsesLabel": "Tối đa Sử dụng",
+ "anthropicAdvisorMaxUsesPlaceholder": "Không giới hạn",
"awsBedrock1MContextBetaLabel": "Bật cửa sổ ngữ cảnh 1M (Beta)",
"awsBedrock1MContextBetaDescription": "Mở rộng cửa sổ ngữ cảnh lên 1 triệu token cho Claude Sonnet 4.x / Claude Opus 4.6",
"vertex1MContextBetaLabel": "Bật cửa sổ ngữ cảnh 1M (Beta)",
diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json
index fea5dcc684c..591fdb4ec1a 100644
--- a/webview-ui/src/i18n/locales/zh-CN/settings.json
+++ b/webview-ui/src/i18n/locales/zh-CN/settings.json
@@ -374,6 +374,10 @@
"anthropicUseAuthToken": "将 Anthropic API 密钥作为 Authorization 标头传递,而不是 X-Api-Key",
"anthropic1MContextBetaLabel": "启用 1M 上下文窗口 (Beta)",
"anthropic1MContextBetaDescription": "为 Claude Sonnet 4.x / Claude Opus 4.6 将上下文窗口扩展至 100 万个 token",
+ "anthropicAdvisorToolLabel": "启用 Advisor 工具 (测试版)",
+ "anthropicAdvisorModelLabel": "Advisor 模型",
+ "anthropicAdvisorMaxUsesLabel": "最大使用次数",
+ "anthropicAdvisorMaxUsesPlaceholder": "无限制",
"awsBedrock1MContextBetaLabel": "启用 1M 上下文窗口 (Beta)",
"awsBedrock1MContextBetaDescription": "为 Claude Sonnet 4.x / Claude Opus 4.6 将上下文窗口扩展至 100 万个 token",
"vertex1MContextBetaLabel": "启用 1M 上下文窗口 (Beta)",
diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json
index 1a306043a36..957837cbc9e 100644
--- a/webview-ui/src/i18n/locales/zh-TW/settings.json
+++ b/webview-ui/src/i18n/locales/zh-TW/settings.json
@@ -384,6 +384,10 @@
"anthropicUseAuthToken": "將 Anthropic API 金鑰作為 Authorization 標頭傳遞,而非使用 X-Api-Key",
"anthropic1MContextBetaLabel": "啟用 1M 上下文視窗 (Beta)",
"anthropic1MContextBetaDescription": "為 Claude Sonnet 4.x / Claude Opus 4.6 將上下文視窗擴展至 100 萬個 token",
+ "anthropicAdvisorToolLabel": "啟用 Advisor 工具 (測試版)",
+ "anthropicAdvisorModelLabel": "Advisor 模型",
+ "anthropicAdvisorMaxUsesLabel": "最大使用次數",
+ "anthropicAdvisorMaxUsesPlaceholder": "無限制",
"awsBedrock1MContextBetaLabel": "啟用 1M 上下文視窗 (Beta)",
"awsBedrock1MContextBetaDescription": "為 Claude Sonnet 4.x / Claude Opus 4.6 將上下文視窗擴展至 100 萬個 token",
"vertex1MContextBetaLabel": "啟用 1M 上下文視窗 (Beta)",
From 77050ab90e3ddb4cdf6963024d0c77767cc0b805 Mon Sep 17 00:00:00 2001
From: TDFSE <77169190+TDFSE@users.noreply.github.com>
Date: Sat, 11 Apr 2026 00:31:48 -0400
Subject: [PATCH 4/4] Add call/response to chat
---
packages/types/src/message.ts | 2 +
packages/types/src/vscode-extension-host.ts | 6 +
src/api/providers/__tests__/anthropic.spec.ts | 146 ++++++++++++++++++
src/api/providers/anthropic.ts | 59 ++++++-
src/api/transform/stream.ts | 18 +++
src/core/task/Task.ts | 55 ++++++-
webview-ui/src/components/chat/ChatRow.tsx | 25 +++
.../__tests__/ChatRow.advisor-tool.spec.tsx | 128 +++++++++++++++
webview-ui/src/i18n/locales/ca/chat.json | 4 +
webview-ui/src/i18n/locales/de/chat.json | 4 +
webview-ui/src/i18n/locales/en/chat.json | 4 +
webview-ui/src/i18n/locales/es/chat.json | 4 +
webview-ui/src/i18n/locales/fr/chat.json | 4 +
webview-ui/src/i18n/locales/hi/chat.json | 4 +
webview-ui/src/i18n/locales/id/chat.json | 4 +
webview-ui/src/i18n/locales/it/chat.json | 4 +
webview-ui/src/i18n/locales/ja/chat.json | 4 +
webview-ui/src/i18n/locales/ko/chat.json | 4 +
webview-ui/src/i18n/locales/nl/chat.json | 4 +
webview-ui/src/i18n/locales/pl/chat.json | 4 +
webview-ui/src/i18n/locales/pt-BR/chat.json | 4 +
webview-ui/src/i18n/locales/ru/chat.json | 4 +
webview-ui/src/i18n/locales/tr/chat.json | 4 +
webview-ui/src/i18n/locales/vi/chat.json | 4 +
webview-ui/src/i18n/locales/zh-CN/chat.json | 4 +
webview-ui/src/i18n/locales/zh-TW/chat.json | 4 +
26 files changed, 503 insertions(+), 8 deletions(-)
create mode 100644 webview-ui/src/components/chat/__tests__/ChatRow.advisor-tool.spec.tsx
diff --git a/packages/types/src/message.ts b/packages/types/src/message.ts
index e518972a1c2..4b2aa0c2809 100644
--- a/packages/types/src/message.ts
+++ b/packages/types/src/message.ts
@@ -170,6 +170,8 @@ export const clineSays = [
"user_edit_todos",
"too_many_tools_warning",
"tool",
+ "use_advisor_tool",
+ "advisor_tool_result",
] as const
export const clineSaySchema = z.enum(clineSays)
diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts
index b20539afe49..e5ecedb72ea 100644
--- a/packages/types/src/vscode-extension-host.ts
+++ b/packages/types/src/vscode-extension-host.ts
@@ -842,6 +842,12 @@ export interface ClineSayTool {
skill?: string
}
+export interface ClineAskUseAdvisorTool {
+ toolUseId: string
+ name: string
+ input: string // JSON-serialized input
+}
+
export interface ClineAskUseMcpServer {
serverName: string
type: "use_mcp_tool" | "access_mcp_resource"
diff --git a/src/api/providers/__tests__/anthropic.spec.ts b/src/api/providers/__tests__/anthropic.spec.ts
index 7dbad50dcd7..269b66a561d 100644
--- a/src/api/providers/__tests__/anthropic.spec.ts
+++ b/src/api/providers/__tests__/anthropic.spec.ts
@@ -922,5 +922,151 @@ describe("AnthropicHandler", () => {
arguments: '"London"}',
})
})
+
+ it("should emit advisor_tool_use chunk with id from server_tool_use block", async () => {
+ mockCreate.mockImplementationOnce(async () => ({
+ async *[Symbol.asyncIterator]() {
+ yield {
+ type: "message_start",
+ message: { usage: { input_tokens: 100, output_tokens: 50 } },
+ }
+ yield {
+ type: "content_block_start",
+ index: 0,
+ content_block: {
+ type: "server_tool_use",
+ id: "srvtoolu_abc123",
+ name: "advisor",
+ input: {},
+ },
+ }
+ },
+ }))
+
+ const stream = handler.createMessage("system", [{ role: "user", content: "Hello" }], {
+ taskId: "test-task",
+ })
+
+ const chunks: any[] = []
+ for await (const chunk of stream) {
+ chunks.push(chunk)
+ }
+
+ const advisorUseChunk = chunks.find((c) => c.type === "advisor_tool_use")
+ expect(advisorUseChunk).toBeDefined()
+ expect(advisorUseChunk.id).toBe("srvtoolu_abc123")
+ expect(advisorUseChunk.name).toBe("advisor")
+ })
+
+ it("should emit advisor_tool_result chunk with tool_use_id and text content", async () => {
+ mockCreate.mockImplementationOnce(async () => ({
+ async *[Symbol.asyncIterator]() {
+ yield {
+ type: "message_start",
+ message: { usage: { input_tokens: 100, output_tokens: 50 } },
+ }
+ yield {
+ type: "content_block_start",
+ index: 1,
+ content_block: {
+ type: "advisor_tool_result",
+ tool_use_id: "srvtoolu_abc123",
+ content: { type: "advisor_result", text: "Use channel-based coordination." },
+ },
+ }
+ },
+ }))
+
+ const stream = handler.createMessage("system", [{ role: "user", content: "Hello" }], {
+ taskId: "test-task",
+ })
+
+ const chunks: any[] = []
+ for await (const chunk of stream) {
+ chunks.push(chunk)
+ }
+
+ const resultChunk = chunks.find((c) => c.type === "advisor_tool_result")
+ expect(resultChunk).toBeDefined()
+ expect(resultChunk.tool_use_id).toBe("srvtoolu_abc123")
+ expect(resultChunk.content).toBe("Use channel-based coordination.")
+ // rawContent must carry the verbatim object for round-tripping to the API
+ expect(resultChunk.rawContent).toEqual({ type: "advisor_result", text: "Use channel-based coordination." })
+ })
+
+ it("should extract text from advisor_result object content shape", async () => {
+ mockCreate.mockImplementationOnce(async () => ({
+ async *[Symbol.asyncIterator]() {
+ yield {
+ type: "message_start",
+ message: { usage: { input_tokens: 100, output_tokens: 50 } },
+ }
+ yield {
+ type: "content_block_start",
+ index: 0,
+ content_block: {
+ type: "advisor_tool_result",
+ tool_use_id: "srvtoolu_xyz",
+ content: { type: "advisor_result", text: "Plan: do X then Y." },
+ },
+ }
+ },
+ }))
+
+ const stream = handler.createMessage("system", [{ role: "user", content: "Plan?" }], {
+ taskId: "test-task",
+ })
+
+ const chunks: any[] = []
+ for await (const chunk of stream) {
+ chunks.push(chunk)
+ }
+
+ const resultChunk = chunks.find((c) => c.type === "advisor_tool_result")
+ expect(resultChunk).toBeDefined()
+ expect(resultChunk.content).toBe("Plan: do X then Y.")
+ // rawContent must be the verbatim object, not just the extracted text
+ expect(resultChunk.rawContent).toEqual({ type: "advisor_result", text: "Plan: do X then Y." })
+ })
+
+ it("should emit empty string for encrypted advisor_redacted_result content", async () => {
+ mockCreate.mockImplementationOnce(async () => ({
+ async *[Symbol.asyncIterator]() {
+ yield {
+ type: "message_start",
+ message: { usage: { input_tokens: 100, output_tokens: 50 } },
+ }
+ yield {
+ type: "content_block_start",
+ index: 0,
+ content_block: {
+ type: "advisor_tool_result",
+ tool_use_id: "srvtoolu_redacted",
+ content: { type: "advisor_redacted_result", encrypted_content: "opaque-blob" },
+ },
+ }
+ },
+ }))
+
+ const stream = handler.createMessage("system", [{ role: "user", content: "Plan?" }], {
+ taskId: "test-task",
+ })
+
+ const chunks: any[] = []
+ for await (const chunk of stream) {
+ chunks.push(chunk)
+ }
+
+ const resultChunk = chunks.find((c) => c.type === "advisor_tool_result")
+ expect(resultChunk).toBeDefined()
+ expect(resultChunk.tool_use_id).toBe("srvtoolu_redacted")
+ // Encrypted content has no text field — content should be empty string
+ expect(resultChunk.content).toBe("")
+ // rawContent must carry the verbatim encrypted object for round-tripping
+ expect(resultChunk.rawContent).toEqual({
+ type: "advisor_redacted_result",
+ encrypted_content: "opaque-blob",
+ })
+ })
})
})
diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts
index 010d0df38d0..009fbc11452 100644
--- a/src/api/providers/anthropic.ts
+++ b/src/api/providers/anthropic.ts
@@ -272,8 +272,9 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
case "message_stop":
// No usage data, just an indicator that the message is done.
break
- case "content_block_start":
- switch (chunk.content_block.type) {
+ case "content_block_start": {
+ const contentBlock = chunk.content_block as any
+ switch (contentBlock.type) {
case "thinking":
// We may receive multiple text blocks, in which
// case just insert a line break between them.
@@ -281,7 +282,7 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
yield { type: "reasoning", text: "\n" }
}
- yield { type: "reasoning", text: chunk.content_block.thinking }
+ yield { type: "reasoning", text: contentBlock.thinking }
break
case "text":
// We may receive multiple text blocks, in which
@@ -290,21 +291,67 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
yield { type: "text", text: "\n" }
}
- yield { type: "text", text: chunk.content_block.text }
+ yield { type: "text", text: contentBlock.text }
break
case "tool_use": {
// Emit initial tool call partial with id and name
yield {
type: "tool_call_partial",
index: chunk.index,
- id: chunk.content_block.id,
- name: chunk.content_block.name,
+ id: contentBlock.id,
+ name: contentBlock.name,
arguments: undefined,
}
break
}
+ case "server_tool_use": {
+ const { id, name, input } = contentBlock
+ yield {
+ type: "advisor_tool_use",
+ id,
+ name,
+ input: typeof input === "object" ? JSON.stringify(input) : String(input ?? "{}"),
+ }
+ break
+ }
+ case "advisor_tool_result": {
+ const block = contentBlock as {
+ type: "advisor_tool_result"
+ tool_use_id: string
+ content:
+ | string
+ | { type: string; text?: string }
+ | Array<{ type: string; text?: string }>
+ | undefined
+ }
+ const rawContent = block.content
+ let text: string
+ if (typeof rawContent === "string") {
+ text = rawContent
+ } else if (Array.isArray(rawContent)) {
+ text = rawContent
+ .filter((b) => b.type === "text")
+ .map((b) => b.text ?? "")
+ .join("\n")
+ } else if (rawContent && typeof rawContent === "object" && "text" in rawContent) {
+ // advisor_result shape: { type: "advisor_result", text: "..." }
+ text = (rawContent as { text?: string }).text ?? ""
+ } else {
+ text = ""
+ }
+ yield {
+ type: "advisor_tool_result",
+ tool_use_id: block.tool_use_id,
+ content: text,
+ // Pass through the verbatim content object so it can be
+ // round-tripped on subsequent turns as the Anthropic API requires.
+ rawContent: rawContent,
+ }
+ break
+ }
}
break
+ }
case "content_block_delta":
switch (chunk.delta.type) {
case "thinking_delta":
diff --git a/src/api/transform/stream.ts b/src/api/transform/stream.ts
index 960ebbe770d..daa37fbcdc6 100644
--- a/src/api/transform/stream.ts
+++ b/src/api/transform/stream.ts
@@ -11,6 +11,8 @@ export type ApiStreamChunk =
| ApiStreamToolCallDeltaChunk
| ApiStreamToolCallEndChunk
| ApiStreamToolCallPartialChunk
+ | ApiStreamAdvisorToolUseChunk
+ | ApiStreamAdvisorToolResultChunk
| ApiStreamError
export interface ApiStreamError {
@@ -107,6 +109,22 @@ export interface ApiStreamToolCallPartialChunk {
arguments?: string
}
+export interface ApiStreamAdvisorToolUseChunk {
+ type: "advisor_tool_use"
+ id: string
+ name: string
+ input: string // JSON-serialized
+}
+
+export interface ApiStreamAdvisorToolResultChunk {
+ type: "advisor_tool_result"
+ tool_use_id: string
+ /** Extracted text for display purposes */
+ content: string
+ /** Verbatim original content object from the API, for round-tripping on subsequent turns */
+ rawContent: unknown
+}
+
export interface GroundingSource {
title: string
url: string
diff --git a/src/core/task/Task.ts b/src/core/task/Task.ts
index 005bb0f292b..94d3f2d28d6 100644
--- a/src/core/task/Task.ts
+++ b/src/core/task/Task.ts
@@ -35,6 +35,7 @@ import {
type ModelInfo,
type ClineApiReqCancelReason,
type ClineApiReqInfo,
+ type ClineAskUseAdvisorTool,
RooCodeEventName,
TelemetryEventName,
TaskStatus,
@@ -2792,6 +2793,18 @@ export class Task extends EventEmitter implements TaskLike {
let assistantMessage = ""
let reasoningMessage = ""
let pendingGroundingSources: GroundingSource[] = []
+ let hasAdvisorEvents = false
+ // Accumulate advisor blocks in arrival order so they can be saved to API history.
+ // Anthropic requires the full assistant content (including server_tool_use /
+ // advisor_tool_result blocks) to be round-tripped on subsequent turns.
+ const pendingAdvisorBlocks: Array<{
+ type: "server_tool_use" | "advisor_tool_result"
+ id?: string
+ name?: string
+ input?: Record
+ tool_use_id?: string
+ content?: unknown
+ }> = []
this.isStreaming = true
try {
@@ -3014,6 +3027,37 @@ export class Task extends EventEmitter implements TaskLike {
presentAssistantMessage(this)
break
}
+ case "advisor_tool_use": {
+ hasAdvisorEvents = true
+ pendingAdvisorBlocks.push({
+ type: "server_tool_use",
+ id: chunk.id,
+ name: chunk.name,
+ input:
+ typeof chunk.input === "string" ? {} : (chunk.input as Record),
+ })
+ const payload: ClineAskUseAdvisorTool = {
+ toolUseId: chunk.id,
+ name: chunk.name,
+ input: chunk.input,
+ }
+ await this.say("use_advisor_tool", JSON.stringify(payload))
+ break
+ }
+ case "advisor_tool_result": {
+ hasAdvisorEvents = true
+ pendingAdvisorBlocks.push({
+ type: "advisor_tool_result",
+ tool_use_id: chunk.tool_use_id,
+ // Use rawContent (the verbatim original object from the API) for
+ // round-tripping to Anthropic. The API requires content to be the
+ // original discriminated union object (e.g. { type: "advisor_result", text: "..." })
+ // not a plain string. chunk.content is the extracted text for display only.
+ content: chunk.rawContent,
+ })
+ await this.say("advisor_tool_result", chunk.content)
+ break
+ }
case "text": {
assistantMessage += chunk.text
@@ -3410,14 +3454,14 @@ export class Task extends EventEmitter implements TaskLike {
// the assistant message is already in history. Otherwise, tool_result blocks would appear
// BEFORE their corresponding tool_use blocks, causing API errors.
- // Check if we have any content to process (text or tool uses)
+ // Check if we have any content to process (text, tool uses, or advisor interactions)
const hasTextContent = assistantMessage.length > 0
const hasToolUses = this.assistantMessageContent.some(
(block) => block.type === "tool_use" || block.type === "mcp_tool_use",
)
- if (hasTextContent || hasToolUses) {
+ if (hasTextContent || hasToolUses || hasAdvisorEvents) {
// Reset counter when we get a successful response with content
this.consecutiveNoAssistantMessagesCount = 0
// Display grounding sources to the user if they exist
@@ -3505,6 +3549,13 @@ export class Task extends EventEmitter implements TaskLike {
}
}
+ // Append advisor blocks (server_tool_use / advisor_tool_result) that arrived during
+ // this stream. The Anthropic API requires these to be round-tripped verbatim on
+ // subsequent turns; omitting them causes a 400 invalid_request_error.
+ for (const advisorBlock of pendingAdvisorBlocks) {
+ assistantContent.push(advisorBlock as unknown as Anthropic.ToolUseBlockParam)
+ }
+
// Enforce new_task isolation: if new_task is called alongside other tools,
// truncate any tools that come after it and inject error tool_results.
// This prevents orphaned tools when delegation disposes the parent task.
diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx
index 1f3f8f5a4f2..9fa9dcaa0e5 100644
--- a/webview-ui/src/components/chat/ChatRow.tsx
+++ b/webview-ui/src/components/chat/ChatRow.tsx
@@ -263,6 +263,8 @@ export const ChatRowContent = ({
const isMcpServerResponding = isLast && lastModifiedMessage?.say === "mcp_server_request_started"
+ const isAdvisorResponding = isLast && message.say === "use_advisor_tool"
+
const type = message.type === "ask" ? message.ask : message.say
const normalColor = "var(--vscode-foreground)"
@@ -1040,6 +1042,29 @@ export const ChatRowContent = ({
)}
)
+ case "use_advisor_tool":
+ return (
+
+ {isAdvisorResponding ? (
+
+ ) : (
+
+ )}
+
{t("chat:advisor.isConsulting")}
+
+ )
+ case "advisor_tool_result":
+ return (
+
+
+
+ {t("chat:advisor.resultLabel")}
+
+
+
+
+
+ )
case "reasoning":
return (
({
+ useTranslation: () => ({
+ t: (key: string) => {
+ const map: Record = {
+ "chat:advisor.isConsulting": "Consulting advisor...",
+ "chat:advisor.resultLabel": "Advisor response",
+ }
+ return map[key] || key
+ },
+ }),
+ Trans: ({ children }: { children?: React.ReactNode }) => <>{children}>,
+ initReactI18next: { type: "3rdParty", init: () => {} },
+}))
+
+// Mock CodeBlock (avoid ESM/highlighter costs)
+vi.mock("@src/components/common/CodeBlock", () => ({
+ default: () => null,
+}))
+
+// Mock VSCodeBadge
+vi.mock("@vscode/webview-ui-toolkit/react", () => ({
+ VSCodeBadge: ({ children, ...props }: { children: React.ReactNode }) => {children} ,
+}))
+
+const queryClient = new QueryClient()
+
+function renderChatRow(message: ClineMessage, isLast = false) {
+ return render(
+
+
+ {}}
+ onSuggestionClick={() => {}}
+ onBatchFileResponse={() => {}}
+ onFollowUpUnmount={() => {}}
+ isFollowUpAnswered={false}
+ />
+
+ ,
+ )
+}
+
+describe("ChatRow - advisor tool messages", () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ it("renders use_advisor_tool as a single header line with no badge", () => {
+ const message: ClineMessage = {
+ type: "say",
+ say: "use_advisor_tool",
+ ts: Date.now(),
+ partial: false,
+ text: JSON.stringify({
+ toolUseId: "tool-1",
+ name: "advisor",
+ input: "{}",
+ }),
+ }
+
+ renderChatRow(message)
+
+ expect(screen.getByText("Consulting advisor...")).toBeInTheDocument()
+ // No badge rendered — the "advisor" text should NOT appear
+ expect(screen.queryByText("advisor")).not.toBeInTheDocument()
+ })
+
+ it("renders use_advisor_tool with non-empty input as a single header line (no input shown)", () => {
+ const message: ClineMessage = {
+ type: "say",
+ say: "use_advisor_tool",
+ ts: Date.now(),
+ partial: false,
+ text: JSON.stringify({
+ toolUseId: "tool-2",
+ name: "advisor",
+ input: '{"query":"review this function"}',
+ }),
+ }
+
+ renderChatRow(message)
+
+ expect(screen.getByText("Consulting advisor...")).toBeInTheDocument()
+ // Input text is NOT rendered in the simplified header-only view
+ expect(screen.queryByText('{"query":"review this function"}')).not.toBeInTheDocument()
+ })
+
+ it("renders advisor_tool_result with header and content box", () => {
+ const message: ClineMessage = {
+ type: "say",
+ say: "advisor_tool_result",
+ ts: Date.now(),
+ partial: false,
+ text: "The code looks good overall.",
+ }
+
+ renderChatRow(message)
+
+ expect(screen.getByText("Advisor response")).toBeInTheDocument()
+ })
+
+ it("renders use_advisor_tool header even with invalid JSON (no early return)", () => {
+ const message: ClineMessage = {
+ type: "say",
+ say: "use_advisor_tool",
+ ts: Date.now(),
+ partial: false,
+ text: "not-valid-json",
+ }
+
+ renderChatRow(message)
+
+ // Header still renders — no JSON parsing required in simplified view
+ expect(screen.getByText("Consulting advisor...")).toBeInTheDocument()
+ })
+})
diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json
index 57f0acecd0c..88aaeba9ffc 100644
--- a/webview-ui/src/i18n/locales/ca/chat.json
+++ b/webview-ui/src/i18n/locales/ca/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Afegeix el missatge a la cua (s'enviarà quan acabi la tasca actual)",
"scrollToBottom": "Desplaça't al final del xat",
"about": "Roo Code és tot un equip de desenvolupament d'IA al teu editor.",
+ "advisor": {
+ "isConsulting": "Consultant l'assessor...",
+ "resultLabel": "Resposta de l'assessor"
+ },
"docs": "Consulta els nostres documents per a més informació.",
"onboarding": "La teva llista de tasques en aquest espai de treball està buida.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json
index 727ec44c2d0..dd8aeff76ae 100644
--- a/webview-ui/src/i18n/locales/de/chat.json
+++ b/webview-ui/src/i18n/locales/de/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Nachricht zur Warteschlange hinzufügen (wird nach Abschluss der aktuellen Aufgabe gesendet)",
"scrollToBottom": "Zum Chat-Ende scrollen",
"about": "Roo Code ist ein ganzes KI-Entwicklerteam in deinem Editor.",
+ "advisor": {
+ "isConsulting": "Berater wird konsultiert...",
+ "resultLabel": "Berater-Antwort"
+ },
"docs": "Schau in unsere Dokumentation , um mehr zu erfahren.",
"onboarding": "Deine Aufgabenliste in diesem Arbeitsbereich ist leer.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json
index 81338ad7868..12514188bec 100644
--- a/webview-ui/src/i18n/locales/en/chat.json
+++ b/webview-ui/src/i18n/locales/en/chat.json
@@ -125,6 +125,10 @@
},
"scrollToBottom": "Scroll to bottom of chat",
"about": "Roo is a whole AI dev team in your editor",
+ "advisor": {
+ "isConsulting": "Consulting advisor...",
+ "resultLabel": "Advisor response"
+ },
"docs": "Check our docs to get started",
"onboarding": "What would you like to do?",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json
index 1aa49f74f02..d2589d431a3 100644
--- a/webview-ui/src/i18n/locales/es/chat.json
+++ b/webview-ui/src/i18n/locales/es/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Agregar mensaje a la cola (se enviará después de que termine la tarea actual)",
"scrollToBottom": "Desplazarse al final del chat",
"about": "Roo Code es todo un equipo de desarrollo de IA en tu editor.",
+ "advisor": {
+ "isConsulting": "Consultando asesor...",
+ "resultLabel": "Respuesta del asesor"
+ },
"docs": "Consulta nuestra documentación para saber más.",
"onboarding": "Tu lista de tareas en este espacio de trabajo está vacía.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json
index 316a8461999..0e74acc6dbe 100644
--- a/webview-ui/src/i18n/locales/fr/chat.json
+++ b/webview-ui/src/i18n/locales/fr/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Ajouter le message à la file d'attente (sera envoyé après la fin de la tâche en cours)",
"scrollToBottom": "Défiler jusqu'au bas du chat",
"about": "Roo Code est une équipe complète de développeurs IA dans votre éditeur.",
+ "advisor": {
+ "isConsulting": "Consultation du conseiller...",
+ "resultLabel": "Réponse du conseiller"
+ },
"docs": "Consultez notre documentation pour en savoir plus.",
"onboarding": "Votre liste de tâches dans cet espace de travail est vide.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json
index 410cd829add..dc31ed73f9b 100644
--- a/webview-ui/src/i18n/locales/hi/chat.json
+++ b/webview-ui/src/i18n/locales/hi/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "संदेश को कतार में जोड़ें (वर्तमान कार्य पूरा होने के बाद भेजा जाएगा)",
"scrollToBottom": "चैट के निचले हिस्से तक स्क्रॉल करें",
"about": "Roo Code आपके संपादक में एक पूरी AI देव टीम है।",
+ "advisor": {
+ "isConsulting": "सलाहकार से परामर्श...",
+ "resultLabel": "सलाहकार प्रतिक्रिया"
+ },
"docs": "और जानने के लिए हमारे दस्तावेज़ देखें।",
"onboarding": "इस कार्यक्षेत्र में आपकी कार्य सूची खाली है।",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json
index c499024e4c1..54ad312e1aa 100644
--- a/webview-ui/src/i18n/locales/id/chat.json
+++ b/webview-ui/src/i18n/locales/id/chat.json
@@ -128,6 +128,10 @@
"enqueueMessage": "Tambahkan pesan ke antrean (akan dikirim setelah tugas saat ini selesai)",
"scrollToBottom": "Gulir ke bawah chat",
"about": "Roo Code adalah seluruh tim pengembang AI di editor Anda.",
+ "advisor": {
+ "isConsulting": "Berkonsultasi dengan penasihat...",
+ "resultLabel": "Respons penasihat"
+ },
"docs": "Lihat dokumentasi kami untuk mempelajari lebih lanjut.",
"onboarding": "Daftar tugas Anda di ruang kerja ini kosong.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json
index 006ee09a892..9084524ff10 100644
--- a/webview-ui/src/i18n/locales/it/chat.json
+++ b/webview-ui/src/i18n/locales/it/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Aggiungi il messaggio alla coda (sarà inviato dopo che l'attività corrente sarà terminata)",
"scrollToBottom": "Scorri fino alla fine della chat",
"about": "Roo Code è un intero team di sviluppo AI nel tuo editor.",
+ "advisor": {
+ "isConsulting": "Consultazione del consulente...",
+ "resultLabel": "Risposta del consulente"
+ },
"docs": "Consulta la nostra documentazione per saperne di più.",
"onboarding": "La tua lista di attività in questo spazio di lavoro è vuota.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json
index d8bea631f39..6a6a7a14d56 100644
--- a/webview-ui/src/i18n/locales/ja/chat.json
+++ b/webview-ui/src/i18n/locales/ja/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "メッセージをキューに追加(現在のタスク完了後に送信されます)",
"scrollToBottom": "チャットの最下部にスクロール",
"about": "Roo Codeは、エディタに常駐するAI開発チームです。",
+ "advisor": {
+ "isConsulting": "アドバイザーに相談中...",
+ "resultLabel": "アドバイザーからの回答"
+ },
"docs": "詳細については、ドキュメント をご確認ください。",
"onboarding": "このワークスペースのタスクリストは空です。",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json
index c16ac36402c..c37a5f2ff12 100644
--- a/webview-ui/src/i18n/locales/ko/chat.json
+++ b/webview-ui/src/i18n/locales/ko/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "메시지를 대기열에 추가 (현재 작업 완료 후 전송)",
"scrollToBottom": "채팅 하단으로 스크롤",
"about": "Roo Code는 편집기 안에 있는 전체 AI 개발팀입니다.",
+ "advisor": {
+ "isConsulting": "자문가와 상담 중...",
+ "resultLabel": "자문가 응답"
+ },
"docs": "더 알아보려면 문서 를 확인하세요.",
"onboarding": "이 작업 공간의 작업 목록이 비어 있습니다.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json
index 19a128f29d9..f3d3a7c7a5f 100644
--- a/webview-ui/src/i18n/locales/nl/chat.json
+++ b/webview-ui/src/i18n/locales/nl/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Bericht aan de wachtrij toevoegen (wordt verzonden nadat de huidige taak is voltooid)",
"scrollToBottom": "Scroll naar onderaan de chat",
"about": "Roo Code is een heel AI-ontwikkelteam in je editor.",
+ "advisor": {
+ "isConsulting": "Raadpleging van adviseur...",
+ "resultLabel": "Antwoord van adviseur"
+ },
"docs": "Bekijk onze documentatie voor meer informatie.",
"onboarding": "Je takenlijst in deze werkruimte is leeg.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json
index efbb47dad61..fcfb7ce08ca 100644
--- a/webview-ui/src/i18n/locales/pl/chat.json
+++ b/webview-ui/src/i18n/locales/pl/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Dodaj wiadomość do kolejki (zostanie wysłana po zakończeniu bieżącego zadania)",
"scrollToBottom": "Przewiń do dołu czatu",
"about": "Roo Code to cały zespół deweloperów AI w Twoim edytorze.",
+ "advisor": {
+ "isConsulting": "Konsultowanie się z doradcą...",
+ "resultLabel": "Odpowiedź doradcy"
+ },
"docs": "Sprawdź naszą dokumentację , aby dowiedzieć się więcej.",
"onboarding": "Twoja lista zadań w tym obszarze roboczym jest pusta.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json
index 6db70b0342e..9805d3152e9 100644
--- a/webview-ui/src/i18n/locales/pt-BR/chat.json
+++ b/webview-ui/src/i18n/locales/pt-BR/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Adicionar mensagem à fila (será enviada após a conclusão da tarefa atual)",
"scrollToBottom": "Rolar para o final do chat",
"about": "Roo Code é uma equipe inteira de desenvolvimento de IA em seu editor.",
+ "advisor": {
+ "isConsulting": "Consultando conselheiro...",
+ "resultLabel": "Resposta do conselheiro"
+ },
"docs": "Confira nossa documentação para saber mais.",
"onboarding": "Sua lista de tarefas neste espaço de trabalho está vazia.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json
index 50864bff80b..746b73e47c7 100644
--- a/webview-ui/src/i18n/locales/ru/chat.json
+++ b/webview-ui/src/i18n/locales/ru/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Добавить сообщение в очередь (будет отправлено после завершения текущей задачи)",
"scrollToBottom": "Прокрутить чат вниз",
"about": "Roo Code — это целая команда разработчиков ИИ в вашем редакторе.",
+ "advisor": {
+ "isConsulting": "Консультируемся с советником...",
+ "resultLabel": "Ответ советника"
+ },
"docs": "Ознакомьтесь с нашей документацией , чтобы узнать больше.",
"onboarding": "Ваш список задач в этом рабочем пространстве пуст.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json
index 545e61d50e9..eb2c2e3d24f 100644
--- a/webview-ui/src/i18n/locales/tr/chat.json
+++ b/webview-ui/src/i18n/locales/tr/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Mesajı kuyruğa ekle (mevcut görev tamamlandıktan sonra gönderilecek)",
"scrollToBottom": "Sohbetin altına kaydır",
"about": "Roo Code, düzenleyicinizdeki bütün bir yapay zeka geliştirme ekibidir.",
+ "advisor": {
+ "isConsulting": "Danışmana danışılıyor...",
+ "resultLabel": "Danışman yanıtı"
+ },
"docs": "Daha fazla bilgi için belgelerimize göz atın.",
"onboarding": "Bu çalışma alanındaki görev listeniz boş.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json
index e36c58b54a3..78928641e88 100644
--- a/webview-ui/src/i18n/locales/vi/chat.json
+++ b/webview-ui/src/i18n/locales/vi/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "Thêm tin nhắn vào hàng đợi (sẽ gửi sau khi nhiệm vụ hiện tại hoàn tất)",
"scrollToBottom": "Cuộn xuống cuối cuộc trò chuyện",
"about": "Roo Code là một đội ngũ phát triển AI đầy đủ trong trình chỉnh sửa của bạn.",
+ "advisor": {
+ "isConsulting": "Đang tư vấn với cố vấn...",
+ "resultLabel": "Phản hồi từ cố vấn"
+ },
"docs": "Kiểm tra tài liệu của chúng tôi để tìm hiểu thêm.",
"onboarding": "Danh sách nhiệm vụ của bạn trong không gian làm việc này đang trống.",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json
index 3e6f223e717..1e8b41a8bbe 100644
--- a/webview-ui/src/i18n/locales/zh-CN/chat.json
+++ b/webview-ui/src/i18n/locales/zh-CN/chat.json
@@ -98,6 +98,10 @@
"enqueueMessage": "将消息加入队列(当前任务完成后发送)",
"scrollToBottom": "滚动到聊天底部",
"about": "Roo Code 是您编辑器中的整个 AI 开发团队。",
+ "advisor": {
+ "isConsulting": "正在咨询顾问...",
+ "resultLabel": "顾问回复"
+ },
"docs": "查看我们的 文档 了解更多信息。",
"onboarding": "此工作区中的任务列表为空。",
"rooTips": {
diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json
index 4fe9c578432..53e2f441a0e 100644
--- a/webview-ui/src/i18n/locales/zh-TW/chat.json
+++ b/webview-ui/src/i18n/locales/zh-TW/chat.json
@@ -125,6 +125,10 @@
},
"scrollToBottom": "捲動至對話底部",
"about": "Roo 是編輯器中的完整 AI 開發團隊。",
+ "advisor": {
+ "isConsulting": "正在諮詢顧問...",
+ "resultLabel": "顧問回應"
+ },
"docs": "請參閱 說明文件 開始使用。",
"onboarding": "想要做什麼呢?",
"rooTips": {