@paradow/ledge 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cli/index.js +39003 -46
  2. package/dist/cli/reduceWorker.js +2037 -0
  3. package/dist/ledge-guide.md +26 -49
  4. package/package.json +5 -1
  5. package/dist/cli/action-QW2ZQQBN.js +0 -27
  6. package/dist/cli/attach-ULTYWCJ7.js +0 -74
  7. package/dist/cli/bridge-CSLF7EW6.js +0 -70
  8. package/dist/cli/chunk-3DB3VOMM.js +0 -723
  9. package/dist/cli/chunk-4HXJQEUN.js +0 -118
  10. package/dist/cli/chunk-4VNKZOC2.js +0 -160
  11. package/dist/cli/chunk-6IYPRUQG.js +0 -17
  12. package/dist/cli/chunk-ASYAWVFW.js +0 -95
  13. package/dist/cli/chunk-CCSUP5ZI.js +0 -45
  14. package/dist/cli/chunk-CPERVAPQ.js +0 -232
  15. package/dist/cli/chunk-CSLVBADC.js +0 -60
  16. package/dist/cli/chunk-E3LXONBI.js +0 -6
  17. package/dist/cli/chunk-GXL3X7M7.js +0 -144
  18. package/dist/cli/chunk-HOOHS3MX.js +0 -39
  19. package/dist/cli/chunk-JEGPTNWV.js +0 -270
  20. package/dist/cli/chunk-K7UEKSB2.js +0 -305
  21. package/dist/cli/chunk-NLL2EQJ2.js +0 -94
  22. package/dist/cli/chunk-NWIICISV.js +0 -290
  23. package/dist/cli/chunk-OLLQBK6N.js +0 -41
  24. package/dist/cli/chunk-PZ3F4QH3.js +0 -9758
  25. package/dist/cli/chunk-U67V476Y.js +0 -35
  26. package/dist/cli/chunk-WXE2NOE5.js +0 -2674
  27. package/dist/cli/chunk-XOZD4BP5.js +0 -85
  28. package/dist/cli/daemon-5GT545BB.js +0 -2322
  29. package/dist/cli/decide-PFHHOCFZ.js +0 -59
  30. package/dist/cli/handover-EMO6JT7O.js +0 -17
  31. package/dist/cli/hook-W2BU74H5.js +0 -523
  32. package/dist/cli/launch-LP7YJR5N.js +0 -36
  33. package/dist/cli/send-NEI4X33R.js +0 -19
  34. package/dist/cli/setup-K42IVMHS.js +0 -38
  35. package/dist/cli/status-U2HGGKHF.js +0 -28
  36. package/dist/cli/task-PDDCE23D.js +0 -19
  37. package/dist/cli/team-S3ASP22H.js +0 -205
  38. package/dist/cli/tui-UPMRMCPC.js +0 -19216
  39. package/dist/cli/uninstall-4IMMR55T.js +0 -162
  40. package/dist/cli/version-LUMK3Z3T.js +0 -7
  41. package/dist/cli/who-NM3GPAPJ.js +0 -12
@@ -4,14 +4,14 @@ Ce guide est écrit à la main et versionné avec le code. Ledge le recopie dans
4
4
 
5
5
  ## Ce qu'est Ledge
6
6
 
7
- Ledge veille sur les sessions d'agents de l'utilisateur : Claude Code, Codex, Cursor Agent et OMP, lancés dans WSL ou sur un serveur SSH. Il montre ce que fait chaque agent et ce qu'il attend. Il permet de répondre à une demande sans ouvrir son terminal, de lancer des sessions et de monter des équipes.
7
+ Ledge veille sur les sessions d'agents de l'utilisateur : Claude Code, Codex, Cursor Agent et OMP, lancés dans WSL ou sur un serveur SSH. Il montre ce que fait chaque agent et ce qu'il attend. Il permet de répondre à une demande sans ouvrir son terminal et de lancer des sessions.
8
8
 
9
- - **Le daemon** (`ledge daemon`, paquet npm `@paradow/ledge`) tourne dans WSL ou sur un serveur. Il suit les sessions par leurs hooks et par tmux, garde les projets, les équipes, les tâches et les messages entre sessions, et fait tourner le chat de Ledge. La CLI `ledge` lui parle :
9
+ - **Le daemon** (`ledge daemon`, paquet npm `@paradow/ledge`) tourne dans WSL ou sur un serveur. Il suit les sessions par leurs hooks et par tmux, garde les projets, les tâches et les messages entre sessions, et fait tourner le chat de Ledge. La CLI `ledge` lui parle :
10
10
  - `ledge claude|codex|cursor` lance un agent suivi ;
