@mmmbuto/nexuscrew 0.9.21 → 0.9.22

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 CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to NexusCrew are tracked here.
4
4
 
5
+ ## 0.9.22 — 2026-09-11
6
+
7
+ - **Fleet Ollama Cloud: `deepseek-v4.1-flash`** aggiunto ai modelli dell'engine
8
+ (contesto dichiarato 1M → 1048576; capacità text+image, reasoning; parallel
9
+ tool calls non dichiarato finché non misurato su device) e promosso a
10
+ **modello di default dei tre engine ollama-cloud** (`claude`, `codex-vl`,
11
+ `codex`), al posto di `glm-5.2` (che resta disponibile in lista).
12
+ - Il tarball npm non include più gli screenshot di `docs/img/` (restano nel
13
+ repository GitHub, referenziati dal README): il pacchetto 0.9.21 li
14
+ spediva per errore mostrando nomi di ambiente interno.
15
+ - **Fleet codex-vl app-server identity policy.** Managed `codex-vl.*` cells now
16
+ pass `CODEX_APP_SERVER_IDENTITY_REQUIRED=1` through the child environment so
17
+ the app-server daemon started by the TUI enforces the Fleet identity policy;
18
+ an explicit per-engine override remains authoritative.
19
+
5
20
  ## 0.9.21 — 2026-09-10
6
21
 
7
22
  - **Identity channel generation gate is fail-closed.** The per-cell supervisor
@@ -1 +1 @@
1
- {"version":"0.9.21"}
1
+ {"version":"0.9.22"}
@@ -42,6 +42,7 @@ const MAX_TMUXSESSION_LEN = 64;
42
42
  const ENGINE_ID_RE = /^[a-z0-9._-]{1,32}$/; // engine id: lowercase (design 4a/9f)
43
43
  const CELL_ID_RE = /^[A-Za-z0-9._-]{1,32}$/; // cell id: ammette maiuscole (il punto e' un id umano valido)
44
44
  const ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/; // identificatore env POSIX-like
45
+ const CODEX_APP_SERVER_IDENTITY_REQUIRED = 'CODEX_APP_SERVER_IDENTITY_REQUIRED';
45
46
  const TMUX_NAME_RE = /^[\w.-]{1,64}$/; // parsing: ammette il punto (legacy puntato da migrare)
46
47
  const TMUX_SAFE_NAME_RE = /^[\w-]{1,64}$/; // scrittura: nomi tmux-safe (NO punto: tmux lo normalizza in '_')
47
48
 
