nothumanallowed 15.1.14 → 15.1.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "15.1.14",
3
+ "version": "15.1.16",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.mjs CHANGED
@@ -55,12 +55,14 @@ export async function main(argv) {
55
55
  // npm version check (non-blocking). The one-liner uses --prefer-online to
56
56
  // bypass npm's metadata cache, which is the #1 reason `npm install -g`
57
57
  // appears to "do nothing" — it had stale "latest" in the local cache.
58
+ // Every command separated by `&&` so users can copy-paste the whole line.
58
59
  checkNpmVersion().then(result => {
59
60
  if (result?.updateAvailable) {
60
61
  console.log('');
61
62
  warn(`New NHA version available: ${result.current} → ${result.latest}`);
62
63
  info(`Run "nha update" (recommended — auto-installs npm + agents)`);
63
- info(`Or manually: npm cache clean --force && npm install -g nothumanallowed@${result.latest} --prefer-online`);
64
+ info(`Or copy-paste this ENTIRE line (note: --prefer-online, not --pref-online):`);
65
+ info(` npm cache clean --force && npm install -g nothumanallowed@${result.latest} --prefer-online && hash -r && nha version`);
64
66
  }
65
67
  }).catch(() => {});
66
68
  }
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '15.1.14';
8
+ export const VERSION = '15.1.16';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -759,16 +759,35 @@ ${okBlock}`;
759
759
 
760
760
  tok('[Parlamento — Round 2: Cross-Reading & Refinamento] ');
761
761
  const r2Results = [];
762
+ // Per-agent timeout — if any single agent stalls (network, LLM hung)
763
+ // the loop must not block the whole deliberation. After this budget,
764
+ // fall back to the agent's Round 1 output and continue.
765
+ const PER_AGENT_TIMEOUT_MS = 90_000;
762
766
  for (const proposal of eligible) {
763
767
  tok(`[Round 2: ${proposal.label || proposal.agent}] `);
764
768
  const r2Sys = `You are ${proposal.agent}, a specialist AI agent in NHA Studio Parliament. Today is ${today}. Respond entirely in ${language}.\n\n## WORKFLOW GOAL: ${task}\n\n## YOUR ROUND 1 RESPONSE:\n${proposal.output.slice(0,3000)}\n\n## OTHER AGENTS' ROUND 1 PROPOSALS:\n${crossCtx(proposal.agent)}\n\nDELIBERATION ROUND 2 — REFINEMENT:\n1. Review the other agents' proposals carefully\n2. Incorporate valid points where you AGREE — mark with [AGREE]\n3. Flag genuine disagreements with [CONTRADICTION] and explain your reasoning with evidence\n4. Produce your COMPLETE REFINED response — thorough and exhaustive\n5. Keep analysis focused on: ${task}\n\nBe THOROUGH. Minimum 600 words of substantive refined analysis.`;
765
769
  let r2Out = '';
770
+ let fellBack = false;
766
771
  try {
767
- await callLLMStream(config, r2Sys, 'Produce your refined Round 2 response. Write complete content under every heading — never leave a section title without body text.',
768
- (t) => { r2Out += t; }, { max_tokens: 16384 });
769
- } catch { r2Out = proposal.output; }
770
- r2Results.push({ agent: proposal.agent, label: proposal.label, icon: proposal.icon, output: r2Out });
771
- sse({ deliberation_r2: { agent: proposal.agent, label: proposal.label, icon: proposal.icon, output: r2Out } });
772
+ // Race the LLM stream against a hard timeout.
773
+ await Promise.race([
774
+ callLLMStream(config, r2Sys, 'Produce your refined Round 2 response. Write complete content under every heading — never leave a section title without body text.',
775
+ (t) => { r2Out += t; }, { max_tokens: 16384 }),
776
+ new Promise((_, reject) => setTimeout(() => reject(new Error('R2_AGENT_TIMEOUT')), PER_AGENT_TIMEOUT_MS)),
777
+ ]);
778
+ } catch (err) {
779
+ // Fallback: use Round 1 output so the rest of deliberation can proceed.
780
+ fellBack = true;
781
+ r2Out = proposal.output;
782
+ tok(`[Round 2 ${proposal.label || proposal.agent}: timeout — uso Round 1 come fallback] `);
783
+ }
784
+ // If the stream returned but produced no text (LLM hiccup), also fall back.
785
+ if (!r2Out || r2Out.trim().length < 50) {
786
+ fellBack = true;
787
+ r2Out = proposal.output;
788
+ }
789
+ r2Results.push({ agent: proposal.agent, label: proposal.label, icon: proposal.icon, output: r2Out, fellBack });
790
+ sse({ deliberation_r2: { agent: proposal.agent, label: proposal.label, icon: proposal.icon, output: r2Out, fellBack } });
772
791
  }