11
11
  - `ledge attach <id>` met le terminal sur une session ;
12
12
  - `ledge who` et `ledge status` listent les sessions ;
13
13
  - `ledge send` et `ledge read` servent aux messages entre sessions ;
14
- - `ledge task`, `ledge decide`, `ledge team`, `ledge handover` et `ledge close` gèrent les tâches, les décisions, les équipes, la passation de relais et la fermeture ;
14
+ - `ledge task`, `ledge decide`, `ledge handover` et `ledge close` gèrent les tâches, les décisions, la passation de relais et la fermeture ;
15
15
  - `ledge tui` est Ledge dans un terminal ;
16
16
  - `ledge setup` et `ledge uninstall` installent et retirent les hooks et `~/.ledge`.
17
17
  - **Ledge Desktop** est l'application Windows : la fenêtre principale (accueil, atelier, sessions, réglages) et l'**encoche**.
@@ -51,24 +51,16 @@ L'application s'ouvre ici. On y vient aussi par `/` ou par l'entrée « Accueil
51
51
  #### Conversation (`conversation`)
52
52
 
53
53
  C'est la conversation avec Ledge, en pleine largeur.
54
- - On y pose des questions et on mentionne une session ou une équipe.
54
+ - On y pose des questions et on mentionne une session.
55
55
  - On y valide les cartes que Ledge propose.
56
- - Le panneau « Le point » résume trois sections : « À toi », « Équipes » et « Confiées par Ledge ». Le bouton « Résumer la journée » est là aussi.
56
+ - Le panneau « Le point » résume deux sections : « À toi » et « Confiées par Ledge ». Le bouton « Résumer la journée » est là aussi.
57
57
 
58
58
  Y renvoyer l'utilisateur pour une longue discussion avec Ledge, ou pour faire le point sur la journée.
59
59
 
60
- #### Équipes (`teams`)
61
-
62
- Le catalogue a trois parties : « En cours » (les équipes actives), « Modèles » et « Rôles ».
63
- - Les boutons « Lancer une session », « Monter une équipe… » et « Lancer cette équipe… » sont ici.
64
- - Les rôles et les modèles se lisent ici mais se modifient dans leurs fichiers : `~/.ledge/roles/<id>.md` et `~/.ledge/teams/<id>.yaml`, ou les mêmes sous `<dépôt>/.ledge/`.
65
-
66
- Y renvoyer l'utilisateur pour voir ou monter une équipe, ou pour consulter un rôle.
67
-
68
60
  #### Tâches (`tasks`)
69
61
 
70
62
  Toutes les tâches données entre sessions et par Ledge.
71
- - Filtres : « Toutes / Ouvertes / Closes », donneur, équipe, « Décisions ».
63
+ - Filtres : « Toutes / Ouvertes / Closes », donneur, « Décisions ».
72
64
  - Une tâche ouverte montre son résultat, sa raison et son historique.
73
65
  - Une décision se tranche ici : « Répondre », puis « Envoyer la réponse », puis « Confirmer l'envoi ».
74
66
 
@@ -80,10 +72,8 @@ Les conversations du jour avec Ledge, chacune avec « Voir dans la conversation
80
72
 
81
73
  ### Atelier (`overview`)
82
74
 
83
- On y vient par Échap depuis l'accueil ou une session, par « Retour à l'atelier », ou par la vue « Atelier » de la barre latérale. Chaque projet est une table, avec ses agents assis autour et leurs sous-agents en petits bots. Une équipe a sa pièce.
75
+ On y vient par Échap depuis l'accueil ou une session, par « Retour à l'atelier », ou par la vue « Atelier » de la barre latérale. Chaque projet est une table, avec ses agents assis autour et leurs sous-agents en petits bots.
84
76
  - Le menu d'une table propose « Nouvelle session », « Modifier le projet » et « Isoler cette table ».
85
- - Le menu d'une pièce propose « Nouvelle équipe ici… ».
86
- - Le menu d'une équipe propose « Voir les tâches » et « Dissoudre l'équipe ».
87
77
  - On range une session en la glissant sur une table.
