@mmmbuto/nexuscrew 0.8.57 → 0.9.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.
- package/CHANGELOG.md +164 -2
- package/README.md +1 -0
- package/frontend/dist/assets/index-0vuhL1YP.css +32 -0
- package/frontend/dist/assets/index-zjL6kZ7J.js +93 -0
- package/frontend/dist/index.html +2 -2
- package/frontend/dist/version.json +1 -1
- package/lib/audio/adapters.js +50 -6
- package/lib/cli/commands.js +40 -2
- package/lib/cli/doctor.js +95 -12
- package/lib/cli/init.js +25 -3
- package/lib/cli/path.js +43 -10
- package/lib/cli/pidfile.js +23 -2
- package/lib/config.js +15 -0
- package/lib/fleet/builtin.js +161 -19
- package/lib/fleet/catalogs/opencode-go.json +328 -0
- package/lib/fleet/cell-exec.js +87 -9
- package/lib/fleet/cell-lease-server.js +719 -0
- package/lib/fleet/cell-lease.js +112 -0
- package/lib/fleet/definitions.js +101 -7
- package/lib/fleet/launch-broker.js +115 -3
- package/lib/fleet/lease-client.js +191 -0
- package/lib/fleet/lease-routes.js +92 -0
- package/lib/fleet/lease-verifier.js +230 -0
- package/lib/fleet/managed.js +444 -55
- package/lib/fleet/prompt-delivery.js +50 -2
- package/lib/fleet/provider.js +1 -1
- package/lib/fleet/runtime.js +53 -6
- package/lib/live-host/bridge.js +369 -0
- package/lib/live-host/routes.js +184 -0
- package/lib/live-host/store.js +96 -0
- package/lib/mcp/tools.js +51 -0
- package/lib/nodes/commands.js +9 -2
- package/lib/nodes/store.js +14 -0
- package/lib/nodes/tunnel.js +4 -1
- package/lib/proxy/federation.js +106 -9
- package/lib/proxy/node-proxy.js +33 -0
- package/lib/proxy/panel-auth.js +307 -0
- package/lib/proxy/panel-proxy.js +305 -0
- package/lib/server.js +127 -4
- package/package.json +1 -1
- package/skills/alibaba-token-media/SKILL.md +19 -0
- package/skills/crew/SKILL.md +15 -0
- package/skills/fill-forms/SKILL.md +23 -0
- package/skills/mail-assistant/SKILL.md +15 -0
- package/skills/memory/SKILL.md +15 -0
- package/skills/nexuscrew-agent/SKILL.md +18 -0
- package/skills/vl-msa/SKILL.md +15 -0
- package/frontend/dist/assets/index-CYi_lhCg.css +0 -32
- package/frontend/dist/assets/index-_c-1_3iR.js +0 -93
package/lib/fleet/builtin.js
CHANGED
|
@@ -41,6 +41,7 @@ const { probeModel } = require('./model-probe.js');
|
|
|
41
41
|
const { validEnvKey } = require('./env-key.js');
|
|
42
42
|
const { setCredential, removeCredential } = require('./credentials.js');
|
|
43
43
|
const { createLaunchBroker } = require('./launch-broker.js');
|
|
44
|
+
const { createLeaseManager } = require('./cell-lease-server.js');
|
|
44
45
|
const { MINIMAL_ENV_KEYS, termuxRuntimePaths } = require('../runtime/env.js');
|
|
45
46
|
const { requireSharedTmuxProtection } = require('../tmux/shared-server.js');
|
|
46
47
|
|
|
@@ -117,6 +118,56 @@ function backfillAgyEngine(defsPath, defs, cfg = {}) {
|
|
|
117
118
|
try { return atomicWrite(defsPath, draft); } catch (_) { return defs; }
|
|
118
119
|
}
|
|
119
120
|
|
|
121
|
+
// Engine desktop.local: NON managed (nessun client/provider AI, solo command+args
|
|
122
|
+
// come un engine custom). Entra nel container desktop via `docker exec` e
|
|
123
|
+
// precompila panelUrl al pannello web KasmVNC del container. `-u abc` non e' un
|
|
124
|
+
// dettaglio: senza, si entra come root e Chromium nel container rifiuta di
|
|
125
|
+
// partire ("Running as root without --no-sandbox is not supported") — un
|
|
126
|
+
// errore che nomina il soggetto sbagliato. panelUrl e' comodita' sopra il
|
|
127
|
+
// meccanismo condiviso (validPanelUrl in definitions.js): l'engine non ha una
|
|
128
|
+
// sua strada per imporre l'URL, dichiara solo il valore, e resta sovrascrivibile
|
|
129
|
+
// per-cella come qualunque altro panelUrl (vedi parseCell).
|
|
130
|
+
function defaultDesktopEngine() {
|
|
131
|
+
return {
|
|
132
|
+
id: 'desktop.local',
|
|
133
|
+
label: 'Desktop',
|
|
134
|
+
command: 'docker',
|
|
135
|
+
args: ['exec', '-it', '-u', 'abc', 'ai-desktop', 'bash'],
|
|
136
|
+
promptMode: 'send-keys',
|
|
137
|
+
panelUrl: 'https://127.0.0.1:6901',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Backfill dell'engine desktop.local: come backfillKimiEngine, idempotente
|
|
142
|
+
// (gia' presente -> skip) e non distruttivo su collisione id (un 'desktop.local'
|
|
143
|
+
// gia' scelto dall'utente per altro non viene sovrascritto). Nessun platform
|
|
144
|
+
// gate: il container e' un servizio esterno raggiunto via docker, non un
|
|
145
|
+
// binario per-platform come agy/grok.
|
|
146
|
+
//
|
|
147
|
+
// DELIBERATAMENTE NON agganciata al bootstrap (a differenza di shell/agy/kimi/
|
|
148
|
+
// grok/vl, vedi piu' sotto): NON e' una dimenticanza, e' una decisione presa
|
|
149
|
+
// (decisione di progetto, 2026-08-14). Un backfill universale presuppone un container con un
|
|
150
|
+
// nome preciso — `ai-desktop` — che quasi nessuna installazione avra'. E
|
|
151
|
+
// desktop.local non e' managed: non ha un describeManaged che lo segnali come
|
|
152
|
+
// "non configurato" quando il container manca, quindi resterebbe nella lista
|
|
153
|
+
// engine silenziosamente rotto — esattamente la classe di difetto (un gate
|
|
154
|
+
// verde/una feature presente che non significa cio' che sembra) inseguita piu'
|
|
155
|
+
// volte in questa stessa giornata di lavoro.
|
|
156
|
+
// Scartata anche l'opzione apparentemente furba di un gate su un container-probe
|
|
157
|
+
// all'avvio: il probe e' una decisione presa UNA volta, mentre il container puo'
|
|
158
|
+
// nascere e morire dopo — un engine che appare/scompare a seconda di quando hai
|
|
159
|
+
// riavviato e' peggio di uno assente, e richiederebbe interrogare Docker a ogni
|
|
160
|
+
// bootstrap: una dipendenza nuova sul percorso di avvio per una comodita'.
|
|
161
|
+
// Resta MANUALE: chi ha il container se lo aggiunge nella propria procedura
|
|
162
|
+
// — e' il posto dove qualcuno sa gia' che il container esiste.
|
|
163
|
+
function backfillDesktopEngine(defsPath, defs) {
|
|
164
|
+
if (!defs || defs.engines.some((engine) => engine.id === 'desktop.local')) return defs;
|
|
165
|
+
if (defs.engines.length >= CAPS.MAX_ENGINES) return defs;
|
|
166
|
+
const draft = draftFrom(defs);
|
|
167
|
+
draft.engines.push(defaultDesktopEngine());
|
|
168
|
+
try { return atomicWrite(defsPath, draft); } catch (_) { return defs; }
|
|
169
|
+
}
|
|
170
|
+
|
|
120
171
|
// Backfill dell'engine Kimi Code CLI nativo: installazioni esistenti ricevono
|
|
121
172
|
// kimi.native in modo idempotente e non distruttivo. Nessun platform gate: il
|
|
122
173
|
// CLI gira ovunque giri Node e su Termux il resolver applica gia' il workaround
|
|
@@ -214,24 +265,32 @@ function resolveCellCwd(cell, home) {
|
|
|
214
265
|
relNorm = normalizeCwdRel(cell.cwdRel);
|
|
215
266
|
if (relNorm === null) return { ok: false, fail: { reason: 'invalid-rel', cwdRel: cell.cwdRel } };
|
|
216
267
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
268
|
+
// out.unverifiable distingue "non esiste / fuori home / non directory"
|
|
269
|
+
// (legittimo rifiuto) da "esiste ma non ho potuto verificarlo" (EACCES/ELOOP su
|
|
270
|
+
// realpath): stesso verdetto (ok:false, fail-closed di sicurezza), messaggio
|
|
271
|
+
// diverso. Vedi resolveCwd e unportableCwdError. Il discriminante e' CHI ha
|
|
272
|
+
// fallito, non che ci sia stata un'eccezione.
|
|
273
|
+
const homeOut = {};
|
|
274
|
+
const realHome = resolveCwd(home, home, homeOut);
|
|
275
|
+
if (!realHome) return { ok: false, fail: { reason: 'home-unavailable', ...(homeOut.unverifiable ? { unverifiable: homeOut.unverifiable } : {}) } };
|
|
276
|
+
const cwdOut = {};
|
|
277
|
+
const realCwd = hasCwd ? resolveCwd(cell.cwd, home, cwdOut) : null;
|
|
278
|
+
const relOut = {};
|
|
279
|
+
const realFromRel = hasRel ? resolveCwd(path.join(realHome, relNorm), home, relOut) : null;
|
|
221
280
|
if (hasCwd && hasRel) {
|
|
222
|
-
if (!realCwd) return { ok: false, fail: { reason: 'invalid-cwd', cwd: cell.cwd } };
|
|
223
|
-
if (!realFromRel) return { ok: false, fail: { reason: 'invalid-rel', cwdRel: cell.cwdRel } };
|
|
281
|
+
if (!realCwd) return { ok: false, fail: { reason: 'invalid-cwd', cwd: cell.cwd, ...(cwdOut.unverifiable ? { unverifiable: cwdOut.unverifiable } : {}) } };
|
|
282
|
+
if (!realFromRel) return { ok: false, fail: { reason: 'invalid-rel', cwdRel: cell.cwdRel, ...(relOut.unverifiable ? { unverifiable: relOut.unverifiable } : {}) } };
|
|
224
283
|
if (realCwd !== realFromRel) return { ok: false, fail: { reason: 'mismatch', cwd: cell.cwd, cwdRel: cell.cwdRel } };
|
|
225
284
|
return { ok: true, cwd: realCwd, cwdRel: relNorm };
|
|
226
285
|
}
|
|
227
286
|
if (hasCwd) {
|
|
228
|
-
if (!realCwd) return { ok: false, fail: { reason: 'invalid-cwd', cwd: cell.cwd } };
|
|
287
|
+
if (!realCwd) return { ok: false, fail: { reason: 'invalid-cwd', cwd: cell.cwd, ...(cwdOut.unverifiable ? { unverifiable: cwdOut.unverifiable } : {}) } };
|
|
229
288
|
const rel = deriveCwdRel(realCwd, realHome);
|
|
230
289
|
if (rel === null) return { ok: false, fail: { reason: 'not-under-home', cwd: cell.cwd } };
|
|
231
290
|
return { ok: true, cwd: realCwd, cwdRel: rel };
|
|
232
291
|
}
|
|
233
292
|
// solo cwdRel
|
|
234
|
-
if (!realFromRel) return { ok: false, fail: { reason: 'invalid-rel', cwdRel: cell.cwdRel } };
|
|
293
|
+
if (!realFromRel) return { ok: false, fail: { reason: 'invalid-rel', cwdRel: cell.cwdRel, ...(relOut.unverifiable ? { unverifiable: relOut.unverifiable } : {}) } };
|
|
235
294
|
return { ok: true, cwd: realFromRel, cwdRel: relNorm };
|
|
236
295
|
}
|
|
237
296
|
|
|
@@ -258,12 +317,28 @@ function unportableCwdError(failures, home) {
|
|
|
258
317
|
const entry = { id };
|
|
259
318
|
const cwd = typeof fail.cwd === 'string' ? fail.cwd : undefined;
|
|
260
319
|
if (cwd !== undefined) entry.cwd = cwd;
|
|
320
|
+
// "non ho potuto verificare" (EACCES/ELOOP...) vs "non esiste/fuori home":
|
|
321
|
+
// stesso verdetto (rifiuto, fail-closed di sicurezza), ma la causa e' diversa
|
|
322
|
+
// e l'operatore deve saperlo: potrebbe bastare un permesso, non un path
|
|
323
|
+
// sbagliato. Il discriminante e' CHI ha fallito, non che ci sia stata
|
|
324
|
+
// un'eccezione.
|
|
325
|
+
if (fail.unverifiable) entry.unverifiable = fail.unverifiable;
|
|
261
326
|
const suggestion = suggestCwdRel(cwd, home);
|
|
262
327
|
if (suggestion) entry.suggestion = suggestion;
|
|
263
328
|
return entry;
|
|
264
329
|
});
|
|
330
|
+
const unverifiable = failures.filter((f) => f.fail.unverifiable);
|
|
331
|
+
const code = 'unportable-cwd';
|
|
332
|
+
if (unverifiable.length) {
|
|
333
|
+
const codes = [...new Set(unverifiable.map((f) => f.fail.unverifiable))].join(', ');
|
|
334
|
+
return httpError(400, `cwd non verificabile (esiste ma illeggibile: ${codes}), per: ${unverifiable.map((f) => f.id).join(', ')}: il percorso potrebbe esserci ma non si e' potuto verificare (permessi/symlink)`, {
|
|
335
|
+
code,
|
|
336
|
+
cells,
|
|
337
|
+
hint: 'non e\' necessariamente un path sbagliato: il percorso potrebbe esistere sotto la home ma i permessi della directory non hanno permesso di verificarlo',
|
|
338
|
+
});
|
|
339
|
+
}
|
|
265
340
|
return httpError(400, `cwd non portabile (deve esistere sotto la home) per: ${failures.map((f) => f.id).join(', ')}`, {
|
|
266
|
-
code
|
|
341
|
+
code,
|
|
267
342
|
cells,
|
|
268
343
|
hint: 'il percorso appartiene a un altro dispositivo o non esiste sotto la home di questo device: scegli una cartella sotto la home',
|
|
269
344
|
});
|
|
@@ -298,6 +373,9 @@ async function createBuiltinFleet(cfg = {}) {
|
|
|
298
373
|
const off = {
|
|
299
374
|
available: false, provider: 'builtin',
|
|
300
375
|
isCellSession: () => false, capabilities: () => [],
|
|
376
|
+
// B4: close() sempre sicura su qualunque Fleet restituita, anche unavailable:
|
|
377
|
+
// il caller non deve distinguere `off` dalla Fleet reale.
|
|
378
|
+
close: async () => {},
|
|
301
379
|
};
|
|
302
380
|
const blocked = (reason, code) => ({ ...off, reason, ...(code ? { migrationCode: code } : {}) });
|
|
303
381
|
if (cfg.builtinEnabled === false) return off;
|
|
@@ -306,16 +384,38 @@ async function createBuiltinFleet(cfg = {}) {
|
|
|
306
384
|
const defsPath = cfg.fleetDefsPath || path.join(home, '.nexuscrew', 'fleet.json');
|
|
307
385
|
const tmuxBin = cfg.tmuxBin || process.env.TMUX_BIN || 'tmux';
|
|
308
386
|
const readonly = () => (cfg.readonlyDefault === true || process.env.NEXUSCREW_READONLY === '1');
|
|
309
|
-
|
|
387
|
+
// Lease opt-in: attivo solo quando cfg.cellLeaseEnabled === true. server.js lo
|
|
388
|
+
// passa true in start(); i test che chiamano createServer() direttamente non
|
|
389
|
+
// passano il flag, quindi la suite esistente non vede endpoint lease aperti da up().
|
|
390
|
+
const cellLeaseEnabled = cfg.cellLeaseEnabled === true;
|
|
391
|
+
|
|
392
|
+
// --- P1-2 (audit 3405df0): TUTTI i gate availability AVVENGONO PRIMA di creare
|
|
393
|
+
// leaseManager/launchBroker e di leaseManager.boot(). leaseManager non esiste finche'
|
|
394
|
+
// la Fleet non e' confermata disponibile, quindi NESSUN endpoint lease resta vivo su
|
|
395
|
+
// un early return (off/blocked) finche' ogni gate resta sopra questa boundary.
|
|
396
|
+
// P2 (audit 2a05db2): questo e' un fatto contingente del ref corrente, NON una
|
|
397
|
+
// garanzia anti-refactor. Un gate aggiunto DOPO la creazione del manager passerebbe
|
|
398
|
+
// inosservato senza un controllo statico/mutation-sensitive: il commento non impedisce
|
|
399
|
+
// un `return off` futuro oltre la boundary. La promessa vera e' limitata: oggi nessun
|
|
400
|
+
// early return segue la creazione del manager, e la creazione avviene dopo tutti i
|
|
401
|
+
// gate noti. Manternerla richiede che ogni nuovo gate resti qui sopra.
|
|
402
|
+
|
|
403
|
+
// Bootstrap: fleet.json valido? garbage -> unavailable (fail-closed, design §7).
|
|
404
|
+
// ENOENT (missing) o parse invalido -> off (unavailable legittimo, fail-closed);
|
|
405
|
+
// EACCES/ELOOP sul lstat (file presente ma non verificabile) -> off CON reason,
|
|
406
|
+
// perche' "non ho potuto guardare" e' un problema diverso da "non c'e'" o "e'
|
|
407
|
+
// garbage". Verdetto (available:false) invariato; il discriminante e' CHI ha
|
|
408
|
+
// fallito, non che ci sia stata un'eccezione.
|
|
409
|
+
const bootStat = {};
|
|
410
|
+
let boot = loadDefinitions(defsPath, bootStat);
|
|
411
|
+
if (!boot) return bootStat.lstatBlocked
|
|
412
|
+
? { ...off, reason: `fleet.json non verificabile (${bootStat.lstatBlocked}): fail-closed, non "assente" né "invalido"` }
|
|
413
|
+
: off;
|
|
310
414
|
|
|
311
|
-
// Bootstrap: fleet.json valido? garbage -> unavailable (fail-closed, design §7)
|
|
312
|
-
let boot = loadDefinitions(defsPath);
|
|
313
|
-
if (!boot) return off;
|
|
314
415
|
if (!readonly()) {
|
|
315
|
-
// La migrazione precede QUALUNQUE backfill/scrittura: loadDefinitions
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
// seconda sessione safe accanto a quella legacy.
|
|
416
|
+
// La migrazione precede QUALUNQUE backfill/scrittura: loadDefinitions normalizza
|
|
417
|
+
// i nomi legacy solo in memoria. Se il rename e' ambiguo o fallisce, fleet.json
|
|
418
|
+
// resta byte-invariato e la Fleet non puo creare una seconda sessione safe.
|
|
319
419
|
let migration;
|
|
320
420
|
try {
|
|
321
421
|
migration = await migrateLegacyTmuxSessions(tmuxBin, boot, { readonly: false });
|
|
@@ -351,12 +451,46 @@ async function createBuiltinFleet(cfg = {}) {
|
|
|
351
451
|
});
|
|
352
452
|
await ensureProtection();
|
|
353
453
|
|
|
454
|
+
// --- Tutti i gate availability passati. Ora (e solo ora) creiamo leaseManager e
|
|
455
|
+
// launchBroker e riapriamo gli endpoint lease delle celle note (R3.3.1 recovery,
|
|
456
|
+
// rilievo 3). Non fatale: un fallimento di singolo endpoint non blocca il boot.
|
|
457
|
+
const leaseManager = cellLeaseEnabled ? createLeaseManager({ ...cfg, home }) : null;
|
|
458
|
+
const launchBroker = cfg.launchBroker || createLaunchBroker({
|
|
459
|
+
...cfg, home,
|
|
460
|
+
// R3.1.1: la connessione broker one-shot resta APERTA dopo il payload e diviene
|
|
461
|
+
// il canale lease del supervisore.
|
|
462
|
+
...(leaseManager ? {
|
|
463
|
+
onLease: (socket, lease) => {
|
|
464
|
+
// P1-3 (reaudit dd38c83): attachInitial restituisce false se la
|
|
465
|
+
// persistenza del bind fallisce. F-B (audit 2a @ 142e272): ora il
|
|
466
|
+
// broker chiama onLease PRIMA di scrivere il payload. Il ritorno
|
|
467
|
+
// ESPLICITO false (o la socket distrutta qui) comunica al broker di NON
|
|
468
|
+
// consegnare il payload: il supervisore riceve la chiusura prima del
|
|
469
|
+
// frame e non spawna MAI un child con una lease che il server non ha
|
|
470
|
+
// committato; e non resta un lease-client connesso a un manager vuoto
|
|
471
|
+
// (state=none) — l'orfano di prima nasceva cosi'.
|
|
472
|
+
const ok = lease && lease.cellId
|
|
473
|
+
? leaseManager.attachInitial(lease.cellId, socket, { generation: 0 })
|
|
474
|
+
: false;
|
|
475
|
+
if (!ok) {
|
|
476
|
+
try { socket.destroy(); } catch (_) {}
|
|
477
|
+
}
|
|
478
|
+
return ok;
|
|
479
|
+
},
|
|
480
|
+
} : {}),
|
|
481
|
+
});
|
|
482
|
+
if (leaseManager) {
|
|
483
|
+
try { await leaseManager.boot(); } catch {
|
|
484
|
+
// logged dal manager; un fallimento di singolo endpoint non blocca il boot.
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
354
488
|
// Runtime estratto (lib/fleet/runtime.js): possiede cache + definizioni e
|
|
355
489
|
// espone status/up/down/restart/isCellSession + gli accessor allo store
|
|
356
490
|
// (reloadDefs/findCell/findEngine/refreshSessions/commitDefs) che il CRUD
|
|
357
491
|
// qui sotto riusa. status/up/down/restart sono INVARIATI.
|
|
358
492
|
const rt = createBuiltinRuntime({
|
|
359
|
-
cfg, home, defsPath, tmuxBin, readonly, launchBroker, boot, ensureProtection,
|
|
493
|
+
cfg, home, defsPath, tmuxBin, readonly, launchBroker, leaseManager, boot, ensureProtection,
|
|
360
494
|
});
|
|
361
495
|
const {
|
|
362
496
|
status, cellStatus, up, down, restart, isCellSession,
|
|
@@ -1039,7 +1173,7 @@ async function createBuiltinFleet(cfg = {}) {
|
|
|
1039
1173
|
return { engine: profile.id, model: wanted, ...out };
|
|
1040
1174
|
}
|
|
1041
1175
|
|
|
1042
|
-
async function close() { await launchBroker.close(); }
|
|
1176
|
+
async function close() { await launchBroker.close(); if (leaseManager) leaseManager.close(); }
|
|
1043
1177
|
|
|
1044
1178
|
return {
|
|
1045
1179
|
available: true,
|
|
@@ -1050,6 +1184,10 @@ async function createBuiltinFleet(cfg = {}) {
|
|
|
1050
1184
|
schema, definitions, capabilities,
|
|
1051
1185
|
credentialStatus, setLocalCredential, removeLocalCredential, testModel,
|
|
1052
1186
|
defineModel, removeModel, close,
|
|
1187
|
+
// Fetta 2b (D3): il lease Live esposto alle route /api/lease, che il bridge
|
|
1188
|
+
// MCP delle celle consuma per register/refresh/recovery (B5). Assente se il
|
|
1189
|
+
// lease e' disattivato: le route rispondono 501, non 500.
|
|
1190
|
+
...(leaseManager ? { lease: leaseManager } : {}),
|
|
1053
1191
|
};
|
|
1054
1192
|
}
|
|
1055
1193
|
|
|
@@ -1060,6 +1198,10 @@ module.exports = {
|
|
|
1060
1198
|
backfillKimiEngine,
|
|
1061
1199
|
backfillGrokEngine,
|
|
1062
1200
|
backfillVlEngine,
|
|
1201
|
+
// Esportate ma NON chiamate qui sopra (§bootstrap, righe ~354-358): scelta
|
|
1202
|
+
// deliberata, non una dimenticanza — vedi il commento su backfillDesktopEngine.
|
|
1203
|
+
backfillDesktopEngine,
|
|
1204
|
+
defaultDesktopEngine,
|
|
1063
1205
|
resolveCellCwd,
|
|
1064
1206
|
composeLaunchArgv,
|
|
1065
1207
|
composeClientInvocation,
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
{
|
|
2
|
+
"models": [
|
|
3
|
+
{
|
|
4
|
+
"slug": "deepseek-v4-flash",
|
|
5
|
+
"display_name": "deepseek-v4-flash",
|
|
6
|
+
"description": "OpenCode Go: deepseek-v4-flash",
|
|
7
|
+
"default_reasoning_level": "high",
|
|
8
|
+
"supported_reasoning_levels": [
|
|
9
|
+
{
|
|
10
|
+
"effort": "low",
|
|
11
|
+
"description": "Fast responses with lighter reasoning"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"effort": "high",
|
|
15
|
+
"description": "Greater reasoning depth for complex problems"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"effort": "max",
|
|
19
|
+
"description": "Maximum reasoning depth"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"shell_type": "default",
|
|
23
|
+
"visibility": "list",
|
|
24
|
+
"supported_in_api": true,
|
|
25
|
+
"priority": 50,
|
|
26
|
+
"availability_nux": null,
|
|
27
|
+
"upgrade": null,
|
|
28
|
+
"base_instructions": "",
|
|
29
|
+
"supports_reasoning_summaries": true,
|
|
30
|
+
"default_reasoning_summary": "none",
|
|
31
|
+
"support_verbosity": false,
|
|
32
|
+
"default_verbosity": null,
|
|
33
|
+
"apply_patch_tool_type": null,
|
|
34
|
+
"web_search_tool_type": "text",
|
|
35
|
+
"truncation_policy": {
|
|
36
|
+
"mode": "tokens",
|
|
37
|
+
"limit": 1000000
|
|
38
|
+
},
|
|
39
|
+
"supports_parallel_tool_calls": false,
|
|
40
|
+
"supports_image_detail_original": false,
|
|
41
|
+
"context_window": 1000000,
|
|
42
|
+
"effective_context_window_percent": 95,
|
|
43
|
+
"experimental_supported_tools": [],
|
|
44
|
+
"input_modalities": [
|
|
45
|
+
"text"
|
|
46
|
+
],
|
|
47
|
+
"supports_search_tool": false
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"slug": "deepseek-v4-pro",
|
|
51
|
+
"display_name": "deepseek-v4-pro",
|
|
52
|
+
"description": "OpenCode Go: deepseek-v4-pro",
|
|
53
|
+
"default_reasoning_level": "high",
|
|
54
|
+
"supported_reasoning_levels": [
|
|
55
|
+
{
|
|
56
|
+
"effort": "low",
|
|
57
|
+
"description": "Fast responses with lighter reasoning"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"effort": "high",
|
|
61
|
+
"description": "Greater reasoning depth for complex problems"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"effort": "max",
|
|
65
|
+
"description": "Maximum reasoning depth"
|
|
66
|
+
}
|
|
67
|
+
],
|
|
68
|
+
"shell_type": "default",
|
|
69
|
+
"visibility": "list",
|
|
70
|
+
"supported_in_api": true,
|
|
71
|
+
"priority": 56,
|
|
72
|
+
"availability_nux": null,
|
|
73
|
+
"upgrade": null,
|
|
74
|
+
"base_instructions": "",
|
|
75
|
+
"supports_reasoning_summaries": true,
|
|
76
|
+
"default_reasoning_summary": "none",
|
|
77
|
+
"support_verbosity": false,
|
|
78
|
+
"default_verbosity": null,
|
|
79
|
+
"apply_patch_tool_type": null,
|
|
80
|
+
"web_search_tool_type": "text",
|
|
81
|
+
"truncation_policy": {
|
|
82
|
+
"mode": "tokens",
|
|
83
|
+
"limit": 1000000
|
|
84
|
+
},
|
|
85
|
+
"supports_parallel_tool_calls": false,
|
|
86
|
+
"supports_image_detail_original": false,
|
|
87
|
+
"context_window": 1000000,
|
|
88
|
+
"effective_context_window_percent": 95,
|
|
89
|
+
"experimental_supported_tools": [],
|
|
90
|
+
"input_modalities": [
|
|
91
|
+
"text"
|
|
92
|
+
],
|
|
93
|
+
"supports_search_tool": false
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"slug": "gpt-5.6-luna",
|
|
97
|
+
"display_name": "gpt-5.6-luna",
|
|
98
|
+
"description": "OpenCode Go: gpt-5.6-luna",
|
|
99
|
+
"default_reasoning_level": "medium",
|
|
100
|
+
"supported_reasoning_levels": [
|
|
101
|
+
{
|
|
102
|
+
"effort": "low",
|
|
103
|
+
"description": "Fast responses with lighter reasoning"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"effort": "medium",
|
|
107
|
+
"description": "Balanced reasoning depth"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"effort": "high",
|
|
111
|
+
"description": "Greater reasoning depth for complex problems"
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"shell_type": "default",
|
|
115
|
+
"visibility": "list",
|
|
116
|
+
"supported_in_api": true,
|
|
117
|
+
"priority": 51,
|
|
118
|
+
"availability_nux": null,
|
|
119
|
+
"upgrade": null,
|
|
120
|
+
"base_instructions": "",
|
|
121
|
+
"supports_reasoning_summaries": true,
|
|
122
|
+
"default_reasoning_summary": "none",
|
|
123
|
+
"support_verbosity": false,
|
|
124
|
+
"default_verbosity": null,
|
|
125
|
+
"apply_patch_tool_type": null,
|
|
126
|
+
"web_search_tool_type": "text",
|
|
127
|
+
"truncation_policy": {
|
|
128
|
+
"mode": "tokens",
|
|
129
|
+
"limit": 1050000
|
|
130
|
+
},
|
|
131
|
+
"supports_parallel_tool_calls": false,
|
|
132
|
+
"supports_image_detail_original": true,
|
|
133
|
+
"context_window": 1050000,
|
|
134
|
+
"effective_context_window_percent": 95,
|
|
135
|
+
"experimental_supported_tools": [],
|
|
136
|
+
"input_modalities": [
|
|
137
|
+
"text",
|
|
138
|
+
"image"
|
|
139
|
+
],
|
|
140
|
+
"supports_search_tool": false
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"slug": "grok-4.5",
|
|
144
|
+
"display_name": "grok-4.5",
|
|
145
|
+
"description": "OpenCode Go: grok-4.5",
|
|
146
|
+
"default_reasoning_level": "medium",
|
|
147
|
+
"supported_reasoning_levels": [
|
|
148
|
+
{
|
|
149
|
+
"effort": "low",
|
|
150
|
+
"description": "Fast responses with lighter reasoning"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"effort": "medium",
|
|
154
|
+
"description": "Balanced reasoning depth"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"effort": "high",
|
|
158
|
+
"description": "Greater reasoning depth for complex problems"
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
"shell_type": "default",
|
|
162
|
+
"visibility": "list",
|
|
163
|
+
"supported_in_api": true,
|
|
164
|
+
"priority": 52,
|
|
165
|
+
"availability_nux": null,
|
|
166
|
+
"upgrade": null,
|
|
167
|
+
"base_instructions": "",
|
|
168
|
+
"supports_reasoning_summaries": true,
|
|
169
|
+
"default_reasoning_summary": "none",
|
|
170
|
+
"support_verbosity": false,
|
|
171
|
+
"default_verbosity": null,
|
|
172
|
+
"apply_patch_tool_type": null,
|
|
173
|
+
"web_search_tool_type": "text",
|
|
174
|
+
"truncation_policy": {
|
|
175
|
+
"mode": "tokens",
|
|
176
|
+
"limit": 500000
|
|
177
|
+
},
|
|
178
|
+
"supports_parallel_tool_calls": false,
|
|
179
|
+
"supports_image_detail_original": true,
|
|
180
|
+
"context_window": 500000,
|
|
181
|
+
"effective_context_window_percent": 95,
|
|
182
|
+
"experimental_supported_tools": [],
|
|
183
|
+
"input_modalities": [
|
|
184
|
+
"text",
|
|
185
|
+
"image"
|
|
186
|
+
],
|
|
187
|
+
"supports_search_tool": false
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"slug": "glm-5.2",
|
|
191
|
+
"display_name": "glm-5.2",
|
|
192
|
+
"description": "OpenCode Go: glm-5.2",
|
|
193
|
+
"default_reasoning_level": "medium",
|
|
194
|
+
"supported_reasoning_levels": [
|
|
195
|
+
{
|
|
196
|
+
"effort": "low",
|
|
197
|
+
"description": "Fast responses with lighter reasoning"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"effort": "medium",
|
|
201
|
+
"description": "Balanced reasoning depth"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"effort": "high",
|
|
205
|
+
"description": "Greater reasoning depth for complex problems"
|
|
206
|
+
}
|
|
207
|
+
],
|
|
208
|
+
"shell_type": "default",
|
|
209
|
+
"visibility": "list",
|
|
210
|
+
"supported_in_api": true,
|
|
211
|
+
"priority": 53,
|
|
212
|
+
"availability_nux": null,
|
|
213
|
+
"upgrade": null,
|
|
214
|
+
"base_instructions": "",
|
|
215
|
+
"supports_reasoning_summaries": true,
|
|
216
|
+
"default_reasoning_summary": "none",
|
|
217
|
+
"support_verbosity": false,
|
|
218
|
+
"default_verbosity": null,
|
|
219
|
+
"apply_patch_tool_type": null,
|
|
220
|
+
"web_search_tool_type": "text",
|
|
221
|
+
"truncation_policy": {
|
|
222
|
+
"mode": "tokens",
|
|
223
|
+
"limit": 1000000
|
|
224
|
+
},
|
|
225
|
+
"supports_parallel_tool_calls": false,
|
|
226
|
+
"supports_image_detail_original": false,
|
|
227
|
+
"context_window": 1000000,
|
|
228
|
+
"effective_context_window_percent": 95,
|
|
229
|
+
"experimental_supported_tools": [],
|
|
230
|
+
"input_modalities": [
|
|
231
|
+
"text"
|
|
232
|
+
],
|
|
233
|
+
"supports_search_tool": false
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"slug": "glm-5.1",
|
|
237
|
+
"display_name": "glm-5.1",
|
|
238
|
+
"description": "OpenCode Go: glm-5.1",
|
|
239
|
+
"default_reasoning_level": "medium",
|
|
240
|
+
"supported_reasoning_levels": [
|
|
241
|
+
{
|
|
242
|
+
"effort": "low",
|
|
243
|
+
"description": "Fast responses with lighter reasoning"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"effort": "medium",
|
|
247
|
+
"description": "Balanced reasoning depth"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"effort": "high",
|
|
251
|
+
"description": "Greater reasoning depth for complex problems"
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
"shell_type": "default",
|
|
255
|
+
"visibility": "list",
|
|
256
|
+
"supported_in_api": true,
|
|
257
|
+
"priority": 54,
|
|
258
|
+
"availability_nux": null,
|
|
259
|
+
"upgrade": null,
|
|
260
|
+
"base_instructions": "",
|
|
261
|
+
"supports_reasoning_summaries": true,
|
|
262
|
+
"default_reasoning_summary": "none",
|
|
263
|
+
"support_verbosity": false,
|
|
264
|
+
"default_verbosity": null,
|
|
265
|
+
"apply_patch_tool_type": null,
|
|
266
|
+
"web_search_tool_type": "text",
|
|
267
|
+
"truncation_policy": {
|
|
268
|
+
"mode": "tokens",
|
|
269
|
+
"limit": 202752
|
|
270
|
+
},
|
|
271
|
+
"supports_parallel_tool_calls": false,
|
|
272
|
+
"supports_image_detail_original": false,
|
|
273
|
+
"context_window": 202752,
|
|
274
|
+
"effective_context_window_percent": 95,
|
|
275
|
+
"experimental_supported_tools": [],
|
|
276
|
+
"input_modalities": [
|
|
277
|
+
"text"
|
|
278
|
+
],
|
|
279
|
+
"supports_search_tool": false
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"slug": "glm-5",
|
|
283
|
+
"display_name": "glm-5",
|
|
284
|
+
"description": "OpenCode Go: glm-5",
|
|
285
|
+
"default_reasoning_level": "medium",
|
|
286
|
+
"supported_reasoning_levels": [
|
|
287
|
+
{
|
|
288
|
+
"effort": "low",
|
|
289
|
+
"description": "Fast responses with lighter reasoning"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"effort": "medium",
|
|
293
|
+
"description": "Balanced reasoning depth"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"effort": "high",
|
|
297
|
+
"description": "Greater reasoning depth for complex problems"
|
|
298
|
+
}
|
|
299
|
+
],
|
|
300
|
+
"shell_type": "default",
|
|
301
|
+
"visibility": "list",
|
|
302
|
+
"supported_in_api": true,
|
|
303
|
+
"priority": 55,
|
|
304
|
+
"availability_nux": null,
|
|
305
|
+
"upgrade": null,
|
|
306
|
+
"base_instructions": "",
|
|
307
|
+
"supports_reasoning_summaries": true,
|
|
308
|
+
"default_reasoning_summary": "none",
|
|
309
|
+
"support_verbosity": false,
|
|
310
|
+
"default_verbosity": null,
|
|
311
|
+
"apply_patch_tool_type": null,
|
|
312
|
+
"web_search_tool_type": "text",
|
|
313
|
+
"truncation_policy": {
|
|
314
|
+
"mode": "tokens",
|
|
315
|
+
"limit": 202752
|
|
316
|
+
},
|
|
317
|
+
"supports_parallel_tool_calls": false,
|
|
318
|
+
"supports_image_detail_original": false,
|
|
319
|
+
"context_window": 202752,
|
|
320
|
+
"effective_context_window_percent": 95,
|
|
321
|
+
"experimental_supported_tools": [],
|
|
322
|
+
"input_modalities": [
|
|
323
|
+
"text"
|
|
324
|
+
],
|
|
325
|
+
"supports_search_tool": false
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
}
|