Modes plan / act : deux rôles sous une même architecture
Responsabilités
Cline sépare « discuter avec l'utilisateur » et « réellement modifier les fichiers » en deux modes (modes) plan et act, explicitement annotés par le type Mode = "plan" | "act" (Mode type:14). Une même instance de Task n'appartient qu'à un seul mode ; changer de mode reconstruit la Task, donc au sein d'une tâche donnée le mode est fixe. Ce paramètre mode remonte de buildApiHandler jusqu'à ApiHandler, puis d'attemptApiRequest jusqu'au context de getSystemPrompt, de bout en bout.
Deux responsabilités principales : d'une part influencer le choix de l'ApiHandler — buildApiHandler sélectionne le provider depuis planModeApiProvider ou actModeApiProvider selon le mode (mode provider:520), ce qui permet à plan et act d'utiliser des modèles et thinkingBudget distincts ; d'autre part agir sur le contenu du composant ACT_VS_PLAN dans le system prompt (invite système) et sur les indications de disponibilité de certains outils (act_vs_plan template:5).
Motivation de conception
- Deux ApiConfiguration pour plan / act :
planModeApiProvider / actModeApiProvidersont deux champs indépendants, dont la valeur par défaut estDEFAULT_API_PROVIDER(planModeApiProvider:243). L'utilisateur peut faire passer plan par un modèle économique pour discuter rapidement de l'approche, et act par un modèle plus puissant pour modifier le code. - mode propagé jusqu'à la construction du handler : une fois
createHandlerForProviderinformé du mode, il pioche dans la bonne moitié des pairesplanModeApiModelId / actModeApiModelId,planModeReasoningEffort / actModeReasoningEffort,planModeThinkingBudgetTokens / actModeThinkingBudgetTokens(mode-aware options:94). Tous les « budget de réflexion », « reasoning effort » et « model id » sont isolés par mode. - outil plan_mode_respond réservé à plan : la description de l'outil
plan_mode_respondindique explicitementThis tool is only available in PLAN MODE. Le mode act n'a pas de garde-fou runtime bloquant cet outil, mais la sectionACT_VS_PLANdu system prompt prévient le modèle que « ACT MODE ne peut pas utiliser plan_mode_respond » (ACT MODE exclusion:9). - boîte à outils principale d'ACT MODE : parmi les 18 outils déclarés par la variante generic, seul
PLAN_MODE = "plan_mode_respond"est exclusif à plan ; les autres commeexecute_command / read_file / write_to_file / replace_in_file / search_files / list_files / attempt_completionsont disponibles dans les deux modes (generic tools:58). Le mode act s'appuie sur cet ensemble pour modifier des fichiers, lancer des commandes et clôturer viaattempt_completion. - yoloMode affecte le prompt de plan :
getActVsPlanModeTemplateTextvérifiecontext.yoloModeToggled !== true; seule la mode non-yolo ajoute à la description de plan la phrase « peut utiliser ask_followup_question pour poser des questions de clarification » (yolo guard:18). En mode yolo, on n'interroge pas spontanément. - paramètre needs_more_exploration : plan_mode_respond embarque un paramètre booléen optionnel
needs_more_exploration(needs_more_exploration:38), qui permet au modèle, après avoir écrit sa réponse, de revenir en arrière et dire « j'ai besoin de lire d'autres fichiers », évitant d'être enfermé dans son plan initial.
Fichiers clés
Mode type:14—type Mode = "plan" | "act", uniquement ces deux valeurs.buildApiHandler:517— point d'entrée, choisit le provider depuisplanModeApiProvider / actModeApiProvideret propage le mode àcreateHandlerForProvider.anthropic case mode-aware:94— la branchecase "anthropic"récupèreapiModelId / reasoningEffort / thinkingBudgetTokensdepuis les champs appariés selon le mode.mode provider pick:520—const apiProvider = mode === "plan" ? planModeApiProvider : actModeApiProvider.planModeApiProvider default:243— les deux champs ont pour défautDEFAULT_API_PROVIDER; tant que l'utilisateur ne configure rien, plan/act utilisent le même provider.act_vs_plan template:5— modèle de la section ACT_VS_PLAN du system prompt, définissant pour chaque mode la disponibilité des outils et les comportements attendus.ACT MODE description:9— ACT MODE dispose de tous les outils sauf plan_mode_respond, et termine via attempt_completion.PLAN MODE description:11— PLAN MODE ne peut répondre que via plan_mode_respond ; l'objectif est de collecter l'information avant de produire un plan.yolo mode guard:18— en mode yolo, on retire l'indication « peut poser des questions de clarification ».plan_mode_respond generic:25— spec de l'outil exclusif au mode plan, avec trois paramètresresponse / needs_more_exploration / task_progress.PLAN MODE only constraint:7— la description préciseThis tool is only available in PLAN MODE; le modèle se contraint lui-même via le prompt.act_mode_respond description:29— outil exclusif au mode act, pour signaler la progression sans interrompre le flux d'exécution, et qui ne peut pas être appelé consécutivement.generic tools list:58— liste des 18 ids d'outils déclarés par la variante generic, couvrant à la fois les outils plan et act.Task mode field:585— à la construction, la Task appellebuildApiHandleravec le paramètremode, provenant de TaskParams.
Flux de données
La propagation du mode est unidirectionnelle et linéaire : à la construction, la Task reçoit un mode, qui détermine la branche empruntée par buildApiHandler, puis attemptApiRequest transmet ce même mode via SystemPromptContext.providerInfo.mode à la couche de system prompt :
// apps/vscode/src/core/api/index.ts
export function buildApiHandler(configuration: ApiConfiguration, mode: Mode): ApiHandler {
const { planModeApiProvider, actModeApiProvider, ...options } = configuration
const apiProvider = mode === "plan" ? planModeApiProvider : actModeApiProvider
// ... thinkingBudget 限额 ...
return createHandlerForProvider(apiProvider, options, mode)
}Chaque case de createHandlerForProvider sélectionne ses champs en fonction du mode ; la branche Anthropic est typique :
// apps/vscode/src/core/api/index.ts
case "anthropic":
return new AnthropicHandler({
onRetryAttempt: options.onRetryAttempt,
apiKey: options.apiKey,
anthropicBaseUrl: options.anthropicBaseUrl,
apiModelId: mode === "plan" ? options.planModeApiModelId : options.actModeApiModelId,
reasoningEffort: mode === "plan" ? options.planModeReasoningEffort : options.actModeReasoningEffort,
thinkingBudgetTokens:
mode === "plan" ? options.planModeThinkingBudgetTokens : options.actModeThinkingBudgetTokens,
})Le test mode === "plan" se répète dans plus de 30 case ; cela peut sembler verbeux, mais l'avantage est que chaque branche indique explicitement au lecteur « ici il existe deux configurations plan/act », sans devoir mémoriser de convention de nommage. La section ACT_VS_PLAN du system prompt se contente de rendre le context :
// apps/vscode/src/core/prompts/system-prompt/components/act_vs_plan_mode.ts
const getActVsPlanModeTemplateText = (context: SystemPromptContext) => `ACT MODE V.S. PLAN MODE
In each user message, the environment_details will specify the current mode. There are two modes:
- ACT MODE: In this mode, you have access to all tools EXCEPT the plan_mode_respond tool.
- In ACT MODE, you use tools to accomplish the user's task. Once you've completed the user's task, you use the attempt_completion tool to present the result of the task to the user.
- PLAN MODE: In this special mode, you have access to the plan_mode_respond tool.
- In PLAN MODE, the goal is to gather information and get context to create a detailed plan for accomplishing the task, which the user will review and approve before they switch you to ACT MODE to implement the solution.
// ...`À noter : le code ne rend pas un modèle différent selon le mode, mais écrit les règles des deux modes dans la même section de prompt et laisse le modèle décider quelle branche suivre en fonction du champ environment_details.mode (environment_details mode:7). Le véritable « filtrage des outils par mode » est réalisé par ClineToolSet.getEnabledTools, qui filtre la liste d'outils à partir de context.providerInfo.mode (ApiProviderInfo.mode:75).
Limites et échecs
- plan utilisant un outil réservé à act n'est pas bloqué à l'exécution :
getEnabledToolsfiltre d'après la listevariant.tools, sans vérifier runtime le mode pour exclureplan_mode_respond(getEnabledTools:87). La variante generic déclare à la foisPLAN_MODEetATTEMPT; le modèle se contraint principalement via le system prompt. - changer de mode reconstruit la Task : la Task stocke le mode à la construction ; un changement runtime de mode déclenche la construction d'une nouvelle Task plutôt qu'une mutation de champ.
buildApiHandlern'est appelé qu'une seule fois, à la construction (buildApiHandler call:585). - valeur par défaut de planModeApiProvider :
DEFAULT_API_PROVIDERest la valeur par défaut partagée par plan/act (planModeApiProvider default:243). À la première ouverture de Cline, plan et act utilisent donc le même provider et se comportent de manière identique. - thinkingBudget plafonné séparément pour plan / act : dans
buildApiHandler,mode === "plan" ? planModeThinkingBudgetTokens : actModeThinkingBudgetTokensest plafonné individuellement par maxTokens (mode budget:525), sans qu'aucun budget de plan ne vienne impacter act ou inversement. - conflit yoloMode / plan : quand
yoloModeToggled === true, la section plan retire l'indication « peut poser ask_followup_question » (yolo guard:18). Or yolo sert à sauter les confirmations utilisateur et exécuter automatiquement, ce qui entre en tension avec la philosophie de plan « discuter avant d'exécuter » ; en pratique, les utilisateurs yolo n'empruntent quasiment jamais plan. - blocage des appels consécutifs à act_mode_respond : la description de l'outil
act_mode_respondprécise explicitement « ne peut pas être appelé consécutivement, sinon échec » (CRITICAL CONSTRAINT:43), avec un garde-fou runtime. - auto-correction via needs_more_exploration : après avoir écrit son plan, plan_mode_respond peut revenir en arrière et dire « j'ai besoin de plus d'exploration » ; via
needs_more_exploration=true, le tour suivant enchaînera sur des outils d'exploration plutôt que sur la clôture (needs_more_exploration:38), offrant une porte de sortie pour l'auto-correction du modèle.
Résumé
Les modes plan / act tracent la frontière, chez Cline, entre « discuter l'approche » et « modifier le code ». Sur le plan technique, cela se résume au type Mode = "plan" | "act" et à un jeu de champs configurés par paires. Le compromis : ne pas basculer de mode à l'exécution, mais reconstruire la Task à chaque changement, de sorte que handler / prompt / toolset soient tous reconstruits ensemble selon le mode, avec un état proprement isolé. En pratique, le modèle se contraint lui-même via la section ACT_VS_PLAN du system prompt ; les interceptions runtime sont rares.
- Comment la toolset filtre par context :
/prompts/toolset - Comment le system prompt est assemblé :
/prompts/prompt-builder - Comment le mode influence le choix du handler :
/providers/api-handler
Voir la documentation officielle : documentation Cline · README