88
78
  - Le zoom se règle au clavier (+, −, 0) ou avec `Ctrl` + molette.
89
79
  - Le bureau « Parler à Ledge » ouvre le chat ancré.
@@ -91,6 +81,19 @@ On y vient par Échap depuis l'accueil ou une session, par « Retour à l'atelie
91
81
 
92
82
  Y renvoyer l'utilisateur pour avoir une vue d'ensemble de qui travaille où, ou pour ranger une session dans un projet.
93
83
 
84
+ ### OpenRig (`openrig`)
85
+
86
+ On y vient par « OpenRig » dans la barre latérale, sous « Atelier ». La page pilote OpenRig sur une machine ; les puces du haut changent de machine.
87
+ - **Daemon :** « Démarrer », « Arrêter », « Redémarrer ». La case « Au démarrage, relancer les rigs qui tournaient » lance `rig start --last` ; « Sans le kernel » ajoute `--no-kernel`.
88
+ - **Kernel :** l'opérateur d'OpenRig (le rig nommé `kernel`), avec « Démarrer », « Arrêter », « Redémarrer ».
89
+ - **Rigs :** chaque rig montre son état, ses sièges et son dernier snapshot ; un clic sur son nom déplie ses sièges. « Démarrer » lance `rig up <rig> --existing`, « Arrêter » `rig down <rig>`, « Redémarrer » les deux avec un snapshot.
90
+ - **Permissions au lancement** : « Celle de la spec », « Auto » (mode auto de Claude), « Standard », « Ouvert », « YOLO » (aucune demande) ou « Verrouillé », pour tout le rig ; la colonne « Permissions » de la table change un rôle. Avec YOLO, « Accepter les avertissements de premier lancement » (`--non-interruptive`) évite qu'un siège s'arrête sur l'avertissement de Claude.
91
+ - **± Sièges** (rig en marche) : un compteur par rôle ajoute des copies du premier siège du rôle (`build-2`, `build-3`) ou retire les dernières, sans arrêter le rig. Les sièges ajoutés sont reliés par paires ou chacun à tous (OpenRig 0.7 et plus), puis un snapshot garde la nouvelle taille pour un redémarrage.
92
+ - Tout arrêt ou redémarrage demande confirmation, nomme les sièges qui travaillent et montre la commande `rig` lancée.
93
+ - **Lancer un rig…** : choisir une spec (« mes specs » ou celles d'OpenRig), le dossier de travail et le nom, le nombre de sièges par rôle avec leur harnais et leur modèle, puis comment les sièges ajoutés délèguent (par paires ou chacun à tous). « Vérifier » montre ce que `rig up --plan` conclut et la spec qui sera lancée ; « Lancer » la lance. Une spec modifiée est écrite dans `~/.ledge/rigs/<nom>/`, et « Enregistrer dans mes specs » la garde dans la bibliothèque OpenRig.
94
+
95
+ Y renvoyer l'utilisateur pour démarrer, arrêter ou redémarrer OpenRig, son kernel ou un rig, ou pour lancer un rig (par exemple trois développeurs et trois relecteurs), sur n'importe quelle machine.
96
+
94
97
  ### Session (`session`)
95
98
 
96
99
  On l'ouvre en cliquant sur un siège, sur une ligne de la barre latérale ou sur un élément « À toi ». On y accède aussi par `Alt+1…9`, par `Alt+←/→`, ou par `Ctrl+K`. Un sous-agent a sa propre page.
@@ -170,10 +173,9 @@ S'ouvre par `?`. Liste complète des raccourcis.
170
173
  #### Nouvelle session (`launch`)
171
174
 
172
175
  S'ouvre par `N` dans l'atelier, `Ctrl+Alt+N` partout, « Nouvelle session » dans la barre latérale ou un menu de table.
173
- - **Champs :** consigne, agent (Claude Code, Codex, Cursor Agent, OMP), modèle et effort, projet, machine, dossiers et dépôts, rôle éventuel.
174
- - **Mode équipe :** « Nouvelle équipe ». On choisit un modèle, ou des sièges un par un, et le nom de l'équipe.
176
+ - **Champs :** consigne, agent (Claude Code, Codex, Cursor Agent, OMP), modèle et effort, projet, machine, dossiers et dépôts.
175
177
 
176
- Y renvoyer l'utilisateur pour lancer lui-même une session ou une équipe avec des réglages précis.
178
+ Y renvoyer l'utilisateur pour lancer lui-même une session avec des réglages précis.
177
179
 
178
180
  #### Projet (`project`)
179
181
 
@@ -185,7 +187,7 @@ Crée (« Nouveau projet »), modifie ou supprime un projet. On y donne son nom,
185
187
 
186
188
  ## Ledge mobile
187
189
 
188
- Une application web pour le téléphone, avec quatre onglets en bas : « À traiter », « Agents », « Ledge », « Équipes ». Pour la lier :
190
+ Une application web pour le téléphone, avec trois onglets en bas : « À traiter », « Agents », « Ledge ». Pour la lier :
189
191
  1. Sur le PC, dans Réglages › Accès mobile, activer l'accès, choisir le relais et se connecter avec GitHub.
190
192
  2. Sur le téléphone, ouvrir l'adresse du relais et se connecter avec le même compte.
191
193
  3. Comparer le code affiché sur les deux appareils et approuver sur le PC.
@@ -196,11 +198,11 @@ Les demandes en attente, les plus anciennes d'abord, filtrées par type (autoris
196
198
 
197
199
  ### Agents (`agents`)
198
200
 
199
- Les sessions par projet et par table, avec les tables d'équipe. Une session ouvre son fil, l'en-tête d'une équipe ouvre l'équipe en cours.
201
+ Les sessions par projet. Une session ouvre son fil.
200
202
 
201
203
  ### Ledge (`chat`)
202
204
 
203
- Le chat de Ledge sur le téléphone, avec « Le point ». Les cartes proposent une session, une équipe ou une tâche. Cette conversation est propre au téléphone.
205
+ Le chat de Ledge sur le téléphone, avec « Le point ». Les cartes proposent une session ou une tâche. Cette conversation est propre au téléphone.
204
206
 
205
207
  ### Fil d'une session (`thread`)
206
208
 
@@ -218,30 +220,6 @@ Une demande seule : autorisation, question, plan ou modifications. On l'approuve
218
220
 
219
221
  S'ouvre depuis l'état de la liaison en en-tête. On y voit le PC, le compte, le serveur et les empreintes, et on y règle l'apparence. « Le PC » met à jour ou redémarre le daemon du PC. On peut aussi s'y déconnecter.
220
222
 
221
- ### Équipes (`teams`)
222
-
223
- Les équipes et les rôles. « Nouvelle équipe », « Nouveau rôle ». « Lever » lance une équipe dans un projet, après confirmation par passkey.
224
-
225
- ### Éditeur d'équipe (`team`)
226
-
227
- Les sièges d'une équipe, où la ranger (maison ou dépôt), Enregistrer ou Supprimer.
228
-
229
- ### Copier une équipe (`team-copy`)
230
-
231
- Enregistre la composition d'une équipe en cours comme nouvelle équipe.
232
-
233
- ### Éditeur de rôle (`role`)
234
-
235
- Identifiant, libellé, consigne, et les valeurs par défaut : outil, modèle, effort, autonomie.
236
-
237
- ### Équipe en cours (`live`)
238
-
239
- La fiche d'une équipe active : ses sièges, sa consigne, « Modifier la composition », « Enregistrer comme équipe », « Dissoudre l'équipe ».
240
-
241
- ### Composition (`compose`)
242
-
243
- Modifier les sièges d'une équipe en cours, puis « Appliquer ».
244
-
245
223
  ### Écrans qui s'affichent d'eux-mêmes
246
224
 
247
225
  Ces écrans ne sont pas des adresses : l'application les montre d'elle-même, selon l'état de la liaison avec le PC.
@@ -255,11 +233,10 @@ Ces écrans ne sont pas des adresses : l'application les montre d'elle-même, se
255
233
  |---|---|
256
234
  | répondre à un agent, voir ses modifications | Session (desktop), Demande ou Fil (mobile) |
257
235
  | voir ce qui l'attend | « À toi » (desktop), À traiter (mobile) |
258
- | lancer une session ou une équipe lui-même | Nouvelle session (`N`, `Ctrl+Alt+N`) |
236
+ | lancer une session lui-même | Nouvelle session (`N`, `Ctrl+Alt+N`) |
259
237
  | créer, modifier ou supprimer un projet | Réglages › Projets, ou le menu d'une table |
260
238
  | renommer, archiver, supprimer une session, passer le relais | Session › « Gérer la session » |
261
239
  | trancher une décision, suivre une tâche | Accueil › Tâches |
262
- | écrire un rôle ou un modèle d'équipe | Ses fichiers `.ledge/roles` et `.ledge/teams`, ou Équipes (mobile) |
263
240
  | ajouter un serveur | Réglages › Machines |
264
241
  | lier un téléphone | Réglages › Accès mobile |
265
242
  | changer l'agent du chat | Réglages › Général › Agent par défaut |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paradow/ledge",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "Follow and answer your WSL agent sessions (Claude Code, Codex, Cursor Agent) from the Ledge island on Windows.",
5
5
  "type": "module",
6
6
  "bin": { "ledge": "dist/cli/index.js" },
@@ -19,9 +19,12 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "ink": "7.1.1",
22
+ "jpeg-js": "^0.4.4",
23
+ "pngjs": "^7.0.0",
22
24
  "react": "^19.3.0",
23
25
  "string-width": "^8.3.0",
24
26
  "ws": "^8.18.0",
27
+ "yaml": "2.8.1",
25
28
  "zod": "^3.23.8"
26
29
  },
