diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index fef7d811a4..c22683117f 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -47,6 +47,7 @@ export const providerNames = [ "zai", "fireworks", "io-intelligence", + "roo", ] as const export const providerNamesSchema = z.enum(providerNames) @@ -288,6 +289,10 @@ const ioIntelligenceSchema = apiModelIdProviderModelSchema.extend({ ioIntelligenceApiKey: z.string().optional(), }) +const rooSchema = apiModelIdProviderModelSchema.extend({ + // No additional fields needed - uses cloud authentication +}) + const defaultSchema = z.object({ apiProvider: z.undefined(), }) @@ -324,6 +329,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv zaiSchema.merge(z.object({ apiProvider: z.literal("zai") })), fireworksSchema.merge(z.object({ apiProvider: z.literal("fireworks") })), ioIntelligenceSchema.merge(z.object({ apiProvider: z.literal("io-intelligence") })), + rooSchema.merge(z.object({ apiProvider: z.literal("roo") })), defaultSchema, ]) @@ -360,6 +366,7 @@ export const providerSettingsSchema = z.object({ ...zaiSchema.shape, ...fireworksSchema.shape, ...ioIntelligenceSchema.shape, + ...rooSchema.shape, ...codebaseIndexProviderSchema.shape, }) diff --git a/packages/types/src/providers/index.ts b/packages/types/src/providers/index.ts index b7f1cd334e..6dff64a979 100644 --- a/packages/types/src/providers/index.ts +++ b/packages/types/src/providers/index.ts @@ -25,3 +25,4 @@ export * from "./xai.js" export * from "./doubao.js" export * from "./zai.js" export * from "./fireworks.js" +export * from "./roo.js" diff --git a/packages/types/src/providers/roo.ts b/packages/types/src/providers/roo.ts new file mode 100644 index 0000000000..a213e35780 --- /dev/null +++ b/packages/types/src/providers/roo.ts @@ -0,0 +1,19 @@ +import type { ModelInfo } from "../model.js" + +// Roo provider with single model +export type RooModelId = "roo/sonic" + +export const rooDefaultModelId: RooModelId = "roo/sonic" + +export const rooModels = { + "roo/sonic": { + maxTokens: 8192, + contextWindow: 262_144, + supportsImages: false, + supportsPromptCache: false, + inputPrice: 0, + outputPrice: 0, + description: + "Stealth coding model with 262K context window, accessible for free through Roo Code Cloud for a limited time. (Note: prompts and completions are logged by the model creator and used to improve the model.)", + }, +} as const satisfies Record diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d615c6e04..c9fc6bb27f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -584,8 +584,8 @@ importers: specifier: ^1.14.0 version: 1.14.0(typescript@5.8.3) '@roo-code/cloud': - specifier: ^0.17.0 - version: 0.17.0 + specifier: ^0.18.0 + version: 0.18.0 '@roo-code/ipc': specifier: workspace:^ version: link:../packages/ipc @@ -3106,11 +3106,11 @@ packages: cpu: [x64] os: [win32] - '@roo-code/cloud@0.17.0': - resolution: {integrity: sha512-Sh7KGbVapxocnoyDzWkvvtVzam5jZnU2RGKT7V0v3CbFMQc329NBnHRAgVtJUwcGPHUFyAkwEHo181Fn3rFpZw==} + '@roo-code/cloud@0.18.0': + resolution: {integrity: sha512-Y2jbcUVB9RCQFAxHDPrfjWQU1o7yRvWaPAdA3eZjsUf+zfDL59Rwfghg6loqDfE/8HCkcJmHfLCKovNX5ju5qA==} - '@roo-code/types@1.52.0': - resolution: {integrity: sha512-jPCVZ2j4Y0MUiHvAJbXduR3yFGb5A3KDvIThi8cKBAUg8zb7jhIYKTvJ5vub1MGZkpK11K0JG6ex4RL19FjobA==} + '@roo-code/types@1.54.0': + resolution: {integrity: sha512-Xj3Zn2FhXbG2bpwXuhrjKnkeuWypQCIPKljOLXnOCUqaMUhP1zkWwNZ+I3gIBUpDng/iWN3KHon1if0UaoXYQw==} '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -12314,9 +12314,9 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.40.2': optional: true - '@roo-code/cloud@0.17.0': + '@roo-code/cloud@0.18.0': dependencies: - '@roo-code/types': 1.52.0 + '@roo-code/types': 1.54.0 ioredis: 5.6.1 p-wait-for: 5.0.2 socket.io-client: 4.8.1 @@ -12326,7 +12326,7 @@ snapshots: - supports-color - utf-8-validate - '@roo-code/types@1.52.0': + '@roo-code/types@1.54.0': dependencies: zod: 3.25.76 diff --git a/src/api/index.ts b/src/api/index.ts index 92a5c95770..c80fd5bf72 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -35,6 +35,7 @@ import { DoubaoHandler, ZAiHandler, FireworksHandler, + RooHandler, } from "./providers" import { NativeOllamaHandler } from "./providers/native-ollama" @@ -140,6 +141,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler { return new FireworksHandler(options) case "io-intelligence": return new IOIntelligenceHandler(options) + case "roo": + return new RooHandler(options) default: apiProvider satisfies "gemini-cli" | undefined return new AnthropicHandler(options) diff --git a/src/api/providers/__tests__/roo.spec.ts b/src/api/providers/__tests__/roo.spec.ts new file mode 100644 index 0000000000..5c89e8e1ad --- /dev/null +++ b/src/api/providers/__tests__/roo.spec.ts @@ -0,0 +1,436 @@ +// npx vitest run api/providers/__tests__/roo.spec.ts + +import { Anthropic } from "@anthropic-ai/sdk" +import { rooDefaultModelId, rooModels } from "@roo-code/types" + +import { ApiHandlerOptions } from "../../../shared/api" + +// Mock OpenAI client +const mockCreate = vitest.fn() + +vitest.mock("openai", () => { + return { + __esModule: true, + default: vitest.fn().mockImplementation(() => ({ + chat: { + completions: { + create: mockCreate.mockImplementation(async (options) => { + if (!options.stream) { + return { + id: "test-completion", + choices: [ + { + message: { role: "assistant", content: "Test response" }, + finish_reason: "stop", + index: 0, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, + }, + } + } + + return { + [Symbol.asyncIterator]: async function* () { + yield { + choices: [ + { + delta: { content: "Test response" }, + index: 0, + }, + ], + usage: null, + } + yield { + choices: [ + { + delta: {}, + index: 0, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 5, + total_tokens: 15, + }, + } + }, + } + }), + }, + }, + })), + } +}) + +// Mock CloudService - Define functions outside to avoid initialization issues +const mockGetSessionToken = vitest.fn() +const mockHasInstance = vitest.fn() + +// Create mock functions that we can control +const mockGetSessionTokenFn = vitest.fn() +const mockHasInstanceFn = vitest.fn() + +vitest.mock("@roo-code/cloud", () => ({ + CloudService: { + hasInstance: () => mockHasInstanceFn(), + get instance() { + return { + authService: { + getSessionToken: () => mockGetSessionTokenFn(), + }, + } + }, + }, +})) + +// Mock i18n +vitest.mock("../../../i18n", () => ({ + t: vitest.fn((key: string) => { + if (key === "common:errors.roo.authenticationRequired") { + return "Authentication required for Roo Code Cloud" + } + return key + }), +})) + +// Import after mocks are set up +import { RooHandler } from "../roo" +import { CloudService } from "@roo-code/cloud" +import { t } from "../../../i18n" + +describe("RooHandler", () => { + let handler: RooHandler + let mockOptions: ApiHandlerOptions + const systemPrompt = "You are a helpful assistant." + const messages: Anthropic.Messages.MessageParam[] = [ + { + role: "user", + content: "Hello!", + }, + ] + + beforeEach(() => { + mockOptions = { + apiModelId: "roo/sonic", + } + // Set up CloudService mocks for successful authentication + mockHasInstanceFn.mockReturnValue(true) + mockGetSessionTokenFn.mockReturnValue("test-session-token") + mockCreate.mockClear() + vitest.clearAllMocks() + }) + + describe("constructor", () => { + it("should initialize with valid session token", () => { + handler = new RooHandler(mockOptions) + expect(handler).toBeInstanceOf(RooHandler) + expect(handler.getModel().id).toBe(mockOptions.apiModelId) + }) + + it("should throw error if CloudService is not available", () => { + mockHasInstanceFn.mockReturnValue(false) + expect(() => { + new RooHandler(mockOptions) + }).toThrow("Authentication required for Roo Code Cloud") + expect(t).toHaveBeenCalledWith("common:errors.roo.authenticationRequired") + }) + + it("should throw error if session token is not available", () => { + mockHasInstanceFn.mockReturnValue(true) + mockGetSessionTokenFn.mockReturnValue(null) + expect(() => { + new RooHandler(mockOptions) + }).toThrow("Authentication required for Roo Code Cloud") + expect(t).toHaveBeenCalledWith("common:errors.roo.authenticationRequired") + }) + + it("should initialize with default model if no model specified", () => { + handler = new RooHandler({}) + expect(handler).toBeInstanceOf(RooHandler) + expect(handler.getModel().id).toBe(rooDefaultModelId) + }) + + it("should pass correct configuration to base class", () => { + handler = new RooHandler(mockOptions) + expect(handler).toBeInstanceOf(RooHandler) + // The handler should be initialized with correct base URL and API key + // We can't directly test the parent class constructor, but we can verify the handler works + expect(handler).toBeDefined() + }) + }) + + describe("createMessage", () => { + beforeEach(() => { + handler = new RooHandler(mockOptions) + }) + + it("should handle streaming responses", async () => { + const stream = handler.createMessage(systemPrompt, messages) + const chunks: any[] = [] + for await (const chunk of stream) { + chunks.push(chunk) + } + + expect(chunks.length).toBeGreaterThan(0) + const textChunks = chunks.filter((chunk) => chunk.type === "text") + expect(textChunks).toHaveLength(1) + expect(textChunks[0].text).toBe("Test response") + }) + + it("should include usage information", async () => { + const stream = handler.createMessage(systemPrompt, messages) + const chunks: any[] = [] + for await (const chunk of stream) { + chunks.push(chunk) + } + + const usageChunks = chunks.filter((chunk) => chunk.type === "usage") + expect(usageChunks).toHaveLength(1) + expect(usageChunks[0].inputTokens).toBe(10) + expect(usageChunks[0].outputTokens).toBe(5) + }) + + it("should handle API errors", async () => { + mockCreate.mockRejectedValueOnce(new Error("API Error")) + const stream = handler.createMessage(systemPrompt, messages) + await expect(async () => { + for await (const _chunk of stream) { + // Should not reach here + } + }).rejects.toThrow("API Error") + }) + + it("should handle empty response content", async () => { + mockCreate.mockResolvedValueOnce({ + [Symbol.asyncIterator]: async function* () { + yield { + choices: [ + { + delta: { content: null }, + index: 0, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 0, + total_tokens: 10, + }, + } + }, + }) + + const stream = handler.createMessage(systemPrompt, messages) + const chunks: any[] = [] + for await (const chunk of stream) { + chunks.push(chunk) + } + + const textChunks = chunks.filter((chunk) => chunk.type === "text") + expect(textChunks).toHaveLength(0) + const usageChunks = chunks.filter((chunk) => chunk.type === "usage") + expect(usageChunks).toHaveLength(1) + }) + + it("should handle multiple messages in conversation", async () => { + const multipleMessages: Anthropic.Messages.MessageParam[] = [ + { role: "user", content: "First message" }, + { role: "assistant", content: "First response" }, + { role: "user", content: "Second message" }, + ] + + const stream = handler.createMessage(systemPrompt, multipleMessages) + const chunks: any[] = [] + for await (const chunk of stream) { + chunks.push(chunk) + } + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + messages: expect.arrayContaining([ + expect.objectContaining({ role: "system", content: systemPrompt }), + expect.objectContaining({ role: "user", content: "First message" }), + expect.objectContaining({ role: "assistant", content: "First response" }), + expect.objectContaining({ role: "user", content: "Second message" }), + ]), + }), + ) + }) + }) + + describe("completePrompt", () => { + beforeEach(() => { + handler = new RooHandler(mockOptions) + }) + + it("should complete prompt successfully", async () => { + const result = await handler.completePrompt("Test prompt") + expect(result).toBe("Test response") + expect(mockCreate).toHaveBeenCalledWith({ + model: mockOptions.apiModelId, + messages: [{ role: "user", content: "Test prompt" }], + }) + }) + + it("should handle API errors", async () => { + mockCreate.mockRejectedValueOnce(new Error("API Error")) + await expect(handler.completePrompt("Test prompt")).rejects.toThrow( + "Roo Code Cloud completion error: API Error", + ) + }) + + it("should handle empty response", async () => { + mockCreate.mockResolvedValueOnce({ + choices: [{ message: { content: "" } }], + }) + const result = await handler.completePrompt("Test prompt") + expect(result).toBe("") + }) + + it("should handle missing response content", async () => { + mockCreate.mockResolvedValueOnce({ + choices: [{ message: {} }], + }) + const result = await handler.completePrompt("Test prompt") + expect(result).toBe("") + }) + }) + + describe("getModel", () => { + beforeEach(() => { + handler = new RooHandler(mockOptions) + }) + + it("should return model info for specified model", () => { + const modelInfo = handler.getModel() + expect(modelInfo.id).toBe(mockOptions.apiModelId) + expect(modelInfo.info).toBeDefined() + // roo/sonic is a valid model in rooModels + expect(modelInfo.info).toBe(rooModels["roo/sonic"]) + }) + + it("should return default model when no model specified", () => { + const handlerWithoutModel = new RooHandler({}) + const modelInfo = handlerWithoutModel.getModel() + expect(modelInfo.id).toBe(rooDefaultModelId) + expect(modelInfo.info).toBeDefined() + expect(modelInfo.info).toBe(rooModels[rooDefaultModelId]) + }) + + it("should handle unknown model ID with fallback info", () => { + const handlerWithUnknownModel = new RooHandler({ + apiModelId: "unknown-model-id", + }) + const modelInfo = handlerWithUnknownModel.getModel() + expect(modelInfo.id).toBe("unknown-model-id") + expect(modelInfo.info).toBeDefined() + // Should return fallback info for unknown models + expect(modelInfo.info.maxTokens).toBe(8192) + expect(modelInfo.info.contextWindow).toBe(262_144) + expect(modelInfo.info.supportsImages).toBe(false) + expect(modelInfo.info.supportsPromptCache).toBe(false) + expect(modelInfo.info.inputPrice).toBe(0) + expect(modelInfo.info.outputPrice).toBe(0) + }) + + it("should return correct model info for all Roo models", () => { + // Test each model in rooModels + const modelIds = Object.keys(rooModels) as Array + + for (const modelId of modelIds) { + const handlerWithModel = new RooHandler({ apiModelId: modelId }) + const modelInfo = handlerWithModel.getModel() + expect(modelInfo.id).toBe(modelId) + expect(modelInfo.info).toBe(rooModels[modelId]) + } + }) + }) + + describe("temperature and model configuration", () => { + it("should use default temperature of 0.7", async () => { + handler = new RooHandler(mockOptions) + const stream = handler.createMessage(systemPrompt, messages) + for await (const _chunk of stream) { + // Consume stream + } + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + temperature: 0.7, + }), + ) + }) + + it("should respect custom temperature setting", async () => { + handler = new RooHandler({ + ...mockOptions, + modelTemperature: 0.9, + }) + const stream = handler.createMessage(systemPrompt, messages) + for await (const _chunk of stream) { + // Consume stream + } + + expect(mockCreate).toHaveBeenCalledWith( + expect.objectContaining({ + temperature: 0.9, + }), + ) + }) + + it("should use correct API endpoint", () => { + // The base URL should be set to Roo's API endpoint + // We can't directly test the OpenAI client configuration, but we can verify the handler initializes + handler = new RooHandler(mockOptions) + expect(handler).toBeInstanceOf(RooHandler) + // The handler should work with the Roo API endpoint + }) + }) + + describe("authentication flow", () => { + it("should use session token as API key", () => { + const testToken = "test-session-token-123" + mockGetSessionTokenFn.mockReturnValue(testToken) + + handler = new RooHandler(mockOptions) + expect(handler).toBeInstanceOf(RooHandler) + expect(mockGetSessionTokenFn).toHaveBeenCalled() + }) + + it("should handle undefined auth service", () => { + mockHasInstanceFn.mockReturnValue(true) + // Mock CloudService with undefined authService + const originalGetter = Object.getOwnPropertyDescriptor(CloudService, "instance")?.get + + try { + Object.defineProperty(CloudService, "instance", { + get: () => ({ authService: undefined }), + configurable: true, + }) + + expect(() => { + new RooHandler(mockOptions) + }).toThrow("Authentication required for Roo Code Cloud") + } finally { + // Always restore original getter, even if test fails + if (originalGetter) { + Object.defineProperty(CloudService, "instance", { + get: originalGetter, + configurable: true, + }) + } + } + }) + + it("should handle empty session token", () => { + mockGetSessionTokenFn.mockReturnValue("") + + expect(() => { + new RooHandler(mockOptions) + }).toThrow("Authentication required for Roo Code Cloud") + }) + }) +}) diff --git a/src/api/providers/index.ts b/src/api/providers/index.ts index 736da82d51..80ef0a2879 100644 --- a/src/api/providers/index.ts +++ b/src/api/providers/index.ts @@ -29,3 +29,4 @@ export { VsCodeLmHandler } from "./vscode-lm" export { XAIHandler } from "./xai" export { ZAiHandler } from "./zai" export { FireworksHandler } from "./fireworks" +export { RooHandler } from "./roo" diff --git a/src/api/providers/roo.ts b/src/api/providers/roo.ts new file mode 100644 index 0000000000..3b0540c2ea --- /dev/null +++ b/src/api/providers/roo.ts @@ -0,0 +1,53 @@ +import { rooDefaultModelId, rooModels, type RooModelId } from "@roo-code/types" +import { CloudService } from "@roo-code/cloud" + +import type { ApiHandlerOptions } from "../../shared/api" +import { BaseOpenAiCompatibleProvider } from "./base-openai-compatible-provider" +import { t } from "../../i18n" + +export class RooHandler extends BaseOpenAiCompatibleProvider { + constructor(options: ApiHandlerOptions) { + // Check if CloudService is available and get the session token. + if (!CloudService.hasInstance()) { + throw new Error(t("common:errors.roo.authenticationRequired")) + } + + const sessionToken = CloudService.instance.authService?.getSessionToken() + + if (!sessionToken) { + throw new Error(t("common:errors.roo.authenticationRequired")) + } + + super({ + ...options, + providerName: "Roo Code Cloud", + baseURL: "https://api.roocode.com/proxy/v1", + apiKey: sessionToken, + defaultProviderModelId: rooDefaultModelId, + providerModels: rooModels, + defaultTemperature: 0.7, + }) + } + + override getModel() { + const modelId = this.options.apiModelId || rooDefaultModelId + const modelInfo = this.providerModels[modelId as RooModelId] ?? this.providerModels[rooDefaultModelId] + + if (modelInfo) { + return { id: modelId as RooModelId, info: modelInfo } + } + + // Return the requested model ID even if not found, with fallback info. + return { + id: modelId as RooModelId, + info: { + maxTokens: 8192, + contextWindow: 262_144, + supportsImages: false, + supportsPromptCache: false, + inputPrice: 0, + outputPrice: 0, + }, + } + } +} diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index d4fddfebf3..6235593f7e 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -104,6 +104,9 @@ "noResponseBody": "Error de l'API de Cerebras: No hi ha cos de resposta", "completionError": "Error de finalització de Cerebras: {{error}}" }, + "roo": { + "authenticationRequired": "El proveïdor Roo requereix autenticació al núvol. Si us plau, inicieu sessió a Roo Code Cloud." + }, "mode_import_failed": "Ha fallat la importació del mode: {{error}}" }, "warnings": { diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index af69ed7cfe..6819b27d73 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras API-Fehler ({{status}}): {{message}}", "noResponseBody": "Cerebras API-Fehler: Kein Antworttext vorhanden", "completionError": "Cerebras-Vervollständigungsfehler: {{error}}" + }, + "roo": { + "authenticationRequired": "Roo-Anbieter erfordert Cloud-Authentifizierung. Bitte melde dich bei Roo Code Cloud an." } }, "warnings": { diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 05d039a495..696ecb44d4 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras API Error ({{status}}): {{message}}", "noResponseBody": "Cerebras API Error: No response body", "completionError": "Cerebras completion error: {{error}}" + }, + "roo": { + "authenticationRequired": "Roo provider requires cloud authentication. Please sign in to Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 28e2fc3812..c1b399b84f 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -100,6 +100,9 @@ "genericError": "Error de la API de Cerebras ({{status}}): {{message}}", "noResponseBody": "Error de la API de Cerebras: Sin cuerpo de respuesta", "completionError": "Error de finalización de Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "El proveedor Roo requiere autenticación en la nube. Por favor, inicia sesión en Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index c3264e7ba3..682e12e224 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -100,6 +100,9 @@ "genericError": "Erreur de l'API Cerebras ({{status}}) : {{message}}", "noResponseBody": "Erreur de l'API Cerebras : Aucun corps de réponse", "completionError": "Erreur d'achèvement de Cerebras : {{error}}" + }, + "roo": { + "authenticationRequired": "Le fournisseur Roo nécessite une authentification cloud. Veuillez vous connecter à Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index c68d002e1d..05e0a622cc 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras API त्रुटि ({{status}}): {{message}}", "noResponseBody": "Cerebras API त्रुटि: कोई प्रतिक्रिया मुख्य भाग नहीं", "completionError": "Cerebras पूर्णता त्रुटि: {{error}}" + }, + "roo": { + "authenticationRequired": "Roo प्रदाता को क्लाउड प्रमाणीकरण की आवश्यकता है। कृपया Roo Code Cloud में साइन इन करें।" } }, "warnings": { diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index 4045b7e8bb..1595b795cf 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -100,6 +100,9 @@ "genericError": "Kesalahan API Cerebras ({{status}}): {{message}}", "noResponseBody": "Kesalahan API Cerebras: Tidak ada isi respons", "completionError": "Kesalahan penyelesaian Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "Penyedia Roo memerlukan autentikasi cloud. Silakan masuk ke Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index a059c48a9b..73f4d47788 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -100,6 +100,9 @@ "genericError": "Errore API Cerebras ({{status}}): {{message}}", "noResponseBody": "Errore API Cerebras: Nessun corpo di risposta", "completionError": "Errore di completamento Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "Il provider Roo richiede l'autenticazione cloud. Accedi a Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index f9eceb5979..cb55c7bf0b 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras APIエラー ({{status}}): {{message}}", "noResponseBody": "Cerebras APIエラー: レスポンスボディなし", "completionError": "Cerebras完了エラー: {{error}}" + }, + "roo": { + "authenticationRequired": "Rooプロバイダーはクラウド認証が必要です。Roo Code Cloudにサインインしてください。" } }, "warnings": { diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 4292677e30..9bb61b6563 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras API 오류 ({{status}}): {{message}}", "noResponseBody": "Cerebras API 오류: 응답 본문 없음", "completionError": "Cerebras 완료 오류: {{error}}" + }, + "roo": { + "authenticationRequired": "Roo 제공업체는 클라우드 인증이 필요합니다. Roo Code Cloud에 로그인하세요." } }, "warnings": { diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json index 2133e7003b..fb2fcec9f9 100644 --- a/src/i18n/locales/nl/common.json +++ b/src/i18n/locales/nl/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras API-fout ({{status}}): {{message}}", "noResponseBody": "Cerebras API-fout: Geen responslichaam", "completionError": "Cerebras-voltooiingsfout: {{error}}" + }, + "roo": { + "authenticationRequired": "Roo provider vereist cloud authenticatie. Log in bij Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index 1c63702911..2a6fee3e23 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -100,6 +100,9 @@ "genericError": "Błąd API Cerebras ({{status}}): {{message}}", "noResponseBody": "Błąd API Cerebras: Brak treści odpowiedzi", "completionError": "Błąd uzupełniania Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "Dostawca Roo wymaga uwierzytelnienia w chmurze. Zaloguj się do Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index 6aeb5f6ee7..83d960ad2d 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -104,6 +104,9 @@ "genericError": "Erro da API Cerebras ({{status}}): {{message}}", "noResponseBody": "Erro da API Cerebras: Sem corpo de resposta", "completionError": "Erro de conclusão do Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "O provedor Roo requer autenticação na nuvem. Faça login no Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 0d7b800d8b..9c37cfe3ed 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -100,6 +100,9 @@ "genericError": "Ошибка Cerebras API ({{status}}): {{message}}", "noResponseBody": "Ошибка Cerebras API: Нет тела ответа", "completionError": "Ошибка завершения Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "Провайдер Roo требует облачной аутентификации. Войдите в Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 49d0fba113..d99008755e 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -100,6 +100,9 @@ "genericError": "Cerebras API Hatası ({{status}}): {{message}}", "noResponseBody": "Cerebras API Hatası: Yanıt gövdesi yok", "completionError": "Cerebras tamamlama hatası: {{error}}" + }, + "roo": { + "authenticationRequired": "Roo sağlayıcısı bulut kimlik doğrulaması gerektirir. Lütfen Roo Code Cloud'a giriş yapın." } }, "warnings": { diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 3f8947e620..d29525cc03 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -100,6 +100,9 @@ "genericError": "Lỗi API Cerebras ({{status}}): {{message}}", "noResponseBody": "Lỗi API Cerebras: Không có nội dung phản hồi", "completionError": "Lỗi hoàn thành Cerebras: {{error}}" + }, + "roo": { + "authenticationRequired": "Nhà cung cấp Roo yêu cầu xác thực đám mây. Vui lòng đăng nhập vào Roo Code Cloud." } }, "warnings": { diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index 808d534572..fc0386c95d 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -105,6 +105,9 @@ "genericError": "Cerebras API 错误 ({{status}}):{{message}}", "noResponseBody": "Cerebras API 错误:无响应主体", "completionError": "Cerebras 完成错误:{{error}}" + }, + "roo": { + "authenticationRequired": "Roo 提供商需要云认证。请登录 Roo Code Cloud。" } }, "warnings": { diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index 81e098fbcf..753463b9f5 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -100,6 +100,9 @@ "noResponseBody": "Cerebras API 錯誤:無回應主體", "completionError": "Cerebras 完成錯誤:{{error}}" }, + "roo": { + "authenticationRequired": "Roo 提供者需要雲端認證。請登入 Roo Code Cloud。" + }, "mode_import_failed": "匯入模式失敗:{{error}}" }, "warnings": { diff --git a/src/package.json b/src/package.json index 48e785d7b9..d6c447db39 100644 --- a/src/package.json +++ b/src/package.json @@ -427,7 +427,7 @@ "@mistralai/mistralai": "^1.3.6", "@modelcontextprotocol/sdk": "^1.9.0", "@qdrant/js-client-rest": "^1.14.0", - "@roo-code/cloud": "^0.17.0", + "@roo-code/cloud": "^0.18.0", "@roo-code/ipc": "workspace:^", "@roo-code/telemetry": "workspace:^", "@roo-code/types": "workspace:^", diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx index b51b171354..6db3dab529 100644 --- a/webview-ui/src/components/settings/ApiOptions.tsx +++ b/webview-ui/src/components/settings/ApiOptions.tsx @@ -1,7 +1,7 @@ import React, { memo, useCallback, useEffect, useMemo, useState } from "react" import { convertHeadersToObject } from "./utils/headers" import { useDebounce } from "react-use" -import { VSCodeLink } from "@vscode/webview-ui-toolkit/react" +import { VSCodeLink, VSCodeButton } from "@vscode/webview-ui-toolkit/react" import { ExternalLinkIcon } from "@radix-ui/react-icons" import { @@ -32,6 +32,7 @@ import { mainlandZAiDefaultModelId, fireworksDefaultModelId, ioIntelligenceDefaultModelId, + rooDefaultModelId, } from "@roo-code/types" import { vscode } from "@src/utils/vscode" @@ -124,7 +125,7 @@ const ApiOptions = ({ setErrorMessage, }: ApiOptionsProps) => { const { t } = useAppTranslation() - const { organizationAllowList } = useExtensionState() + const { organizationAllowList, cloudIsAuthenticated } = useExtensionState() const [customHeaders, setCustomHeaders] = useState<[string, string][]>(() => { const headers = apiConfiguration?.openAiHeaders || {} @@ -327,6 +328,7 @@ const ApiOptions = ({ }, fireworks: { field: "apiModelId", default: fireworksDefaultModelId }, "io-intelligence": { field: "ioIntelligenceModelId", default: ioIntelligenceDefaultModelId }, + roo: { field: "apiModelId", default: rooDefaultModelId }, openai: { field: "openAiModelId" }, ollama: { field: "ollamaModelId" }, lmstudio: { field: "lmStudioModelId" }, @@ -579,6 +581,25 @@ const ApiOptions = ({ )} + {selectedProvider === "roo" && ( +
+ {cloudIsAuthenticated ? ( +
+ {t("settings:providers.roo.authenticatedMessage")} +
+ ) : ( +
+ vscode.postMessage({ type: "rooCloudSignIn" })} + className="w-fit"> + {t("settings:providers.roo.connectButton")} + +
+ )} +
+ )} + {selectedProviderModels.length > 0 && ( <>
diff --git a/webview-ui/src/components/settings/ModelDescriptionMarkdown.tsx b/webview-ui/src/components/settings/ModelDescriptionMarkdown.tsx index d6aac8ba74..b04ab1163e 100644 --- a/webview-ui/src/components/settings/ModelDescriptionMarkdown.tsx +++ b/webview-ui/src/components/settings/ModelDescriptionMarkdown.tsx @@ -34,7 +34,7 @@ export const ModelDescriptionMarkdown = memo( return ( -
+
{content}
diff --git a/webview-ui/src/components/settings/ModelInfoView.tsx b/webview-ui/src/components/settings/ModelInfoView.tsx index 2ba732effa..5091fb1a68 100644 --- a/webview-ui/src/components/settings/ModelInfoView.tsx +++ b/webview-ui/src/components/settings/ModelInfoView.tsx @@ -26,6 +26,18 @@ export const ModelInfoView = ({ const { t } = useAppTranslation() const infoItems = [ + typeof modelInfo?.contextWindow === "number" && modelInfo.contextWindow > 0 && ( + <> + {t("settings:modelInfo.contextWindow")}{" "} + {modelInfo.contextWindow?.toLocaleString()} tokens + + ), + typeof modelInfo?.maxTokens === "number" && modelInfo.maxTokens > 0 && ( + <> + {t("settings:modelInfo.maxOutput")}:{" "} + {modelInfo.maxTokens?.toLocaleString()} tokens + + ), , - typeof modelInfo?.contextWindow === "number" && modelInfo.contextWindow > 0 && ( - <> - {t("settings:modelInfo.contextWindow")}{" "} - {modelInfo.contextWindow?.toLocaleString()} tokens - - ), - typeof modelInfo?.maxTokens === "number" && modelInfo.maxTokens > 0 && ( - <> - {t("settings:modelInfo.maxOutput")}:{" "} - {modelInfo.maxTokens?.toLocaleString()} tokens - - ), modelInfo?.inputPrice !== undefined && modelInfo.inputPrice > 0 && ( <> {t("settings:modelInfo.inputPrice")}:{" "} @@ -119,11 +119,7 @@ const ModelInfoSupportsItem = ({ supportsLabel: string doesNotSupportLabel: string }) => ( -
+
{isSupported ? supportsLabel : doesNotSupportLabel}
diff --git a/webview-ui/src/components/settings/constants.ts b/webview-ui/src/components/settings/constants.ts index 5882b1bf4a..dc54d367eb 100644 --- a/webview-ui/src/components/settings/constants.ts +++ b/webview-ui/src/components/settings/constants.ts @@ -18,6 +18,7 @@ import { doubaoModels, internationalZAiModels, fireworksModels, + rooModels, } from "@roo-code/types" export const MODELS_BY_PROVIDER: Partial>> = { @@ -38,6 +39,7 @@ export const MODELS_BY_PROVIDER: Partial a.label.localeCompare(b.label)) diff --git a/webview-ui/src/components/ui/hooks/useSelectedModel.ts b/webview-ui/src/components/ui/hooks/useSelectedModel.ts index b188f3e342..a4a36857a0 100644 --- a/webview-ui/src/components/ui/hooks/useSelectedModel.ts +++ b/webview-ui/src/components/ui/hooks/useSelectedModel.ts @@ -48,6 +48,8 @@ import { fireworksDefaultModelId, ioIntelligenceDefaultModelId, ioIntelligenceModels, + rooDefaultModelId, + rooModels, BEDROCK_CLAUDE_SONNET_4_MODEL_ID, } from "@roo-code/types" @@ -296,6 +298,11 @@ function getSelectedModel({ routerModels["io-intelligence"]?.[id] ?? ioIntelligenceModels[id as keyof typeof ioIntelligenceModels] return { id, info } } + case "roo": { + const id = apiConfiguration.apiModelId ?? rooDefaultModelId + const info = rooModels[id as keyof typeof rooModels] + return { id, info } + } // case "anthropic": // case "human-relay": // case "fake-ai": diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index ede37e530e..3f7f1c901a 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Versió {{version}} - Feu clic per veure les notes de llançament" }, "rooCloudCTA": { - "title": "Roo Code Cloud arribarà aviat!", + "title": "Roo Code Cloud està evolucionant!", "description": "Executa agents remots al núvol, accedeix a les teves tasques des de qualsevol lloc, col·labora amb altres i molt més.", - "joinWaitlist": "Uneix-te a la llista d'espera per obtenir accés anticipat." + "joinWaitlist": "Registra't per rebre les últimes actualitzacions." }, "editMessage": { "placeholder": "Edita el teu missatge..." diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 5964798684..97c5e39352 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -377,6 +377,10 @@ "description": "No es requereix clau API, però l'usuari necessita ajuda per copiar i enganxar informació al xat d'IA web.", "instructions": "Durant l'ús, apareixerà un diàleg i el missatge actual es copiarà automàticament al porta-retalls. Necessiteu enganxar-lo a les versions web d'IA (com ChatGPT o Claude), després copiar la resposta de l'IA de nou al diàleg i fer clic al botó de confirmació." }, + "roo": { + "authenticatedMessage": "Autenticat de forma segura a través del teu compte de Roo Code Cloud.", + "connectButton": "Connecta amb Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Encaminament de Proveïdors d'OpenRouter", diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 0574da2df3..2eaee9feac 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Version {{version}} - Klicken Sie, um die Versionshinweise anzuzeigen" }, "rooCloudCTA": { - "title": "Roo Code Cloud kommt bald!", + "title": "Roo Code Cloud entwickelt sich weiter!", "description": "Führe Remote-Agenten in der Cloud aus, greife von überall auf deine Aufgaben zu, arbeite mit anderen zusammen und vieles mehr.", - "joinWaitlist": "Tritt der Warteliste bei, um frühen Zugang zu erhalten." + "joinWaitlist": "Melde dich an, um die neuesten Updates zu erhalten." }, "command": { "triggerDescription": "Starte den {{name}} Befehl" diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 28f3e847fa..2d699a0e96 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -377,6 +377,10 @@ "description": "Es ist kein API-Schlüssel erforderlich, aber der Benutzer muss beim Kopieren und Einfügen der Informationen in den Web-Chat-KI helfen.", "instructions": "Während der Verwendung wird ein Dialogfeld angezeigt und die aktuelle Nachricht wird automatisch in die Zwischenablage kopiert. Du musst diese in Web-Versionen von KI (wie ChatGPT oder Claude) einfügen, dann die Antwort der KI zurück in das Dialogfeld kopieren und auf die Bestätigungsschaltfläche klicken." }, + "roo": { + "authenticatedMessage": "Sicher authentifiziert über dein Roo Code Cloud-Konto.", + "connectButton": "Mit Roo Code Cloud verbinden" + }, "openRouter": { "providerRouting": { "title": "OpenRouter Anbieter-Routing", diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 3479cdf69b..ef5ff39e9a 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -352,9 +352,9 @@ "ariaLabel": "Version {{version}} - Click to view release notes" }, "rooCloudCTA": { - "title": "Roo Code Cloud is coming soon!", + "title": "Roo Code Cloud is evolving!", "description": "Run Roomote agents in the cloud, access your tasks from anywhere, collaborate with others, and more.", - "joinWaitlist": "Join the waitlist to get early access." + "joinWaitlist": "Sign up to get the latest updates." }, "command": { "triggerDescription": "Trigger the {{name}} command" diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index fca3d1ade9..4f70e437c2 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -376,6 +376,10 @@ "description": "No API key is required, but the user needs to help copy and paste the information to the web chat AI.", "instructions": "During use, a dialog box will pop up and the current message will be copied to the clipboard automatically. You need to paste these to web versions of AI (such as ChatGPT or Claude), then copy the AI's reply back to the dialog box and click the confirm button." }, + "roo": { + "authenticatedMessage": "Securely authenticated through your Roo Code Cloud account.", + "connectButton": "Connect to Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "OpenRouter Provider Routing", diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 3621aa16cf..dc28671d04 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Versión {{version}} - Haz clic para ver las notas de la versión" }, "rooCloudCTA": { - "title": "¡Roo Code Cloud llegará pronto!", + "title": "¡Roo Code Cloud está evolucionando!", "description": "Ejecuta agentes remotos en la nube, accede a tus tareas desde cualquier lugar, colabora con otros y mucho más.", - "joinWaitlist": "Únete a la lista de espera para obtener acceso anticipado." + "joinWaitlist": "Regístrate para recibir las últimas actualizaciones." }, "editMessage": { "placeholder": "Edita tu mensaje..." diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index fd6e1e2715..7f22887ee1 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -377,6 +377,10 @@ "description": "No se requiere clave API, pero el usuario necesita ayudar a copiar y pegar la información en el chat web de IA.", "instructions": "Durante el uso, aparecerá un cuadro de diálogo y el mensaje actual se copiará automáticamente al portapapeles. Debe pegarlo en las versiones web de IA (como ChatGPT o Claude), luego copiar la respuesta de la IA de vuelta al cuadro de diálogo y hacer clic en el botón de confirmar." }, + "roo": { + "authenticatedMessage": "Autenticado de forma segura a través de tu cuenta de Roo Code Cloud.", + "connectButton": "Conectar a Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Enrutamiento de Proveedores de OpenRouter", diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 41ea4dd5a1..f7acde6eec 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Version {{version}} - Cliquez pour voir les notes de version" }, "rooCloudCTA": { - "title": "Roo Code Cloud arrive bientôt !", + "title": "Roo Code Cloud évolue !", "description": "Exécutez des agents distants dans le cloud, accédez à vos tâches de n'importe où, collaborez avec d'autres et bien plus encore.", - "joinWaitlist": "Rejoignez la liste d'attente pour obtenir un accès anticipé." + "joinWaitlist": "Inscrivez-vous pour recevoir les dernières mises à jour." }, "editMessage": { "placeholder": "Modifiez votre message..." diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 451e51d084..c544673df6 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -377,6 +377,10 @@ "description": "Aucune clé API n'est requise, mais l'utilisateur doit aider à copier et coller les informations dans le chat web de l'IA.", "instructions": "Pendant l'utilisation, une boîte de dialogue apparaîtra et le message actuel sera automatiquement copié dans le presse-papiers. Vous devez le coller dans les versions web de l'IA (comme ChatGPT ou Claude), puis copier la réponse de l'IA dans la boîte de dialogue et cliquer sur le bouton de confirmation." }, + "roo": { + "authenticatedMessage": "Authentifié de manière sécurisée via ton compte Roo Code Cloud.", + "connectButton": "Se connecter à Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Routage des fournisseurs OpenRouter", diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 05288792cf..3c8984b405 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "संस्करण {{version}} - रिलीज़ नोट्स देखने के लिए क्लिक करें" }, "rooCloudCTA": { - "title": "Roo Code Cloud जल्द आ रहा है!", + "title": "Roo Code Cloud विकसित हो रहा है!", "description": "क्लाउड में रिमोट एजेंट चलाएं, कहीं से भी अपने कार्यों तक पहुंचें, दूसरों के साथ सहयोग करें, और बहुत कुछ।", - "joinWaitlist": "जल्दी पहुंच पाने के लिए प्रतीक्षा सूची में शामिल हों।" + "joinWaitlist": "नवीनतम अपडेट प्राप्त करने के लिए साइन अप करें।" }, "editMessage": { "placeholder": "अपना संदेश संपादित करें..." diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 83a4b7b81b..536d63d2a5 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -377,6 +377,10 @@ "description": "कोई API कुंजी आवश्यक नहीं है, लेकिन उपयोगकर्ता को वेब चैट AI में जानकारी कॉपी और पेस्ट करने में मदद करनी होगी।", "instructions": "उपयोग के दौरान, एक डायलॉग बॉक्स पॉप अप होगा और वर्तमान संदेश स्वचालित रूप से क्लिपबोर्ड पर कॉपी हो जाएगा। आपको इन्हें AI के वेब संस्करणों (जैसे ChatGPT या Claude) में पेस्ट करना होगा, फिर AI की प्रतिक्रिया को डायलॉग बॉक्स में वापस कॉपी करें और पुष्टि बटन पर क्लिक करें।" }, + "roo": { + "authenticatedMessage": "आपके Roo Code Cloud खाते के माध्यम से सुरक्षित रूप से प्रमाणित।", + "connectButton": "Roo Code Cloud से कनेक्ट करें" + }, "openRouter": { "providerRouting": { "title": "OpenRouter प्रदाता रूटिंग", diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index 909606ee91..bfcf3614f6 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -355,9 +355,9 @@ "ariaLabel": "Versi {{version}} - Klik untuk melihat catatan rilis" }, "rooCloudCTA": { - "title": "Roo Code Cloud segera hadir!", + "title": "Roo Code Cloud sedang berkembang!", "description": "Jalankan agen jarak jauh di cloud, akses tugas Anda dari mana saja, berkolaborasi dengan orang lain, dan banyak lagi.", - "joinWaitlist": "Bergabunglah dengan daftar tunggu untuk mendapatkan akses awal." + "joinWaitlist": "Daftar untuk mendapatkan pembaruan terbaru." }, "editMessage": { "placeholder": "Edit pesan Anda..." diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index fd7edf40cf..672adb9eda 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -381,6 +381,10 @@ "description": "Tidak diperlukan API key, tetapi pengguna perlu membantu menyalin dan menempel informasi ke web chat AI.", "instructions": "Selama penggunaan, kotak dialog akan muncul dan pesan saat ini akan disalin ke clipboard secara otomatis. Kamu perlu menempel ini ke versi web AI (seperti ChatGPT atau Claude), lalu salin balasan AI kembali ke kotak dialog dan klik tombol konfirmasi." }, + "roo": { + "authenticatedMessage": "Terautentikasi dengan aman melalui akun Roo Code Cloud Anda.", + "connectButton": "Hubungkan ke Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "OpenRouter Provider Routing", diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 480cc13fad..90ee97b7ce 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Versione {{version}} - Clicca per visualizzare le note di rilascio" }, "rooCloudCTA": { - "title": "Roo Code Cloud arriva presto!", + "title": "Roo Code Cloud si sta evolvendo!", "description": "Esegui agenti remoti nel cloud, accedi alle tue attività da qualsiasi luogo, collabora con altri e molto altro.", - "joinWaitlist": "Unisciti alla lista d'attesa per ottenere l'accesso anticipato." + "joinWaitlist": "Registrati per ricevere gli ultimi aggiornamenti." }, "editMessage": { "placeholder": "Modifica il tuo messaggio..." diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index c8a8800e4f..a04258d398 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -377,6 +377,10 @@ "description": "Non è richiesta alcuna chiave API, ma l'utente dovrà aiutare a copiare e incollare le informazioni nella chat web AI.", "instructions": "Durante l'uso, apparirà una finestra di dialogo e il messaggio corrente verrà automaticamente copiato negli appunti. Dovrai incollarlo nelle versioni web dell'AI (come ChatGPT o Claude), quindi copiare la risposta dell'AI nella finestra di dialogo e fare clic sul pulsante di conferma." }, + "roo": { + "authenticatedMessage": "Autenticato in modo sicuro tramite il tuo account Roo Code Cloud.", + "connectButton": "Connetti a Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Routing dei fornitori OpenRouter", diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 6b3340e7f0..46c228638a 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "バージョン {{version}} - クリックしてリリースノートを表示" }, "rooCloudCTA": { - "title": "Roo Code Cloud が間もなく登場!", + "title": "Roo Code Cloud が進化中!", "description": "クラウドでリモートエージェントを実行し、どこからでもタスクにアクセスし、他の人と協力し、その他多くの機能を利用できます。", - "joinWaitlist": "早期アクセスを取得するためにウェイトリストに参加してください。" + "joinWaitlist": "最新のアップデートを受け取るためにサインアップしてください。" }, "editMessage": { "placeholder": "メッセージを編集..." diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index d3e7b04baf..6c1859c85d 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -377,6 +377,10 @@ "description": "APIキーは不要ですが、ユーザーはウェブチャットAIに情報をコピー&ペーストする必要があります。", "instructions": "使用中にダイアログボックスが表示され、現在のメッセージが自動的にクリップボードにコピーされます。これらをウェブ版のAI(ChatGPTやClaudeなど)に貼り付け、AIの返答をダイアログボックスにコピーして確認ボタンをクリックする必要があります。" }, + "roo": { + "authenticatedMessage": "Roo Code Cloudアカウントを通じて安全に認証されています。", + "connectButton": "Roo Code Cloudに接続" + }, "openRouter": { "providerRouting": { "title": "OpenRouterプロバイダールーティング", diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 4b8d652f03..9b625a7ae7 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "버전 {{version}} - 릴리스 노트를 보려면 클릭하세요" }, "rooCloudCTA": { - "title": "Roo Code Cloud가 곧 출시됩니다!", + "title": "Roo Code Cloud가 진화하고 있습니다!", "description": "클라우드에서 원격 에이전트를 실행하고, 어디서나 작업에 액세스하고, 다른 사람들과 협업하는 등 다양한 기능을 이용하세요.", - "joinWaitlist": "얼리 액세스를 받으려면 대기 목록에 가입하세요." + "joinWaitlist": "최신 업데이트를 받으려면 가입하세요." }, "editMessage": { "placeholder": "메시지 편집..." diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index a5bcd1f385..e77a806920 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -377,6 +377,10 @@ "description": "API 키가 필요하지 않지만, 사용자가 웹 채팅 AI에 정보를 복사하여 붙여넣어야 합니다.", "instructions": "사용 중에 대화 상자가 나타나고 현재 메시지가 자동으로 클립보드에 복사됩니다. 이를 웹 버전 AI(예: ChatGPT 또는 Claude)에 붙여넣은 다음, AI의 응답을 대화 상자에 복사하고 확인 버튼을 클릭해야 합니다." }, + "roo": { + "authenticatedMessage": "Roo Code Cloud 계정을 통해 안전하게 인증되었습니다.", + "connectButton": "Roo Code Cloud에 연결" + }, "openRouter": { "providerRouting": { "title": "OpenRouter 제공자 라우팅", diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 871ab1371e..5fc5001750 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Versie {{version}} - Klik om release notes te bekijken" }, "rooCloudCTA": { - "title": "Roo Code Cloud komt binnenkort!", + "title": "Roo Code Cloud evolueert!", "description": "Voer externe agenten uit in de cloud, krijg overal toegang tot je taken, werk samen met anderen en nog veel meer.", - "joinWaitlist": "Sluit je aan bij de wachtlijst voor vroege toegang." + "joinWaitlist": "Meld je aan om de laatste updates te ontvangen." }, "editMessage": { "placeholder": "Bewerk je bericht..." diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index b54e021be0..42c1d97bdb 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -377,6 +377,10 @@ "description": "Geen API-sleutel vereist, maar de gebruiker moet helpen met kopiëren en plakken naar de webchat-AI.", "instructions": "Tijdens gebruik verschijnt een dialoogvenster en wordt het huidige bericht automatisch naar het klembord gekopieerd. Je moet deze plakken in webversies van AI (zoals ChatGPT of Claude), vervolgens het antwoord van de AI terugkopiëren naar het dialoogvenster en op bevestigen klikken." }, + "roo": { + "authenticatedMessage": "Veilig geauthenticeerd via je Roo Code Cloud-account.", + "connectButton": "Verbinden met Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "OpenRouter-providerroutering", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 5a06dc3091..8e8500bea1 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Wersja {{version}} - Kliknij, aby wyświetlić informacje o wydaniu" }, "rooCloudCTA": { - "title": "Roo Code Cloud już wkrótce!", + "title": "Roo Code Cloud się rozwija!", "description": "Uruchamiaj zdalne agenty w chmurze, uzyskuj dostęp do swoich zadań z dowolnego miejsca, współpracuj z innymi i wiele więcej.", - "joinWaitlist": "Dołącz do listy oczekujących, aby uzyskać wczesny dostęp." + "joinWaitlist": "Zarejestruj się, aby otrzymywać najnowsze aktualizacje." }, "editMessage": { "placeholder": "Edytuj swoją wiadomość..." diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 194bd9029d..f1abf9c79d 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -377,6 +377,10 @@ "description": "Nie jest wymagany klucz API, ale użytkownik będzie musiał pomóc w kopiowaniu i wklejaniu informacji do czatu internetowego AI.", "instructions": "Podczas użytkowania pojawi się okno dialogowe, a bieżąca wiadomość zostanie automatycznie skopiowana do schowka. Będziesz musiał wkleić ją do internetowych wersji AI (takich jak ChatGPT lub Claude), a następnie skopiować odpowiedź AI z powrotem do okna dialogowego i kliknąć przycisk potwierdzenia." }, + "roo": { + "authenticatedMessage": "Bezpiecznie uwierzytelniony przez twoje konto Roo Code Cloud.", + "connectButton": "Połącz z Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Routing dostawców OpenRouter", diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 65854c508d..72e3fc4b7d 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Versão {{version}} - Clique para ver as notas de lançamento" }, "rooCloudCTA": { - "title": "Roo Code Cloud chegará em breve!", + "title": "Roo Code Cloud está evoluindo!", "description": "Execute agentes remotos na nuvem, acesse suas tarefas de qualquer lugar, colabore com outros e muito mais.", - "joinWaitlist": "Junte-se à lista de espera para obter acesso antecipado." + "joinWaitlist": "Cadastre-se para receber as últimas atualizações." }, "editMessage": { "placeholder": "Edite sua mensagem..." diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 7879dd5154..c566ee1e2d 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -377,6 +377,10 @@ "description": "Não é necessária chave de API, mas o usuário precisa ajudar a copiar e colar as informações para a IA do chat web.", "instructions": "Durante o uso, uma caixa de diálogo será exibida e a mensagem atual será copiada para a área de transferência automaticamente. Você precisa colar isso nas versões web de IA (como ChatGPT ou Claude), depois copiar a resposta da IA de volta para a caixa de diálogo e clicar no botão confirmar." }, + "roo": { + "authenticatedMessage": "Autenticado com segurança através da sua conta Roo Code Cloud.", + "connectButton": "Conectar ao Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Roteamento de Provedores OpenRouter", diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index ff43851495..a9e242ac34 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Версия {{version}} - Нажмите, чтобы просмотреть примечания к выпуску" }, "rooCloudCTA": { - "title": "Roo Code Cloud скоро появится!", + "title": "Roo Code Cloud развивается!", "description": "Запускайте удаленные агенты в облаке, получайте доступ к своим задачам из любого места, сотрудничайте с другими и многое другое.", - "joinWaitlist": "Присоединитесь к списку ожидания для получения раннего доступа." + "joinWaitlist": "Зарегистрируйтесь, чтобы получать последние обновления." }, "editMessage": { "placeholder": "Редактировать сообщение..." diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 3744ecedff..98df1f0138 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -377,6 +377,10 @@ "description": "API-ключ не требуется, но пользователю нужно вручную копировать и вставлять информацию в веб-чат ИИ.", "instructions": "Во время использования появится диалоговое окно, и текущее сообщение будет скопировано в буфер обмена автоматически. Вам нужно вставить его в веб-версию ИИ (например, ChatGPT или Claude), затем скопировать ответ ИИ обратно в диалоговое окно и нажать кнопку подтверждения." }, + "roo": { + "authenticatedMessage": "Безопасно аутентифицирован через твой аккаунт Roo Code Cloud.", + "connectButton": "Подключиться к Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Маршрутизация провайдера OpenRouter", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index cf3dee847b..361902d50a 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Sürüm {{version}} - Sürüm notlarını görüntülemek için tıklayın" }, "rooCloudCTA": { - "title": "Roo Code Cloud yakında geliyor!", + "title": "Roo Code Cloud gelişiyor!", "description": "Bulutta uzak ajanlar çalıştırın, görevlerinize her yerden erişin, başkalarıyla işbirliği yapın ve daha fazlası.", - "joinWaitlist": "Erken erişim için bekleme listesine katılın." + "joinWaitlist": "En son güncellemeleri almak için kaydolun." }, "editMessage": { "placeholder": "Mesajını düzenle..." diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index be1a7a0169..4fb043a8a0 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -377,6 +377,10 @@ "description": "API anahtarı gerekmez, ancak kullanıcının bilgileri web sohbet yapay zekasına kopyalayıp yapıştırması gerekir.", "instructions": "Kullanım sırasında bir iletişim kutusu açılacak ve mevcut mesaj otomatik olarak panoya kopyalanacaktır. Bunları web yapay zekalarına (ChatGPT veya Claude gibi) yapıştırmanız, ardından yapay zekanın yanıtını iletişim kutusuna kopyalayıp onay düğmesine tıklamanız gerekir." }, + "roo": { + "authenticatedMessage": "Roo Code Cloud hesabın üzerinden güvenli bir şekilde kimlik doğrulandı.", + "connectButton": "Roo Code Cloud'a Bağlan" + }, "openRouter": { "providerRouting": { "title": "OpenRouter Sağlayıcı Yönlendirmesi", diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index e1bf274511..11466382a7 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "Phiên bản {{version}} - Nhấp để xem ghi chú phát hành" }, "rooCloudCTA": { - "title": "Roo Code Cloud sắp ra mắt!", + "title": "Roo Code Cloud đang phát triển!", "description": "Chạy các agent từ xa trên cloud, truy cập các tác vụ của bạn từ mọi nơi, cộng tác với người khác và nhiều hơn nữa.", - "joinWaitlist": "Tham gia danh sách chờ để được truy cập sớm." + "joinWaitlist": "Đăng ký để nhận các cập nhật mới nhất." }, "editMessage": { "placeholder": "Chỉnh sửa tin nhắn của bạn..." diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 7526cf31a7..c9e6b5afbb 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -377,6 +377,10 @@ "description": "Không cần khóa API, nhưng người dùng cần giúp sao chép và dán thông tin vào AI trò chuyện web.", "instructions": "Trong quá trình sử dụng, một hộp thoại sẽ xuất hiện và tin nhắn hiện tại sẽ được tự động sao chép vào clipboard. Bạn cần dán chúng vào các phiên bản web của AI (như ChatGPT hoặc Claude), sau đó sao chép phản hồi của AI trở lại hộp thoại và nhấp vào nút xác nhận." }, + "roo": { + "authenticatedMessage": "Đã xác thực an toàn thông qua tài khoản Roo Code Cloud của bạn.", + "connectButton": "Kết nối với Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "Định tuyến nhà cung cấp OpenRouter", diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 1d446b43f5..83da424df0 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -349,9 +349,9 @@ "ariaLabel": "版本 {{version}} - 点击查看发布说明" }, "rooCloudCTA": { - "title": "Roo Code Cloud 即将推出!", + "title": "Roo Code Cloud 正在进化!", "description": "在云端运行远程代理,随时随地访问任务,与他人协作等更多功能。", - "joinWaitlist": "加入等待列表获取早期访问权限。" + "joinWaitlist": "注册获取最新更新。" }, "command": { "triggerDescription": "触发 {{name}} 命令" diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index c1985e7490..cc16cf349d 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -377,6 +377,10 @@ "description": "不需要 API 密钥,但用户需要帮助将信息复制并粘贴到网页聊天 AI。", "instructions": "使用期间,将弹出对话框并自动将当前消息复制到剪贴板。您需要将这些内容粘贴到 AI 的网页版本(如 ChatGPT 或 Claude),然后将 AI 的回复复制回对话框并点击确认按钮。" }, + "roo": { + "authenticatedMessage": "已通过 Roo Code Cloud 账户安全认证。", + "connectButton": "连接到 Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "OpenRouter 提供商路由", diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 0386a7540c..9cfbef6765 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -352,9 +352,9 @@ "ariaLabel": "版本 {{version}} - 點選查看發布說明" }, "rooCloudCTA": { - "title": "Roo Code Cloud 即將推出!", + "title": "Roo Code Cloud 正在進化!", "description": "在雲端執行 Roomote 遠端代理、隨時隨地存取您的工作、與他人協作等等。", - "joinWaitlist": "加入等候名單以獲得早期存取權限。" + "joinWaitlist": "註冊以獲得最新更新。" }, "command": { "triggerDescription": "觸發 {{name}} 命令" diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 6a673de60a..791be9ac02 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -377,6 +377,10 @@ "description": "不需要 API 金鑰,但使用者需要協助將資訊複製並貼上到網頁聊天 AI。", "instructions": "使用期間會彈出對話框,並自動將目前訊息複製到剪貼簿。您需要將這些內容貼上到網頁版 AI(如 ChatGPT 或 Claude),然後將 AI 的回覆複製回對話框並點選確認按鈕。" }, + "roo": { + "authenticatedMessage": "已透過 Roo Code Cloud 帳戶安全認證。", + "connectButton": "連接到 Roo Code Cloud" + }, "openRouter": { "providerRouting": { "title": "OpenRouter 供應商路由",