@@ -334,9 +335,22 @@ function parseEngine(e, { extraModels = null, onIssue = null } = {}) {
334
335
  if (e.managed !== undefined) {
335
336
  const managed = normalizeManagedSpec(e.managed, { extraModels, engineId: e.id, onIssue });
336
337
  if (!managed) return null;
337
- for (const key of ['command', 'args', 'env', 'promptMode', 'promptFlag', 'model']) {
338
+ for (const key of ['command', 'args', 'promptMode', 'promptFlag', 'model']) {
338
339
  if (e[key] !== undefined) return null;
339
340
  }
341
+ // Managed engines compose their environment from the profile. The sole
342
+ // user override permitted here is the daemon policy switch consumed by
343
+ // codex-vl app-server; arbitrary env values would bypass that boundary.
344
+ let managedEnv;
345
+ if (e.env !== undefined) {
346
+ if (managed.client !== 'codex-vl') return null;
347
+ if (!e.env || typeof e.env !== 'object' || Array.isArray(e.env)) return null;
348
+ const keys = Object.keys(e.env);
349
+ if (keys.length !== 1 || keys[0] !== CODEX_APP_SERVER_IDENTITY_REQUIRED) return null;
350
+ const value = e.env[CODEX_APP_SERVER_IDENTITY_REQUIRED];
351
+ if (typeof value !== 'string' || value.length > MAX_ENV_VAL_LEN) return null;
352
+ managedEnv = { [CODEX_APP_SERVER_IDENTITY_REQUIRED]: value };
353
+ }
340
354
  // panelUrl (opzionale): STESSO validatore e STESSA conservazione del ramo
341
355
  // custom, qui sotto. Un engine managed puo' legittimamente avere un
342
356
  // pannello, e il fallback engine->cella di cellStatus vale per entrambi.
@@ -349,6 +363,7 @@ function parseEngine(e, { extraModels = null, onIssue = null } = {}) {
349
363
  managedPanelUrl = e.panelUrl;
350
364
  }
351
365
  const managedOut = { id: e.id, label, rc, managed };
366
+ if (managedEnv) managedOut.env = managedEnv;
352
367
  if (managedPanelUrl !== undefined) managedOut.panelUrl = managedPanelUrl;
353
368
  return managedOut;
354
369
  }
@@ -24,6 +24,11 @@ const OLLAMA_CLOUD_MODELS = Object.freeze([
24
24
  // dichiara Context 1M tokens, Input Text, Image e le badge vision/tools/thinking/cloud.
25
25
  // DICHIARATO 2026-09-06 https://ollama.com/library/kimi-k3
26
26
  'kimi-k3',
27
+ // deepseek-v4.1-flash: disponibile su ollama.com/library (2026-09-11). La
28
+ // scheda dichiara Context 1M tokens, Input Text, Image e le badge
29
+ // tools/thinking/vision/cloud; 552B MoE (8B attivi).
30
+ // DICHIARATO 2026-09-11 https://ollama.com/library/deepseek-v4.1-flash
31
+ 'deepseek-v4.1-flash',
27
32
  ]);
28
33
  // Autorita' per OLLAMA_CONTEXT = IL CAMPO STRUTTURATO «Context» della scheda
29
34
  // canale (ollama.com/library, fetch 2026-08-27) — NON la descrizione, che
@@ -55,6 +60,9 @@ const OLLAMA_CONTEXT = Object.freeze({
55
60
  // kimi-k3: scheda «Context / 1M tokens», Input Text, Image (2026-09-06).
56
61
  // DICHIARATO 2026-09-06 https://ollama.com/library/kimi-k3
57
62
  'kimi-k3': 1000000,
63
+ // deepseek-v4.1-flash: scheda «Context / 1M tokens» (2026-09-11); come gli
64
+ // altri deepseek vale la convenzione binaria del repo (1M -> 1048576).
65
+ 'deepseek-v4.1-flash': 1048576,
58
66
  });
59
67
  // Capacita' per modello OSSERVATE dalla scheda canale (ollama.com/library,
60
68
  // 2026-08-27). Assenza = default conservativo (comportamento odierno, nessuna
@@ -73,6 +81,10 @@ const OLLAMA_MODEL_CAPABILITIES = Object.freeze({
73
81
  // PARALLEL NON dichiarato: default conservativo false finche' non misurato su device.
74
82
  // DICHIARATO 2026-09-06 https://ollama.com/library/kimi-k3
75
83
  'kimi-k3': Object.freeze({ input: ['text', 'image'], reasoning: true, supportsParallelToolCalls: false }),
84
+ // deepseek-v4.1-flash: scheda tools/thinking/vision/cloud, Input Text, Image
85
+ // (2026-09-11). PARALLEL NON dichiarato: default conservativo false finche'
86
+ // non misurato su device.
87
+ 'deepseek-v4.1-flash': Object.freeze({ input: ['text', 'image'], reasoning: true, supportsParallelToolCalls: false }),
76
88
  });
77
89
  // Descrittori dell'engine ollama-cloud per la generazione del catalogo client:
78
90
  // stessa forma dei descrittori custom/PI (id, label, contextWindow, input,
@@ -346,6 +358,8 @@ const MANAGED_KEYS = new Set(['client', 'provider', 'credentialProfile', 'model'
346
358
  // D3: massimo numero di nomi in `envPassthrough`. L'allowlist e' opt-in e per
347
359
  // nome, mai un passthrough in blocco: un tetto basso ferma una lista incontrollata.
348
360
  const MAX_ENV_PASSTHROUGH = 32;
361
+ const CODEX_APP_SERVER_IDENTITY_REQUIRED = 'CODEX_APP_SERVER_IDENTITY_REQUIRED';
362
+ const CODEX_APP_SERVER_IDENTITY_REQUIRED_DEFAULT = '1';
349
363
  // Explicit credential source policy. Default 'auto' preserves the legacy
350
364
  // resolution order (runtime -> store -> shell -> key files -> legacy) so a
351
365
  // pre-WP1 fleet.json migrates no-op: no existing cell changes resolution.
@@ -400,7 +414,7 @@ const CATALOG = Object.freeze([
400
414
  // launch valorizza ANTHROPIC_API_KEY, non ANTHROPIC_AUTH_TOKEN come Z.AI.
401
415
  { id: 'claude.opencode-go', client: 'claude', provider: 'opencode-go', label: 'OpenCode Go', auth: 'OPENCODE_API_KEY', endpoint: OPENCODE_GO_ANTHROPIC_ROOT, protocol: 'anthropic_messages', model: 'deepseek-v4-flash', models: OPENCODE_GO_MESSAGES_MODELS, strictModels: true, core: true },
402
416
  { id: 'claude.openrouter', client: 'claude', provider: 'openrouter', label: 'OpenRouter', auth: 'OPENROUTER_API_KEY', endpoint: 'https://openrouter.ai/api', protocol: 'anthropic_messages', requiresModel: true, core: true, notice: 'claude-openrouter' },
403
- { id: 'claude.ollama-cloud', client: 'claude', provider: 'ollama-cloud', label: 'Ollama Cloud', auth: 'OLLAMA_API_KEY', endpoint: 'https://ollama.com', protocol: 'anthropic_messages', model: 'glm-5.2', models: OLLAMA_CLOUD_MODELS, legacySecrets: true, core: true },
417
+ { id: 'claude.ollama-cloud', client: 'claude', provider: 'ollama-cloud', label: 'Ollama Cloud', auth: 'OLLAMA_API_KEY', endpoint: 'https://ollama.com', protocol: 'anthropic_messages', model: 'deepseek-v4.1-flash', models: OLLAMA_CLOUD_MODELS, legacySecrets: true, core: true },
404
418
  { id: 'claude.bedrock', client: 'claude', provider: 'bedrock', label: 'Amazon Bedrock', auth: 'login', endpoint: 'AWS Bedrock', protocol: 'anthropic_messages', core: true, providerEnv: { CLAUDE_CODE_USE_BEDROCK: '1' } },
405
419
  { id: 'claude.vertex', client: 'claude', provider: 'vertex', label: 'Google Vertex AI', auth: 'login', endpoint: 'Google Vertex AI', protocol: 'anthropic_messages', core: true, providerEnv: { CLAUDE_CODE_USE_VERTEX: '1' } },
406
420
  { id: 'claude.foundry', client: 'claude', provider: 'foundry', label: 'Microsoft Foundry', auth: 'login', endpoint: 'Microsoft Foundry', protocol: 'anthropic_messages', core: true, providerEnv: { CLAUDE_CODE_USE_FOUNDRY: '1' } },
@@ -414,7 +428,7 @@ const CATALOG = Object.freeze([
414
428
  { id: 'codex-vl.alibaba-token-plan', client: 'codex-vl', provider: 'alibaba-token-plan', label: 'Alibaba Token Plan Personal', auth: 'ALIBABA_CODE_API_KEY', endpoint: 'https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1', protocol: 'openai_responses', model: 'qwen3.8-max', models: ALIBABA_CODEX_MODELS, strictModels: true, core: true, notice: 'alibaba-token-plan' },
415
429
  { id: 'codex-vl.opencode-go', client: 'codex-vl', provider: 'opencode-go', label: 'OpenCode Go', auth: 'OPENCODE_API_KEY', endpoint: OPENCODE_GO_API_BASE, protocol: 'openai_responses', model: 'deepseek-v4-flash', models: OPENCODE_GO_RESPONSES_MODELS, strictModels: true, core: true },
416
430
  { id: 'codex-vl.openrouter', client: 'codex-vl', provider: 'openrouter', label: 'OpenRouter', auth: 'OPENROUTER_API_KEY', endpoint: 'https://openrouter.ai/api/v1', protocol: 'openai_responses', requiresModel: true, core: true, notice: 'codex-openrouter' },
417
- { id: 'codex-vl.ollama-cloud', client: 'codex-vl', provider: 'ollama-cloud', label: 'Ollama Cloud', auth: 'OLLAMA_API_KEY', endpoint: 'https://ollama.com/v1', protocol: 'openai_responses', model: 'glm-5.2', models: OLLAMA_CLOUD_MODELS, legacySecrets: true, core: true },
431
+ { id: 'codex-vl.ollama-cloud', client: 'codex-vl', provider: 'ollama-cloud', label: 'Ollama Cloud', auth: 'OLLAMA_API_KEY', endpoint: 'https://ollama.com/v1', protocol: 'openai_responses', model: 'deepseek-v4.1-flash', models: OLLAMA_CLOUD_MODELS, legacySecrets: true, core: true },
418
432
  { id: 'codex-vl.zai-a', client: 'codex-vl', provider: 'zai-a', label: 'Z.AI A (Responses nativo)', auth: 'ZAI_API_KEY_A', endpoint: 'https://api.z.ai/api/v1', protocol: 'openai_responses', model: 'glm-5.3', models: ZAI_RESPONSES_MODELS, strictModels: true, core: true },
419
433
  { id: 'codex-vl.zai-p', client: 'codex-vl', provider: 'zai-p', label: 'Z.AI P (Responses nativo)', auth: 'ZAI_API_KEY_P', endpoint: 'https://api.z.ai/api/v1', protocol: 'openai_responses', model: 'glm-5.3', models: ZAI_RESPONSES_MODELS, strictModels: true, core: true },
420
434
  { id: 'codex-vl.openai-api', client: 'codex-vl', provider: 'openai-api', label: 'OpenAI API', auth: 'OPENAI_API_KEY', endpoint: 'https://api.openai.com/v1', protocol: 'openai_responses', core: true },
@@ -425,7 +439,7 @@ const CATALOG = Object.freeze([
425
439
  // Codex (upstream OpenAI, Responses).
426
440
  { id: 'codex.native', client: 'codex', provider: 'native', label: 'OpenAI / ChatGPT account', auth: 'login', endpoint: 'OpenAI account', protocol: 'openai_responses', default: true, core: true },
427
441
  { id: 'codex.openai-api', client: 'codex', provider: 'openai-api', label: 'OpenAI API', auth: 'OPENAI_API_KEY', endpoint: 'https://api.openai.com/v1', protocol: 'openai_responses', core: true },
428
- { id: 'codex.ollama-cloud', client: 'codex', provider: 'ollama-cloud', label: 'Ollama Cloud', auth: 'OLLAMA_API_KEY', endpoint: 'https://ollama.com/v1', protocol: 'openai_responses', model: 'glm-5.2', models: OLLAMA_CLOUD_MODELS, legacySecrets: true, core: true },
442
+ { id: 'codex.ollama-cloud', client: 'codex', provider: 'ollama-cloud', label: 'Ollama Cloud', auth: 'OLLAMA_API_KEY', endpoint: 'https://ollama.com/v1', protocol: 'openai_responses', model: 'deepseek-v4.1-flash', models: OLLAMA_CLOUD_MODELS, legacySecrets: true, core: true },
429
443
  { id: 'codex.ollama', client: 'codex', provider: 'ollama', label: 'Ollama local', auth: 'none', endpoint: 'local provider', protocol: 'openai_responses', localProvider: 'ollama', core: true },
430
444
  { id: 'codex.lmstudio', client: 'codex', provider: 'lmstudio', label: 'LM Studio', auth: 'none', endpoint: 'local provider', protocol: 'openai_responses', localProvider: 'lmstudio', core: true },
431
445
  { id: 'codex.custom', client: 'codex', provider: 'custom', label: 'Custom Responses endpoint', auth: 'dynamic', protocol: 'openai_responses', protocols: ['openai_responses'], custom: true, core: true },
@@ -2024,6 +2038,28 @@ function resolveManagedEngine(engine, cell, cfg = {}) {
2024
2038
  // TUI interattivo nella cwd della cella.
2025
2039
  if (model) args.push('--model', model);
2026
2040
  }
2041
+ // The codex-vl TUI starts the app-server daemon itself, so this
2042
+ // launcher-owned switch must be in the child environment (not argv). A
2043
+ // definition-level value is an explicit user override; cfg.env is retained
2044
+ // as the runtime compatibility override for callers that do not carry a
2045
+ // parsed engine definition. Other managed clients never receive this key.
2046
+ if (spec.client === 'codex-vl') {
2047
+ const definitionEnv = engine && engine.env;
2048
+ const runtimeEnv = cfg && cfg.env;
2049
+ const hasDefinitionOverride = definitionEnv && Object.prototype.hasOwnProperty.call(
2050
+ definitionEnv, CODEX_APP_SERVER_IDENTITY_REQUIRED,
2051
+ );
2052
+ const hasRuntimeOverride = runtimeEnv && Object.prototype.hasOwnProperty.call(
2053
+ runtimeEnv, CODEX_APP_SERVER_IDENTITY_REQUIRED,
2054
+ );
2055
+ if (hasDefinitionOverride && typeof definitionEnv[CODEX_APP_SERVER_IDENTITY_REQUIRED] === 'string') {
2056
+ env[CODEX_APP_SERVER_IDENTITY_REQUIRED] = definitionEnv[CODEX_APP_SERVER_IDENTITY_REQUIRED];
2057
+ } else if (hasRuntimeOverride && typeof runtimeEnv[CODEX_APP_SERVER_IDENTITY_REQUIRED] === 'string') {
2058
+ env[CODEX_APP_SERVER_IDENTITY_REQUIRED] = runtimeEnv[CODEX_APP_SERVER_IDENTITY_REQUIRED];
2059
+ } else {
2060
+ env[CODEX_APP_SERVER_IDENTITY_REQUIRED] = CODEX_APP_SERVER_IDENTITY_REQUIRED_DEFAULT;
2061
+ }
2062
+ }
2027
2063
  // Prompt su argv (0.8.47): SOLO i client che non hanno un percorso classified
2028
2064
  // delivery. kimi.native e claude.kimi-code usano promptMode 'send-keys' con
2029
2065
  // deliverBootstrapPrompt (readiness classificata + at-most-once): il prompt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmmbuto/nexuscrew",
3
- "version": "0.9.21",
3
+ "version": "0.9.22",
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": {
@@ -22,8 +22,6 @@
22
22
  "docs/live-prompt-templates/LIVE_PROMPT.en.md",
23
23
  "docs/live-prompt-templates/LIVE_PROMPT.es.md",
24
24
  "docs/live-prompt-templates/LIVE_PROMPT.it.md",
25
- "docs/img/fleet-deck-desktop.png",
26
- "docs/img/session-mobile.png",
27
25
  "docs/MCP.md",
28
26
  "docs/NODES.md",
29
27
  "docs/NOTIFICATIONS.md",
Binary file
Binary file