Entrada de la extensión: flujo de activate
Responsabilidades
activate() es el punto de entrada que VSCode invoca cuando el usuario dispara por primera vez una funcionalidad de la extensión; está en apps/vscode/src/extension.ts. Cline descompone ahí todo el arranque en cinco pasos: primero prepara el HostProvider (relacionado con la plataforma); luego limpia el formato de almacenamiento heredado de versiones anteriores; después exporta el almacenamiento nativo de VSCode al almacenamiento compartido en archivos; a continuación ejecuta la inicialización transversal (initialize); y solo al final registra los comandos, vistas, URI handler y CodeAction Provider específicos de VSCode. La función cierra con createClineAPI, que devuelve un objeto API mínimo que los consumidores externos pueden invocar directamente.
Su razón de ser es separar «cómo VSCode levanta la extensión» (algo específico de plataforma) de «cómo Cline se inicializa a sí mismo» (algo transversal). El initialize() de common.ts lo comparten VSCode, CLI y JetBrains (initialize:34); extension.ts solo se encarga de enchufar el context, los comandos y los URI handlers propios de VSCode. Por eso, al leer extension.ts, casi todo lo que se ve son acciones de registro tipo vscode.commands.registerCommand(...); el ensamblado real de servicios vive en initialize() y en el constructor de Controller.
Motivación de diseño
- La abstracción de plataforma antes que nada:
setupHostProviderdebe ejecutarse primero (setupHostProvider:73), porque todos los servicios posteriores obtienen webview, terminal y callback URL víaHostProvider.get(). Aquí se inyectan las implementaciones específicas de VSCode (VscodeWebviewProvider, VscodeTerminalManager, etc.). - Migración antes que exportación:
cleanupLegacyVSCodeStoragese ejecuta antes queexportVSCodeStorageToSharedFiles(cleanupLegacyVSCodeStorage:78). Primero se limpian las basuras históricas (workspace→global, task history→file, custom instructions→rules) y luego se exporta el state limpio a~/.cline/data/, para que las demás plataformas lean un estado consistente. - Inicialización compartida extraída a
common.ts: los servicios transversales (StateManager, ErrorService, PostHog, ClineTempManager, FileContextTracker, etc.) se levantan dentro deinitialize()(external services:56); VSCode no los reimplementa. Así, CLI y JetBrains reutilizan el mismo flujo de arranque. - Webview con
retainContextWhenHidden:registerWebviewViewProviderse invoca conretainContextWhenHidden: true(webview retain:124), de modo que al cerrar la barra lateral no se pierde el estado de React y no hace falta re-renderizar al reabrirla. El coste es que la webview permanece residente en memoria, pero el contexto de conversación de Cline merece ese gasto. - Registro de comandos en dos capas: VSCode obtiene los ids constantes de
ExtensionRegistryInfo.commands(ExtensionRegistryInfo:130), garantizando que los ids de comando coincidan entrepackage.jsony el código. En modo dev se cargan además los comandos de depuración dedev/commands/tasks(dev commands:193). - URI handler con reintento de respaldo: cuando
handleUriprocesa un deep link y el sidebar aún no está inicializado, primero llama aopenClineSidebarForTaskUriy vuelve a procesarlo (task uri retry:178), evitando la carrera entre la inicialización del sidebar y la llegada del deep link en la primera instalación.
Archivos clave
activate:68— entrada de toda la extensión; los cinco pasos del arranque están aquí.setupHostProvider call:73— primer paso: ensambla elHostProviderpara VSCode (webview, diff, comment review, terminal, callback URL).cleanupLegacyVSCodeStorage:78— segundo paso: limpia formatos históricos (workspace→global, task history→file, custom instructions→rules).exportVSCodeStorageToSharedFiles:84— tercer paso: exporta el almacenamiento nativo de VSCode al almacenamiento compartido en~/.cline/data/, legible por otras plataformas.initialize call:88— cuarto paso: ejecuta la inicialización transversal decommon.ts, que devuelve elVscodeWebviewProvider.registerWebviewViewProvider:124— registra la webview del sidebar ante VSCode, activandoretainContextWhenHidden.registerUriHandler:187— registra el URI handler, que procesa deep linksvscode://extension.id/cline/task/....registerCodeActionsProvider:248— registra el CodeAction Provider, que añade «Add to Cline / Explain / Improve / Fix with Cline» a la bombilla de errores del editor.setupHostProvider:602— función real que ensambla el HostProvider, inyectando VscodeWebviewProvider, VscodeDiffViewProvider, VscodeTerminalManager y otras fábricas.createClineAPI:553— devuelve la API externa con cuatro métodos:startNewTask,sendMessage,pressPrimaryButton,pressSecondaryButton.initialize:34— cuerpo de inicialización transversal: StateManager, PostHog, ErrorService y syncWorker se levantan aquí.deactivate:699— al desactivar, invocatearDown()y dispone el comment review controller.
Flujo de datos
El orden de arranque se ve de un vistazo en la parte superior de activate. El núcleo es «migrar antes de inicializar, compartir antes que plataforma»:
// 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 VscodeWebviewProviderEste bloque está cerca de activation sequence:73. Dentro de initialize() (createWebviewProvider:63) se invoca HostProvider.get().createWebviewProvider(), fábrica que devuelve una instancia de VscodeWebviewProvider. Esa instancia, en su constructor, hace un new Controller(context) sincrónico, y en el constructor de Controller se levantan a su vez StateManager, AuthService, McpHub, BannerService y una larga lista de dependencias. Así, cuando initialize() retorna, Controller ya está listo para recibir mensajes del webview. De vuelta en activate(), el tramo final registra los comandos, el URI handler y el CodeAction Provider; todas esas registraciones acaban derivando las peticiones a webview.controller o a WebviewProvider.getInstance().
Límites y fallos
- Fallo de inicialización de StateManager no es fatal:
initialize()envuelveStateManager.initializeen un try/catch; si falla, muestra un mensaje ERROR pero sigue adelante (stateManager try:45), porque el almacenamiento en memoria sigue disponible y solo la persistencia queda comprometida. - Carrera entre task URI e inicialización del sidebar: el URI handler intenta procesar el deep link de task; si falla, primero llama a
openClineSidebarForTaskUripara esperar a que el sidebar sea visible y reintenta (task uri retry:178), con un máximo de 3 segundos. - Carga asíncrona de comandos extra en modo dev: la rama
IS_DEVcarga los comandos de depuración con unimport("./dev/commands/tasks")dinámico (dev import:193); si falla, solo se registra en el log y el flujo principal no se ve afectado. - Sincronización de secrets entre ventanas: se escucha
storageContext.secrets.onDidChange; cuandocline:clineAccountIdcambia, el nuevo valor indica un login en otra ventana, y un valor vacío indica un logout en otra ventana (secrets listener:533), manteniendo coherente el estado de login entre ventanas. - Detección de la ruta de ripgrep: VSCode 1.122 migró ripgrep de
@vscode/ripgrepa@vscode/ripgrep-universal.getBinaryLocationprueba primero el nuevo layout y, si falla, cae al path antiguo (ripgrep path probe:685). deactivateinvocatearDown:deactivate()llama altearDown()decommon.ts(tearDown:153), que dispone en orden PostHog, telemetry, ErrorService, featureFlags, WebviewProvider, syncWorker, HookProcessRegistry y ClineTempManager, evitando procesos zombi.
Resumen
activate() separa con claridad la plataforma VSCode de la lógica de negocio de Cline: VSCode solo registra comandos, vistas, URI handler y CodeAction, mientras que el ensamblado real de servicios se delega al initialize() de common.ts y al constructor de Controller. Esta capa permite que CLI y JetBrains reutilicen el mismo código de inicialización. Para ver cómo Controller ensambla dependencias después del arranque y cómo conecta el webview con Task, ver /startup/controller; para ver la comunicación gRPC-over-postMessage entre webview y extensión, ver /startup/webview-bridge.