nothumanallowed 13.2.43 → 13.2.45
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 +173 -4
- package/src/constants.mjs +1 -1
- package/src/services/web-ui.mjs +71 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.2.
|
|
3
|
+
"version": "13.2.45",
|
|
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
|
@@ -2600,7 +2600,11 @@ export async function cmdUI(args) {
|
|
|
2600
2600
|
if (!hasSpecialist && (hasBriefing || steps.length > 0)) {
|
|
2601
2601
|
steps.push({icon:'\u{1F4F0}',agent:'HERALD',label:it?'HERALD \u2014 Briefing esecutivo':'HERALD \u2014 Executive briefing',prompt:'Based on ALL the data collected by the previous steps, write a complete executive briefing with priorities, findings, and strategic recommendations. Do NOT invent data — only use what was provided.'});
|
|
2602
2602
|
}
|
|
2603
|
-
|
|
2603
|
+
// Add CanvasAgent: always when explicitly requested OR when 2+ specialist agents ran (complex analysis deserves a visual report)
|
|
2604
|
+
const specialistCount = [hasSecurity,hasFinance,hasStrategy,hasReputation,hasCode,hasWriting,hasData].filter(Boolean).length;
|
|
2605
|
+
if (hasCanvas || specialistCount >= 2 || (hasSpecialist && hasBriefing)) {
|
|
2606
|
+
steps.push({icon:'\u{1F4CA}',agent:'CanvasAgent',label:it?'Dashboard HTML':'HTML Dashboard',prompt:'Create a professional HTML dashboard report summarizing all findings from the previous agents'});
|
|
2607
|
+
}
|
|
2604
2608
|
return steps;
|
|
2605
2609
|
};
|
|
2606
2610
|
|
|
@@ -2822,8 +2826,12 @@ RULES:
|
|
|
2822
2826
|
// These agents fetched real data — use a focused prompt (no tool definitions to avoid JSON output)
|
|
2823
2827
|
const agentInstruction = `You are ${agent}, a specialist AI agent inside NHA Studio. Today is ${today}. Respond entirely in ${language}.
|
|
2824
2828
|
|
|
2829
|
+
## OVERALL WORKFLOW GOAL:
|
|
2830
|
+
${task}
|
|
2831
|
+
|
|
2825
2832
|
CRITICAL: Do NOT invent, hallucinate, or add any data not present in the DATA sections below. ONLY use the exact data provided.
|
|
2826
2833
|
Do NOT output JSON, tool calls, or code blocks. Write in plain text with markdown headers.
|
|
2834
|
+
Always apply your analysis specifically to the subject mentioned in the WORKFLOW GOAL.
|
|
2827
2835
|
|
|
2828
2836
|
${toolData ? `## DATA FROM TOOLS:\n${toolData.slice(0, 6000)}\n` : '## DATA: No data was retrieved by this agent.\n'}
|
|
2829
2837
|
${context ? `## OUTPUT FROM PREVIOUS AGENTS:\n${context.slice(0, 4000)}\n` : ''}
|
|
@@ -2837,10 +2845,12 @@ Your task: ${stepPrompt}`;
|
|
|
2837
2845
|
: stepPrompt;
|
|
2838
2846
|
} else {
|
|
2839
2847
|
// All other agents (WriterAgent, DataAnalystAgent, specialist agents, etc.)
|
|
2840
|
-
// Use a focused prompt with NO TOOL_DEFINITIONS to prevent JSON/tool-call output
|
|
2841
2848
|
const hasRealData = !!(toolData || context);
|
|
2842
2849
|
sysPrompt = `You are ${agent}, a specialist AI agent inside NHA Studio. Today is ${today}. You MUST respond entirely in ${language}.
|
|
2843
2850
|
|
|
2851
|
+
## OVERALL WORKFLOW GOAL:
|
|
2852
|
+
${task}
|
|
2853
|
+
|
|
2844
2854
|
CRITICAL RULES:
|
|
2845
2855
|
- Do NOT output JSON, tool calls, function calls, or code blocks
|
|
2846
2856
|
- NEVER invent, fabricate, or hallucinate data, events, emails, meetings, or news
|
|
@@ -2848,12 +2858,13 @@ CRITICAL RULES:
|
|
|
2848
2858
|
- Do NOT add fictional examples, placeholder content, or generic suggestions not grounded in the data
|
|
2849
2859
|
- Write in plain prose, structured with markdown headers (##) and bullet points (-)
|
|
2850
2860
|
- Be thorough and specific — this is for an executive briefing based on REAL data only
|
|
2861
|
+
- Always keep the OVERALL WORKFLOW GOAL in mind — apply your analysis specifically to the subject mentioned
|
|
2851
2862
|
|
|
2852
2863
|
${toolData ? `## LIVE DATA FROM TOOLS:\n${toolData.slice(0, 6000)}\n` : '## LIVE DATA: No tool data was fetched for this step.\n'}
|
|
2853
2864
|
${context ? `## OUTPUT FROM PREVIOUS AGENTS:\n${context.slice(0, 6000)}\n` : ''}`;
|
|
2854
2865
|
userMsg = hasRealData
|
|
2855
|
-
? `Based ONLY on the real data above, complete this task: ${stepPrompt}`
|
|
2856
|
-
: `No real data is available. State clearly
|
|
2866
|
+
? `Based ONLY on the real data above, complete this task specifically for the subject in the WORKFLOW GOAL: ${stepPrompt}`
|
|
2867
|
+
: `No real data is available for "${task}". State this clearly and explain what data would be needed to complete: ${stepPrompt}`;
|
|
2857
2868
|
}
|
|
2858
2869
|
|
|
2859
2870
|
// ── Stream LLM response ───────────────────────────────────────
|
|
@@ -2936,6 +2947,164 @@ ${context ? `## OUTPUT FROM PREVIOUS AGENTS:\n${context.slice(0, 6000)}\n` : ''}
|
|
|
2936
2947
|
return;
|
|
2937
2948
|
}
|
|
2938
2949
|
|
|
2950
|
+
// ── Studio: Parliament deliberation (SSE streaming) ──────────────────
|
|
2951
|
+
// Implements the Legion DeliberationEngine protocol adapted for Studio:
|
|
2952
|
+
// Round 1 outputs already exist (from normal workflow steps).
|
|
2953
|
+
// Round 2: each agent cross-reads all others' Round 1 outputs and refines.
|
|
2954
|
+
// Convergence: Jaccard similarity on key terms between R1 and R2 outputs.
|
|
2955
|
+
// Round 3 (optional): if divergence > threshold, HERALD mediates.
|
|
2956
|
+
if (pathname === '/api/studio/deliberate' && method === 'POST') {
|
|
2957
|
+
const body = await parseBody(req);
|
|
2958
|
+
const { task, proposals, language: bodyLang } = body;
|
|
2959
|
+
if (!task || !Array.isArray(proposals) || proposals.length < 2) {
|
|
2960
|
+
sendJSON(res, 400, { error: 'task and at least 2 proposals required' });
|
|
2961
|
+
logRequest(method, pathname, 400, Date.now() - start);
|
|
2962
|
+
return;
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
res.writeHead(200, {
|
|
2966
|
+
'Content-Type': 'text/event-stream',
|
|
2967
|
+
'Cache-Control': 'no-cache',
|
|
2968
|
+
'Connection': 'keep-alive',
|
|
2969
|
+
'Access-Control-Allow-Origin': '*',
|
|
2970
|
+
});
|
|
2971
|
+
|
|
2972
|
+
const sendEv2 = (data) => { try { res.write(`data: ${JSON.stringify(data)}\n\n`); } catch {} };
|
|
2973
|
+
const sendTok2 = (t) => sendEv2({ token: t });
|
|
2974
|
+
const keepaliveD = setInterval(() => { try { res.write(': keepalive\n\n'); } catch {} }, 5000);
|
|
2975
|
+
const language = bodyLang || 'Italian';
|
|
2976
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
2977
|
+
|
|
2978
|
+
// Jaccard similarity between two texts (key terms 4+ chars)
|
|
2979
|
+
const jaccard = (a, b) => {
|
|
2980
|
+
const terms = (s) => new Set(s.toLowerCase().match(/\b\w{4,}\b/g) || []);
|
|
2981
|
+
const sa = terms(a), sb = terms(b);
|
|
2982
|
+
let inter = 0;
|
|
2983
|
+
for (const w of sa) { if (sb.has(w)) inter++; }
|
|
2984
|
+
const union = sa.size + sb.size - inter;
|
|
2985
|
+
return union > 0 ? inter / union : 1;
|
|
2986
|
+
};
|
|
2987
|
+
|
|
2988
|
+
const measureConvergence = (outputs) => {
|
|
2989
|
+
if (outputs.length < 2) return 1.0;
|
|
2990
|
+
let total = 0, pairs = 0;
|
|
2991
|
+
for (let i = 0; i < outputs.length; i++) {
|
|
2992
|
+
for (let j = i + 1; j < outputs.length; j++) {
|
|
2993
|
+
total += jaccard(outputs[i], outputs[j]);
|
|
2994
|
+
pairs++;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
return pairs > 0 ? total / pairs : 1.0;
|
|
2998
|
+
};
|
|
2999
|
+
|
|
3000
|
+
try {
|
|
3001
|
+
const eligibleProposals = proposals.filter(p => p.agent !== 'CanvasAgent' && p.agent !== 'GitHubAgent' && p.agent !== 'EmailAgent' && p.agent !== 'CalendarAgent');
|
|
3002
|
+
if (eligibleProposals.length < 2) {
|
|
3003
|
+
sendEv2({ deliberation_done: true, skipped: true, reason: 'not enough specialist agents' });
|
|
3004
|
+
sendEv2({ done: true });
|
|
3005
|
+
res.write('data: [DONE]\n\n');
|
|
3006
|
+
res.end();
|
|
3007
|
+
clearInterval(keepaliveD);
|
|
3008
|
+
logRequest(method, pathname, 200, Date.now() - start);
|
|
3009
|
+
return;
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
// Round 1 convergence
|
|
3013
|
+
const r1Convergence = measureConvergence(eligibleProposals.map(p => p.output));
|
|
3014
|
+
sendTok2(`[Parlamento — Round 1 convergenza: ${(r1Convergence * 100).toFixed(0)}%] `);
|
|
3015
|
+
|
|
3016
|
+
const buildCrossReadCtx = (excludeAgent) =>
|
|
3017
|
+
eligibleProposals
|
|
3018
|
+
.filter(p => p.agent !== excludeAgent)
|
|
3019
|
+
.map(p => `## ${p.label || p.agent} (Round 1):\n${p.output.slice(0, 2000)}`)
|
|
3020
|
+
.join('\n\n---\n\n');
|
|
3021
|
+
|
|
3022
|
+
// Round 2: cross-reading + refinement (sequential to save tokens)
|
|
3023
|
+
sendTok2('[Parlamento — Round 2: Cross-Reading & Refinamento] ');
|
|
3024
|
+
const r2Results = [];
|
|
3025
|
+
|
|
3026
|
+
for (const proposal of eligibleProposals) {
|
|
3027
|
+
sendTok2(`[Round 2: ${proposal.label || proposal.agent}] `);
|
|
3028
|
+
const crossCtx = buildCrossReadCtx(proposal.agent);
|
|
3029
|
+
const r2Sys = `You are ${proposal.agent}, a specialist AI agent in NHA Studio Parliament. Today is ${today}. Respond entirely in ${language}.
|
|
3030
|
+
|
|
3031
|
+
## WORKFLOW GOAL: ${task}
|
|
3032
|
+
|
|
3033
|
+
## YOUR ROUND 1 RESPONSE:
|
|
3034
|
+
${proposal.output.slice(0, 1500)}
|
|
3035
|
+
|
|
3036
|
+
## OTHER AGENTS' ROUND 1 PROPOSALS:
|
|
3037
|
+
${crossCtx}
|
|
3038
|
+
|
|
3039
|
+
DELIBERATION ROUND 2 — REFINEMENT:
|
|
3040
|
+
1. Review the other agents' proposals
|
|
3041
|
+
2. Incorporate valid points where you AGREE — mark with [ASSIST]
|
|
3042
|
+
3. Flag genuine disagreements with [CONTRADICTION] and explain your reasoning
|
|
3043
|
+
4. Produce your COMPLETE REFINED response (full answer, not a diff)
|
|
3044
|
+
5. Keep your analysis focused on: ${task}`;
|
|
3045
|
+
|
|
3046
|
+
let r2Out = '';
|
|
3047
|
+
try {
|
|
3048
|
+
await callLLMStream(config, r2Sys, 'Produce your refined Round 2 response.',
|
|
3049
|
+
(tok) => { r2Out += tok; }, { max_tokens: 2048 });
|
|
3050
|
+
} catch (e) { r2Out = proposal.output; }
|
|
3051
|
+
r2Results.push({ agent: proposal.agent, label: proposal.label, icon: proposal.icon, output: r2Out });
|
|
3052
|
+
sendEv2({ deliberation_r2: { agent: proposal.agent, label: proposal.label, icon: proposal.icon, output: r2Out } });
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
// Round 2 convergence
|
|
3056
|
+
const r2Convergence = measureConvergence(r2Results.map(r => r.output));
|
|
3057
|
+
sendTok2(`[Parlamento — Round 2 convergenza: ${(r2Convergence * 100).toFixed(0)}%] `);
|
|
3058
|
+
const converged = r2Convergence >= 0.30;
|
|
3059
|
+
|
|
3060
|
+
// Round 3: mediation only if still divergent
|
|
3061
|
+
let mediationOutput = '';
|
|
3062
|
+
if (!converged) {
|
|
3063
|
+
sendTok2('[Parlamento — Round 3: Mediazione...] ');
|
|
3064
|
+
const allR2Ctx = r2Results
|
|
3065
|
+
.map(r => `## ${r.label || r.agent}:\n${r.output.slice(0, 1500)}`)
|
|
3066
|
+
.join('\n\n---\n\n');
|
|
3067
|
+
const medSys = `You are HERALD, the Parliament Mediator in NHA Studio. Today is ${today}. Respond entirely in ${language}.
|
|
3068
|
+
|
|
3069
|
+
## WORKFLOW GOAL: ${task}
|
|
3070
|
+
|
|
3071
|
+
## ALL AGENTS' REFINED POSITIONS (Round 2):
|
|
3072
|
+
${allR2Ctx}
|
|
3073
|
+
|
|
3074
|
+
MEDIATION TASK:
|
|
3075
|
+
1. Identify core points of AGREEMENT across all agents
|
|
3076
|
+
2. For each disagreement, evaluate which position has stronger evidence
|
|
3077
|
+
3. Produce a UNIFIED synthesis preserving genuine insights from each agent
|
|
3078
|
+
4. Make clear editorial choices — do NOT blend blindly
|
|
3079
|
+
5. Output a complete executive summary with concrete action items for: ${task}`;
|
|
3080
|
+
try {
|
|
3081
|
+
await callLLMStream(config, medSys, 'Produce the mediated Parliament consensus.',
|
|
3082
|
+
(tok) => { mediationOutput += tok; }, { max_tokens: 3000 });
|
|
3083
|
+
} catch (e) { mediationOutput = ''; }
|
|
3084
|
+
sendEv2({ deliberation_r3: { output: mediationOutput } });
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
clearInterval(keepaliveD);
|
|
3088
|
+
sendEv2({
|
|
3089
|
+
deliberation_done: true,
|
|
3090
|
+
r1_convergence: r1Convergence,
|
|
3091
|
+
r2_convergence: r2Convergence,
|
|
3092
|
+
converged,
|
|
3093
|
+
r2_results: r2Results,
|
|
3094
|
+
mediation: mediationOutput || null,
|
|
3095
|
+
});
|
|
3096
|
+
sendEv2({ done: true });
|
|
3097
|
+
res.write('data: [DONE]\n\n');
|
|
3098
|
+
res.end();
|
|
3099
|
+
} catch (e) {
|
|
3100
|
+
clearInterval(keepaliveD);
|
|
3101
|
+
sendEv2({ error: e.message });
|
|
3102
|
+
res.end();
|
|
3103
|
+
}
|
|
3104
|
+
logRequest(method, pathname, 200, Date.now() - start);
|
|
3105
|
+
return;
|
|
3106
|
+
}
|
|
3107
|
+
|
|
2939
3108
|
// ── 404 ──────────────────────────────────────────────────────────
|
|
2940
3109
|
sendJSON(res, 404, { error: 'Not found' });
|
|
2941
3110
|
logRequest(method, pathname, 404, Date.now() - start);
|
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.45';
|
|
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
|
@@ -2971,12 +2971,13 @@ function renderSidebar() {
|
|
|
2971
2971
|
|
|
2972
2972
|
var studioState = {
|
|
2973
2973
|
task: '',
|
|
2974
|
-
nodes: [], // [{icon,agent,label,status:'waiting'|'running'|'done'|'error'}]
|
|
2974
|
+
nodes: [], // [{icon,agent,label,status:'waiting'|'running'|'done'|'error',output:''}]
|
|
2975
2975
|
log: [], // [{agent,icon,text,time,type:'agent'|'system'|'error'}]
|
|
2976
2976
|
result: '',
|
|
2977
2977
|
canvas: null, // HTML canvas content if generated
|
|
2978
2978
|
running: false,
|
|
2979
|
-
planned: false
|
|
2979
|
+
planned: false,
|
|
2980
|
+
parliamentMode: false
|
|
2980
2981
|
};
|
|
2981
2982
|
|
|
2982
2983
|
var studioAbortController = null;
|
|
@@ -3001,6 +3002,7 @@ function studioReset() {
|
|
|
3001
3002
|
studioState.nodes = [];
|
|
3002
3003
|
studioState.log = [];
|
|
3003
3004
|
studioState.result = '';
|
|
3005
|
+
studioState.canvas = null;
|
|
3004
3006
|
studioState.running = false;
|
|
3005
3007
|
studioState.planned = false;
|
|
3006
3008
|
studioTokens = {in:0, out:0};
|
|
@@ -3176,6 +3178,7 @@ async function runStudio() {
|
|
|
3176
3178
|
}
|
|
3177
3179
|
studioSetNodeStatus(i, 'done');
|
|
3178
3180
|
var realOutput = (stepResult.output && stepResult.output !== '(no output)') ? stepResult.output : null;
|
|
3181
|
+
studioState.nodes[i].output = realOutput || '';
|
|
3179
3182
|
studioLog(node.label, node.icon, realOutput || (stepResult.canvas ? '[Canvas report generated]' : '(done)'), 'agent', true);
|
|
3180
3183
|
// If CanvasAgent produced HTML, open it in the canvas panel
|
|
3181
3184
|
if (stepResult.canvas) {
|
|
@@ -3191,6 +3194,68 @@ async function runStudio() {
|
|
|
3191
3194
|
context = realOutput || stepResult.canvas || context;
|
|
3192
3195
|
}
|
|
3193
3196
|
|
|
3197
|
+
// Parliament mode: Round 2 cross-reading deliberation
|
|
3198
|
+
var parliamentChk = document.getElementById(\x27studioParliamentMode\x27);
|
|
3199
|
+
if (parliamentChk && parliamentChk.checked && studioState.nodes.length >= 2) {
|
|
3200
|
+
var proposals = studioState.nodes
|
|
3201
|
+
.filter(function(n) { return n.output && n.output !== \x27(no output)\x27 && n.agent !== \x27CanvasAgent\x27; })
|
|
3202
|
+
.map(function(n) { return {agent: n.agent, label: n.label, output: n.output}; });
|
|
3203
|
+
if (proposals.length >= 2) {
|
|
3204
|
+
studioLog(\x27Parlamento\x27, \x27♖\x27, \x27Avvio deliberazione — Round 2 cross-reading tra agenti...\x27, \x27system\x27);
|
|
3205
|
+
var deliberateBody = JSON.stringify({task: task, proposals: proposals, language: document.getElementById(\x27langSelect\x27) ? document.getElementById(\x27langSelect\x27).value : \x27it\x27});
|
|
3206
|
+
try {
|
|
3207
|
+
var delRes = await fetch(\x27/api/studio/deliberate\x27, {method:\x27POST\x27, headers:{\x27Content-Type\x27:\x27application/json\x27}, body: deliberateBody, signal: studioAbortController ? studioAbortController.signal : undefined});
|
|
3208
|
+
if (delRes.ok) {
|
|
3209
|
+
var delReader = delRes.body.getReader();
|
|
3210
|
+
var delDecoder = new TextDecoder();
|
|
3211
|
+
var delBuf = \x27\x27;
|
|
3212
|
+
var delDone = false;
|
|
3213
|
+
while (!delDone) {
|
|
3214
|
+
var delChunk = await delReader.read();
|
|
3215
|
+
if (delChunk.done) break;
|
|
3216
|
+
delBuf += delDecoder.decode(delChunk.value, {stream:true});
|
|
3217
|
+
var delLines = delBuf.split(\x27\\n\x27);
|
|
3218
|
+
delBuf = delLines.pop();
|
|
3219
|
+
delLines.forEach(function(ln) {
|
|
3220
|
+
if (!ln.startsWith(\x27data: \x27)) return;
|
|
3221
|
+
var dd = ln.slice(6).trim();
|
|
3222
|
+
if (dd === \x27[DONE]\x27) { delDone = true; return; }
|
|
3223
|
+
try {
|
|
3224
|
+
var dev = JSON.parse(dd);
|
|
3225
|
+
if (dev.token) {
|
|
3226
|
+
// Status tokens from server — update last log entry text inline
|
|
3227
|
+
var delEntries = document.querySelectorAll(\x27.studio-log-entry\x27);
|
|
3228
|
+
var delLast = delEntries[delEntries.length - 1];
|
|
3229
|
+
if (delLast) { var delTb = delLast.querySelector(\x27.studio-log-entry__text\x27); if (delTb) delTb.textContent = dev.token; }
|
|
3230
|
+
} else if (dev.deliberation_r2) {
|
|
3231
|
+
var r2d = dev.deliberation_r2;
|
|
3232
|
+
studioLog(r2d.label || r2d.agent, \x27♖\x27, \x27[R2] \x27 + (r2d.output || \x27\x27).slice(0, 300), \x27agent\x27, true);
|
|
3233
|
+
var ni2 = studioState.nodes.findIndex(function(x){return x.agent===r2d.agent;});
|
|
3234
|
+
if (ni2 >= 0) { studioState.nodes[ni2].output = r2d.output; }
|
|
3235
|
+
context = r2d.output || context;
|
|
3236
|
+
} else if (dev.deliberation_r3) {
|
|
3237
|
+
studioLog(\x27HERALD\x27, \x27🔧\x27, \x27[Mediazione] \x27 + (dev.deliberation_r3.output || \x27\x27).slice(0, 300), \x27system\x27, true);
|
|
3238
|
+
context = dev.deliberation_r3.output || context;
|
|
3239
|
+
} else if (dev.deliberation_done) {
|
|
3240
|
+
var r2Conv = Math.round((dev.r2_convergence || 0) * 100);
|
|
3241
|
+
studioLog(\x27Parlamento\x27, \x27♖\x27, \x27Deliberazione completa — convergenza R2: \x27 + r2Conv + \x27%\x27, \x27system\x27);
|
|
3242
|
+
if (dev.mediation) { context = dev.mediation; }
|
|
3243
|
+
delDone = true;
|
|
3244
|
+
} else if (dev.done) {
|
|
3245
|
+
delDone = true;
|
|
3246
|
+
}
|
|
3247
|
+
} catch(e2) {}
|
|
3248
|
+
});
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
} catch(e3) {
|
|
3252
|
+
if (e3.name !== \x27AbortError\x27) {
|
|
3253
|
+
studioLog(\x27Parlamento\x27, \x27♖\x27, \x27Deliberazione non disponibile: \x27 + (e3.message || String(e3)), \x27error\x27);
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
|
|
3194
3259
|
// Final result is the last step's output
|
|
3195
3260
|
studioState.result = context;
|
|
3196
3261
|
renderStudioResult();
|
|
@@ -3497,6 +3562,10 @@ function renderStudio(el) {
|
|
|
3497
3562
|
'<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>' +
|
|
3498
3563
|
'</div>' +
|
|
3499
3564
|
'</div>' +
|
|
3565
|
+
'<label style="display:flex;align-items:center;gap:8px;margin-top:8px;cursor:pointer;user-select:none">' +
|
|
3566
|
+
'<input type="checkbox" id="studioParliamentMode" style="width:15px;height:15px;accent-color:var(--green3)" ' + (studioState.parliamentMode ? \x27checked\x27 : \x27\x27) + ' onchange="studioState.parliamentMode=this.checked">' +
|
|
3567
|
+
'<span style="font-size:12px;color:var(--dim)">♖ <strong style="color:var(--green)">Parlamento</strong> — Round 2 cross-reading tra agenti (2x token)</span>' +
|
|
3568
|
+
'</label>' +
|
|
3500
3569
|
'</div>' +
|
|
3501
3570
|
|
|
3502
3571
|
// ── MANUAL BUILDER MODE ──
|