Nouveau workspace packages/vscode (git-arboretum, privé, non publié sur npm), client REST/WS réutilisant @arboretum/shared. Auth Authorization: Bearer sur REST et l'upgrade WS (via `ws`) ; un client Node sans en-tête Origin passe le check Origin strict du serveur. - Arbres temps réel : Repositories (repos → worktrees → sessions) et Groups, via le WebSocket. - Terminaux natifs (vscode.Pseudoterminal) pour attacher/observer une session — rendu et scrollback de VS Code ; décodage UTF-8 streaming + comptabilité ACK dans des modules purs. - Status bar (compteur waiting) + notifications natives sur passage en waiting, réponses Yes/No via la commande WS answer. - Mutations git (create worktree, commit, push, promote), start/kill/hide/resume/fork, session de groupe ; conscience du workspace (reveal + start/create here). - Bundle esbuild (format cjs, external vscode) inlinant @arboretum/shared → VSIX autonome. Logique réutilisable sans import vscode → testée par vitest (19 tests). - CI : .gitea/workflows/vscode-release.yml package le VSIX sur tag vscode-vX.Y.Z (artefact + asset de release best-effort). build:vscode hors du build principal (comme le site). - spikes/s5-vscode/STUDY.md : décision de conception (GO phasé A→D), marquée implémentée.
8.3 KiB
Spike S5 — Extension VSCode (intégration native) — ÉTUDE : ✅ GO (phasé)
✅ IMPLÉMENTÉ dans
packages/vscode(git-arboretum, privé) — phases A→D livrées : connexion + auth SecretStorage, arbres temps réel (Repos/Groups), terminaux natifsPseudoterminal, status bar + notificationswaiting(commandeanswer), mutations git, conscience du workspace. Bundle esbuild (shared inliné), packagé en VSIX (npm run build:vscodepuisvsce package --no-dependencies). CI :.gitea/workflows/vscode-release.ymlsur tagvscode-vX.Y.Z. L'étude ci-dessous reste la justification de conception.
Étude de conception (pas de mesure Go/No-Go : c'est un design + plan d'implémentation phasé). Objectif validé avec l'utilisateur : une vraie intégration native dans VSCode, pas un simple webview — une connexion réelle avec ce qui se passe dans l'éditeur (terminaux natifs, arbre, statut, notifications, conscience du workspace).
Contexte & contrainte
Arboretum est déjà un daemon qui sert une SPA et expose :
- une API REST (
/api/v1/...) : repos, worktrees (+ mutations git commit/push/promote), sessions, groupes, auth ; - un protocole WebSocket multiplexé (
@arboretum/shared→protocol.ts) : attach/stdin/resize, frames binaires[type u8][channel u32le][payload], flow-control par watermarks (FLOW), events temps réelsessions/worktrees/groups, commandeanswer(dialogues),hello/hello_ok.
Un plugin n'a donc rien à réimplémenter côté logique : il est un client de cette API. La question n'est pas « comment afficher le dashboard » mais « comment exposer Arboretum avec les primitives natives de VSCode ». Le webview (iframe du dashboard) reste un fallback optionnel ; ce n'est pas le cœur.
Pourquoi pas « juste un webview »
- Un webview = iframe vers
http://127.0.0.1:7317: lourd, isolé (CSP stricte,acquireVsCodeApiindisponible dans l'iframe), pas d'intégration avec les terminaux/arbres/statut de VSCode, auth à re-bricoler (cookie/token dans une iframe cross-origin). On retrouve les bugs xterm-in-webview (rendu, scrollback) qu'on cherche justement à éviter. - Une intégration native réutilise le rendu terminal, le scrollback, le copier/coller, les liens de VSCode (gratuitement robustes), et place Arboretum là où l'utilisateur travaille déjà.
Architecture proposée — packages/vscode
Nouveau workspace privé @arboretum/vscode, extension TypeScript, packagée en VSIX via vsce
(build esbuild). Le @arboretum/shared est résolu en dev par le symlink workspace et inliné au
packaging (même principe que scripts/inline-shared.mjs côté serveur) → VSIX autonome.
Connexion au daemon
- Réglages :
arboretum.url(défauthttp://127.0.0.1:7317),arboretum.token. - Auth : commande
Arboretum: Sign inqui demande le token et le stocke dans VS Code SecretStorage (les tokens daemon sont stockés hashés et le bootstrap ne s'affiche qu'une fois → impossible de « lire » le token existant ; on le saisit une fois). Option avancée : commande qui spawn le daemon (npx @johanleroy/git-arboretum) et capture le bootstrap token au premier démarrage. - Le check Origin strict du daemon ne s'applique qu'aux navigateurs (en-tête
Origin) : un client Node/extension n'envoie pas d'Origin→ OK ; l'auth par token (en-tête/cookie) reste requise.
Réutilisation du protocole (le « vrai » lien)
Importer @arboretum/shared : decodeBinaryFrame/encodage, BINARY_FRAME, FLOW, PROTOCOL_VERSION,
types de messages et SessionSummary/WorktreeSummary/GroupSummary. Le pont terminal et la liste
restent synchronisés avec le serveur par construction.
Surfaces natives
-
Activity Bar + TreeView(s) (
vscode.window.createTreeView) : arbre Repos → Worktrees → Sessions, avec badges d'état fins (activitybusy/waiting/idle,dialog) déjà portés parSessionSummary. Une vue Groupes en parallèle. Rafraîchi en temps réel par les events WS (onDidChangeTreeData). -
Terminaux VSCode natifs via
Pseudoterminal(pièce maîtresse) :vscode.window.createTerminal({ name, pty })où lePseudoterminalponte la session Arboretum :open()→wsClient.attach(sessionId);- OUTPUT WS (frames binaires) →
writeEmitter.fire(text)(onDidWrite) ; handleInput(data)→ WSstdin;setDimensions({columns, rows})→ WSresize;close()→detach. On réutilise le renderer + scrollback natifs de VSCode : règle au passage, côté VSCode, les problèmes de rendu et d'historique de la SPA. Flow-control : réutiliserFLOW/les ACK du protocole (envoyer un ACK des octets écrits) pour ne pas saturer.
-
Status bar (
createStatusBarItem) : compteur des sessionswaiting(à traiter) ; clic → focus de l'arbre / quick-pick des sessions en attente. -
Notifications natives : sur transition d'une session vers
waiting(event WS),showInformation Messageavec actions (« Ouvrir le terminal », « Oui »/« Non » → commande WSanswer). Doublonne utilement le Web Push : ici, natif dans l'éditeur. -
Conscience du workspace : mapper
workspace.workspaceFolders→ repo/worktree Arboretum (par chemin). Actions contextuelles : « Démarrer une session Claude ici », « Créer un worktree pour ce repo », et les mutations git existantes (commit/push/promote via REST). Met aussi en évidence dans l'arbre le worktree correspondant au dossier ouvert. -
Commandes (
contributes.commands+ palette VSCode) : sign in, ouvrir le dashboard (webview optionnel), rafraîchir, attacher/observer une session, créer worktree, commit/push/promote, start/hide session, répondre à un dialogue. -
Webview : seulement en option (vue dashboard complète pour qui la veut). UX primaire = native.
Découpage phasé (livrable séparé — non implémenté dans ce lot)
- A — Lecture & connexion : auth (SecretStorage) + client REST/WS + TreeView lecture seule (repos/worktrees/sessions/groupes) en temps réel. Valeur immédiate, risque faible.
- B — Terminaux natifs :
Pseudoterminalattach/observe via pont WS réutilisant@arboretum/shared(flow-control inclus). Le cœur de la valeur ; à faire juste après A. - C — Actions & supervision : mutations (créer worktree, commit/push/promote, start/hide), status
bar
waiting, notifications + commandeanswer. - D — Workspace-aware : mapping dossier ↔ repo/worktree + actions contextuelles.
Intégration monorepo & packaging
packages/vscode/:package.jsond'extension (engines.vscode,activationEvents,contributes.{commands,views,viewsContainers,configuration}), buildesbuild(bundle Node), test via@vscode/test-electron(optionnel). Publication : VSIX (vsce package) — le registre privé Gitea ne sert pas d'extensions VSCode, donc distribution par VSIX (et/ou Open VSX) plutôt que le Marketplace si l'on veut rester privé.- Le
tsconfigreste hors dutsc -bserver/shared actuel (build séparé) pour ne pas alourdir le typecheck CI existant.
Risques / questions ouvertes
- Auth bootstrap : saisie manuelle du token vs spawn+capture. MVP = saisie manuelle (SecretStorage).
- Flow-control côté extension : reprendre
FLOW(ACK par octets) pour les terminaux natifs ; unPseudoterminaln'expose pas de back-pressure → ACK « ce qui a été émis dansonDidWrite». - Remote/SSH/Codespaces : si l'on veut le webview fallback, prévoir
vscode.env.asExternalUri+portMapping. Les surfaces natives (REST/WS viaarboretum.url) restent valides tant que le daemon est joignable depuis l'hôte de l'extension. - Multi-fenêtres VSCode : une connexion WS par fenêtre (acceptable, outil mono-utilisateur).
Verdict
GO sur une extension native packages/vscode, en commençant par A → B (TreeView temps réel +
terminaux natifs Pseudoterminal), qui apportent l'essentiel de la valeur et réutilisent directement
l'API REST + le protocole WS de @arboretum/shared. Le webview n'est qu'un fallback optionnel.
Références API : Webview, Tree View, Pseudoterminal/createTerminal, StatusBarItem, SecretStorage,
asExternalUri (docs officielles VSCode).