773
792
 
774
793
  const r2Conv = measureConvergence(r2Results.map(r => r.output));
@@ -792,9 +811,22 @@ ${okBlock}`;
792
811
  const medSys = `You are HERALD, the Parliament Mediator in NHA Studio. Today is ${today}. Respond entirely in ${language}.\n\n## WORKFLOW GOAL: ${task}\n\n## ALL AGENTS' REFINED POSITIONS (Round 2):\n${allR2Ctx}${contBlock}\n\n${medTask}\n\nCRITICAL: NEVER write a heading without immediately writing full content below it. Every section MUST have at least 5-8 concrete bullet points or detailed paragraphs. Be EXHAUSTIVE.`;
793
812
 
794
813
  let mediationOutput = '';
814
+ const HERALD_TIMEOUT_MS = 120_000;
795
815
  try {
796
- await callLLMStream(config, medSys, 'Produce the Parliament final synthesis. Be thorough and complete.', (t) => { mediationOutput += t; }, { max_tokens: 16384 });
797
- } catch {}
816
+ await Promise.race([
817
+ callLLMStream(config, medSys, 'Produce the Parliament final synthesis. Be thorough and complete.', (t) => { mediationOutput += t; }, { max_tokens: 16384 }),
818
+ new Promise((_, reject) => setTimeout(() => reject(new Error('HERALD_TIMEOUT')), HERALD_TIMEOUT_MS)),
819
+ ]);
820
+ } catch (err) {
821
+ // HERALD timed out — emit whatever we got so the client isn't stuck.
822
+ tok(`[HERALD mediation: timeout dopo ${HERALD_TIMEOUT_MS/1000}s — restituisco contenuto parziale] `);
823
+ }
824
+ // If absolutely nothing came back, fall back to a concatenation of the
825
+ // r2 outputs so the user has SOMETHING to read instead of a blank panel.
826
+ if (!mediationOutput || mediationOutput.trim().length < 50) {
827
+ mediationOutput = `# Sintesi automatica (HERALD non disponibile)\n\n` +
828
+ r2Results.map(r => `## ${r.label || r.agent}\n${r.output.slice(0, 2000)}`).join('\n\n---\n\n');
829
+ }
798
830
  sse({ deliberation_r3: { output: mediationOutput, converged } });
799
831
 
800
832
  clearInterval(keepalive);
@@ -547,8 +547,9 @@ class TelegramResponder {
547
547
  const msg =
548
548
  `🆕 NHA v${latest} disponibile!\n\n` +
549
549
  `Una nuova versione di NotHumanAllowed è stata pubblicata.\n\n` +
550
- `Aggiorna con:\nnpm install -g nothumanallowed@latest\n\n` +
551
- `Poi riavvia il bot con: nha ops stop && nha ops start`;
550
+ `Aggiorna con UN SOLO comando (copia e incolla tutto):\n` +
551
+ `npm cache clean --force && npm install -g nothumanallowed@latest --prefer-online && nha ops stop && nha ops start\n\n` +
552
+ `Importante: usa esattamente "--prefer-online" (NON "--pref-online") e tieni tutti i "&&" tra i comandi.`;
552
553
 
553
554
  this.log(`[Telegram] Broadcasting update notification v${latest} to ${chatIds.length} users`);
554
555