Skip to content

Entrée d'extension : flux de démarrage activate ​

源码版本v4.0.10

Responsabilités ​

activate() est le point d'entrée (entry point) appelé par VSCode lorsque l'utilisateur déclenche pour la première fois une fonctionnalité de l'extension. Il est défini dans apps/vscode/src/extension.ts. Cline y découpe tout le processus de démarrage en cinq étapes : d'abord mettre en place le HostProvider lié à la plateforme, puis nettoyer les formats de stockage hérités de la version précédente, ensuite exporter le stockage natif de VSCode vers un stockage de fichiers partagé, puis exécuter une initialisation multi-plateforme (initialize), et seulement alors enregistrer les commandes, vues, URI handler et CodeAction Provider propres à VSCode. Toute la fonction se termine par createClineAPI, qui renvoie un objet API minimal que les consommateurs externes peuvent appeler directement.

Son intérêt est de séparer « comment l'extension est levée par VSCode » — un sujet lié à la plateforme — de « comment Cline lui-même s'initialise » — un sujet multi-plateforme. Le initialize() de common.ts est partagé par les trois hôtes VSCode, CLI et JetBrains (initialize:34). extension.ts se borne à brancher le context, les commandes et les URI propres à VSCode. C'est pourquoi, en lisant extension.ts, vous ne voyez quasiment que des appels du genre vscode.commands.registerCommand(...) : l'assemblage réel des services se trouve dans initialize() et le constructeur de Controller.

Motivation de conception ​

  • L'abstraction plateforme avant tout : setupHostProvider doit s'exécuter en premier (setupHostProvider:73), car tous les services suivants obtiennent webview, terminal et callback URL via HostProvider.get(). Les implémentations propres à VSCode (VscodeWebviewProvider, VscodeTerminalManager, etc.) y sont injectées.
  • Migration avant export : cleanupLegacyVSCodeStorage s'exécute avant exportVSCodeStorageToSharedFiles (cleanupLegacyVSCodeStorage:78). Il nettoie d'abord les données historiques (workspace→global, task history→fichier, custom instructions→rules), puis exporte un state propre vers ~/.cline/data/, afin que les autres plateformes lisent un état cohérent.
  • Initialisation partagée dans common.ts : les services multi-plateformes (StateManager, ErrorService, PostHog, ClineTempManager, FileContextTracker, etc.) sont levés dans initialize() (external services:56), VSCode ne les réinvente pas. Ainsi CLI et JetBrains réutilisent le même démarrage.
  • Webview en retainContextWhenHidden : registerWebviewViewProvider reçoit retainContextWhenHidden: true (webview retain:124), pour que l'état React ne se perde pas quand la sidebar se ferme et que la réouverture n'entraîne pas de re-render. Le coût est une mémoire résidente, mais le contexte de conversation Cline mérite cette dépense.
  • Enregistrement des commandes en deux couches : les commandes VSCode tirent d'abord leurs ID constants de ExtensionRegistryInfo.commands (ExtensionRegistryInfo:130), pour garantir la cohérence des command ID entre package.json et le code. En mode dev, des commandes de debug sont également chargées depuis dev/commands/tasks (dev commands:193).
  • URI handler avec repli et retry : quand handleUri traite un deep link et que la sidebar n'est pas encore initialisée, il appelle openClineSidebarForTaskUri puis retente (task uri retry:178), afin d'éviter la race condition entre l'initialisation de la sidebar et l'arrivée du deep link à la première installation.

Fichiers clés ​

  • activate:68 — entrée de toute l'extension, le démarrage en cinq étapes se trouve ici.
  • setupHostProvider call:73 — première étape, assemble le HostProvider VSCode (webview, diff, comment review, terminal, callback URL).
  • cleanupLegacyVSCodeStorage:78 — deuxième étape, nettoie les formats historiques workspace→global, task history→file, custom instructions→rules.
  • exportVSCodeStorageToSharedFiles:84 — troisième étape, exporte le stockage natif VSCode vers ~/.cline/data/, le stockage de fichiers partagé lisible par les autres plateformes.
  • initialize call:88 — quatrième étape, exécute l'initialisation multi-plateforme de common.ts, renvoie VscodeWebviewProvider.
  • registerWebviewViewProvider:124 — enregistre la webview sidebar auprès de VSCode, active retainContextWhenHidden.
  • registerUriHandler:187 — enregistre l'URI handler, traite les deep links vscode://extension.id/cline/task/....
  • registerCodeActionsProvider:248 — enregistre le CodeAction Provider, expose quatre actions « Add to Cline / Explain / Improve / Fix with Cline » sur l'ampoule d'erreur de l'éditeur.
  • setupHostProvider:602 — fonction effectuant l'assemblage du HostProvider, transmet les factory VscodeWebviewProvider, VscodeDiffViewProvider, VscodeTerminalManager, etc.
  • createClineAPI:553 — renvoie l'API externe, expose startNewTask, sendMessage, pressPrimaryButton, pressSecondaryButton.
  • initialize:34 — corps de l'initialisation multi-plateforme, StateManager, PostHog, ErrorService, syncWorker sont levés ici.
  • deactivate:699 — à la désactivation, appelle tearDown() + dispose du comment review controller.

