nothumanallowed 13.2.25 → 13.2.27
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 +1 -1
- package/src/commands/ui.mjs +25 -8
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +109 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.2.
|
|
3
|
+
"version": "13.2.27",
|
|
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/commands/ui.mjs
CHANGED
|
@@ -2562,19 +2562,36 @@ Example output:
|
|
|
2562
2562
|
{"steps":[{"icon":"🔍","agent":"WebSearchAgent","label":"Cerca notizie","prompt":"Cerca le ultime notizie su intelligenza artificiale oggi"},{"icon":"📰","agent":"HERALD","label":"Analisi notizie","prompt":"Analizza le notizie trovate e crea un briefing esecutivo"},{"icon":"📊","agent":"CanvasAgent","label":"Dashboard HTML","prompt":"Crea una dashboard HTML visuale con i risultati"}]}`;
|
|
2563
2563
|
|
|
2564
2564
|
try {
|
|
2565
|
-
|
|
2565
|
+
// Force thinking OFF for planner — we need deterministic JSON, not reasoning chains
|
|
2566
|
+
const planConfig = Object.assign({}, config, { thinking: 'off' });
|
|
2567
|
+
const planRaw = await callLLM(planConfig, 'You are a JSON workflow planner. Output ONLY valid JSON. No thinking, no explanation, no markdown.', planPrompt, { max_tokens: 1500 });
|
|
2568
|
+
process.stderr.write('[STUDIO PLAN RAW] ' + planRaw.slice(0, 400) + '\n');
|
|
2566
2569
|
let steps;
|
|
2567
2570
|
try {
|
|
2568
|
-
// Strip <think>...</think> blocks
|
|
2569
|
-
let clean = planRaw
|
|
2570
|
-
|
|
2571
|
+
// Strip ALL <think>...</think> blocks (greedy — handles nested/multiple)
|
|
2572
|
+
let clean = planRaw;
|
|
2573
|
+
let prev = '';
|
|
2574
|
+
while (prev !== clean) { prev = clean; clean = clean.replace(/<think>[\s\S]*?<\/think>/g, ''); }
|
|
2575
|
+
clean = clean.trim();
|
|
2576
|
+
// Strip markdown fences
|
|
2577
|
+
clean = clean.replace(/^```[\w]*\r?\n?/,'').replace(/\r?\n?```$/,'').trim();
|
|
2578
|
+
// Extract first complete JSON object
|
|
2571
2579
|
const jsonMatch = clean.match(/\{[\s\S]*\}/);
|
|
2572
2580
|
const parsed = JSON.parse(jsonMatch ? jsonMatch[0] : clean);
|
|
2573
2581
|
steps = parsed.steps;
|
|
2574
|
-
} catch {
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2582
|
+
} catch (parseErr) {
|
|
2583
|
+
process.stderr.write('[STUDIO PLAN PARSE ERR] ' + parseErr.message + '\n');
|
|
2584
|
+
// Fallback: build a sensible default plan from the task keywords
|
|
2585
|
+
const hasEmail = /email|mail/i.test(task);
|
|
2586
|
+
const hasCalendar = /calendar|agenda|calendari/i.test(task);
|
|
2587
|
+
const hasSearch = /cerca|search|notizie|news/i.test(task);
|
|
2588
|
+
const hasCanvas = /html|dashboard|visua|report/i.test(task);
|
|
2589
|
+
steps = [];
|
|
2590
|
+
if (hasEmail) steps.push({icon:'📧',agent:'EmailAgent',label:'Controlla email',prompt:task});
|
|
2591
|
+
if (hasCalendar) steps.push({icon:'📅',agent:'CalendarAgent',label:'Rivedi calendario',prompt:task});
|
|
2592
|
+
if (hasSearch || steps.length === 0) steps.push({icon:'🔍',agent:'WebSearchAgent',label:'Ricerca web',prompt:task});
|
|
2593
|
+
steps.push({icon:'📰',agent:'HERALD',label:'Analisi e briefing',prompt:task});
|
|
2594
|
+
if (hasCanvas) steps.push({icon:'📊',agent:'CanvasAgent',label:'Dashboard HTML',prompt:task});
|
|
2578
2595
|
}
|
|
2579
2596
|
if (!Array.isArray(steps) || !steps.length) {
|
|
2580
2597
|
sendJSON(res, 500, { error: 'Empty workflow plan' });
|
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 = '13.2.
|
|
8
|
+
export const VERSION = '13.2.27';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -2749,6 +2749,104 @@ function stopVoiceInput() {
|
|
|
2749
2749
|
}
|
|
2750
2750
|
|
|
2751
2751
|
// ---- STUDIO ----
|
|
2752
|
+
// ── i18n — UI string translations ────────────────────────────────────────────
|
|
2753
|
+
var I18N = {
|
|
2754
|
+
en: {
|
|
2755
|
+
chat:'Chat', studio:'Studio', settings:'Settings', agents:'Agents',
|
|
2756
|
+
run:'▶ Run', stop:'⬛ Stop', reset:'New workflow',
|
|
2757
|
+
placeholder_chat:'Message NHA... (Enter to send)',
|
|
2758
|
+
placeholder_studio:'Describe what you want to accomplish... (Ctrl+Enter to run)',
|
|
2759
|
+
planning:'Planning...', workflow_complete:'Workflow complete.',
|
|
2760
|
+
workflow_stopped:'Workflow stopped by user.',
|
|
2761
|
+
canvas_open:'Open Canvas', canvas_generated:'HTML Dashboard generated in Canvas panel.',
|
|
2762
|
+
saved:'Saved!', lang_set:'Language set to',
|
|
2763
|
+
agents_respond:'All agents will respond in',
|
|
2764
|
+
examples:'Examples', recent_sessions:'Recent sessions',
|
|
2765
|
+
restore:'Restore', delete:'Delete',
|
|
2766
|
+
send:'Send', attach:'Attach',
|
|
2767
|
+
settings_save:'Save',
|
|
2768
|
+
no_output:'(no output)', done:'(done)',
|
|
2769
|
+
token_label:'Tokens',
|
|
2770
|
+
},
|
|
2771
|
+
it: {
|
|
2772
|
+
chat:'Chat', studio:'Studio', settings:'Impostazioni', agents:'Agenti',
|
|
2773
|
+
run:'▶ Avvia', stop:'⬛ Ferma', reset:'Nuovo workflow',
|
|
2774
|
+
placeholder_chat:'Scrivi a NHA... (Invio per inviare)',
|
|
2775
|
+
placeholder_studio:'Descrivi cosa vuoi fare... (Ctrl+Invio per avviare)',
|
|
2776
|
+
planning:'Pianificazione...', workflow_complete:'Workflow completato.',
|
|
2777
|
+
workflow_stopped:'Workflow fermato dall\u2019utente.',
|
|
2778
|
+
canvas_open:'Apri Canvas', canvas_generated:'Dashboard HTML generata nel pannello Canvas.',
|
|
2779
|
+
saved:'Salvato!', lang_set:'Lingua impostata su',
|
|
2780
|
+
agents_respond:'Tutti gli agenti risponderanno in',
|
|
2781
|
+
examples:'Esempi', recent_sessions:'Sessioni recenti',
|
|
2782
|
+
restore:'Ripristina', delete:'Elimina',
|
|
2783
|
+
send:'Invia', attach:'Allega',
|
|
2784
|
+
settings_save:'Salva',
|
|
2785
|
+
no_output:'(nessun output)', done:'(completato)',
|
|
2786
|
+
token_label:'Token',
|
|
2787
|
+
},
|
|
2788
|
+
es: {
|
|
2789
|
+
chat:'Chat', studio:'Studio', settings:'Configuración', agents:'Agentes',
|
|
2790
|
+
run:'▶ Ejecutar', stop:'⬛ Detener', reset:'Nuevo flujo',
|
|
2791
|
+
placeholder_chat:'Mensaje a NHA... (Enter para enviar)',
|
|
2792
|
+
placeholder_studio:'Describe lo que quieres hacer... (Ctrl+Enter para ejecutar)',
|
|
2793
|
+
planning:'Planificando...', workflow_complete:'Flujo completado.',
|
|
2794
|
+
workflow_stopped:'Flujo detenido por el usuario.',
|
|
2795
|
+
canvas_open:'Abrir Canvas', canvas_generated:'Panel HTML generado en Canvas.',
|
|
2796
|
+
saved:'¡Guardado!', lang_set:'Idioma establecido en',
|
|
2797
|
+
agents_respond:'Todos los agentes responderán en',
|
|
2798
|
+
examples:'Ejemplos', recent_sessions:'Sesiones recientes',
|
|
2799
|
+
restore:'Restaurar', delete:'Eliminar',
|
|
2800
|
+
send:'Enviar', attach:'Adjuntar',
|
|
2801
|
+
settings_save:'Guardar',
|
|
2802
|
+
no_output:'(sin salida)', done:'(hecho)',
|
|
2803
|
+
token_label:'Tokens',
|
|
2804
|
+
},
|
|
2805
|
+
fr: {
|
|
2806
|
+
chat:'Chat', studio:'Studio', settings:'Paramètres', agents:'Agents',
|
|
2807
|
+
run:'▶ Lancer', stop:'⬛ Arrêter', reset:'Nouveau flux',
|
|
2808
|
+
placeholder_chat:'Message à NHA... (Entrée pour envoyer)',
|
|
2809
|
+
placeholder_studio:'Décrivez ce que vous voulez faire... (Ctrl+Entrée pour lancer)',
|
|
2810
|
+
planning:'Planification...', workflow_complete:'Flux terminé.',
|
|
2811
|
+
workflow_stopped:'Flux arr\u00eat\u00e9 par l\u2019utilisateur.',
|
|
2812
|
+
canvas_open:'Ouvrir Canvas', canvas_generated:'Tableau de bord HTML généré dans Canvas.',
|
|
2813
|
+
saved:'Sauvegardé!', lang_set:'Langue définie sur',
|
|
2814
|
+
agents_respond:'Tous les agents répondront en',
|
|
2815
|
+
examples:'Exemples', recent_sessions:'Sessions récentes',
|
|
2816
|
+
restore:'Restaurer', delete:'Supprimer',
|
|
2817
|
+
send:'Envoyer', attach:'Joindre',
|
|
2818
|
+
settings_save:'Sauvegarder',
|
|
2819
|
+
no_output:'(aucune sortie)', done:'(terminé)',
|
|
2820
|
+
token_label:'Tokens',
|
|
2821
|
+
},
|
|
2822
|
+
de: {
|
|
2823
|
+
chat:'Chat', studio:'Studio', settings:'Einstellungen', agents:'Agenten',
|
|
2824
|
+
run:'▶ Starten', stop:'⬛ Stopp', reset:'Neuer Workflow',
|
|
2825
|
+
placeholder_chat:'Nachricht an NHA... (Enter zum Senden)',
|
|
2826
|
+
placeholder_studio:'Beschreibe was du tun möchtest... (Strg+Enter zum Starten)',
|
|
2827
|
+
planning:'Planung...', workflow_complete:'Workflow abgeschlossen.',
|
|
2828
|
+
workflow_stopped:'Workflow vom Benutzer gestoppt.',
|
|
2829
|
+
canvas_open:'Canvas öffnen', canvas_generated:'HTML-Dashboard im Canvas-Panel generiert.',
|
|
2830
|
+
saved:'Gespeichert!', lang_set:'Sprache auf',
|
|
2831
|
+
agents_respond:'Alle Agenten antworten auf',
|
|
2832
|
+
examples:'Beispiele', recent_sessions:'Letzte Sitzungen',
|
|
2833
|
+
restore:'Wiederherstellen', delete:'Löschen',
|
|
2834
|
+
send:'Senden', attach:'Anhängen',
|
|
2835
|
+
settings_save:'Speichern',
|
|
2836
|
+
no_output:'(keine Ausgabe)', done:'(erledigt)',
|
|
2837
|
+
token_label:'Token',
|
|
2838
|
+
},
|
|
2839
|
+
};
|
|
2840
|
+
// Fallback to 'en' for unmapped languages
|
|
2841
|
+
function t(key) {
|
|
2842
|
+
try {
|
|
2843
|
+
var cfg = JSON.parse(localStorage.getItem('nha_config_cache') || '{}');
|
|
2844
|
+
var lang = (cfg.lang || 'it').slice(0,2);
|
|
2845
|
+
var map = I18N[lang] || I18N.en;
|
|
2846
|
+
return map[key] || I18N.en[key] || key;
|
|
2847
|
+
} catch(e) { return I18N.en[key] || key; }
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2752
2850
|
var studioState = {
|
|
2753
2851
|
task: '',
|
|
2754
2852
|
nodes: [], // [{icon,agent,label,status:'waiting'|'running'|'done'|'error'}]
|
|
@@ -2765,10 +2863,10 @@ function stopStudio() {
|
|
|
2765
2863
|
if (studioAbortController) { try { studioAbortController.abort(); } catch(e) {} studioAbortController = null; }
|
|
2766
2864
|
studioState.running = false;
|
|
2767
2865
|
var btn = document.getElementById('studioRunBtn');
|
|
2768
|
-
if (btn) { btn.disabled = false; btn.textContent = '
|
|
2866
|
+
if (btn) { btn.disabled = false; btn.textContent = t('run'); }
|
|
2769
2867
|
var stopBtn = document.getElementById('studioStopBtn');
|
|
2770
2868
|
if (stopBtn) stopBtn.style.display = 'none';
|
|
2771
|
-
studioLog('Studio', '⬛', '
|
|
2869
|
+
studioLog('Studio', '⬛', t('workflow_stopped'), 'system');
|
|
2772
2870
|
// Mark any still-running nodes as error
|
|
2773
2871
|
studioState.nodes.forEach(function(n) { if (n.status === 'running') n.status = 'error'; });
|
|
2774
2872
|
renderStudioNodes();
|
|
@@ -2875,7 +2973,7 @@ function renderStudioResult() {
|
|
|
2875
2973
|
el.style.display = 'block';
|
|
2876
2974
|
var isHtml = studioState.result.trimStart().startsWith('<');
|
|
2877
2975
|
var body = isHtml
|
|
2878
|
-
? '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><span style="color:var(--dim);font-size:13px">✓
|
|
2976
|
+
? '<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><span style="color:var(--dim);font-size:13px">✓ ' + t('canvas_generated') + '</span><button onclick="openCanvasPanel()" style="padding:6px 14px;background:var(--greendim);border:1px solid var(--green3);border-radius:8px;color:var(--green);font-size:12px;cursor:pointer;font-weight:700">▣ ' + t('canvas_open') + '</button></div>'
|
|
2879
2977
|
: '<div class="md-body">' + renderMd(studioState.result) + '</div>';
|
|
2880
2978
|
el.innerHTML = '<div class="studio-result__title">✓ Workflow completato</div>' + body;
|
|
2881
2979
|
}
|
|
@@ -2906,7 +3004,7 @@ async function runStudio() {
|
|
|
2906
3004
|
studioAbortController = new AbortController();
|
|
2907
3005
|
|
|
2908
3006
|
var btn = document.getElementById('studioRunBtn');
|
|
2909
|
-
if (btn) { btn.disabled = true; btn.textContent = '
|
|
3007
|
+
if (btn) { btn.disabled = true; btn.textContent = t('planning'); }
|
|
2910
3008
|
var stopBtn = document.getElementById('studioStopBtn');
|
|
2911
3009
|
if (stopBtn) stopBtn.style.display = '';
|
|
2912
3010
|
|
|
@@ -2969,7 +3067,7 @@ async function runStudio() {
|
|
|
2969
3067
|
// Final result is the last step's output
|
|
2970
3068
|
studioState.result = context;
|
|
2971
3069
|
renderStudioResult();
|
|
2972
|
-
studioLog('Studio', '🎉', '
|
|
3070
|
+
studioLog('Studio', '🎉', t('workflow_complete'), 'system');
|
|
2973
3071
|
|
|
2974
3072
|
// Save session to localStorage for reuse in Chat
|
|
2975
3073
|
saveStudioSession(task, studioState.nodes, studioState.log, context);
|
|
@@ -3015,7 +3113,7 @@ function renderStudioSessionsBar() {
|
|
|
3015
3113
|
var sessions = loadStudioSessions();
|
|
3016
3114
|
if (!sessions.length) { el.style.display = 'none'; return; }
|
|
3017
3115
|
el.style.display = 'block';
|
|
3018
|
-
el.innerHTML = '<div style="font-size:10px;color:var(--dim);margin-bottom:8px;text-transform:uppercase;letter-spacing:1px">
|
|
3116
|
+
el.innerHTML = '<div style="font-size:10px;color:var(--dim);margin-bottom:8px;text-transform:uppercase;letter-spacing:1px">' + t('recent_sessions') + '</div>' +
|
|
3019
3117
|
'<div style="max-height:220px;overflow-y:auto;padding-right:4px">' +
|
|
3020
3118
|
sessions.map(function(s,i) {
|
|
3021
3119
|
return '<div class="studio-session-item">' +
|
|
@@ -3262,15 +3360,15 @@ function renderStudio(el) {
|
|
|
3262
3360
|
// ── AUTO MODE ──
|
|
3263
3361
|
'<div id="studioAutoMode">' +
|
|
3264
3362
|
'<div style="margin-bottom:10px">' +
|
|
3265
|
-
'<div style="font-size:10px;color:var(--dim);margin-bottom:6px;text-transform:uppercase;letter-spacing:1px">
|
|
3363
|
+
'<div style="font-size:10px;color:var(--dim);margin-bottom:6px;text-transform:uppercase;letter-spacing:1px">' + t('examples') + '</div>' +
|
|
3266
3364
|
examplesHtml +
|
|
3267
3365
|
'</div>' +
|
|
3268
3366
|
'<div class="studio-input-row">' +
|
|
3269
|
-
'<textarea id="studioTaskInput" placeholder="
|
|
3367
|
+
'<textarea id="studioTaskInput" placeholder="' + t('placeholder_studio') + '" onkeydown="if(event.key===\\x27Enter\\x27&&(event.ctrlKey||event.metaKey)){runStudio();event.preventDefault()}">' + esc(studioState.task) + '</textarea>' +
|
|
3270
3368
|
'<div style="display:flex;gap:6px">' +
|
|
3271
|
-
'<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '
|
|
3272
|
-
'<button id="studioStopBtn" onclick="stopStudio()" title="
|
|
3273
|
-
'<button onclick="studioReset()" title="
|
|
3369
|
+
'<button id="studioRunBtn" class="studio-run-btn" onclick="runStudio()" style="flex:1" ' + (studioState.running ? 'disabled' : '') + '>' + t('run') + '</button>' +
|
|
3370
|
+
'<button id="studioStopBtn" onclick="stopStudio()" title="' + t('stop') + '" style="padding:8px 14px;background:#7f1d1d;border:1px solid #ef4444;border-radius:8px;color:#ef4444;cursor:pointer;font-size:13px;font-weight:700;white-space:nowrap;' + (studioState.running ? '' : 'display:none') + '">■ ' + t('stop') + '</button>' +
|
|
3371
|
+
'<button onclick="studioReset()" title="' + t('reset') + '" style="padding:8px 12px;background:none;border:1px solid var(--border);border-radius:8px;color:var(--dim);cursor:pointer;font-size:16px;line-height:1" ' + (studioState.running ? 'disabled' : '') + '>↻</button>' +
|
|
3274
3372
|
'</div>' +
|
|
3275
3373
|
'</div>' +
|
|
3276
3374
|
'</div>' +
|