Skip to content

Commit 08dbb1e

Browse files
mrubenscte
authored andcommitted
Support config policies that require use of cloud (#4762)
* Support config policies that require use of cloud * Switch to vitest
1 parent d6011fc commit 08dbb1e

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
@@ -52,6 +52,7 @@ import { MarketplaceManager } from "../../services/marketplace"
5252
import { ShadowCheckpointService } from "../../services/checkpoints/ShadowCheckpointService"
5353
import { CodeIndexManager } from "../../services/code-index/manager"
5454
import type { IndexProgressUpdate } from "../../services/code-index/interfaces/manager"
55+
import { MdmService } from "../../services/mdm/MdmService"
5556
import { fileExistsAtPath } from "../../utils/fs"
5657
import { setTtsEnabled, setTtsSpeed } from "../../utils/tts"
5758
import { ContextProxy } from "../config/ContextProxy"
@@ -105,6 +106,7 @@ export class ClineProvider
105106
}
106107
protected mcpHub?: McpHub // Change from private to protected
107108
private marketplaceManager: MarketplaceManager
109+
private mdmService?: MdmService
108110

109111
public isViewLaunched = false
110112
public settingsImportedAt?: number
@@ -118,13 +120,15 @@ export class ClineProvider
118120
private readonly renderContext: "sidebar" | "editor" = "sidebar",
119121
public readonly contextProxy: ContextProxy,
120122
public readonly codeIndexManager?: CodeIndexManager,
123+
mdmService?: MdmService,
121124
) {
122125
super()
123126

124127
this.log("ClineProvider instantiated")
125128
ClineProvider.activeInstances.add(this)
126129

127130
this.codeIndexManager = codeIndexManager
131+
this.mdmService = mdmService
128132
this.updateGlobalState("codebaseIndexModels", EMBEDDING_MODEL_PROFILES)
129133

130134
// Start configuration loading (which might trigger indexing) in the background.
@@ -527,6 +531,11 @@ export class ClineProvider
527531
>
528532
> = {},
529533
) {
534+
// Check MDM compliance before proceeding
535+
if (!this.checkMdmCompliance()) {
536+
return // Block task creation if not compliant
537+
}
538+
530539
const {
531540
apiConfiguration,
532541
organizationAllowList,
@@ -1702,6 +1711,29 @@ export class ClineProvider
17021711
return this.mcpHub
17031712
}
17041713

1714+
/**
1715+
* Check if the current state is compliant with MDM policy
1716+
* @returns true if compliant, false if blocked
1717+
*/
1718+
public checkMdmCompliance(): boolean {
1719+
if (!this.mdmService) {
1720+
return true // No MDM service, allow operation
1721+
}
1722+
1723+
const compliance = this.mdmService.isCompliant()
1724+
1725+
if (!compliance.compliant) {
1726+
vscode.window.showErrorMessage(compliance.reason, "Sign In").then((selection) => {
1727+
if (selection === "Sign In") {
1728+
this.postMessageToWebview({ type: "action", action: "accountButtonClicked" })
1729+
}
1730+
})
1731+
return false
1732+
}
1733+
1734+
return true
1735+
}
1736+
17051737
/**
17061738
* Returns properties to be included in every telemetry event
17071739
* 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)