27
30
  "devDependencies": {
@@ -30,6 +33,7 @@
30
33
  "@ledge/seal": "workspace:*",
31
34
  "@ledge/ui": "workspace:*",
32
35
  "@types/node": "^22.7.0",
36
+ "@types/pngjs": "^6.0.5",
33
37
  "@types/react": "^19.3.0",
34
38
  "@types/ws": "^8.5.12",
35
39
  "ink-testing-library": "4.0.0",
@@ -1,27 +0,0 @@
1
- import {
2
- CLOSE_USAGE,
3
- DAEMON_DOWN,
4
- RUN_MS,
5
- actionArgs,
6
- callerOf,
7
- closeArgs,
8
- resultLine,
9
- runClose,
10
- runOnClient
11
- } from "./chunk-XOZD4BP5.js";
12
- import "./chunk-JEGPTNWV.js";
13
- import "./chunk-ASYAWVFW.js";
14
- import "./chunk-WXE2NOE5.js";
15
- import "./chunk-HOOHS3MX.js";
16
- import "./chunk-U67V476Y.js";
17
- export {
18
- CLOSE_USAGE,
19
- DAEMON_DOWN,
20
- RUN_MS,
21
- actionArgs,
22
- callerOf,
23
- closeArgs,
24
- resultLine,
25
- runClose,
26
- runOnClient
27
- };
@@ -1,74 +0,0 @@
1
- import {
2
- attachEnv
3
- } from "./chunk-CPERVAPQ.js";
4
- import "./chunk-PZ3F4QH3.js";
5
- import "./chunk-OLLQBK6N.js";
6
- import "./chunk-NWIICISV.js";
7
- import "./chunk-3DB3VOMM.js";
8
- import "./chunk-4VNKZOC2.js";
9
- import "./chunk-JEGPTNWV.js";
10
- import {
11
- connect
12
- } from "./chunk-ASYAWVFW.js";
13
- import {
14
- PROTOCOL_PORT,
15
- backendOf
16
- } from "./chunk-WXE2NOE5.js";
17
- import "./chunk-E3LXONBI.js";
18
- import {
19
- realTmux
20
- } from "./chunk-NLL2EQJ2.js";
21
- import "./chunk-6IYPRUQG.js";
22
- import "./chunk-HOOHS3MX.js";
23
- import "./chunk-U67V476Y.js";
24
-
25
- // src/cli/attach.ts
26
- import { spawn } from "child_process";
27
- var TMUX_SOCKET = "ledge";
28
- function attachInherit(args, env) {
29
- return new Promise((resolve) => {
30
- const child = spawn("tmux", args, { stdio: "inherit", env });
31
- child.on("error", () => resolve(1));
32
- child.on("exit", (c) => resolve(c ?? 1));
33
- });
34
- }
35
- async function nativeSession(id, port) {
36
- try {
37
- const c = await connect({ port, timeoutMs: 800 });
38
- const snap = await c.next("snapshot");
39
- await Promise.race([c.close(), new Promise((r) => setTimeout(r, 500))]);
40
- const s = snap.sessions.find((x) => x.id === id);
41
- return s && backendOf(s) === "omp-rpc" ? s.name : null;
42
- } catch {
43
- return null;
44
- }
45
- }
46
- async function attach(id, opts = {}) {
47
- if (!id) {
48
- console.error("ledge attach: missing session id");
49
- return 2;
50
- }
51
- const tmux = realTmux(opts.tmuxSocket ?? TMUX_SOCKET);
52
- const tmuxName = `ledge-${id}`;
53
- if (!await tmux.hasSession(tmuxName)) {
54
- const native = await nativeSession(id, opts.port ?? PROTOCOL_PORT);
55
- console.error(native ? `ledge attach: ${native} is driven by Ledge over OMP's own protocol: there is no terminal to attach to (open a shell from the app)` : `ledge attach: no session ${id}`);
56
- return 1;
57
- }
58
- let title = tmuxName;
59
- try {
60
- const c = await connect({ port: opts.port ?? PROTOCOL_PORT, timeoutMs: 800 });
61
- const snap = await c.next("snapshot");
62
- title = snap.sessions.find((s) => s.id === id)?.title ?? title;
63
- await Promise.race([c.close(), new Promise((r) => setTimeout(r, 500))]);
64
- } catch {
65
- }
66
- const write = opts.write ?? ((s) => {
67
- if (process.stdout.isTTY) process.stdout.write(s);
68
- });
69
- write(`\x1B]0;${title}\x07`);
70
- return (opts.attach ?? attachInherit)(tmux.attachArgs(tmuxName, { readOnly: opts.readOnly }), attachEnv(process.env));
71
- }
72
- export {
73
- attach
74
- };
@@ -1,70 +0,0 @@
1
- import {
2
- MAX_FRAME,
3
- readFrames
4
- } from "./chunk-OLLQBK6N.js";
5
- import {
6
- PROTOCOL_PORT,
7
- parseClientMessage,
8
- parseServerMessage,
9
- readDaemonToken
10
- } from "./chunk-WXE2NOE5.js";
11
- import "./chunk-HOOHS3MX.js";
12
- import "./chunk-U67V476Y.js";
13
-
14
- // src/cli/bridge.ts
15
- import WebSocket from "ws";
16
- function bearerHeaders() {
17
- const token = readDaemonToken();
18
- return token ? { authorization: `Bearer ${token}` } : {};
19
- }
20
- function bridge(opts = {}) {
21
- const input = opts.input ?? process.stdin, output = opts.output ?? process.stdout;
22
- const ws = new WebSocket(`ws://127.0.0.1:${opts.port ?? PROTOCOL_PORT}`, { maxPayload: MAX_FRAME, handshakeTimeout: 1e4, headers: bearerHeaders() });
23
- return new Promise((resolve, reject) => {
24
- let settled = false, off = () => {
25
- };
26
- const finish = (error) => {
27
- if (settled) return;
28
- settled = true;
29
- off();
30
- input.pause();
31
- input.off("end", end);
32
- input.off("error", fail);
33
- output.off("error", fail);
34
- output.off("drain", drain);
35
- ws.terminate();
36
- error ? reject(error) : resolve();
37
- };
38
- const fail = (e) => finish(e);
39
- const end = () => ws.close();
40
- const drain = () => ws.resume();
41
- input.on("error", fail);
42
- output.on("error", fail);
43
- output.on("drain", drain);
44
- ws.on("open", () => {
45
- off = readFrames(input, (raw) => {
46
- const msg = parseClientMessage(raw);
47
- if (msg.type === "machines.set" || msg.type === "projects.set" || msg.type === "island.set") return;
48
- if (ws.bufferedAmount > MAX_FRAME) throw new Error("Ledge bridge is overloaded");
49
- ws.send(JSON.stringify(msg));
50
- }, fail);
51
- input.on("end", end);
52
- if (input.readableEnded) end();
53
- });
54
- ws.on("message", (data) => {
55
- try {
56
- const msg = parseServerMessage(JSON.parse(String(data)));
57
- if (msg.type === "machines" || msg.type === "projects" || msg.type === "island") return;
58
- if (!output.write(`${JSON.stringify(msg)}
59
- `)) ws.pause();
60
- } catch (e) {
61
- fail(e);
62
- }
63
- });
64
- ws.on("error", fail);
65
- ws.on("close", (code) => finish(code === 1e3 || code === 1005 ? void 0 : new Error(`Ledge daemon disconnected (${code})`)));
66
- });
67
- }
68
- export {
69
- bridge
70
- };