feat: add Claude Code provider for local CLI integration (#4864)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Daniel <57051444+daniel-lxs@users.noreply.github.com>
Co-authored-by: Daniel Riccio <ricciodaniel98@gmail.com>
Co-authored-by: Matt Rubens <mrubens@users.noreply.github.com>
This commit is contained in:
Hannes Rudolph 2025-06-22 21:17:55 -06:00 • committed by GitHub
parent 9750d868c1
commit ff9b6b3ef6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 714 additions and 52 deletions

View file

@ -9,6 +9,7 @@ import { codebaseIndexProviderSchema } from "./codebase-index.js"
export const providerNames = [
"anthropic",
"claude-code",
"glama",
"openrouter",
"bedrock",
@ -76,6 +77,10 @@ const anthropicSchema = apiModelIdProviderModelSchema.extend({
anthropicUseAuthToken: z.boolean().optional(),
})
const claudeCodeSchema = apiModelIdProviderModelSchema.extend({
claudeCodePath: z.string().optional(),
})
const glamaSchema = baseProviderSettingsSchema.extend({
glamaModelId: z.string().optional(),
glamaApiKey: z.string().optional(),
@ -208,6 +213,7 @@ const defaultSchema = z.object({
export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProvider", [
anthropicSchema.merge(z.object({ apiProvider: z.literal("anthropic") })),
claudeCodeSchema.merge(z.object({ apiProvider: z.literal("claude-code") })),
glamaSchema.merge(z.object({ apiProvider: z.literal("glama") })),
openRouterSchema.merge(z.object({ apiProvider: z.literal("openrouter") })),
bedrockSchema.merge(z.object({ apiProvider: z.literal("bedrock") })),
@ -234,6 +240,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
export const providerSettingsSchema = z.object({
apiProvider: providerNamesSchema.optional(),
...anthropicSchema.shape,
...claudeCodeSchema.shape,
...glamaSchema.shape,
...openRouterSchema.shape,
...bedrockSchema.shape,

View file

@ -0,0 +1,13 @@
import type { ModelInfo } from "../model.js"
import { anthropicModels } from "./anthropic.js"
// Claude Code
export type ClaudeCodeModelId = keyof typeof claudeCodeModels
export const claudeCodeDefaultModelId: ClaudeCodeModelId = "claude-sonnet-4-20250514"
export const claudeCodeModels = {
"claude-sonnet-4-20250514": anthropicModels["claude-sonnet-4-20250514"],
"claude-opus-4-20250514": anthropicModels["claude-opus-4-20250514"],
"claude-3-7-sonnet-20250219": anthropicModels["claude-3-7-sonnet-20250219"],
"claude-3-5-sonnet-20241022": anthropicModels["claude-3-5-sonnet-20241022"],
"claude-3-5-haiku-20241022": anthropicModels["claude-3-5-haiku-20241022"],
} as const satisfies Record<string, ModelInfo>

View file

@ -1,6 +1,7 @@
export * from "./anthropic.js"
export * from "./bedrock.js"
export * from "./chutes.js"
export * from "./claude-code.js"
export * from "./deepseek.js"
export * from "./gemini.js"
export * from "./glama.js"

View file

@ -27,6 +27,7 @@ import {
GroqHandler,
ChutesHandler,
LiteLLMHandler,
ClaudeCodeHandler,
} from "./providers"
export interface SingleCompletionHandler {
@ -64,6 +65,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
switch (apiProvider) {
case "anthropic":
return new AnthropicHandler(options)
case "claude-code":
return new ClaudeCodeHandler(options)
case "glama":
return new GlamaHandler(options)
case "openrouter":

View file

@ -0,0 +1,171 @@
import type { Anthropic } from "@anthropic-ai/sdk"
import { claudeCodeDefaultModelId, type ClaudeCodeModelId, claudeCodeModels } from "@roo-code/types"
import { type ApiHandler } from ".."
import { ApiStreamUsageChunk, type ApiStream } from "../transform/stream"
import { runClaudeCode } from "../../integrations/claude-code/run"
import { ClaudeCodeMessage } from "../../integrations/claude-code/types"
import { BaseProvider } from "./base-provider"
import { t } from "../../i18n"
import { ApiHandlerOptions } from "../../shared/api"
export class ClaudeCodeHandler extends BaseProvider implements ApiHandler {
private options: ApiHandlerOptions
constructor(options: ApiHandlerOptions) {
super()
this.options = options
}
override async *createMessage(systemPrompt: string, messages: Anthropic.Messages.MessageParam[]): ApiStream {
const claudeProcess = runClaudeCode({
systemPrompt,
messages,
path: this.options.claudeCodePath,
modelId: this.getModel().id,
})
const dataQueue: string[] = []
let processError = null
let errorOutput = ""
let exitCode: number | null = null
claudeProcess.stdout.on("data", (data) => {
const output = data.toString()
const lines = output.split("\n").filter((line: string) => line.trim() !== "")
for (const line of lines) {
dataQueue.push(line)
}
})
claudeProcess.stderr.on("data", (data) => {
errorOutput += data.toString()
})
claudeProcess.on("close", (code) => {
exitCode = code
})
claudeProcess.on("error", (error) => {
processError = error
})
// Usage is included with assistant messages,
// but cost is included in the result chunk
let usage: ApiStreamUsageChunk = {
type: "usage",
inputTokens: 0,
outputTokens: 0,
cacheReadTokens: 0,
cacheWriteTokens: 0,
}
while (exitCode !== 0 || dataQueue.length > 0) {
if (dataQueue.length === 0) {
await new Promise((resolve) => setImmediate(resolve))
}
if (exitCode !== null && exitCode !== 0) {
if (errorOutput) {
throw new Error(
t("common:errors.claudeCode.processExitedWithError", {
exitCode,
output: errorOutput.trim(),
}),
)
}
throw new Error(t("common:errors.claudeCode.processExited", { exitCode }))
}
const data = dataQueue.shift()
if (!data) {
continue
}
const chunk = this.attemptParseChunk(data)
if (!chunk) {
yield {
type: "text",
text: data || "",
}
continue
}
if (chunk.type === "system" && chunk.subtype === "init") {
continue
}
if (chunk.type === "assistant" && "message" in chunk) {
const message = chunk.message
if (message.stop_reason !== null && message.stop_reason !== "tool_use") {
const errorMessage =
message.content[0]?.text ||
t("common:errors.claudeCode.stoppedWithReason", { reason: message.stop_reason })
if (errorMessage.includes("Invalid model name")) {
throw new Error(errorMessage + `\n\n${t("common:errors.claudeCode.apiKeyModelPlanMismatch")}`)
}
throw new Error(errorMessage)
}
for (const content of message.content) {
if (content.type === "text") {
yield {
type: "text",
text: content.text,
}
} else {
console.warn("Unsupported content type:", content.type)
}
}
usage.inputTokens += message.usage.input_tokens
usage.outputTokens += message.usage.output_tokens
usage.cacheReadTokens = (usage.cacheReadTokens || 0) + (message.usage.cache_read_input_tokens || 0)
usage.cacheWriteTokens =
(usage.cacheWriteTokens || 0) + (message.usage.cache_creation_input_tokens || 0)
continue
}
if (chunk.type === "result" && "result" in chunk) {
// Only use the cost from the CLI if provided
// Don't calculate cost as it may be $0 for subscription users
usage.totalCost = chunk.cost_usd ?? 0
yield usage
}
if (processError) {
throw processError
}
}
}
getModel() {
const modelId = this.options.apiModelId
if (modelId && modelId in claudeCodeModels) {
const id = modelId as ClaudeCodeModelId
return { id, info: claudeCodeModels[id] }
}
return {
id: claudeCodeDefaultModelId,
info: claudeCodeModels[claudeCodeDefaultModelId],
}
}
// TODO: Validate instead of parsing
private attemptParseChunk(data: string): ClaudeCodeMessage | null {
try {
return JSON.parse(data)
} catch (error) {
console.error("Error parsing chunk:", error)
return null
}
}
}

View file

@ -2,6 +2,7 @@ export { AnthropicVertexHandler } from "./anthropic-vertex"
export { AnthropicHandler } from "./anthropic"
export { AwsBedrockHandler } from "./bedrock"
export { ChutesHandler } from "./chutes"
export { ClaudeCodeHandler } from "./claude-code"
export { DeepSeekHandler } from "./deepseek"
export { FakeAIHandler } from "./fake-ai"
export { GeminiHandler } from "./gemini"

View file

@ -1,6 +1,12 @@
export type ApiStream = AsyncGenerator<ApiStreamChunk>
export type ApiStreamChunk = ApiStreamTextChunk | ApiStreamUsageChunk | ApiStreamReasoningChunk
export type ApiStreamChunk = ApiStreamTextChunk | ApiStreamUsageChunk | ApiStreamReasoningChunk | ApiStreamError
export interface ApiStreamError {
type: "error"
error: string
message: string
}
export interface ApiStreamTextChunk {
type: "text"

View file

@ -66,7 +66,14 @@
"share_no_active_task": "No hi ha cap tasca activa per compartir",
"share_auth_required": "Es requereix autenticació. Si us plau, inicia sessió per compartir tasques.",
"share_not_enabled": "La compartició de tasques no està habilitada per a aquesta organització.",
"share_task_not_found": "Tasca no trobada o accés denegat."
"share_task_not_found": "Tasca no trobada o accés denegat.",
"claudeCode": {
"processExited": "El procés Claude Code ha sortit amb codi {{exitCode}}.",
"errorOutput": "Sortida d'error: {{output}}",
"processExitedWithError": "El procés Claude Code ha sortit amb codi {{exitCode}}. Sortida d'error: {{output}}",
"stoppedWithReason": "Claude Code s'ha aturat per la raó: {{reason}}",
"apiKeyModelPlanMismatch": "Les claus API i els plans de subscripció permeten models diferents. Assegura't que el model seleccionat estigui inclòs al teu pla."
}
},
"warnings": {
"no_terminal_content": "No s'ha seleccionat contingut de terminal",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Clau API de Groq",
"getGroqApiKey": "Obté la clau API de Groq"
"getGroqApiKey": "Obté la clau API de Groq",
"claudeCode": {
"pathLabel": "Ruta de Claude Code",
"description": "Ruta opcional a la teva CLI de Claude Code. Per defecte 'claude' si no s'estableix.",
"placeholder": "Per defecte: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Keine aktive Aufgabe zum Teilen",
"share_auth_required": "Authentifizierung erforderlich. Bitte melde dich an, um Aufgaben zu teilen.",
"share_not_enabled": "Aufgabenfreigabe ist für diese Organisation nicht aktiviert.",
"share_task_not_found": "Aufgabe nicht gefunden oder Zugriff verweigert."
"share_task_not_found": "Aufgabe nicht gefunden oder Zugriff verweigert.",
"claudeCode": {
"processExited": "Claude Code Prozess wurde mit Code {{exitCode}} beendet.",
"errorOutput": "Fehlerausgabe: {{output}}",
"processExitedWithError": "Claude Code Prozess wurde mit Code {{exitCode}} beendet. Fehlerausgabe: {{output}}",
"stoppedWithReason": "Claude Code wurde mit Grund gestoppt: {{reason}}",
"apiKeyModelPlanMismatch": "API-Schlüssel und Abonnement-Pläne erlauben verschiedene Modelle. Stelle sicher, dass das ausgewählte Modell in deinem Plan enthalten ist."
}
},
"warnings": {
"no_terminal_content": "Kein Terminal-Inhalt ausgewählt",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Groq API-Schlüssel",
"getGroqApiKey": "Groq API-Schlüssel erhalten"
"getGroqApiKey": "Groq API-Schlüssel erhalten",
"claudeCode": {
"pathLabel": "Claude Code Pfad",
"description": "Optionaler Pfad zu deiner Claude Code CLI. Standardmäßig 'claude', falls nicht festgelegt.",
"placeholder": "Standard: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "No active task to share",
"share_auth_required": "Authentication required. Please sign in to share tasks.",
"share_not_enabled": "Task sharing is not enabled for this organization.",
"share_task_not_found": "Task not found or access denied."
"share_task_not_found": "Task not found or access denied.",
"claudeCode": {
"processExited": "Claude Code process exited with code {{exitCode}}.",
"errorOutput": "Error output: {{output}}",
"processExitedWithError": "Claude Code process exited with code {{exitCode}}. Error output: {{output}}",
"stoppedWithReason": "Claude Code stopped with reason: {{reason}}",
"apiKeyModelPlanMismatch": "API keys and subscription plans allow different models. Make sure the selected model is included in your plan."
}
},
"warnings": {
"no_terminal_content": "No terminal content selected",

View file

@ -62,7 +62,14 @@
"share_no_active_task": "No hay tarea activa para compartir",
"share_auth_required": "Se requiere autenticación. Por favor, inicia sesión para compartir tareas.",
"share_not_enabled": "La compartición de tareas no está habilitada para esta organización.",
"share_task_not_found": "Tarea no encontrada o acceso denegado."
"share_task_not_found": "Tarea no encontrada o acceso denegado.",
"claudeCode": {
"processExited": "El proceso de Claude Code terminó con código {{exitCode}}.",
"errorOutput": "Salida de error: {{output}}",
"processExitedWithError": "El proceso de Claude Code terminó con código {{exitCode}}. Salida de error: {{output}}",
"stoppedWithReason": "Claude Code se detuvo por la razón: {{reason}}",
"apiKeyModelPlanMismatch": "Las claves API y los planes de suscripción permiten diferentes modelos. Asegúrate de que el modelo seleccionado esté incluido en tu plan."
}
},
"warnings": {
"no_terminal_content": "No hay contenido de terminal seleccionado",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Clave API de Groq",
"getGroqApiKey": "Obtener clave API de Groq"
"getGroqApiKey": "Obtener clave API de Groq",
"claudeCode": {
"pathLabel": "Ruta de Claude Code",
"description": "Ruta opcional a tu CLI de Claude Code. Por defecto 'claude' si no se establece.",
"placeholder": "Por defecto: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Aucune tâche active à partager",
"share_auth_required": "Authentification requise. Veuillez vous connecter pour partager des tâches.",
"share_not_enabled": "Le partage de tâches n'est pas activé pour cette organisation.",
"share_task_not_found": "Tâche non trouvée ou accès refusé."
"share_task_not_found": "Tâche non trouvée ou accès refusé.",
"claudeCode": {
"processExited": "Le processus Claude Code s'est terminé avec le code {{exitCode}}.",
"errorOutput": "Sortie d'erreur : {{output}}",
"processExitedWithError": "Le processus Claude Code s'est terminé avec le code {{exitCode}}. Sortie d'erreur : {{output}}",
"stoppedWithReason": "Claude Code s'est arrêté pour la raison : {{reason}}",
"apiKeyModelPlanMismatch": "Les clés API et les plans d'abonnement permettent différents modèles. Assurez-vous que le modèle sélectionné est inclus dans votre plan."
}
},
"warnings": {
"no_terminal_content": "Aucun contenu de terminal sélectionné",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Clé API Groq",
"getGroqApiKey": "Obtenir la clé API Groq"
"getGroqApiKey": "Obtenir la clé API Groq",
"claudeCode": {
"pathLabel": "Chemin de Claude Code",
"description": "Chemin optionnel vers votre CLI Claude Code. Par défaut 'claude' si non défini.",
"placeholder": "Par défaut : claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "साझा करने के लिए कोई सक्रिय कार्य नहीं",
"share_auth_required": "प्रमाणीकरण आवश्यक है। कार्य साझा करने के लिए कृपया साइन इन करें।",
"share_not_enabled": "इस संगठन के लिए कार्य साझाकरण सक्षम नहीं है।",
"share_task_not_found": "कार्य नहीं मिला या पहुंच अस्वीकृत।"
"share_task_not_found": "कार्य नहीं मिला या पहुंच अस्वीकृत।",
"claudeCode": {
"processExited": "Claude Code प्रक्रिया कोड {{exitCode}} के साथ समाप्त हुई।",
"errorOutput": "त्रुटि आउटपुट: {{output}}",
"processExitedWithError": "Claude Code प्रक्रिया कोड {{exitCode}} के साथ समाप्त हुई। त्रुटि आउटपुट: {{output}}",
"stoppedWithReason": "Claude Code इस कारण से रुका: {{reason}}",
"apiKeyModelPlanMismatch": "API कुंजी और सब्सक्रिप्शन प्लान अलग-अलग मॉडल की अनुमति देते हैं। सुनिश्चित करें कि चयनित मॉडल आपकी योजना में शामिल है।"
}
},
"warnings": {
"no_terminal_content": "कोई टर्मिनल सामग्री चयनित नहीं",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "ग्रोक एपीआई कुंजी",
"getGroqApiKey": "ग्रोक एपीआई कुंजी प्राप्त करें"
"getGroqApiKey": "ग्रोक एपीआई कुंजी प्राप्त करें",
"claudeCode": {
"pathLabel": "क्लाउड कोड पाथ",
"description": "आपके क्लाउड कोड CLI का वैकल्पिक पाथ। सेट न होने पर डिफ़ॉल्ट रूप से 'claude'。",
"placeholder": "डिफ़ॉल्ट: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Tidak ada tugas aktif untuk dibagikan",
"share_auth_required": "Autentikasi diperlukan. Silakan masuk untuk berbagi tugas.",
"share_not_enabled": "Berbagi tugas tidak diaktifkan untuk organisasi ini.",
"share_task_not_found": "Tugas tidak ditemukan atau akses ditolak."
"share_task_not_found": "Tugas tidak ditemukan atau akses ditolak.",
"claudeCode": {
"processExited": "Proses Claude Code keluar dengan kode {{exitCode}}.",
"errorOutput": "Output error: {{output}}",
"processExitedWithError": "Proses Claude Code keluar dengan kode {{exitCode}}. Output error: {{output}}",
"stoppedWithReason": "Claude Code berhenti karena alasan: {{reason}}",
"apiKeyModelPlanMismatch": "Kunci API dan paket berlangganan memungkinkan model yang berbeda. Pastikan model yang dipilih termasuk dalam paket Anda."
}
},
"warnings": {
"no_terminal_content": "Tidak ada konten terminal yang dipilih",
@ -102,6 +109,17 @@
"task_prompt": "Apa yang harus Roo lakukan?",
"task_placeholder": "Ketik tugas kamu di sini"
},
"settings": {
"providers": {
"groqApiKey": "Kunci API Groq",
"getGroqApiKey": "Dapatkan Kunci API Groq",
"claudeCode": {
"pathLabel": "Jalur Claude Code",
"description": "Jalur opsional ke CLI Claude Code Anda. Defaultnya 'claude' jika tidak diatur.",
"placeholder": "Default: claude"
}
}
},
"mdm": {
"errors": {
"cloud_auth_required": "Organisasi kamu memerlukan autentikasi Roo Code Cloud. Silakan masuk untuk melanjutkan.",

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Nessuna attività attiva da condividere",
"share_auth_required": "Autenticazione richiesta. Accedi per condividere le attività.",
"share_not_enabled": "La condivisione delle attività non è abilitata per questa organizzazione.",
"share_task_not_found": "Attività non trovata o accesso negato."
"share_task_not_found": "Attività non trovata o accesso negato.",
"claudeCode": {
"processExited": "Il processo Claude Code è terminato con codice {{exitCode}}.",
"errorOutput": "Output di errore: {{output}}",
"processExitedWithError": "Il processo Claude Code è terminato con codice {{exitCode}}. Output di errore: {{output}}",
"stoppedWithReason": "Claude Code si è fermato per il motivo: {{reason}}",
"apiKeyModelPlanMismatch": "Le chiavi API e i piani di abbonamento consentono modelli diversi. Assicurati che il modello selezionato sia incluso nel tuo piano."
}
},
"warnings": {
"no_terminal_content": "Nessun contenuto del terminale selezionato",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Chiave API Groq",
"getGroqApiKey": "Ottieni chiave API Groq"
"getGroqApiKey": "Ottieni chiave API Groq",
"claudeCode": {
"pathLabel": "Percorso Claude Code",
"description": "Percorso opzionale alla tua CLI Claude Code. Predefinito 'claude' se non impostato.",
"placeholder": "Predefinito: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "共有するアクティブなタスクがありません",
"share_auth_required": "認証が必要です。タスクを共有するにはサインインしてください。",
"share_not_enabled": "この組織ではタスク共有が有効になっていません。",
"share_task_not_found": "タスクが見つからないか、アクセスが拒否されました。"
"share_task_not_found": "タスクが見つからないか、アクセスが拒否されました。",
"claudeCode": {
"processExited": "Claude Code プロセスがコード {{exitCode}} で終了しました。",
"errorOutput": "エラー出力:{{output}}",
"processExitedWithError": "Claude Code プロセスがコード {{exitCode}} で終了しました。エラー出力:{{output}}",
"stoppedWithReason": "Claude Code が理由により停止しました:{{reason}}",
"apiKeyModelPlanMismatch": "API キーとサブスクリプションプランでは異なるモデルが利用可能です。選択したモデルがプランに含まれていることを確認してください。"
}
},
"warnings": {
"no_terminal_content": "選択されたターミナルコンテンツがありません",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Groq APIキー",
"getGroqApiKey": "Groq APIキーを取得"
"getGroqApiKey": "Groq APIキーを取得",
"claudeCode": {
"pathLabel": "Claude Code パス",
"description": "Claude Code CLI へのオプションのパス。設定されていない場合は、デフォルトで「claude」になります。",
"placeholder": "デフォルト: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "공유할 활성 작업이 없습니다",
"share_auth_required": "인증이 필요합니다. 작업을 공유하려면 로그인하세요.",
"share_not_enabled": "이 조직에서는 작업 공유가 활성화되지 않았습니다.",
"share_task_not_found": "작업을 찾을 수 없거나 액세스가 거부되었습니다."
"share_task_not_found": "작업을 찾을 수 없거나 액세스가 거부되었습니다.",
"claudeCode": {
"processExited": "Claude Code 프로세스가 코드 {{exitCode}}로 종료되었습니다.",
"errorOutput": "오류 출력: {{output}}",
"processExitedWithError": "Claude Code 프로세스가 코드 {{exitCode}}로 종료되었습니다. 오류 출력: {{output}}",
"stoppedWithReason": "Claude Code가 다음 이유로 중지되었습니다: {{reason}}",
"apiKeyModelPlanMismatch": "API 키와 구독 플랜에서 다른 모델을 허용합니다. 선택한 모델이 플랜에 포함되어 있는지 확인하세요."
}
},
"warnings": {
"no_terminal_content": "선택된 터미널 내용이 없습니다",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Groq API 키",
"getGroqApiKey": "Groq API 키 받기"
"getGroqApiKey": "Groq API 키 받기",
"claudeCode": {
"pathLabel": "Claude Code 경로",
"description": "Claude Code CLI의 선택적 경로입니다. 설정되지 않은 경우 기본값은 'claude'입니다.",
"placeholder": "기본값: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Geen actieve taak om te delen",
"share_auth_required": "Authenticatie vereist. Log in om taken te delen.",
"share_not_enabled": "Taken delen is niet ingeschakeld voor deze organisatie.",
"share_task_not_found": "Taak niet gevonden of toegang geweigerd."
"share_task_not_found": "Taak niet gevonden of toegang geweigerd.",
"claudeCode": {
"processExited": "Claude Code proces beëindigd met code {{exitCode}}.",
"errorOutput": "Foutuitvoer: {{output}}",
"processExitedWithError": "Claude Code proces beëindigd met code {{exitCode}}. Foutuitvoer: {{output}}",
"stoppedWithReason": "Claude Code gestopt om reden: {{reason}}",
"apiKeyModelPlanMismatch": "API-sleutels en abonnementsplannen staan verschillende modellen toe. Zorg ervoor dat het geselecteerde model is opgenomen in je plan."
}
},
"warnings": {
"no_terminal_content": "Geen terminalinhoud geselecteerd",
@ -102,6 +109,17 @@
"task_prompt": "Wat moet Roo doen?",
"task_placeholder": "Typ hier je taak"
},
"settings": {
"providers": {
"groqApiKey": "Groq API-sleutel",
"getGroqApiKey": "Groq API-sleutel ophalen",
"claudeCode": {
"pathLabel": "Claude Code Pad",
"description": "Optioneel pad naar je Claude Code CLI. Standaard 'claude' indien niet ingesteld.",
"placeholder": "Standaard: claude"
}
}
},
"mdm": {
"errors": {
"cloud_auth_required": "Je organisatie vereist Roo Code Cloud-authenticatie. Log in om door te gaan.",

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Brak aktywnego zadania do udostępnienia",
"share_auth_required": "Wymagana autoryzacja. Zaloguj się, aby udostępniać zadania.",
"share_not_enabled": "Udostępnianie zadań nie jest włączone dla tej organizacji.",
"share_task_not_found": "Zadanie nie znalezione lub dostęp odmówiony."
"share_task_not_found": "Zadanie nie znalezione lub dostęp odmówiony.",
"claudeCode": {
"processExited": "Proces Claude Code zakończył się kodem {{exitCode}}.",
"errorOutput": "Wyjście błędu: {{output}}",
"processExitedWithError": "Proces Claude Code zakończył się kodem {{exitCode}}. Wyjście błędu: {{output}}",
"stoppedWithReason": "Claude Code zatrzymał się z powodu: {{reason}}",
"apiKeyModelPlanMismatch": "Klucze API i plany subskrypcji pozwalają na różne modele. Upewnij się, że wybrany model jest zawarty w twoim planie."
}
},
"warnings": {
"no_terminal_content": "Nie wybrano zawartości terminala",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Klucz API Groq",
"getGroqApiKey": "Uzyskaj klucz API Groq"
"getGroqApiKey": "Uzyskaj klucz API Groq",
"claudeCode": {
"pathLabel": "Ścieżka Claude Code",
"description": "Opcjonalna ścieżka do Twojego CLI Claude Code. Domyślnie 'claude', jeśli nie ustawiono.",
"placeholder": "Domyślnie: claude"
}
}
},
"mdm": {

View file

@ -66,7 +66,14 @@
"share_no_active_task": "Nenhuma tarefa ativa para compartilhar",
"share_auth_required": "Autenticação necessária. Faça login para compartilhar tarefas.",
"share_not_enabled": "O compartilhamento de tarefas não está habilitado para esta organização.",
"share_task_not_found": "Tarefa não encontrada ou acesso negado."
"share_task_not_found": "Tarefa não encontrada ou acesso negado.",
"claudeCode": {
"processExited": "O processo Claude Code saiu com código {{exitCode}}.",
"errorOutput": "Saída de erro: {{output}}",
"processExitedWithError": "O processo Claude Code saiu com código {{exitCode}}. Saída de erro: {{output}}",
"stoppedWithReason": "Claude Code parou pela razão: {{reason}}",
"apiKeyModelPlanMismatch": "Chaves de API e planos de assinatura permitem modelos diferentes. Certifique-se de que o modelo selecionado esteja incluído no seu plano."
}
},
"warnings": {
"no_terminal_content": "Nenhum conteúdo do terminal selecionado",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Chave de API Groq",
"getGroqApiKey": "Obter chave de API Groq"
"getGroqApiKey": "Obter chave de API Groq",
"claudeCode": {
"pathLabel": "Caminho do Claude Code",
"description": "Caminho opcional para sua CLI do Claude Code. Padrão 'claude' se não for definido.",
"placeholder": "Padrão: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Нет активной задачи для совместного использования",
"share_auth_required": "Требуется аутентификация. Войдите в систему для совместного доступа к задачам.",
"share_not_enabled": "Совместный доступ к задачам не включен для этой организации.",
"share_task_not_found": "Задача не найдена или доступ запрещен."
"share_task_not_found": "Задача не найдена или доступ запрещен.",
"claudeCode": {
"processExited": "Процесс Claude Code завершился с кодом {{exitCode}}.",
"errorOutput": "Вывод ошибки: {{output}}",
"processExitedWithError": "Процесс Claude Code завершился с кодом {{exitCode}}. Вывод ошибки: {{output}}",
"stoppedWithReason": "Claude Code остановился по причине: {{reason}}",
"apiKeyModelPlanMismatch": "API-ключи и планы подписки позволяют использовать разные модели. Убедитесь, что выбранная модель включена в ваш план."
}
},
"warnings": {
"no_terminal_content": "Не выбрано содержимое терминала",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Ключ API Groq",
"getGroqApiKey": "Получить ключ API Groq"
"getGroqApiKey": "Получить ключ API Groq",
"claudeCode": {
"pathLabel": "Путь к Claude Code",
"description": "Необязательный путь к вашему CLI Claude Code. По умолчанию 'claude', если не установлено.",
"placeholder": "По умолчанию: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Paylaşılacak aktif görev yok",
"share_auth_required": "Kimlik doğrulama gerekli. Görevleri paylaşmak için lütfen giriş yapın.",
"share_not_enabled": "Bu kuruluş için görev paylaşımı etkinleştirilmemiş.",
"share_task_not_found": "Görev bulunamadı veya erişim reddedildi."
"share_task_not_found": "Görev bulunamadı veya erişim reddedildi.",
"claudeCode": {
"processExited": "Claude Code işlemi {{exitCode}} koduyla çıktı.",
"errorOutput": "Hata çıktısı: {{output}}",
"processExitedWithError": "Claude Code işlemi {{exitCode}} koduyla çıktı. Hata çıktısı: {{output}}",
"stoppedWithReason": "Claude Code şu nedenle durdu: {{reason}}",
"apiKeyModelPlanMismatch": "API anahtarları ve abonelik planları farklı modellere izin verir. Seçilen modelin planınıza dahil olduğundan emin olun."
}
},
"warnings": {
"no_terminal_content": "Seçili terminal içeriği yok",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Groq API Anahtarı",
"getGroqApiKey": "Groq API Anahtarı Al"
"getGroqApiKey": "Groq API Anahtarı Al",
"claudeCode": {
"pathLabel": "Claude Code Yolu",
"description": "Claude Code CLI'nizin isteğe bağlı yolu. Ayarlanmazsa varsayılan olarak 'claude' olur.",
"placeholder": "Varsayılan: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "Không có nhiệm vụ hoạt động để chia sẻ",
"share_auth_required": "Cần xác thực. Vui lòng đăng nhập để chia sẻ nhiệm vụ.",
"share_not_enabled": "Chia sẻ nhiệm vụ không được bật cho tổ chức này.",
"share_task_not_found": "Không tìm thấy nhiệm vụ hoặc truy cập bị từ chối."
"share_task_not_found": "Không tìm thấy nhiệm vụ hoặc truy cập bị từ chối.",
"claudeCode": {
"processExited": "Tiến trình Claude Code thoát với mã {{exitCode}}.",
"errorOutput": "Đầu ra lỗi: {{output}}",
"processExitedWithError": "Tiến trình Claude Code thoát với mã {{exitCode}}. Đầu ra lỗi: {{output}}",
"stoppedWithReason": "Claude Code dừng lại vì lý do: {{reason}}",
"apiKeyModelPlanMismatch": "Khóa API và gói đăng ký cho phép các mô hình khác nhau. Đảm bảo rằng mô hình đã chọn được bao gồm trong gói của bạn."
}
},
"warnings": {
"no_terminal_content": "Không có nội dung terminal được chọn",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Khóa API Groq",
"getGroqApiKey": "Lấy khóa API Groq"
"getGroqApiKey": "Lấy khóa API Groq",
"claudeCode": {
"pathLabel": "Đường dẫn Claude Code",
"description": "Đường dẫn tùy chọn đến CLI Claude Code của bạn. Mặc định là 'claude' nếu không được đặt.",
"placeholder": "Mặc định: claude"
}
}
},
"mdm": {

View file

@ -67,7 +67,14 @@
"share_no_active_task": "没有活跃任务可分享",
"share_auth_required": "需要身份验证。请登录以分享任务。",
"share_not_enabled": "此组织未启用任务分享功能。",
"share_task_not_found": "未找到任务或访问被拒绝。"
"share_task_not_found": "未找到任务或访问被拒绝。",
"claudeCode": {
"processExited": "Claude Code 进程退出,退出码:{{exitCode}}。",
"errorOutput": "错误输出:{{output}}",
"processExitedWithError": "Claude Code 进程退出,退出码:{{exitCode}}。错误输出:{{output}}",
"stoppedWithReason": "Claude Code 停止,原因:{{reason}}",
"apiKeyModelPlanMismatch": "API 密钥和订阅计划支持不同的模型。请确保所选模型包含在您的计划中。"
}
},
"warnings": {
"no_terminal_content": "没有选择终端内容",
@ -110,7 +117,12 @@
"settings": {
"providers": {
"groqApiKey": "Groq API 密钥",
"getGroqApiKey": "获取 Groq API 密钥"
"getGroqApiKey": "获取 Groq API 密钥",
"claudeCode": {
"pathLabel": "Claude Code 路径",
"description": "Claude Code CLI 的可选路径。如果未设置,默认为 'claude'。",
"placeholder": "默认: claude"
}
}
},
"mdm": {

View file

@ -62,7 +62,14 @@
"share_no_active_task": "沒有活躍的工作可分享",
"share_auth_required": "需要身份驗證。請登入以分享工作。",
"share_not_enabled": "此組織未啟用工作分享功能。",
"share_task_not_found": "未找到工作或存取被拒絕。"
"share_task_not_found": "未找到工作或存取被拒絕。",
"claudeCode": {
"processExited": "Claude Code 程序退出,退出碼:{{exitCode}}。",
"errorOutput": "錯誤輸出:{{output}}",
"processExitedWithError": "Claude Code 程序退出,退出碼:{{exitCode}}。錯誤輸出:{{output}}",
"stoppedWithReason": "Claude Code 停止,原因:{{reason}}",
"apiKeyModelPlanMismatch": "API 金鑰和訂閱方案允許不同的模型。請確保所選模型包含在您的方案中。"
}
},
"warnings": {
"no_terminal_content": "沒有選擇終端機內容",
@ -105,7 +112,12 @@
"settings": {
"providers": {
"groqApiKey": "Groq API 金鑰",
"getGroqApiKey": "取得 Groq API 金鑰"
"getGroqApiKey": "取得 Groq API 金鑰",
"claudeCode": {
"pathLabel": "Claude Code 路徑",
"description": "Claude Code CLI 的選用路徑。如果未設定,預設為 'claude'。",
"placeholder": "預設: claude"
}
}
},
"mdm": {

View file

@ -0,0 +1,44 @@
import * as vscode from "vscode"
import Anthropic from "@anthropic-ai/sdk"
import { execa } from "execa"
export function runClaudeCode({
systemPrompt,
messages,
path,
modelId,
}: {
systemPrompt: string
messages: Anthropic.Messages.MessageParam[]
path?: string
modelId?: string
}) {
const claudePath = path || "claude"
// TODO: Is it worth using sessions? Where do we store the session ID?
const args = [
"-p",
JSON.stringify(messages),
"--system-prompt",
systemPrompt,
"--verbose",
"--output-format",
"stream-json",
// Cline will handle recursive calls
"--max-turns",
"1",
]
if (modelId) {
args.push("--model", modelId)
}
const cwd = vscode.workspace.workspaceFolders?.map((folder) => folder.uri.fsPath).at(0)
return execa(claudePath, args, {
stdin: "ignore",
stdout: "pipe",
stderr: "pipe",
env: process.env,
cwd,
})
}

View file

@ -0,0 +1,52 @@
type InitMessage = {
type: "system"
subtype: "init"
session_id: string
tools: string[]
mcp_servers: string[]
}
type ClaudeCodeContent = {
type: "text"
text: string
}
type AssistantMessage = {
type: "assistant"
message: {
id: string
type: "message"
role: "assistant"
model: string
content: ClaudeCodeContent[]
stop_reason: string | null
stop_sequence: null
usage: {
input_tokens: number
cache_creation_input_tokens?: number
cache_read_input_tokens?: number
output_tokens: number
service_tier: "standard"
}
}
session_id: string
}
type ErrorMessage = {
type: "error"
}
type ResultMessage = {
type: "result"
subtype: "success"
cost_usd: number
is_error: boolean
duration_ms: number
duration_api_ms: number
num_turns: number
result: string
total_cost: number
session_id: string
}
export type ClaudeCodeMessage = InitMessage | AssistantMessage | ErrorMessage | ResultMessage

View file

@ -13,6 +13,7 @@ import {
litellmDefaultModelId,
openAiNativeDefaultModelId,
anthropicDefaultModelId,
claudeCodeDefaultModelId,
geminiDefaultModelId,
deepSeekDefaultModelId,
mistralDefaultModelId,
@ -36,6 +37,7 @@ import {
Anthropic,
Bedrock,
Chutes,
ClaudeCode,
DeepSeek,
Gemini,
Glama,
@ -254,6 +256,7 @@ const ApiOptions = ({
requesty: { field: "requestyModelId", default: requestyDefaultModelId },
litellm: { field: "litellmModelId", default: litellmDefaultModelId },
anthropic: { field: "apiModelId", default: anthropicDefaultModelId },
"claude-code": { field: "apiModelId", default: claudeCodeDefaultModelId },
"openai-native": { field: "apiModelId", default: openAiNativeDefaultModelId },
gemini: { field: "apiModelId", default: geminiDefaultModelId },
deepseek: { field: "apiModelId", default: deepSeekDefaultModelId },
@ -383,6 +386,10 @@ const ApiOptions = ({
<Anthropic apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
)}
{selectedProvider === "claude-code" && (
<ClaudeCode apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
)}
{selectedProvider === "openai-native" && (
<OpenAI apiConfiguration={apiConfiguration} setApiConfigurationField={setApiConfigurationField} />
)}

View file

@ -3,6 +3,7 @@ import {
type ModelInfo,
anthropicModels,
bedrockModels,
claudeCodeModels,
deepSeekModels,
geminiModels,
mistralModels,
@ -15,6 +16,7 @@ import {
export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, ModelInfo>>> = {
anthropic: anthropicModels,
"claude-code": claudeCodeModels,
bedrock: bedrockModels,
deepseek: deepSeekModels,
gemini: geminiModels,
@ -29,6 +31,7 @@ export const MODELS_BY_PROVIDER: Partial<Record<ProviderName, Record<string, Mod
export const PROVIDERS = [
{ value: "openrouter", label: "OpenRouter" },
{ value: "anthropic", label: "Anthropic" },
{ value: "claude-code", label: "Claude Code" },
{ value: "gemini", label: "Google Gemini" },
{ value: "deepseek", label: "DeepSeek" },
{ value: "openai-native", label: "OpenAI" },

View file

@ -0,0 +1,40 @@
import React from "react"
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import { type ProviderSettings } from "@roo-code/types"
import { useAppTranslation } from "@src/i18n/TranslationContext"
interface ClaudeCodeProps {
apiConfiguration: ProviderSettings
setApiConfigurationField: (field: keyof ProviderSettings, value: ProviderSettings[keyof ProviderSettings]) => void
}
export const ClaudeCode: React.FC<ClaudeCodeProps> = ({ apiConfiguration, setApiConfigurationField }) => {
const { t } = useAppTranslation()
const handleInputChange = (e: Event | React.FormEvent<HTMLElement>) => {
const element = e.target as HTMLInputElement
setApiConfigurationField("claudeCodePath", element.value)
}
return (
<div>
<VSCodeTextField
value={apiConfiguration?.claudeCodePath || ""}
style={{ width: "100%", marginTop: 3 }}
type="text"
onInput={handleInputChange}
placeholder={t("settings:providers.claudeCode.placeholder")}>
{t("settings:providers.claudeCode.pathLabel")}
</VSCodeTextField>
<p
style={{
fontSize: "12px",
marginTop: 3,
color: "var(--vscode-descriptionForeground)",
}}>
{t("settings:providers.claudeCode.description")}
</p>
</div>
)
}

View file

@ -1,6 +1,7 @@
export { Anthropic } from "./Anthropic"
export { Bedrock } from "./Bedrock"
export { Chutes } from "./Chutes"
export { ClaudeCode } from "./ClaudeCode"
export { DeepSeek } from "./DeepSeek"
export { Gemini } from "./Gemini"
export { Glama } from "./Glama"

View file

@ -303,7 +303,12 @@
"medium": "Mitjà",
"low": "Baix"
},
"setReasoningLevel": "Activa l'esforç de raonament"
"setReasoningLevel": "Activa l'esforç de raonament",
"claudeCode": {
"pathLabel": "Ruta del Codi Claude",
"description": "Ruta opcional al teu CLI de Claude Code. Per defecte, 'claude' si no s'estableix.",
"placeholder": "Per defecte: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Mittel",
"low": "Niedrig"
},
"setReasoningLevel": "Denkaufwand aktivieren"
"setReasoningLevel": "Denkaufwand aktivieren",
"claudeCode": {
"pathLabel": "Claude-Code-Pfad",
"description": "Optionaler Pfad zu Ihrer Claude Code CLI. Standard ist 'claude', wenn nicht festgelegt.",
"placeholder": "Standard: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Medium",
"low": "Low"
},
"setReasoningLevel": "Enable Reasoning Effort"
"setReasoningLevel": "Enable Reasoning Effort",
"claudeCode": {
"pathLabel": "Claude Code Path",
"description": "Optional path to your Claude Code CLI. Defaults to 'claude' if not set.",
"placeholder": "Default: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Medio",
"low": "Bajo"
},
"setReasoningLevel": "Habilitar esfuerzo de razonamiento"
"setReasoningLevel": "Habilitar esfuerzo de razonamiento",
"claudeCode": {
"pathLabel": "Ruta de Claude Code",
"description": "Ruta opcional a su CLI de Claude Code. Por defecto, es 'claude' si no se establece.",
"placeholder": "Por defecto: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Moyen",
"low": "Faible"
},
"setReasoningLevel": "Activer l'effort de raisonnement"
"setReasoningLevel": "Activer l'effort de raisonnement",
"claudeCode": {
"pathLabel": "Chemin du code Claude",
"description": "Chemin facultatif vers votre CLI Claude Code. La valeur par défaut est 'claude' si non défini.",
"placeholder": "Défaut : claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "मध्यम",
"low": "निम्न"
},
"setReasoningLevel": "तर्क प्रयास सक्षम करें"
"setReasoningLevel": "तर्क प्रयास सक्षम करें",
"claudeCode": {
"pathLabel": "क्लाउड कोड पथ",
"description": "आपके क्लाउड कोड सीएलआई का वैकल्पिक पथ। यदि सेट नहीं है तो डिफ़ॉल्ट 'claude' है।",
"placeholder": "डिफ़ॉल्ट: claude"
}
},
"browser": {
"enable": {

View file

@ -307,7 +307,12 @@
"medium": "Sedang",
"low": "Rendah"
},
"setReasoningLevel": "Aktifkan Upaya Reasoning"
"setReasoningLevel": "Aktifkan Upaya Reasoning",
"claudeCode": {
"pathLabel": "Jalur Kode Claude",
"description": "Jalur opsional ke Claude Code CLI Anda. Defaultnya adalah 'claude' jika tidak diatur.",
"placeholder": "Default: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Medio",
"low": "Basso"
},
"setReasoningLevel": "Abilita sforzo di ragionamento"
"setReasoningLevel": "Abilita sforzo di ragionamento",
"claudeCode": {
"pathLabel": "Percorso Claude Code",
"description": "Percorso facoltativo per la tua CLI Claude Code. Predefinito 'claude' se non impostato.",
"placeholder": "Predefinito: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "中",
"low": "低"
},
"setReasoningLevel": "推論労力を有効にする"
"setReasoningLevel": "推論労力を有効にする",
"claudeCode": {
"pathLabel": "クロードコードパス",
"description": "Claude Code CLIへのオプションパス。設定されていない場合、デフォルトは「claude」です。",
"placeholder": "デフォルト:claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "중간",
"low": "낮음"
},
"setReasoningLevel": "추론 노력 활성화"
"setReasoningLevel": "추론 노력 활성화",
"claudeCode": {
"pathLabel": "클로드 코드 경로",
"description": "Claude Code CLI의 선택적 경로입니다. 설정하지 않으면 'claude'가 기본값입니다.",
"placeholder": "기본값: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Middel",
"low": "Laag"
},
"setReasoningLevel": "Redeneervermogen inschakelen"
"setReasoningLevel": "Redeneervermogen inschakelen",
"claudeCode": {
"pathLabel": "Claude Code Pad",
"description": "Optioneel pad naar uw Claude Code CLI. Standaard 'claude' als niet ingesteld.",
"placeholder": "Standaard: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Średni",
"low": "Niski"
},
"setReasoningLevel": "Włącz wysiłek rozumowania"
"setReasoningLevel": "Włącz wysiłek rozumowania",
"claudeCode": {
"pathLabel": "Ścieżka Claude Code",
"description": "Opcjonalna ścieżka do Twojego CLI Claude Code. Domyślnie 'claude', jeśli nie ustawiono.",
"placeholder": "Domyślnie: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Médio",
"low": "Baixo"
},
"setReasoningLevel": "Habilitar esforço de raciocínio"
"setReasoningLevel": "Habilitar esforço de raciocínio",
"claudeCode": {
"pathLabel": "Caminho do Claude Code",
"description": "Caminho opcional para o seu Claude Code CLI. O padrão é 'claude' se não for definido.",
"placeholder": "Padrão: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Средние",
"low": "Низкие"
},
"setReasoningLevel": "Включить усилие рассуждения"
"setReasoningLevel": "Включить усилие рассуждения",
"claudeCode": {
"pathLabel": "Путь к Claude Code",
"description": "Необязательный путь к вашему Claude Code CLI. По умолчанию используется 'claude', если не установлено.",
"placeholder": "По умолчанию: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Orta",
"low": "Düşük"
},
"setReasoningLevel": "Akıl Yürütme Çabasını Etkinleştir"
"setReasoningLevel": "Akıl Yürütme Çabasını Etkinleştir",
"claudeCode": {
"pathLabel": "Claude Code Yolu",
"description": "Claude Code CLI'nize isteğe bağlı yol. Ayarlanmazsa varsayılan olarak 'claude' kullanılır.",
"placeholder": "Varsayılan: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "Trung bình",
"low": "Thấp"
},
"setReasoningLevel": "Kích hoạt nỗ lực suy luận"
"setReasoningLevel": "Kích hoạt nỗ lực suy luận",
"claudeCode": {
"pathLabel": "Đường dẫn Claude Code",
"description": "Đường dẫn tùy chọn đến Claude Code CLI của bạn. Mặc định là 'claude' nếu không được đặt.",
"placeholder": "Mặc định: claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "中",
"low": "低"
},
"setReasoningLevel": "启用推理工作量"
"setReasoningLevel": "启用推理工作量",
"claudeCode": {
"pathLabel": "Claude Code 路径",
"description": "您的 Claude Code CLI 的可选路径。如果未设置,则默认为 “claude”。",
"placeholder": "默认:claude"
}
},
"browser": {
"enable": {

View file

@ -303,7 +303,12 @@
"medium": "中",
"low": "低"
},
"setReasoningLevel": "啟用推理工作量"
"setReasoningLevel": "啟用推理工作量",
"claudeCode": {
"pathLabel": "Claude Code 路徑",
"description": "可選的 Claude Code CLI 路徑。如果未設定,則預設為 'claude'。",
"placeholder": "預設:claude"
}
},
"browser": {
"enable": {