Flux de données ​

La séquence de démarrage est visible en haut de activate. Le cœur est « migration avant initialisation, partagé avant plateforme » :

typescript
// apps/vscode/src/extension.ts
// 1. Set up HostProvider for VSCode
setupHostProvider(context)

// 2. Clean up legacy data patterns within VSCode's native storage.
await cleanupLegacyVSCodeStorage(context)

// 3. One-time export of VSCode's native storage to shared file-backed stores.
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath
const storageContext = createStorageContext({ workspacePath })
await exportVSCodeStorageToSharedFiles(context, storageContext)

// 4. Register services and perform common initialization
const webview = (await initialize(storageContext)) as VscodeWebviewProvider

Ce bloc se trouve près de activation sequence:73. À l'intérieur de initialize() (createWebviewProvider:63), on appelle HostProvider.get().createWebviewProvider(). Cette factory renvoie une instance VscodeWebviewProvider qui, dans son constructeur, new synchro new Controller(context), lequel lève à son tour StateManager, AuthService, McpHub, BannerService et toute une chaîne de dépendances. À la fin de initialize(), Controller est donc déjà prêt à recevoir les messages de la webview. De retour dans activate(), la suite enregistre les commandes, l'URI handler et le CodeAction Provider ; ces enregistrements font tous transiter les requêtes vers webview.controller ou WebviewProvider.getInstance().

Limites et échecs ​

  • Échec d'initialisation du StateManager non fatal : initialize() enveloppe StateManager.initialize dans un try/catch. En cas d'échec, il affiche un message ERROR mais poursuit (stateManager try:45), car le stockage reste utilisable en mémoire, seule la persistance est perdue.
  • Race entre task URI et initialisation de la sidebar : l'URI handler tente d'abord de traiter le deep link task ; en cas d'échec, il appelle openClineSidebarForTaskUri puis attend que la sidebar soit visible pour réessayer (task uri retry:178), avec un délai maximal de 3 secondes.
  • Commandes dev chargées en asynchrone : dans la branche IS_DEV, les commandes de debug sont chargées via import("./dev/commands/tasks") dynamique (dev import:193). En cas d'échec, on se contente de loguer, sans impacter le flux principal.
  • Synchronisation cross-fenêtre des secrets : écoute storageContext.secrets.onDidChange. Quand cline:clineAccountId change, la nouvelle valeur signifie qu'une autre fenêtre s'est connectée, une valeur vide qu'une autre fenêtre s'est déconnectée (secrets listener:533), ce qui maintient la cohérence de l'état de login entre fenêtres.
  • Détection du chemin ripgrep : VSCode 1.122 migre ripgrep de @vscode/ripgrep vers @vscode/ripgrep-universal. getBinaryLocation tente d'abord la nouvelle disposition, et repli sur l'ancien chemin en cas d'échec (ripgrep path probe:685).
  • deactivate appelle tearDown : deactivate() appelle le tearDown() de common.ts (tearDown:153), qui dispose dans l'ordre PostHog, telemetry, ErrorService, featureFlags, WebviewProvider, syncWorker, HookProcessRegistry, ClineTempManager, pour éviter de laisser des zombies.

Résumé ​

activate() sépare proprement la spécificité plateforme VSCode de la logique métier de Cline : côté VSCode, on ne fait qu'enregistrer commandes, vues, URI handler et CodeAction ; l'assemblage réel des services est délégué à initialize() de common.ts et au constructeur de Controller. Cette séparation permet à CLI et JetBrains de réutiliser la même initialisation. Pour voir comment Controller assemble les dépendances et relie webview et Task, voir /startup/controller ; pour voir comment webview et extension communiquent via gRPC-over-postMessage, voir /startup/webview-bridge.

Voir la documentation officielle : documentation Cline · README.