separate task sync roomote control (#7799)

* feat: separate Task Sync and Roomote Control settings

- Add new taskSyncEnabled setting to control task content syncing
- Keep remoteControlEnabled for Roomote Control functionality
- Task Sync controls whether task content is sent to cloud
- Roomote Control controls whether cloud can send instructions back
- Roomote Control now depends on Task Sync being enabled
- Usage metrics (tokens, cost) always reported regardless of settings
- Update UI with two separate toggles and clear descriptions
- Add info text explaining usage metrics are always reported

* feat: add missing translations for Task Sync and Roomote Control settings

- Added taskSync, taskSyncDescription, remoteControlRequiresTaskSync, and usageMetricsAlwaysReported keys to all non-English cloud.json files
- Updated cloudBenefit keys to match English structure
- Ensured all languages have consistent translation keys for the new Task Sync and Roomote Control features

* Cloud: cleanup taskSyncEnabled additions

* fix: correct indentation localization files

---------

Co-authored-by: Roo Code <roomote@roocode.com>
This commit is contained in:
John Richmond 2025-09-10 12:43:11 -07:00 committed by GitHub
parent 7cd6520302
commit 80af39dc74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 789 additions and 286 deletions

View file

@ -248,6 +248,11 @@ export class CloudService extends EventEmitter<CloudServiceEvents> implements Di
return this.settingsService!.updateUserSettings(settings)
}
public isTaskSyncEnabled(): boolean {
this.ensureInitialized()
return this.settingsService!.isTaskSyncEnabled()
}
// TelemetryClient
public captureEvent(event: TelemetryEvent): void {

View file

@ -266,6 +266,21 @@ export class CloudSettingsService extends EventEmitter<SettingsServiceEvents> im
}
}
public isTaskSyncEnabled(): boolean {
// Org settings take precedence
if (this.authService.getStoredOrganizationId()) {
return this.settings?.cloudSettings?.recordTaskMessages ?? false
}
// User settings default to true if unspecified
const userSettings = this.userSettings
if (userSettings) {
return userSettings.settings.taskSyncEnabled ?? true
}
return false
}
private async removeSettings(): Promise<void> {
this.settings = undefined
this.userSettings = undefined

View file

@ -51,6 +51,7 @@ export class StaticSettingsService implements SettingsService {
},
settings: {
extensionBridgeEnabled: true,
taskSyncEnabled: true,
},
version: 1,
}
@ -65,6 +66,7 @@ export class StaticSettingsService implements SettingsService {
public getUserSettingsConfig(): UserSettingsConfig {
return {
extensionBridgeEnabled: true,
taskSyncEnabled: true,
}
}
@ -72,6 +74,11 @@ export class StaticSettingsService implements SettingsService {
throw new Error("User settings updates are not supported in static mode")
}
public isTaskSyncEnabled(): boolean {
// Static settings always enable task sync
return true
}
public dispose(): void {
// No resources to clean up for static settings.
}

View file

@ -233,9 +233,9 @@ export class CloudTelemetryClient extends BaseTelemetryClient {
return false
}
// Only record message telemetry if a cloud account is present and explicitly configured to record messages
// Only record message telemetry if task sync is enabled
if (eventName === TelemetryEventName.TASK_MESSAGE) {
return this.settingsService.getSettings()?.cloudSettings?.recordTaskMessages || false
return this.settingsService.isTaskSyncEnabled()
}
// Other telemetry types are capturable at this point

View file

@ -59,6 +59,7 @@ describe("CloudService", () => {
initialize: ReturnType<typeof vi.fn>
getSettings: ReturnType<typeof vi.fn>
getAllowList: ReturnType<typeof vi.fn>
isTaskSyncEnabled: ReturnType<typeof vi.fn>
dispose: ReturnType<typeof vi.fn>
on: ReturnType<typeof vi.fn>
off: ReturnType<typeof vi.fn>
@ -130,6 +131,7 @@ describe("CloudService", () => {
initialize: vi.fn(),
getSettings: vi.fn(),
getAllowList: vi.fn(),
isTaskSyncEnabled: vi.fn().mockReturnValue(true),
dispose: vi.fn(),
on: vi.fn(),
off: vi.fn(),
@ -343,6 +345,12 @@ describe("CloudService", () => {
cloudService.getAllowList()
expect(mockSettingsService.getAllowList).toHaveBeenCalled()
})
it("should delegate isTaskSyncEnabled to SettingsService", () => {
const result = cloudService.isTaskSyncEnabled()
expect(mockSettingsService.isTaskSyncEnabled).toHaveBeenCalled()
expect(result).toBe(true)
})
})
describe("error handling", () => {

View file

@ -20,6 +20,7 @@ describe("CloudSettingsService", () => {
getSessionToken: ReturnType<typeof vi.fn>
hasActiveSession: ReturnType<typeof vi.fn>
on: ReturnType<typeof vi.fn>
getStoredOrganizationId: ReturnType<typeof vi.fn>
}
let mockRefreshTimer: {
start: ReturnType<typeof vi.fn>
@ -63,6 +64,7 @@ describe("CloudSettingsService", () => {
getSessionToken: vi.fn(),
hasActiveSession: vi.fn().mockReturnValue(false),
on: vi.fn(),
getStoredOrganizationId: vi.fn().mockReturnValue(null),
}
mockRefreshTimer = {
@ -532,4 +534,191 @@ describe("CloudSettingsService", () => {
expect(mockContext.globalState.update).toHaveBeenCalledWith("user-settings", undefined)
})
})
describe("isTaskSyncEnabled", () => {
beforeEach(async () => {
await cloudSettingsService.initialize()
})
it("should return true when org recordTaskMessages is true", () => {
// Set up mock settings with org recordTaskMessages = true
const mockSettings = {
version: 1,
cloudSettings: {
recordTaskMessages: true,
},
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
// Mock that user has organization ID (indicating org settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(true)
})
it("should return false when org recordTaskMessages is false", () => {
// Set up mock settings with org recordTaskMessages = false
const mockSettings = {
version: 1,
cloudSettings: {
recordTaskMessages: false,
},
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
// Mock that user has organization ID (indicating org settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
})
it("should fall back to user taskSyncEnabled when org recordTaskMessages is undefined", () => {
// Set up mock settings with org recordTaskMessages undefined
const mockSettings = {
version: 1,
cloudSettings: {},
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
const mockUserSettings = {
version: 1,
features: {},
settings: {
taskSyncEnabled: true,
},
}
// Mock that user has no organization ID (indicating user settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
mockUserSettings
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(true)
})
it("should return false when user taskSyncEnabled is false", () => {
// Set up mock settings with org recordTaskMessages undefined
const mockSettings = {
version: 1,
cloudSettings: {},
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
const mockUserSettings = {
version: 1,
features: {},
settings: {
taskSyncEnabled: false,
},
}
// Mock that user has no organization ID (indicating user settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
mockUserSettings
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
})
it("should return true when user taskSyncEnabled is undefined (default)", () => {
// Set up mock settings with org recordTaskMessages undefined
const mockSettings = {
version: 1,
cloudSettings: {},
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
const mockUserSettings = {
version: 1,
features: {},
settings: {},
}
// Mock that user has no organization ID (indicating user settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
mockUserSettings
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(true)
})
it("should return false when no settings are available", () => {
// Mock that user has no organization ID
mockAuthService.getStoredOrganizationId.mockReturnValue(null)
// Clear both settings
;(cloudSettingsService as unknown as { settings: undefined }).settings = undefined
;(cloudSettingsService as unknown as { userSettings: undefined }).userSettings = undefined
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
})
it("should return false when only org settings are available but cloudSettings is undefined", () => {
const mockSettings = {
version: 1,
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
// Mock that user has organization ID (indicating org settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
;(cloudSettingsService as unknown as { userSettings: undefined }).userSettings = undefined
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
})
it("should prioritize org settings over user settings", () => {
// Set up conflicting settings: org = false, user = true
const mockSettings = {
version: 1,
cloudSettings: {
recordTaskMessages: false,
},
defaultSettings: {},
allowList: { allowAll: true, providers: {} },
}
const mockUserSettings = {
version: 1,
features: {},
settings: {
taskSyncEnabled: true,
},
}
// Mock that user has organization ID (indicating org settings should be used)
mockAuthService.getStoredOrganizationId.mockReturnValue("org-123")
// Use reflection to set private settings
;(cloudSettingsService as unknown as { settings: typeof mockSettings }).settings = mockSettings
;(cloudSettingsService as unknown as { userSettings: typeof mockUserSettings }).userSettings =
mockUserSettings
// Should return false (org setting takes precedence)
expect(cloudSettingsService.isTaskSyncEnabled()).toBe(false)
})
})
})

View file

@ -98,5 +98,28 @@ describe("StaticSettingsService", () => {
expect(mockLog).not.toHaveBeenCalled()
})
describe("isTaskSyncEnabled", () => {
it("should always return true", () => {
const service = new StaticSettingsService(validBase64)
expect(service.isTaskSyncEnabled()).toBe(true)
})
it("should return true regardless of settings content", () => {
// Create settings with different content
const differentSettings = {
version: 2,
cloudSettings: {
recordTaskMessages: false,
},
defaultSettings: {},
allowList: { allowAll: false, providers: {} },
}
const differentBase64 = Buffer.from(JSON.stringify(differentSettings)).toString("base64")
const service = new StaticSettingsService(differentBase64)
expect(service.isTaskSyncEnabled()).toBe(true)
})
})
})
})

View file

@ -35,6 +35,14 @@ describe("TelemetryClient", () => {
recordTaskMessages: true,
},
}),
getUserSettings: vi.fn().mockReturnValue({
features: {},
settings: {
taskSyncEnabled: true,
},
version: 1,
}),
isTaskSyncEnabled: vi.fn().mockReturnValue(true),
}
mockFetch.mockResolvedValue({
@ -76,12 +84,8 @@ describe("TelemetryClient", () => {
expect(isEventCapturable(TelemetryEventName.TASK_CONVERSATION_MESSAGE)).toBe(false)
})
it("should return true for TASK_MESSAGE events when recordTaskMessages is true", () => {
mockSettingsService.getSettings.mockReturnValue({
cloudSettings: {
recordTaskMessages: true,
},
})
it("should return true for TASK_MESSAGE events when isTaskSyncEnabled returns true", () => {
mockSettingsService.isTaskSyncEnabled.mockReturnValue(true)
const client = new TelemetryClient(mockAuthService, mockSettingsService)
@ -91,55 +95,11 @@ describe("TelemetryClient", () => {
).bind(client)
expect(isEventCapturable(TelemetryEventName.TASK_MESSAGE)).toBe(true)
expect(mockSettingsService.isTaskSyncEnabled).toHaveBeenCalled()
})
it("should return false for TASK_MESSAGE events when recordTaskMessages is false", () => {
mockSettingsService.getSettings.mockReturnValue({
cloudSettings: {
recordTaskMessages: false,
},
})
const client = new TelemetryClient(mockAuthService, mockSettingsService)
const isEventCapturable = getPrivateProperty<(eventName: TelemetryEventName) => boolean>(
client,
"isEventCapturable",
).bind(client)
expect(isEventCapturable(TelemetryEventName.TASK_MESSAGE)).toBe(false)
})
it("should return false for TASK_MESSAGE events when recordTaskMessages is undefined", () => {
mockSettingsService.getSettings.mockReturnValue({
cloudSettings: {},
})
const client = new TelemetryClient(mockAuthService, mockSettingsService)
const isEventCapturable = getPrivateProperty<(eventName: TelemetryEventName) => boolean>(
client,
"isEventCapturable",
).bind(client)
expect(isEventCapturable(TelemetryEventName.TASK_MESSAGE)).toBe(false)
})
it("should return false for TASK_MESSAGE events when cloudSettings is undefined", () => {
mockSettingsService.getSettings.mockReturnValue({})
const client = new TelemetryClient(mockAuthService, mockSettingsService)
const isEventCapturable = getPrivateProperty<(eventName: TelemetryEventName) => boolean>(
client,
"isEventCapturable",
).bind(client)
expect(isEventCapturable(TelemetryEventName.TASK_MESSAGE)).toBe(false)
})
it("should return false for TASK_MESSAGE events when getSettings returns undefined", () => {
mockSettingsService.getSettings.mockReturnValue(undefined)
it("should return false for TASK_MESSAGE events when isTaskSyncEnabled returns false", () => {
mockSettingsService.isTaskSyncEnabled.mockReturnValue(false)
const client = new TelemetryClient(mockAuthService, mockSettingsService)
@ -149,6 +109,7 @@ describe("TelemetryClient", () => {
).bind(client)
expect(isEventCapturable(TelemetryEventName.TASK_MESSAGE)).toBe(false)
expect(mockSettingsService.isTaskSyncEnabled).toHaveBeenCalled()
})
})
@ -273,10 +234,8 @@ describe("TelemetryClient", () => {
expect(mockFetch).not.toHaveBeenCalled()
})
it("should not capture TASK_MESSAGE events when recordTaskMessages is undefined", async () => {
mockSettingsService.getSettings.mockReturnValue({
cloudSettings: {},
})
it("should not capture TASK_MESSAGE events when isTaskSyncEnabled returns false", async () => {
mockSettingsService.isTaskSyncEnabled.mockReturnValue(false)
const client = new TelemetryClient(mockAuthService, mockSettingsService)
@ -294,6 +253,7 @@ describe("TelemetryClient", () => {
})
expect(mockFetch).not.toHaveBeenCalled()
expect(mockSettingsService.isTaskSyncEnabled).toHaveBeenCalled()
})
it("should not send request when schema validation fails", async () => {
@ -353,12 +313,8 @@ describe("TelemetryClient", () => {
)
})
it("should attempt to capture TASK_MESSAGE events when recordTaskMessages is true", async () => {
mockSettingsService.getSettings.mockReturnValue({
cloudSettings: {
recordTaskMessages: true,
},
})
it("should attempt to capture TASK_MESSAGE events when isTaskSyncEnabled returns true", async () => {
mockSettingsService.isTaskSyncEnabled.mockReturnValue(true)
const eventProperties = {
appName: "roo-code",
@ -389,6 +345,7 @@ describe("TelemetryClient", () => {
properties: eventProperties,
})
expect(mockSettingsService.isTaskSyncEnabled).toHaveBeenCalled()
expect(mockFetch).toHaveBeenCalledWith(
"https://app.roocode.com/api/events",
expect.objectContaining({

View file

@ -303,6 +303,14 @@ export interface SettingsService {
*/
updateUserSettings(settings: Partial<UserSettingsConfig>): Promise<boolean>
/**
* Determines if task sync/recording is enabled based on organization and user settings
* Organization settings take precedence over user settings.
* User settings default to true if unspecified.
* @returns true if task sync is enabled, false otherwise
*/
isTaskSyncEnabled(): boolean
/**
* Dispose of the settings service and clean up resources
*/

View file

@ -138,8 +138,6 @@ export const globalSettingsSchema = z.object({
mcpEnabled: z.boolean().optional(),
enableMcpServerCreation: z.boolean().optional(),
remoteControlEnabled: z.boolean().optional(),
mode: z.string().optional(),
modeApiConfigs: z.record(z.string(), z.string()).optional(),
customModes: z.array(modeConfigSchema).optional(),
@ -316,8 +314,6 @@ export const EVALS_SETTINGS: RooCodeSettings = {
mcpEnabled: false,
remoteControlEnabled: false,
mode: "code", // "architect",
customModes: [],

View file

@ -867,7 +867,7 @@ export class ClineProvider
fuzzyMatchThreshold,
experiments,
cloudUserInfo,
remoteControlEnabled,
taskSyncEnabled,
} = await this.getState()
const task = new Task({
@ -884,7 +884,7 @@ export class ClineProvider
taskNumber: historyItem.number,
workspacePath: historyItem.workspace,
onCreated: this.taskCreationCallback,
enableBridge: BridgeOrchestrator.isEnabled(cloudUserInfo, remoteControlEnabled),
enableBridge: BridgeOrchestrator.isEnabled(cloudUserInfo, taskSyncEnabled),
})
await this.addClineToStack(task)
@ -1777,10 +1777,12 @@ export class ClineProvider
includeDiagnosticMessages,
maxDiagnosticMessages,
includeTaskHistoryInEnhance,
taskSyncEnabled,
remoteControlEnabled,
openRouterImageApiKey,
openRouterImageGenerationSelectedModel,
openRouterUseMiddleOutTransform,
featureRoomoteControlEnabled,
} = await this.getState()
const telemetryKey = process.env.POSTHOG_API_KEY
@ -1912,10 +1914,12 @@ export class ClineProvider
includeDiagnosticMessages: includeDiagnosticMessages ?? true,
maxDiagnosticMessages: maxDiagnosticMessages ?? 50,
includeTaskHistoryInEnhance: includeTaskHistoryInEnhance ?? true,
taskSyncEnabled,
remoteControlEnabled,
openRouterImageApiKey,
openRouterImageGenerationSelectedModel,
openRouterUseMiddleOutTransform,
featureRoomoteControlEnabled,
}
}
@ -2003,6 +2007,16 @@ export class ClineProvider
)
}
let taskSyncEnabled: boolean = false
try {
taskSyncEnabled = CloudService.instance.isTaskSyncEnabled()
} catch (error) {
console.error(
`[getState] failed to get task sync enabled state: ${error instanceof Error ? error.message : String(error)}`,
)
}
// Return the same structure as before.
return {
apiConfiguration: providerSettings,
@ -2110,6 +2124,7 @@ export class ClineProvider
includeDiagnosticMessages: stateValues.includeDiagnosticMessages ?? true,
maxDiagnosticMessages: stateValues.maxDiagnosticMessages ?? 50,
includeTaskHistoryInEnhance: stateValues.includeTaskHistoryInEnhance ?? true,
taskSyncEnabled,
remoteControlEnabled: (() => {
try {
const cloudSettings = CloudService.instance.getUserSettings()
@ -2123,6 +2138,18 @@ export class ClineProvider
})(),
openRouterImageApiKey: stateValues.openRouterImageApiKey,
openRouterImageGenerationSelectedModel: stateValues.openRouterImageGenerationSelectedModel,
featureRoomoteControlEnabled: (() => {
try {
const userSettings = CloudService.instance.getUserSettings()
const hasOrganization = cloudUserInfo?.organizationId != null
return hasOrganization || (userSettings?.features?.roomoteControlEnabled ?? false)
} catch (error) {
console.error(
`[getState] failed to get featureRoomoteControlEnabled: ${error instanceof Error ? error.message : String(error)}`,
)
return false
}
})(),
}
}

View file

@ -554,6 +554,9 @@ describe("ClineProvider", () => {
diagnosticsEnabled: true,
openRouterImageApiKey: undefined,
openRouterImageGenerationSelectedModel: undefined,
remoteControlEnabled: false,
taskSyncEnabled: false,
featureRoomoteControlEnabled: false,
}
const message: ExtensionMessage = {

View file

@ -11,6 +11,7 @@ import {
type ClineMessage,
type TelemetrySetting,
TelemetryEventName,
UserSettingsConfig,
} from "@roo-code/types"
import { CloudService } from "@roo-code/cloud"
import { TelemetryService } from "@roo-code/telemetry"
@ -1188,16 +1189,21 @@ export const webviewMessageHandler = async (
`CloudService#updateUserSettings failed: ${error instanceof Error ? error.message : String(error)}`,
)
}
try {
await provider.remoteControlEnabled(message.bool ?? false)
} catch (error) {
provider.log(
`ClineProvider#remoteControlEnabled failed: ${error instanceof Error ? error.message : String(error)}`,
)
break
case "taskSyncEnabled":
const enabled = message.bool ?? false
const updatedSettings: Partial<UserSettingsConfig> = {
taskSyncEnabled: enabled,
}
// If disabling task sync, also disable remote control
if (!enabled) {
updatedSettings.extensionBridgeEnabled = false
}
try {
await CloudService.instance.updateUserSettings(updatedSettings)
} catch (error) {
provider.log(`Failed to update cloud settings for task sync: ${error}`)
}
await provider.postStateToWebview()
break
case "refreshAllMcpServers": {
const mcpHub = provider.getMcpHub()

View file

@ -133,7 +133,7 @@ export async function activate(context: vscode.ExtensionContext) {
if (data.state === "logged-out") {
try {
await BridgeOrchestrator.disconnect()
await provider.remoteControlEnabled(false)
cloudLogger("[CloudService] BridgeOrchestrator disconnected on logout")
} catch (error) {
cloudLogger(
@ -148,20 +148,7 @@ export async function activate(context: vscode.ExtensionContext) {
if (userInfo && CloudService.instance.cloudAPI) {
try {
const config = await CloudService.instance.cloudAPI.bridgeConfig()
const isCloudAgent =
typeof process.env.ROO_CODE_CLOUD_TOKEN === "string" && process.env.ROO_CODE_CLOUD_TOKEN.length > 0
const remoteControlEnabled = isCloudAgent
? true
: (CloudService.instance.getUserSettings()?.settings?.extensionBridgeEnabled ?? false)
await BridgeOrchestrator.connectOrDisconnect(userInfo, remoteControlEnabled, {
...config,
provider,
sessionId: vscode.env.sessionId,
})
provider.remoteControlEnabled(CloudService.instance.isTaskSyncEnabled())
} catch (error) {
cloudLogger(
`[CloudService] BridgeOrchestrator#connectOrDisconnect failed on settings change: ${error instanceof Error ? error.message : String(error)}`,
@ -181,20 +168,7 @@ export async function activate(context: vscode.ExtensionContext) {
}
try {
const config = await CloudService.instance.cloudAPI.bridgeConfig()
const isCloudAgent =
typeof process.env.ROO_CODE_CLOUD_TOKEN === "string" && process.env.ROO_CODE_CLOUD_TOKEN.length > 0
const remoteControlEnabled = isCloudAgent
? true
: (CloudService.instance.getUserSettings()?.settings?.extensionBridgeEnabled ?? false)
await BridgeOrchestrator.connectOrDisconnect(userInfo, remoteControlEnabled, {
...config,
provider,
sessionId: vscode.env.sessionId,
})
provider.remoteControlEnabled(CloudService.instance.isTaskSyncEnabled())
} catch (error) {
cloudLogger(
`[CloudService] BridgeOrchestrator#connectOrDisconnect failed on user change: ${error instanceof Error ? error.message : String(error)}`,

View file

@ -278,7 +278,6 @@ export type ExtensionState = Pick<
| "profileThresholds"
| "includeDiagnosticMessages"
| "maxDiagnosticMessages"
| "remoteControlEnabled"
| "openRouterImageGenerationSelectedModel"
| "includeTaskHistoryInEnhance"
> & {
@ -342,6 +341,9 @@ export type ExtensionState = Pick<
mcpServers?: McpServer[]
hasSystemPromptOverride?: boolean
mdmCompliant?: boolean
remoteControlEnabled: boolean
taskSyncEnabled: boolean
featureRoomoteControlEnabled: boolean
}
export interface ClineSayTool {

View file

@ -134,6 +134,7 @@ export interface WebviewMessage {
| "mcpEnabled"
| "enableMcpServerCreation"
| "remoteControlEnabled"
| "taskSyncEnabled"
| "searchCommits"
| "alwaysApproveResubmit"
| "requestDelaySeconds"

View file

@ -23,7 +23,13 @@ type CloudViewProps = {
export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone }: CloudViewProps) => {
const { t } = useAppTranslation()
const { remoteControlEnabled, setRemoteControlEnabled } = useExtensionState()
const {
remoteControlEnabled,
setRemoteControlEnabled,
taskSyncEnabled,
setTaskSyncEnabled,
featureRoomoteControlEnabled,
} = useExtensionState()
const wasAuthenticatedRef = useRef(false)
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
const manualUrlInputRef = useRef<HTMLInputElement | null>(null)
@ -142,6 +148,12 @@ export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone }: Cl
vscode.postMessage({ type: "remoteControlEnabled", bool: newValue })
}
const handleTaskSyncToggle = () => {
const newValue = !taskSyncEnabled
setTaskSyncEnabled(newValue)
vscode.postMessage({ type: "taskSyncEnabled", bool: newValue })
}
return (
<div className="flex flex-col h-full">
<div className="flex justify-between items-center mb-6">
@ -188,24 +200,62 @@ export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone }: Cl
</div>
)}
{userInfo?.extensionBridgeEnabled && (
<div className="border-t border-vscode-widget-border pt-4 mt-4">
<div className="flex items-center gap-3 mb-2">
<ToggleSwitch
checked={remoteControlEnabled}
onChange={handleRemoteControlToggle}
size="medium"
aria-label={t("cloud:remoteControl")}
data-testid="remote-control-toggle"
/>
<span className="font-medium text-vscode-foreground">{t("cloud:remoteControl")}</span>
</div>
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-4 ml-8">
{t("cloud:remoteControlDescription")}
</div>
<hr className="border-vscode-widget-border mb-4" />
{/* Task Sync Toggle - Always shown when authenticated */}
<div className="border-t border-vscode-widget-border pt-4 mt-4">
<div className="flex items-center gap-3 mb-2">
<ToggleSwitch
checked={taskSyncEnabled}
onChange={handleTaskSyncToggle}
size="medium"
aria-label={t("cloud:taskSync")}
data-testid="task-sync-toggle"
disabled={!!userInfo?.organizationId}
/>
<span className="font-medium text-vscode-foreground">{t("cloud:taskSync")}</span>
</div>
)}
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-4 ml-8">
{t("cloud:taskSyncDescription")}
</div>
{userInfo?.organizationId && (
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-4 ml-8 italic">
{t("cloud:taskSyncManagedByOrganization")}
</div>
)}
{/* Remote Control Toggle - Only shown when both extensionBridgeEnabled and featureRoomoteControlEnabled are true */}
{userInfo?.extensionBridgeEnabled && featureRoomoteControlEnabled && (
<>
<div className="flex items-center gap-3 mb-2">
<ToggleSwitch
checked={remoteControlEnabled}
onChange={handleRemoteControlToggle}
size="medium"
aria-label={t("cloud:remoteControl")}
data-testid="remote-control-toggle"
disabled={!taskSyncEnabled}
/>
<span className="font-medium text-vscode-foreground">
{t("cloud:remoteControl")}
</span>
</div>
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-4 ml-8">
{t("cloud:remoteControlDescription")}
{!taskSyncEnabled && (
<div className="text-vscode-errorForeground mt-2">
{t("cloud:remoteControlRequiresTaskSync")}
</div>
)}
</div>
</>
)}
{/* Info text about usage metrics */}
<div className="text-vscode-descriptionForeground text-sm mt-4 mb-4 ml-8 italic">
{t("cloud:usageMetricsAlwaysReported")}
</div>
<hr className="border-vscode-widget-border mb-4" />
</div>
<div className="flex flex-col gap-2 mt-4">
<VSCodeButton appearance="secondary" onClick={handleVisitCloudWebsite} className="w-full">

View file

@ -17,9 +17,14 @@ vi.mock("@src/i18n/TranslationContext", () => ({
"cloud:logOut": "Log out",
"cloud:connect": "Connect Now",
"cloud:visitCloudWebsite": "Visit Roo Code Cloud",
"cloud:taskSync": "Task sync",
"cloud:taskSyncDescription": "Sync your tasks for viewing and sharing on Roo Code Cloud",
"cloud:taskSyncManagedByOrganization": "Task sync is managed by your organization",
"cloud:remoteControl": "Roomote Control",
"cloud:remoteControlDescription":
"Enable following and interacting with tasks in this workspace with Roo Code Cloud",
"cloud:remoteControlRequiresTaskSync": "Task sync must be enabled to use Roomote Control",
"cloud:usageMetricsAlwaysReported": "Model usage info is always reported when logged in",
"cloud:profilePicture": "Profile picture",
"cloud:cloudUrlPillLabel": "Roo Code Cloud URL: ",
}
@ -43,11 +48,17 @@ vi.mock("@src/utils/TelemetryClient", () => ({
}))
// Mock the extension state context
const mockExtensionState = {
remoteControlEnabled: false,
setRemoteControlEnabled: vi.fn(),
taskSyncEnabled: true,
setTaskSyncEnabled: vi.fn(),
featureRoomoteControlEnabled: true, // Default to true for tests
setFeatureRoomoteControlEnabled: vi.fn(),
}
vi.mock("@src/context/ExtensionStateContext", () => ({
useExtensionState: () => ({
remoteControlEnabled: false,
setRemoteControlEnabled: vi.fn(),
}),
useExtensionState: () => mockExtensionState,
}))
// Mock window global for images
@ -105,7 +116,7 @@ describe("CloudView", () => {
expect(screen.getByText("test@example.com")).toBeInTheDocument()
})
it("should display remote control toggle when user has extension bridge enabled", () => {
it("should display remote control toggle when user has extension bridge enabled and roomote control enabled", () => {
const mockUserInfo = {
name: "Test User",
email: "test@example.com",
@ -150,6 +161,65 @@ describe("CloudView", () => {
expect(screen.queryByText("Roomote Control")).not.toBeInTheDocument()
})
it("should not display remote control toggle when roomote control is disabled", () => {
// Temporarily override the mock for this specific test
const originalFeatureRoomoteControlEnabled = mockExtensionState.featureRoomoteControlEnabled
mockExtensionState.featureRoomoteControlEnabled = false
const mockUserInfo = {
name: "Test User",
email: "test@example.com",
extensionBridgeEnabled: true, // Bridge enabled but roomote control disabled
}
render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
// Check that the remote control toggle is NOT displayed
expect(screen.queryByTestId("remote-control-toggle")).not.toBeInTheDocument()
expect(screen.queryByText("Roomote Control")).not.toBeInTheDocument()
// Restore the original value
mockExtensionState.featureRoomoteControlEnabled = originalFeatureRoomoteControlEnabled
})
it("should display remote control toggle for organization users (simulating backend logic)", () => {
// This test simulates what the ClineProvider would do:
// Organization users are treated as having featureRoomoteControlEnabled true
const originalFeatureRoomoteControlEnabled = mockExtensionState.featureRoomoteControlEnabled
mockExtensionState.featureRoomoteControlEnabled = true // Simulating ClineProvider logic for org users
const mockUserInfo = {
name: "Test User",
email: "test@example.com",
organizationId: "org-123", // User is in an organization
extensionBridgeEnabled: true,
}
render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
// Check that the remote control toggle IS displayed for organization users
// (The ClineProvider would set featureRoomoteControlEnabled to true for org users)
expect(screen.getByTestId("remote-control-toggle")).toBeInTheDocument()
expect(screen.getByText("Roomote Control")).toBeInTheDocument()
// Restore the original value
mockExtensionState.featureRoomoteControlEnabled = originalFeatureRoomoteControlEnabled
})
it("should not display cloud URL pill when pointing to production", () => {
const mockUserInfo = {
name: "Test User",
@ -215,4 +285,79 @@ describe("CloudView", () => {
// Check that the cloud URL pill is NOT displayed when cloudApiUrl is undefined
expect(screen.queryByText(/Roo Code Cloud URL:/)).not.toBeInTheDocument()
})
it("should disable task sync toggle for organization users", () => {
const mockUserInfo = {
name: "Test User",
email: "test@example.com",
organizationId: "org-123",
organizationName: "Test Organization",
}
render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
// Check that the task sync toggle is disabled for organization users
const taskSyncToggle = screen.getByTestId("task-sync-toggle")
expect(taskSyncToggle).toBeInTheDocument()
expect(taskSyncToggle).toHaveAttribute("tabindex", "-1")
// Check that the organization message is displayed
expect(screen.getByText("Task sync is managed by your organization")).toBeInTheDocument()
})
it("should enable task sync toggle for non-organization users", () => {
const mockUserInfo = {
name: "Test User",
email: "test@example.com",
// No organizationId - regular user
}
render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
// Check that the task sync toggle is enabled for non-organization users
const taskSyncToggle = screen.getByTestId("task-sync-toggle")
expect(taskSyncToggle).toBeInTheDocument()
expect(taskSyncToggle).toHaveAttribute("tabindex", "0")
// Check that the organization message is NOT displayed
expect(screen.queryByText("Task sync is managed by your organization")).not.toBeInTheDocument()
})
it("should show task sync state correctly for organization users", () => {
const mockUserInfo = {
name: "Test User",
email: "test@example.com",
organizationId: "org-123",
organizationName: "Test Organization",
}
// Test with task sync enabled
render(
<CloudView
userInfo={mockUserInfo}
isAuthenticated={true}
cloudApiUrl="https://app.roocode.com"
onDone={() => {}}
/>,
)
// Check that the toggle shows the current state (enabled in this case)
const taskSyncToggle = screen.getByTestId("task-sync-toggle")
expect(taskSyncToggle).toHaveAttribute("aria-checked", "true")
expect(taskSyncToggle).toHaveAttribute("tabindex", "-1")
})
})

View file

@ -101,6 +101,10 @@ export interface ExtensionStateContextType extends ExtensionState {
setEnableMcpServerCreation: (value: boolean) => void
remoteControlEnabled: boolean
setRemoteControlEnabled: (value: boolean) => void
taskSyncEnabled: boolean
setTaskSyncEnabled: (value: boolean) => void
featureRoomoteControlEnabled: boolean
setFeatureRoomoteControlEnabled: (value: boolean) => void
alwaysApproveResubmit?: boolean
setAlwaysApproveResubmit: (value: boolean) => void
requestDelaySeconds: number
@ -201,6 +205,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
mcpEnabled: true,
enableMcpServerCreation: false,
remoteControlEnabled: false,
taskSyncEnabled: false,
featureRoomoteControlEnabled: false,
alwaysApproveResubmit: false,
requestDelaySeconds: 5,
currentApiConfigName: "default",
@ -417,6 +423,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
alwaysAllowFollowupQuestions,
followupAutoApproveTimeoutMs,
remoteControlEnabled: state.remoteControlEnabled ?? false,
taskSyncEnabled: state.taskSyncEnabled,
featureRoomoteControlEnabled: state.featureRoomoteControlEnabled ?? false,
setExperimentEnabled: (id, enabled) =>
setState((prevState) => ({ ...prevState, experiments: { ...prevState.experiments, [id]: enabled } })),
setApiConfiguration,
@ -464,6 +472,9 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setEnableMcpServerCreation: (value) =>
setState((prevState) => ({ ...prevState, enableMcpServerCreation: value })),
setRemoteControlEnabled: (value) => setState((prevState) => ({ ...prevState, remoteControlEnabled: value })),
setTaskSyncEnabled: (value) => setState((prevState) => ({ ...prevState, taskSyncEnabled: value }) as any),
setFeatureRoomoteControlEnabled: (value) =>
setState((prevState) => ({ ...prevState, featureRoomoteControlEnabled: value })),
setAlwaysApproveResubmit: (value) => setState((prevState) => ({ ...prevState, alwaysApproveResubmit: value })),
setRequestDelaySeconds: (value) => setState((prevState) => ({ ...prevState, requestDelaySeconds: value })),
setCurrentApiConfigName: (value) => setState((prevState) => ({ ...prevState, currentApiConfigName: value })),

View file

@ -211,6 +211,9 @@ describe("mergeExtensionState", () => {
hasOpenedModeSelector: false, // Add the new required property
maxImageFileSize: 5,
maxTotalImageSize: 20,
remoteControlEnabled: false,
taskSyncEnabled: false,
featureRoomoteControlEnabled: false,
}
const prevState: ExtensionState = {

View file

@ -6,14 +6,18 @@
"signIn": "Connecta't a Roo Code Cloud",
"connect": "Connecta",
"cloudBenefitsTitle": "Connecta't a Roo Code Cloud",
"cloudBenefitsSubtitle": "Sincronitza els teus prompts i telemetria per habilitar:",
"cloudBenefitHistory": "Historial de tasques en línia",
"cloudBenefitSharing": "Funcions de compartició i col·laboració",
"cloudBenefitMetrics": "Mètriques d'ús basades en tasques, tokens i costos",
"cloudBenefitWalkaway": "Segueix i controla tasques des de qualsevol lloc amb Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permet seguir i interactuar amb tasques en aquest espai de treball amb Roo Code Cloud",
"cloudBenefitSharing": "Comparteix tasques amb altres",
"cloudBenefitHistory": "Accedeix al teu historial de tasques",
"cloudBenefitMetrics": "Obtén una visió holística del teu consum de tokens",
"visitCloudWebsite": "Visita Roo Code Cloud",
"taskSync": "Sincronització de tasques",
"taskSyncDescription": "Sincronitza les teves tasques per veure-les i compartir-les a Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permet controlar tasques des de Roo Code Cloud",
"remoteControlRequiresTaskSync": "La sincronització de tasques ha d'estar habilitada per utilitzar Roomote Control",
"taskSyncManagedByOrganization": "La sincronització de tasques la gestiona la teva organització",
"usageMetricsAlwaysReported": "La informació d'ús del model sempre es reporta quan s'ha iniciat sessió",
"cloudUrlPillLabel": "URL de Roo Code Cloud",
"authWaiting": "Esperant que es completi l'autenticació...",
"havingTrouble": "Tens problemes?",

View file

@ -4,19 +4,23 @@
"logOut": "Abmelden",
"testApiAuthentication": "API-Authentifizierung testen",
"signIn": "Mit Roo Code Cloud verbinden",
"connect": "Verbinden",
"connect": "Jetzt verbinden",
"cloudBenefitsTitle": "Mit Roo Code Cloud verbinden",
"cloudBenefitsSubtitle": "Synchronisiere deine Prompts und Telemetrie, um folgendes zu aktivieren:",
"cloudBenefitHistory": "Online-Aufgabenverlauf",
"cloudBenefitSharing": "Freigabe- und Kollaborationsfunktionen",
"cloudBenefitMetrics": "Aufgaben-, Token- und kostenbasierte Nutzungsmetriken",
"cloudBenefitWalkaway": "Verfolge und steuere Aufgaben von überall mit Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Ermöglicht das Verfolgen und Interagieren mit Aufgaben in diesem Arbeitsbereich mit Roo Code Cloud",
"cloudBenefitSharing": "Aufgaben mit anderen teilen",
"cloudBenefitHistory": "Auf deinen Aufgabenverlauf zugreifen",
"cloudBenefitMetrics": "Erhalte einen ganzheitlichen Überblick über deinen Token-Verbrauch",
"visitCloudWebsite": "Roo Code Cloud besuchen",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "Aufgabensynchronisierung",
"taskSyncDescription": "Synchronisiere deine Aufgaben zum Anzeigen und Teilen in Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Ermöglicht die Steuerung von Aufgaben über Roo Code Cloud",
"remoteControlRequiresTaskSync": "Die Aufgabensynchronisierung muss aktiviert sein, um Roomote Control zu verwenden",
"taskSyncManagedByOrganization": "Die Aufgabensynchronisierung wird von deiner Organisation verwaltet",
"usageMetricsAlwaysReported": "Modellnutzungsinformationen werden bei Anmeldung immer gemeldet",
"authWaiting": "Warte auf Abschluss der Authentifizierung...",
"havingTrouble": "Probleme?",
"pasteCallbackUrl": "Kopiere die Redirect-URL aus deinem Browser und füge sie hier ein:",
"startOver": "Von vorne beginnen"
"startOver": "Von vorne beginnen",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}

View file

@ -11,8 +11,13 @@
"cloudBenefitHistory": "Access your task history",
"cloudBenefitMetrics": "Get a holistic view of your token consumption",
"visitCloudWebsite": "Visit Roo Code Cloud",
"taskSync": "Task sync",
"taskSyncDescription": "Sync your tasks for viewing and sharing on Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Enable following and interacting with tasks in this workspace with Roo Code Cloud",
"remoteControlDescription": "Allow controlling tasks from Roo Code Cloud",
"remoteControlRequiresTaskSync": "Task sync must be enabled to use Roomote Control",
"taskSyncManagedByOrganization": "Task sync is managed by your organization",
"usageMetricsAlwaysReported": "Model usage info is always reported when logged in",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"authWaiting": "Waiting for browser authentication...",
"havingTrouble": "Having trouble?",

View file

@ -4,19 +4,23 @@
"logOut": "Cerrar sesión",
"testApiAuthentication": "Probar autenticación de API",
"signIn": "Conectar a Roo Code Cloud",
"connect": "Conectar",
"connect": "Conectar ahora",
"cloudBenefitsTitle": "Conectar a Roo Code Cloud",
"cloudBenefitsSubtitle": "Sincroniza tus prompts y telemetría para habilitar:",
"cloudBenefitHistory": "Historial de tareas en línea",
"cloudBenefitSharing": "Funciones de compartir y colaboración",
"cloudBenefitMetrics": "Métricas de uso basadas en tareas, tokens y costos",
"cloudBenefitWalkaway": "Sigue y controla tareas desde cualquier lugar con Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permite seguir e interactuar con tareas en este espacio de trabajo con Roo Code Cloud",
"cloudBenefitSharing": "Comparte tareas con otros",
"cloudBenefitHistory": "Accede a tu historial de tareas",
"cloudBenefitMetrics": "Obtén una visión holística de tu consumo de tokens",
"visitCloudWebsite": "Visitar Roo Code Cloud",
"cloudUrlPillLabel": "URL de Roo Code Cloud",
"taskSync": "Sincronización de tareas",
"taskSyncDescription": "Sincroniza tus tareas para verlas y compartirlas en Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permite controlar tareas desde Roo Code Cloud",
"remoteControlRequiresTaskSync": "La sincronización de tareas debe estar habilitada para usar Roomote Control",
"taskSyncManagedByOrganization": "La sincronización de tareas es gestionada por tu organización",
"usageMetricsAlwaysReported": "La información de uso del modelo siempre se reporta cuando se ha iniciado sesión",
"authWaiting": "Esperando que se complete la autenticación...",
"havingTrouble": "¿Tienes problemas?",
"pasteCallbackUrl": "Copia la URL de redirect desde tu navegador y pégala aquí:",
"startOver": "Empezar de nuevo"
"startOver": "Empezar de nuevo",
"cloudUrlPillLabel": "URL de Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": "Déconnexion",
"testApiAuthentication": "Tester l'authentification API",
"signIn": "Se connecter à Roo Code Cloud",
"connect": "Se connecter",
"connect": "Se connecter maintenant",
"cloudBenefitsTitle": "Se connecter à Roo Code Cloud",
"cloudBenefitsSubtitle": "Synchronise tes prompts et télémétrie pour activer :",
"cloudBenefitHistory": "Historique des tâches en ligne",
"cloudBenefitSharing": "Fonctionnalités de partage et collaboration",
"cloudBenefitMetrics": "Métriques d'utilisation basées sur les tâches, tokens et coûts",
"cloudBenefitWalkaway": "Suivez et contrôlez les tâches depuis n'importe où avec Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permet de suivre et d'interagir avec les tâches dans cet espace de travail avec Roo Code Cloud",
"cloudBenefitSharing": "Partagez des tâches avec d'autres",
"cloudBenefitHistory": "Accédez à votre historique de tâches",
"cloudBenefitMetrics": "Obtenez une vue holistique de votre consommation de tokens",
"visitCloudWebsite": "Visiter Roo Code Cloud",
"cloudUrlPillLabel": "URL de Roo Code Cloud",
"taskSync": "Synchronisation des tâches",
"taskSyncDescription": "Synchronisez vos tâches pour les visualiser et les partager sur Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permet de contrôler les tâches depuis Roo Code Cloud",
"remoteControlRequiresTaskSync": "La synchronisation des tâches doit être activée pour utiliser Roomote Control",
"taskSyncManagedByOrganization": "La synchronisation des tâches est gérée par votre organisation",
"usageMetricsAlwaysReported": "Les informations d'utilisation du modèle sont toujours signalées lors de la connexion",
"authWaiting": "En attente de la fin de l'authentification...",
"havingTrouble": "Des difficultés ?",
"pasteCallbackUrl": "Copie l'URL de redirect depuis ton navigateur et colle-la ici :",
"startOver": "Recommencer"
"startOver": "Recommencer",
"cloudUrlPillLabel": "URL de Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": "लॉग आउट",
"testApiAuthentication": "API प्रमाणीकरण का परीक्षण करें",
"signIn": "Roo Code Cloud से कनेक्ट करें",
"connect": "कनेक्ट करें",
"connect": "अभी कनेक्ट करें",
"cloudBenefitsTitle": "Roo Code Cloud से कनेक्ट करें",
"cloudBenefitsSubtitle": "निम्नलिखित को सक्षम करने के लिए अपने prompts और telemetry को sync करें:",
"cloudBenefitHistory": "ऑनलाइन कार्य इतिहास",
"cloudBenefitSharing": "साझाकरण और सहयोग सुविधाएं",
"cloudBenefitMetrics": "कार्य, token और लागत आधारित उपयोग मेट्रिक्स",
"cloudBenefitWalkaway": "Roomote Control के साथ कहीं से भी कार्यों को फॉलो और नियंत्रित करें",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloud के साथ इस वर्कस्पेस में कार्यों को फॉलो और इंटरैक्ट करने की सुविधा दें",
"cloudBenefitSharing": "दूसरों के साथ कार्य साझा करें",
"cloudBenefitHistory": "अपने कार्य इतिहास तक पहुंचें",
"cloudBenefitMetrics": "अपने टोकन उपभोग का समग्र दृश्य प्राप्त करें",
"visitCloudWebsite": "Roo Code Cloud पर जाएं",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "कार्य सिंक",
"taskSyncDescription": "Roo Code Cloud पर देखने और साझा करने के लिए अपने कार्यों को सिंक करें",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloud से कार्यों को नियंत्रित करने की अनुमति दें",
"remoteControlRequiresTaskSync": "Roomote Control का उपयोग करने के लिए कार्य सिंक सक्षम होना चाहिए",
"taskSyncManagedByOrganization": "कार्य सिंक आपके संगठन द्वारा प्रबंधित किया जाता है",
"usageMetricsAlwaysReported": "लॉग इन होने पर मॉडल उपयोग जानकारी हमेशा रिपोर्ट की जाती है",
"authWaiting": "प्रमाणीकरण पूरा होने की प्रतीक्षा कर रहे हैं...",
"havingTrouble": "समस्या हो रही है?",
"pasteCallbackUrl": "अपने ब्राउज़र से redirect URL कॉपी करें और यहाँ पेस्ट करें:",
"startOver": "फिर से शुरू करें"
"startOver": "फिर से शुरू करें",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}

View file

@ -4,19 +4,23 @@
"logOut": "Keluar",
"testApiAuthentication": "Uji Autentikasi API",
"signIn": "Hubungkan ke Roo Code Cloud",
"connect": "Hubungkan",
"connect": "Hubungkan Sekarang",
"cloudBenefitsTitle": "Hubungkan ke Roo Code Cloud",
"cloudBenefitsSubtitle": "Sinkronkan prompt dan telemetri kamu untuk mengaktifkan:",
"cloudBenefitHistory": "Riwayat tugas online",
"cloudBenefitSharing": "Fitur berbagi dan kolaborasi",
"cloudBenefitMetrics": "Metrik penggunaan berdasarkan tugas, token, dan biaya",
"cloudBenefitWalkaway": "Ikuti dan kontrol tugas dari mana saja dengan Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Memungkinkan mengikuti dan berinteraksi dengan tugas di workspace ini dengan Roo Code Cloud",
"cloudBenefitSharing": "Bagikan tugas dengan orang lain",
"cloudBenefitHistory": "Akses riwayat tugas Anda",
"cloudBenefitMetrics": "Dapatkan tampilan holistik konsumsi token Anda",
"visitCloudWebsite": "Kunjungi Roo Code Cloud",
"cloudUrlPillLabel": "URL Roo Code Cloud",
"taskSync": "Sinkronisasi tugas",
"taskSyncDescription": "Sinkronkan tugas Anda untuk melihat dan berbagi di Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Izinkan mengontrol tugas dari Roo Code Cloud",
"remoteControlRequiresTaskSync": "Sinkronisasi tugas harus diaktifkan untuk menggunakan Roomote Control",
"taskSyncManagedByOrganization": "Sinkronisasi tugas dikelola oleh organisasi Anda",
"usageMetricsAlwaysReported": "Informasi penggunaan model selalu dilaporkan saat masuk",
"authWaiting": "Menunggu autentikasi selesai...",
"havingTrouble": "Ada masalah?",
"pasteCallbackUrl": "Salin URL redirect dari browser dan tempel di sini:",
"startOver": "Mulai dari awal"
"startOver": "Mulai dari awal",
"cloudUrlPillLabel": "URL Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": "Disconnetti",
"testApiAuthentication": "Verifica autenticazione API",
"signIn": "Connetti a Roo Code Cloud",
"connect": "Connetti",
"connect": "Connetti ora",
"cloudBenefitsTitle": "Connetti a Roo Code Cloud",
"cloudBenefitsSubtitle": "Sincronizza i tuoi prompt e telemetria per abilitare:",
"cloudBenefitHistory": "Cronologia attività online",
"cloudBenefitSharing": "Funzionalità di condivisione e collaborazione",
"cloudBenefitMetrics": "Metriche di utilizzo basate su attività, token e costi",
"cloudBenefitWalkaway": "Segui e controlla le attività da qualsiasi luogo con Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Abilita il monitoraggio e l'interazione con le attività in questo workspace con Roo Code Cloud",
"cloudBenefitSharing": "Condividi attività con altri",
"cloudBenefitHistory": "Accedi alla cronologia delle tue attività",
"cloudBenefitMetrics": "Ottieni una visione olistica del tuo consumo di token",
"visitCloudWebsite": "Visita Roo Code Cloud",
"cloudUrlPillLabel": "URL di Roo Code Cloud",
"taskSync": "Sincronizzazione attività",
"taskSyncDescription": "Sincronizza le tue attività per visualizzarle e condividerle su Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Consenti il controllo delle attività da Roo Code Cloud",
"remoteControlRequiresTaskSync": "La sincronizzazione delle attività deve essere abilitata per utilizzare Roomote Control",
"taskSyncManagedByOrganization": "La sincronizzazione delle attività è gestita dalla tua organizzazione",
"usageMetricsAlwaysReported": "Le informazioni sull'utilizzo del modello vengono sempre segnalate quando si è connessi",
"authWaiting": "In attesa del completamento dell'autenticazione...",
"havingTrouble": "Hai problemi?",
"pasteCallbackUrl": "Copia l'URL di redirect dal tuo browser e incollalo qui:",
"startOver": "Ricomincia"
"startOver": "Ricomincia",
"cloudUrlPillLabel": "URL di Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": "ログアウト",
"testApiAuthentication": "API認証をテスト",
"signIn": "Roo Code Cloud に接続",
"connect": "接続",
"connect": "今すぐ接続",
"cloudBenefitsTitle": "Roo Code Cloudに接続",
"cloudBenefitsSubtitle": "プロンプトとテレメトリを同期して以下を有効にする:",
"cloudBenefitHistory": "オンラインタスク履歴",
"cloudBenefitSharing": "共有とコラボレーション機能",
"cloudBenefitMetrics": "タスク、Token、コストベースの使用メトリクス",
"cloudBenefitWalkaway": "Roomote Controlでどこからでもタスクをフォローし制御",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloudでこのワークスペースのタスクをフォローし操作することを有効にする",
"cloudBenefitSharing": "他の人とタスクを共有",
"cloudBenefitHistory": "タスク履歴にアクセス",
"cloudBenefitMetrics": "トークン消費の全体像を把握",
"visitCloudWebsite": "Roo Code Cloudを訪問",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "タスク同期",
"taskSyncDescription": "Roo Code Cloudでタスクを表示・共有するために同期",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloudからタスクを制御できるようにする",
"remoteControlRequiresTaskSync": "Roomote Controlを使用するにはタ스크同期を有効にする必要があります",
"taskSyncManagedByOrganization": "タスク同期は組織によって管理されます",
"usageMetricsAlwaysReported": "ログイン時にはモデル使用情報が常に報告されます",
"authWaiting": "認証完了をお待ちください...",
"havingTrouble": "問題が発生していますか?",
"pasteCallbackUrl": "ブラウザからリダイレクトURLをコピーし、ここに貼り付けてください",
"startOver": "最初からやり直す"
"startOver": "最初からやり直す",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}

View file

@ -4,19 +4,23 @@
"logOut": "로그아웃",
"testApiAuthentication": "API 인증 테스트",
"signIn": "Roo Code Cloud에 연결",
"connect": "연결",
"connect": "지금 연결",
"cloudBenefitsTitle": "Roo Code Cloud에 연결",
"cloudBenefitsSubtitle": "프롬프트와 텔레메트리를 동기화하여 다음을 활성화:",
"cloudBenefitHistory": "온라인 작업 기록",
"cloudBenefitSharing": "공유 및 협업 기능",
"cloudBenefitMetrics": "작업, 토큰, 비용 기반 사용 메트릭",
"cloudBenefitWalkaway": "Roomote Control로 어디서나 작업을 팔로우하고 제어하세요",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloud로 이 워크스페이스의 작업을 팔로우하고 상호작용할 수 있게 합니다",
"cloudBenefitSharing": "다른 사람과 작업 공유",
"cloudBenefitHistory": "작업 기록에 액세스",
"cloudBenefitMetrics": "토큰 소비에 대한 전체적인 보기 얻기",
"visitCloudWebsite": "Roo Code Cloud 방문",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "작업 동기화",
"taskSyncDescription": "Roo Code Cloud에서 보고 공유할 수 있도록 작업을 동기화",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloud에서 작업을 제어할 수 있도록 허용",
"remoteControlRequiresTaskSync": "Roomote Control을 사용하려면 작업 동기화가 활성화되어야 합니다",
"taskSyncManagedByOrganization": "작업 동기화는 조직에서 관리합니다",
"usageMetricsAlwaysReported": "로그인 시 모델 사용 정보가 항상 보고됩니다",
"authWaiting": "인증 완료를 기다리는 중...",
"havingTrouble": "문제가 있나요?",
"pasteCallbackUrl": "브라우저에서 리다이렉트 URL을 복사하여 여기에 붙여넣으세요:",
"startOver": "다시 시작"
"startOver": "다시 시작",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}

View file

@ -4,19 +4,23 @@
"logOut": "Uitloggen",
"testApiAuthentication": "API-authenticatie testen",
"signIn": "Verbind met Roo Code Cloud",
"connect": "Verbinden",
"connect": "Nu verbinden",
"cloudBenefitsTitle": "Verbind met Roo Code Cloud",
"cloudBenefitsSubtitle": "Synchroniseer je prompts en telemetrie om het volgende in te schakelen:",
"cloudBenefitHistory": "Online taakgeschiedenis",
"cloudBenefitSharing": "Deel- en samenwerkingsfuncties",
"cloudBenefitMetrics": "Taak-, token- en kostengebaseerde gebruiksstatistieken",
"cloudBenefitWalkaway": "Volg en beheer taken van overal met Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Schakel het volgen en interacteren met taken in deze workspace in met Roo Code Cloud",
"cloudBenefitSharing": "Deel taken met anderen",
"cloudBenefitHistory": "Toegang tot je taakgeschiedenis",
"cloudBenefitMetrics": "Krijg een holistisch overzicht van je tokenverbruik",
"visitCloudWebsite": "Bezoek Roo Code Cloud",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "Taaksynchronisatie",
"taskSyncDescription": "Synchroniseer je taken om ze te bekijken en delen op Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Sta toe taken te besturen vanuit Roo Code Cloud",
"remoteControlRequiresTaskSync": "Taaksynchronisatie moet ingeschakeld zijn om Roomote Control te gebruiken",
"taskSyncManagedByOrganization": "Taaksynchronisatie wordt beheerd door uw organisatie",
"usageMetricsAlwaysReported": "Modelgebruiksinformatie wordt altijd gerapporteerd wanneer ingelogd",
"authWaiting": "Wachten tot authenticatie voltooid is...",
"havingTrouble": "Problemen?",
"pasteCallbackUrl": "Kopieer de redirect-URL uit je browser en plak hem hier:",
"startOver": "Opnieuw beginnen"
"startOver": "Opnieuw beginnen",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}

View file

@ -4,19 +4,23 @@
"logOut": "Wyloguj",
"testApiAuthentication": "Testuj uwierzytelnianie API",
"signIn": "Połącz z Roo Code Cloud",
"connect": "Połącz",
"connect": "Połącz teraz",
"cloudBenefitsTitle": "Połącz z Roo Code Cloud",
"cloudBenefitsSubtitle": "Synchronizuj swoje prompty i telemetrię, aby włączyć:",
"cloudBenefitHistory": "Historia zadań online",
"cloudBenefitSharing": "Funkcje udostępniania i współpracy",
"cloudBenefitMetrics": "Metryki użycia oparte na zadaniach, tokenach i kosztach",
"cloudBenefitWalkaway": "Śledź i kontroluj zadania z dowolnego miejsca za pomocą Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Umożliwia śledzenie i interakcję z zadaniami w tym obszarze roboczym za pomocą Roo Code Cloud",
"cloudBenefitSharing": "Udostępniaj zadania innym",
"cloudBenefitHistory": "Uzyskaj dostęp do historii zadań",
"cloudBenefitMetrics": "Uzyskaj całościowy widok zużycia tokenów",
"visitCloudWebsite": "Odwiedź Roo Code Cloud",
"cloudUrlPillLabel": "URL Roo Code Cloud",
"taskSync": "Synchronizacja zadań",
"taskSyncDescription": "Synchronizuj swoje zadania, aby przeglądać i udostępniać je w Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Pozwól kontrolować zadania z Roo Code Cloud",
"remoteControlRequiresTaskSync": "Synchronizacja zadań musi być włączona, aby używać Roomote Control",
"taskSyncManagedByOrganization": "Synchronizacja zadań jest zarządzana przez Twoją organizację",
"usageMetricsAlwaysReported": "Informacje o użyciu modelu są zawsze raportowane po zalogowaniu",
"authWaiting": "Oczekiwanie na zakończenie uwierzytelniania...",
"havingTrouble": "Masz problemy?",
"pasteCallbackUrl": "Skopiuj URL redirect z przeglądarki i wklej tutaj:",
"startOver": "Zacznij od nowa"
"startOver": "Zacznij od nowa",
"cloudUrlPillLabel": "URL Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": "Sair",
"testApiAuthentication": "Testar Autenticação de API",
"signIn": "Conectar ao Roo Code Cloud",
"connect": "Conectar",
"connect": "Conectar Agora",
"cloudBenefitsTitle": "Conectar ao Roo Code Cloud",
"cloudBenefitsSubtitle": "Sincronize seus prompts e telemetria para habilitar:",
"cloudBenefitHistory": "Histórico de tarefas online",
"cloudBenefitSharing": "Recursos de compartilhamento e colaboração",
"cloudBenefitMetrics": "Métricas de uso baseadas em tarefas, tokens e custos",
"cloudBenefitWalkaway": "Acompanhe e controle tarefas de qualquer lugar com Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permite acompanhar e interagir com tarefas neste workspace com Roo Code Cloud",
"cloudBenefitSharing": "Compartilhe tarefas com outros",
"cloudBenefitHistory": "Acesse seu histórico de tarefas",
"cloudBenefitMetrics": "Obtenha uma visão holística do seu consumo de tokens",
"visitCloudWebsite": "Visitar Roo Code Cloud",
"cloudUrlPillLabel": "URL do Roo Code Cloud ",
"taskSync": "Sincronização de tarefas",
"taskSyncDescription": "Sincronize suas tarefas para visualizar e compartilhar no Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Permite controlar tarefas a partir do Roo Code Cloud",
"remoteControlRequiresTaskSync": "A sincronização de tarefas deve estar habilitada para usar o Roomote Control",
"taskSyncManagedByOrganization": "A sincronização de tarefas é gerenciada pela sua organização",
"usageMetricsAlwaysReported": "As informações de uso do modelo são sempre reportadas quando conectado",
"authWaiting": "Aguardando conclusão da autenticação...",
"havingTrouble": "Tendo problemas?",
"pasteCallbackUrl": "Copie a URL de redirect do seu navegador e cole aqui:",
"startOver": "Recomeçar"
"startOver": "Recomeçar",
"cloudUrlPillLabel": "URL do Roo Code Cloud "
}

View file

@ -4,19 +4,23 @@
"logOut": "Выход",
"testApiAuthentication": "Проверить аутентификацию API",
"signIn": "Подключиться к Roo Code Cloud",
"connect": "Подключиться",
"connect": "Подключиться сейчас",
"cloudBenefitsTitle": "Подключиться к Roo Code Cloud",
"cloudBenefitsSubtitle": "Синхронизируй свои промпты и телеметрию, чтобы включить:",
"cloudBenefitHistory": "Онлайн-история задач",
"cloudBenefitSharing": "Функции обмена и совместной работы",
"cloudBenefitMetrics": "Метрики использования на основе задач, токенов и затрат",
"cloudBenefitWalkaway": "Отслеживайте и управляйте задачами откуда угодно с Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Позволяет отслеживать и взаимодействовать с задачами в этом рабочем пространстве с Roo Code Cloud",
"cloudBenefitSharing": "Делитесь задачами с другими",
"cloudBenefitHistory": "Получите доступ к истории задач",
"cloudBenefitMetrics": "Получите целостное представление о потреблении токенов",
"visitCloudWebsite": "Посетить Roo Code Cloud",
"cloudUrlPillLabel": "URL Roo Code Cloud",
"taskSync": "Синхронизация задач",
"taskSyncDescription": "Синхронизируйте свои задачи для просмотра и обмена в Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Разрешить управление задачами из Roo Code Cloud",
"remoteControlRequiresTaskSync": "Для использования Roomote Control должна быть включена синхронизация задач",
"taskSyncManagedByOrganization": "Синхронизация задач управляется вашей организацией",
"usageMetricsAlwaysReported": "Информация об использовании модели всегда сообщается при входе в систему",
"authWaiting": "Ожидание завершения аутентификации...",
"havingTrouble": "Проблемы?",
"pasteCallbackUrl": "Скопируй URL перенаправления из браузера и вставь его сюда:",
"startOver": "Начать заново"
"startOver": "Начать заново",
"cloudUrlPillLabel": "URL Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": ıkış yap",
"testApiAuthentication": "API Kimlik Doğrulamayı Test Et",
"signIn": "Roo Code Cloud'a bağlan",
"connect": "Bağlan",
"connect": "Şimdi Bağlan",
"cloudBenefitsTitle": "Roo Code Cloud'a bağlan",
"cloudBenefitsSubtitle": "Aşağıdakileri etkinleştirmek için promptlarını ve telemetriyi senkronize et:",
"cloudBenefitHistory": "Çevrimiçi görev geçmişi",
"cloudBenefitSharing": "Paylaşım ve işbirliği özellikleri",
"cloudBenefitMetrics": "Görev, token ve maliyet tabanlı kullanım metrikleri",
"cloudBenefitWalkaway": "Roomote Control ile görevleri her yerden takip et ve kontrol et",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Bu çalışma alanındaki görevleri Roo Code Cloud ile takip etme ve etkileşim kurma imkanı sağlar",
"cloudBenefitSharing": "Görevleri başkalarıyla paylaş",
"cloudBenefitHistory": "Görev geçmişine eriş",
"cloudBenefitMetrics": "Token tüketiminizin bütünsel görünümünü elde edin",
"visitCloudWebsite": "Roo Code Cloud'u ziyaret et",
"cloudUrlPillLabel": "Roo Code Cloud URL'si",
"taskSync": "Görev senkronizasyonu",
"taskSyncDescription": "Görevlerinizi Roo Code Cloud'da görüntülemek ve paylaşmak için senkronize edin",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Roo Code Cloud'dan görevleri kontrol etmeye izin ver",
"remoteControlRequiresTaskSync": "Roomote Control'ü kullanmak için görev senkronizasyonu etkinleştirilmelidir",
"taskSyncManagedByOrganization": "Görev senkronizasyonu kuruluşunuz tarafından yönetilir",
"usageMetricsAlwaysReported": "Oturum açıldığında model kullanım bilgileri her zaman raporlanır",
"authWaiting": "Kimlik doğrulama tamamlanması bekleniyor...",
"havingTrouble": "Sorun yaşıyor musun?",
"pasteCallbackUrl": "Tarayıcından redirect URL'sini kopyala ve buraya yapıştır:",
"startOver": "Baştan başla"
"startOver": "Baştan başla",
"cloudUrlPillLabel": "Roo Code Cloud URL'si"
}

View file

@ -4,19 +4,23 @@
"logOut": "Đăng xuất",
"testApiAuthentication": "Kiểm tra xác thực API",
"signIn": "Kết nối với Roo Code Cloud",
"connect": "Kết nối",
"connect": "Kết nối ngay",
"cloudBenefitsTitle": "Kết nối với Roo Code Cloud",
"cloudBenefitsSubtitle": "Đồng bộ prompts và telemetry của bạn để kích hoạt:",
"cloudBenefitHistory": "Lịch sử tác vụ trực tuyến",
"cloudBenefitSharing": "Tính năng chia sẻ và cộng tác",
"cloudBenefitMetrics": "Số liệu sử dụng dựa trên tác vụ, token và chi phí",
"cloudBenefitWalkaway": "Theo dõi và điều khiển tác vụ từ bất kỳ đâu với Roomote Control",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Cho phép theo dõi và tương tác với các tác vụ trong workspace này với Roo Code Cloud",
"cloudBenefitSharing": "Chia sẻ tác vụ với người khác",
"cloudBenefitHistory": "Truy cập lịch sử tác vụ của bạn",
"cloudBenefitMetrics": "Có cái nhìn toàn diện về mức tiêu thụ token của bạn",
"visitCloudWebsite": "Truy cập Roo Code Cloud",
"cloudUrlPillLabel": "URL Roo Code Cloud",
"taskSync": "Đồng bộ tác vụ",
"taskSyncDescription": "Đồng bộ tác vụ của bạn để xem và chia sẻ trên Roo Code Cloud",
"remoteControl": "Roomote Control",
"remoteControlDescription": "Cho phép điều khiển tác vụ từ Roo Code Cloud",
"remoteControlRequiresTaskSync": "Đồng bộ tác vụ phải được bật để sử dụng Roomote Control",
"taskSyncManagedByOrganization": "Việc đồng bộ hóa công việc được quản lý bởi tổ chức của bạn",
"usageMetricsAlwaysReported": "Thông tin sử dụng mô hình luôn được báo cáo khi đăng nhập",
"authWaiting": "Đang chờ hoàn tất xác thực...",
"havingTrouble": "Gặp vấn đề?",
"pasteCallbackUrl": "Sao chép URL redirect từ trình duyệt và dán vào đây:",
"startOver": "Bắt đầu lại"
"startOver": "Bắt đầu lại",
"cloudUrlPillLabel": "URL Roo Code Cloud"
}

View file

@ -4,19 +4,23 @@
"logOut": "退出登录",
"testApiAuthentication": "测试 API 认证",
"signIn": "连接到 Roo Code Cloud",
"connect": "连接",
"connect": "立即连接",
"cloudBenefitsTitle": "连接到 Roo Code Cloud",
"cloudBenefitsSubtitle": "同步你的提示词和遥测数据以启用:",
"cloudBenefitHistory": "在线任务历史",
"cloudBenefitSharing": "共享和协作功能",
"cloudBenefitMetrics": "基于任务、Token 和成本的使用指标",
"cloudBenefitWalkaway": "使用 Roomote Control 随时随地跟踪和控制任务",
"remoteControl": "Roomote Control",
"remoteControlDescription": "允许通过 Roo Code Cloud 跟踪和操作此工作区中的任务",
"cloudBenefitSharing": "与他人共享任务",
"cloudBenefitHistory": "访问您的任务历史",
"cloudBenefitMetrics": "获取您的令牌消耗的整体视图",
"visitCloudWebsite": "访问 Roo Code Cloud",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "任务同步",
"taskSyncDescription": "同步您的任务以在 Roo Code Cloud 上查看和共享",
"remoteControl": "Roomote Control",
"remoteControlDescription": "允许从 Roo Code Cloud 控制任务",
"remoteControlRequiresTaskSync": "必须启用任务同步才能使用 Roomote Control",
"taskSyncManagedByOrganization": "任务同步由您的组织管理",
"usageMetricsAlwaysReported": "登录时始终报告模型使用信息",
"authWaiting": "等待身份验证完成...",
"havingTrouble": "遇到问题?",
"pasteCallbackUrl": "从浏览器复制重定向 URL 并粘贴到这里:",
"startOver": "重新开始"
"startOver": "重新开始",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}

View file

@ -3,20 +3,24 @@
"profilePicture": "個人圖片",
"logOut": "登出",
"testApiAuthentication": "測試 API 認證",
"signIn": "登入 Roo Code Cloud",
"connect": "連線",
"signIn": "連線至 Roo Code Cloud",
"connect": "立即連線",
"cloudBenefitsTitle": "連線至 Roo Code Cloud",
"cloudBenefitsSubtitle": "同步您的提示詞和遙測資料以啟用:",
"cloudBenefitHistory": "線上工作歷史紀錄",
"cloudBenefitSharing": "分享和協作功能",
"cloudBenefitMetrics": "基於工作任務、Token 和成本的用量指標",
"cloudBenefitWalkaway": "使用 Roomote Control 隨時隨地追蹤和控制工作",
"remoteControl": "Roomote Control",
"remoteControlDescription": "允許透過 Roo Code Cloud 追蹤和操作此工作區中的工作",
"cloudBenefitWalkaway": "使用 Roomote Control 隨時隨地追蹤和控制任務",
"cloudBenefitSharing": "與他人分享任務",
"cloudBenefitHistory": "存取您的任務歷史",
"cloudBenefitMetrics": "獲得您的代幣消耗的整體視圖",
"visitCloudWebsite": "造訪 Roo Code Cloud",
"cloudUrlPillLabel": "Roo Code Cloud URL",
"taskSync": "任務同步",
"taskSyncDescription": "同步您的任務以在 Roo Code Cloud 上檢視和分享",
"remoteControl": "Roomote Control",
"remoteControlDescription": "允許從 Roo Code Cloud 控制任務",
"remoteControlRequiresTaskSync": "必須啟用任務同步才能使用 Roomote Control",
"taskSyncManagedByOrganization": "工作同步由您的組織管理",
"usageMetricsAlwaysReported": "登入時始終報告模型使用資訊",
"authWaiting": "等待身份驗證完成...",
"havingTrouble": "遇到問題?",
"pasteCallbackUrl": "從瀏覽器複製重新導向 URL 並貼上到這裡:",
"startOver": "重新開始"
"startOver": "重新開始",
"cloudUrlPillLabel": "Roo Code Cloud URL"
}