Skip to content

Commit 8dd99a0

Browse files
authored
Support config policies that require use of cloud (#4762)
* Support config policies that require use of cloud * Switch to vitest
1 parent 322a15e commit 8dd99a0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+890
-4
lines changed

src/core/tools/newTaskTool.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } f
44
import { Task } from "../task/Task"
55
import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
66
import { formatResponse } from "../prompts/responses"
7+
import { t } from "../../i18n"
78

89
export async function newTaskTool(
910
cline: Task,
@@ -43,7 +44,7 @@ export async function newTaskTool(
4344

4445
cline.consecutiveMistakeCount = 0
4546
// Un-escape one level of backslashes before '@' for hierarchical subtasks
46-
// Un-escape one level: \\@ -> \@ (removes one backslash for hierarchical subtasks)
47+
// Un-escape one level: \\@ -> \@ (removes one backslash for hierarchical subtasks)
4748
const unescapedMessage = message.replace(/\\\\@/g, "\\@")
4849

4950
// Verify the mode exists
@@ -86,6 +87,10 @@ export async function newTaskTool(
8687
await delay(500)
8788

8889
const newCline = await provider.initClineWithTask(unescapedMessage, undefined, cline)
90+
if (!newCline) {
91+
pushToolResult(t("tools:newTask.errors.policy_restriction"))
92+
return
93+
}
8994
cline.emit("taskSpawned", newCline.taskId)
9095

9196
pushToolResult(`Successfully created new task in ${targetMode.name} mode with message: ${unescapedMessage}`)

src/core/webview/ClineProvider.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import { MarketplaceManager } from "../../services/marketplace"
5151
import { ShadowCheckpointService } from "../../services/checkpoints/ShadowCheckpointService"
5252
import { CodeIndexManager } from "../../services/code-index/manager"
5353
import type { IndexProgressUpdate } from "../../services/code-index/interfaces/manager"
54+
import { MdmService } from "../../services/mdm/MdmService"
5455
import { fileExistsAtPath } from "../../utils/fs"
5556
import { setTtsEnabled, setTtsSpeed } from "../../utils/tts"
5657
import { ContextProxy } from "../config/ContextProxy"
@@ -103,6 +104,7 @@ export class ClineProvider
103104
}
104105
protected mcpHub?: McpHub // Change from private to protected
105106
private marketplaceManager: MarketplaceManager
107+
private mdmService?: MdmService
106108

107109
public isViewLaunched = false
108110
public settingsImportedAt?: number
@@ -116,13 +118,15 @@ export class ClineProvider
116118
private readonly renderContext: "sidebar" | "editor" = "sidebar",
117119
public readonly contextProxy: ContextProxy,
118120
public readonly codeIndexManager?: CodeIndexManager,
121+
mdmService?: MdmService,
119122
) {
120123
super()
121124

122125
this.log("ClineProvider instantiated")
123126
ClineProvider.activeInstances.add(this)
124127

125128
this.codeIndexManager = codeIndexManager
129+
this.mdmService = mdmService
126130
this.updateGlobalState("codebaseIndexModels", EMBEDDING_MODEL_PROFILES)
127131

128132
// Start configuration loading (which might trigger indexing) in the background.
@@ -525,6 +529,11 @@ export class ClineProvider
525529
>
526530
> = {},
527531
) {
532+
// Check MDM compliance before proceeding
533+
if (!this.checkMdmCompliance()) {
534+
return // Block task creation if not compliant
535+
}
536+
528537
const {
529538
apiConfiguration,
530539
organizationAllowList,
@@ -1700,6 +1709,29 @@ export class ClineProvider
17001709
return this.mcpHub
17011710
}
17021711

1712+
/**
1713+
* Check if the current state is compliant with MDM policy
1714+
* @returns true if compliant, false if blocked
1715+
*/
1716+
public checkMdmCompliance(): boolean {
1717+
if (!this.mdmService) {
1718+
return true // No MDM service, allow operation
1719+
}
1720+
1721+
const compliance = this.mdmService.isCompliant()
1722+
1723+
if (!compliance.compliant) {
1724+
vscode.window.showErrorMessage(compliance.reason, "Sign In").then((selection) => {
1725+
if (selection === "Sign In") {
1726+
this.postMessageToWebview({ type: "action", action: "accountButtonClicked" })
1727+
}
1728+
})
1729+
return false
1730+
}
1731+
1732+
return true
1733+
}
1734+
17031735
/**
17041736
* Returns properties to be included in every telemetry event
17051737
* This method is called by the telemetry service to get context information

src/extension.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { DIFF_VIEW_URI_SCHEME } from "./integrations/editor/DiffViewProvider"
2626
import { TerminalRegistry } from "./integrations/terminal/TerminalRegistry"
2727
import { McpServerManager } from "./services/mcp/McpServerManager"
2828
import { CodeIndexManager } from "./services/code-index/manager"
29+
import { MdmService } from "./services/mdm/MdmService"
2930
import { migrateSettings } from "./utils/migrateSettings"
3031
import { API } from "./extension/api"
3132

@@ -78,6 +79,9 @@ export async function activate(context: vscode.ExtensionContext) {
7879
log: cloudLogger,
7980
})
8081

82+
// Initialize MDM service
83+
const mdmService = await MdmService.createInstance(cloudLogger)
84+
8185
// Initialize i18n for internationalization support
8286
initializeI18n(context.globalState.get("language") ?? formatLanguage(vscode.env.language))
8387

@@ -103,7 +107,7 @@ export async function activate(context: vscode.ExtensionContext) {
103107
)
104108
}
105109

106-
const provider = new ClineProvider(context, outputChannel, "sidebar", contextProxy, codeIndexManager)
110+
const provider = new ClineProvider(context, outputChannel, "sidebar", contextProxy, codeIndexManager, mdmService)
107111
TelemetryService.instance.setProvider(provider)
108112

109113
if (codeIndexManager) {

src/extension/api.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,15 @@ export class API extends EventEmitter<RooCodeEvents> implements RooCodeAPI {
132132
await provider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
133133
await provider.postMessageToWebview({ type: "invoke", invoke: "newChat", text, images })
134134

135-
const { taskId } = await provider.initClineWithTask(text, images, undefined, {
135+
const cline = await provider.initClineWithTask(text, images, undefined, {
136136
consecutiveMistakeLimit: Number.MAX_SAFE_INTEGER,
137137
})
138138

139-
return taskId
139+
if (!cline) {
140+
throw new Error("Failed to create task due to policy restrictions")
141+
}
142+
143+
return cline.taskId
140144
}
141145

142146
public async resumeTask(taskId: string): Promise<void> {

src/i18n/locales/ca/common.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,12 @@
102102
"groqApiKey": "Clau API de Groq",
103103
"getGroqApiKey": "Obté la clau API de Groq"
104104
}
105+
},
106+
"mdm": {
107+
"errors": {
108+
"cloud_auth_required": "La teva organització requereix autenticació de Roo Code Cloud. Si us plau, inicia sessió per continuar.",
109+
"organization_mismatch": "Has d'estar autenticat amb el compte de Roo Code Cloud de la teva organització.",
110+
"verification_failed": "No s'ha pogut verificar l'autenticació de l'organització."
111+
}
105112
}
106113
}

src/i18n/locales/ca/tools.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@
77
"toolRepetitionLimitReached": "Roo sembla estar atrapat en un bucle, intentant la mateixa acció ({{toolName}}) repetidament. Això podria indicar un problema amb la seva estratègia actual. Considera reformular la tasca, proporcionar instruccions més específiques o guiar-lo cap a un enfocament diferent.",
88
"codebaseSearch": {
99
"approval": "Cercant '{{query}}' a la base de codi..."
10+
},
11+
"newTask": {
12+
"errors": {
13+
"policy_restriction": "No s'ha pogut crear una nova tasca a causa de restriccions de política."
14+
}
1015
}
1116
}

src/i18n/locales/de/common.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,5 +102,12 @@
102102
"groqApiKey": "Groq API-Schlüssel",
103103
"getGroqApiKey": "Groq API-Schlüssel erhalten"
104104
}
105+
},
106+
"mdm": {
107+
"errors": {
108+
"cloud_auth_required": "Deine Organisation erfordert eine Roo Code Cloud-Authentifizierung. Bitte melde dich an, um fortzufahren.",
109+
"organization_mismatch": "Du musst mit dem Roo Code Cloud-Konto deiner Organisation authentifiziert sein.",
110+
"verification_failed": "Die Organisationsauthentifizierung konnte nicht verifiziert werden."
111+
}
105112
}
106113
}

src/i18n/locales/de/tools.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@
77
"toolRepetitionLimitReached": "Roo scheint in einer Schleife festzustecken und versucht wiederholt dieselbe Aktion ({{toolName}}). Dies könnte auf ein Problem mit der aktuellen Strategie hindeuten. Überlege dir, die Aufgabe umzuformulieren, genauere Anweisungen zu geben oder Roo zu einem anderen Ansatz zu führen.",
88
"codebaseSearch": {
99
"approval": "Suche nach '{{query}}' im Codebase..."
10+
},
11+
"newTask": {
12+
"errors": {
13+
"policy_restriction": "Neue Aufgabe konnte aufgrund von Richtlinienbeschränkungen nicht erstellt werden."
14+
}
1015
}
1116
}

src/i18n/locales/en/common.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,12 @@
9696
"input": {
9797
"task_prompt": "What should Roo do?",
9898
"task_placeholder": "Type your task here"
99+
},
100+
"mdm": {
101+
"errors": {
102+
"cloud_auth_required": "Your organization requires Roo Code Cloud authentication. Please sign in to continue.",
103+
"organization_mismatch": "You must be authenticated with your organization's Roo Code Cloud account.",
104+
"verification_failed": "Unable to verify organization authentication."
105+
}
99106
}
100107
}

src/i18n/locales/en/tools.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@
77
"toolRepetitionLimitReached": "Roo appears to be stuck in a loop, attempting the same action ({{toolName}}) repeatedly. This might indicate a problem with its current strategy. Consider rephrasing the task, providing more specific instructions, or guiding it towards a different approach.",
88
"codebaseSearch": {
99
"approval": "Searching for '{{query}}' in codebase..."
10+
},
11+
"newTask": {
12+
"errors": {
13+
"policy_restriction": "Failed to create new task due to policy restrictions."
14+
}
1015
}
1116
}

0 commit comments

Comments
 (0)