@mmmbuto/nexuscrew 0.9.1 → 0.9.2

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.
@@ -11,7 +11,7 @@
11
11
  <meta name="apple-mobile-web-app-title" content="NexusCrew" />
12
12
  <link rel="manifest" href="/manifest.json" />
13
13
  <title>NexusCrew</title>
14
- <script type="module" crossorigin src="/assets/index-Bu_-2-Uu.js"></script>
14
+ <script type="module" crossorigin src="/assets/index-uRh_hSop.js"></script>
15
15
  <link rel="stylesheet" crossorigin href="/assets/index-0vuhL1YP.css">
16
16
  </head>
17
17
  <body>
@@ -1 +1 @@
1
- {"version":"0.9.1"}
1
+ {"version":"0.9.2"}
@@ -26,6 +26,7 @@
26
26
  // mutazione fleet e ogni up (§9d): passano solo status/schema/capabilities.
27
27
  // - promptMode 'send-keys' inietta via bracketed paste; se il command e' gia'
28
28
  // uscito (sessione morta) NON digita (§9e).
29
+ const fs = require('node:fs');
29
30
  const os = require('node:os');
30
31
  const path = require('node:path');
31
32
  const {
@@ -127,11 +128,41 @@ function backfillAgyEngine(defsPath, defs, cfg = {}) {
127
128
  // meccanismo condiviso (validPanelUrl in definitions.js): l'engine non ha una
128
129
  // sua strada per imporre l'URL, dichiara solo il valore, e resta sovrascrivibile
129
130
  // per-cella come qualunque altro panelUrl (vedi parseCell).
131
+ // Risolve un eseguibile del PATH nel suo path assoluto REALE. Il realpath non
132
+ // e' pignoleria: `validateCommandTrust` usa `lstat` e rifiuta i symlink — e in
133
+ // molte installazioni il primo hit nel PATH e' proprio un symlink. Senza questo
134
+ // passaggio l'engine sarebbe rifiutato dalla stessa trust boundary del
135
+ // progetto, con un messaggio che parla di path assoluti mentre il problema e'
136
+ // un link.
137
+ function risolviEseguibile(nome) {
138
+ const dirs = String(process.env.PATH || '').split(path.delimiter).filter(Boolean);
139
+ for (const dir of dirs) {
140
+ try {
141
+ const reale = fs.realpathSync(path.join(dir, nome));
142
+ const st = fs.statSync(reale);
143
+ if (st.isFile() && (st.mode & 0o100)) return reale;
144
+ } catch (_) { /* voce del PATH inservibile: si prova la prossima */ }
145
+ }
146
+ return null;
147
+ }
148
+
149
+ // Il command DEVE essere un path assoluto: `validateCommandTrust` e' la trust
150
+ // boundary degli engine, e un nome relativo si risolverebbe via PATH — cioe'
151
+ // via qualcosa che l'ambiente puo' cambiare sotto di noi. Dichiarare 'docker'
152
+ // rendeva questo engine built-in NON avviabile: veniva offerto nell'elenco e
153
+ // rifiutato al salvataggio con «command deve essere un path assoluto», un
154
+ // errore che descrive la forma del valore invece di dire che il comando non
155
+ // era stato risolto.
156
+ //
157
+ // Se docker non e' installato si ricade sul path convenzionale: l'engine resta
158
+ // visibile e il rifiuto diventa «non accessibile (ENOENT)», che nomina la
159
+ // causa vera — docker manca — invece di sembrare un difetto di
160
+ // configurazione.
130
161
  function defaultDesktopEngine() {
131
162
  return {
132
163
  id: 'desktop.local',
133
164
  label: 'Desktop',
134
- command: 'docker',
165
+ command: risolviEseguibile('docker') || '/usr/bin/docker',
135
166
  args: ['exec', '-it', '-u', 'abc', 'ai-desktop', 'bash'],
136
167
  promptMode: 'send-keys',
137
168
  panelUrl: 'https://127.0.0.1:6901',
@@ -161,13 +192,37 @@ function defaultDesktopEngine() {
161
192
  // Resta MANUALE: chi ha il container se lo aggiunge nella propria procedura
162
193
  // — e' il posto dove qualcuno sa gia' che il container esiste.
163
194
  function backfillDesktopEngine(defsPath, defs) {
164
- if (!defs || defs.engines.some((engine) => engine.id === 'desktop.local')) return defs;
195
+ if (!defs) return defs;
196
+ const esistente = defs.engines.find((engine) => engine.id === 'desktop.local');
197
+ if (esistente) return riparaDesktopEngine(defsPath, defs, esistente);
165
198
  if (defs.engines.length >= CAPS.MAX_ENGINES) return defs;
166
199
  const draft = draftFrom(defs);
167
200
  draft.engines.push(defaultDesktopEngine());
168
201
  try { return atomicWrite(defsPath, draft); } catch (_) { return defs; }
169
202
  }
170
203
 
204
+ // Le installazioni che hanno gia' ricevuto il backfill portano in
205
+ // configurazione un `command` RELATIVO, che la trust boundary rifiuta: per
206
+ // loro l'aggiornamento del default non cambia nulla, perche' il backfill salta
207
+ // cio' che esiste gia'. Senza questa riparazione il difetto resterebbe
208
+ // esattamente dove e' stato visto — su una macchina gia' configurata.
209
+ //
210
+ // Prudente per costruzione: interviene SOLO se il comando non e' assoluto e si
211
+ // chiama ancora `docker`. Un path assoluto — o un comando che l'utente ha
212
+ // cambiato in altro — non viene toccato: quella e' una scelta, non un residuo.
213
+ function riparaDesktopEngine(defsPath, defs, esistente) {
214
+ const cmd = typeof esistente.command === 'string' ? esistente.command : '';
215
+ if (!cmd || path.isAbsolute(cmd)) return defs;
216
+ if (path.basename(cmd) !== 'docker') return defs;
217
+ const risolto = risolviEseguibile('docker');
218
+ if (!risolto) return defs; // niente docker qui: meglio invariato che finto
219
+ const draft = draftFrom(defs);
220
+ const voce = draft.engines.find((engine) => engine.id === 'desktop.local');
221
+ if (!voce) return defs;
222
+ voce.command = risolto;
223
+ try { return atomicWrite(defsPath, draft); } catch (_) { return defs; }
224
+ }
225
+
171
226
  // Backfill dell'engine Kimi Code CLI nativo: installazioni esistenti ricevono
172
227
  // kimi.native in modo idempotente e non distruttivo. Nessun platform gate: il
173
228
  // CLI gira ovunque giri Node e su Termux il resolver applica gia' il workaround
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmbuto/nexuscrew",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Faithful browser tmux client — attach to live sessions over a real PTY, localhost-only, mobile-easy",
5
5
  "main": "lib/server.js",
6
6
  "bin": {