nothumanallowed 15.1.48 → 15.1.50
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.
|
|
3
|
+
"version": "15.1.50",
|
|
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/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.
|
|
8
|
+
export const VERSION = '15.1.50';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -302,17 +302,47 @@ export function register(router) {
|
|
|
302
302
|
semanticBag = 'proposal';
|
|
303
303
|
}
|
|
304
304
|
|
|
305
|
-
|
|
305
|
+
// "allegato / attachment / PDF" → user wants to read the content of
|
|
306
|
+
// an attachment of a specific email. We extract identifier tokens from
|
|
307
|
+
// the message (capitalized phrases, alphanumeric codes with dots/slashes
|
|
308
|
+
// like "NCSARMEMAIL.08/05", PO numbers, etc.) and search the local DB
|
|
309
|
+
// for matching subjects, then chain imap_read + imap_attachment_read
|
|
310
|
+
// server-side. This bypasses the LLM's habit of saying "Let me read..."
|
|
311
|
+
// without actually emitting the tool.
|
|
312
|
+
const wantsReadAttachment = /\b(allegato|attachment|allegata|allegat[oi]|pdf|documento\s+allegato|file\s+allegato|enclosed|attached)\b/i.test(msg);
|
|
313
|
+
|
|
314
|
+
if ((wantsReadEmail || semanticBag || wantsReadAttachment) && !actions.some(a => a.action?.startsWith('imap_') || a.action === 'list_emails')) {
|
|
306
315
|
try {
|
|
307
316
|
const { listAccounts: _la } = await import('../../services/email-db.mjs');
|
|
308
317
|
const imapAccs = _la();
|
|
309
318
|
if (imapAccs.length > 0) {
|
|
310
319
|
const firstAcc = imapAccs[0];
|
|
311
|
-
if (
|
|
320
|
+
if (wantsReadAttachment) {
|
|
321
|
+
// Extract subject identifiers from the user message. Heuristic:
|
|
322
|
+
// - Quoted substrings ("..." or «...»)
|
|
323
|
+
// - Alphanumeric codes ≥4 chars with dot/slash/dash (PO/RDA codes)
|
|
324
|
+
// - Capitalized multi-word phrases ("Purchase Order", "Tagliando BMW")
|
|
325
|
+
// - Standalone uppercase tokens ≥4 chars (NCSARMEMAIL)
|
|
326
|
+
const ids = new Set();
|
|
327
|
+
const quoted = msg.match(/["«""']([^"«»""'\n]{3,80})["»""']/g) || [];
|
|
328
|
+
quoted.forEach(q => ids.add(q.replace(/^["«""']|["»""']$/g, '').trim()));
|
|
329
|
+
const codes = msg.match(/\b[A-Z0-9][A-Z0-9._/\-]{3,}\b/g) || [];
|
|
330
|
+
codes.forEach(c => ids.add(c));
|
|
331
|
+
const phrases = msg.match(/\b([A-Z][a-zà-ÿ]+(?:\s+[A-Za-zà-ÿ0-9]+){1,3})\b/g) || [];
|
|
332
|
+
phrases.filter(p => p.length >= 6).forEach(p => ids.add(p));
|
|
333
|
+
const tokens = [...ids].slice(0, 5);
|
|
334
|
+
if (tokens.length === 0) {
|
|
335
|
+
// No specific identifier — fall back to a broad list of recent
|
|
336
|
+
// messages with attachments.
|
|
337
|
+
actions.push({ action: 'imap_list', params: { accountId: firstAcc.id, limit: 30 } });
|
|
338
|
+
} else {
|
|
339
|
+
for (const q of tokens) {
|
|
340
|
+
actions.push({ action: 'imap_search', params: { accountId: firstAcc.id, query: q, limit: 10 } });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
} else if (semanticBag) {
|
|
312
344
|
// Push one imap_search per keyword variant in the bag. The
|
|
313
|
-
// synthesis step will dedupe overlapping hits.
|
|
314
|
-
// 60-day window (limit=80 per query) — much wider than the
|
|
315
|
-
// 5-email peek the old branch did.
|
|
345
|
+
// synthesis step will dedupe overlapping hits.
|
|
316
346
|
const bag = QUOTE_KEYWORDS[semanticBag] || [];
|
|
317
347
|
const variants = [
|
|
318
348
|
...(QUOTE_KEYWORDS.offerta || []).slice(0, 3),
|
|
@@ -395,6 +425,12 @@ export function register(router) {
|
|
|
395
425
|
}
|
|
396
426
|
}
|
|
397
427
|
|
|
428
|
+
// Capture the pre-synthesis prose (what the model said in Round 1).
|
|
429
|
+
// We will combine this with the synthesis output so the user keeps
|
|
430
|
+
// BOTH — currently the UI was overwriting Round 1 with Round 2 alone,
|
|
431
|
+
// which made long prose disappear and leave only "Let me read…".
|
|
432
|
+
const round1Prose = fullResponse;
|
|
433
|
+
|
|
398
434
|
// Synthesis round if tools ran
|
|
399
435
|
if (toolResults.length > 0) {
|
|
400
436
|
// Strip raw JSON from tool results — present as clean prose summaries
|
|
@@ -425,23 +461,84 @@ export function register(router) {
|
|
|
425
461
|
const synthesisPrompt = `${enrichedPrompt}\n\n## DATA FROM TOOLS:\n${toolContext}\n\n## STRICT OUTPUT RULES:\n- Write ONLY plain prose or markdown (headers, bullets, bold)\n- NEVER use \`\`\`json, \`\`\`data, or any fenced code block containing data\n- NEVER output raw JSON, arrays, or objects\n- Format numbers/prices as plain text (e.g. "Bitcoin: $103,000")\n- Be concise and human-readable`;
|
|
426
462
|
const synthesisMsg = `${effectiveMsg}\n\nAnswer using ONLY the data above. Plain text/markdown only — zero JSON, zero code blocks.`;
|
|
427
463
|
sse('tool_synthesis', {});
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
464
|
+
// Keep the pre-synthesis prose around. If the synthesis call returns
|
|
465
|
+
// empty (provider error, content filter, model bailed), we fall back
|
|
466
|
+
// to "first-round prose + raw tool output" so the user never sees a
|
|
467
|
+
// blank message and can still read what the tools returned.
|
|
468
|
+
const preSynthesis = fullResponse;
|
|
469
|
+
let synthesized = '';
|
|
470
|
+
try {
|
|
471
|
+
synthesized = await callLLMStream(config, synthesisPrompt, synthesisMsg, (chunk) => {
|
|
472
|
+
sse('token', { content: chunk });
|
|
473
|
+
});
|
|
474
|
+
} catch (synthErr) {
|
|
475
|
+
sse('error', { message: `Synthesis failed: ${synthErr.message}` });
|
|
476
|
+
}
|
|
477
|
+
if (synthesized && synthesized.trim()) {
|
|
478
|
+
fullResponse = synthesized;
|
|
479
|
+
} else {
|
|
480
|
+
// Fallback: stream the raw tool context so the user gets the data
|
|
481
|
+
// even when the LLM round failed silently.
|
|
482
|
+
const fallback = (preSynthesis && preSynthesis.trim() ? preSynthesis.trim() + '\n\n' : '') +
|
|
483
|
+
toolResults.map(t => `**${t.action}**\n${cleanResult(t.action, t.result)}`).join('\n\n');
|
|
484
|
+
sse('token', { content: fallback });
|
|
485
|
+
fullResponse = fallback;
|
|
486
|
+
}
|
|
432
487
|
}
|
|
433
488
|
|
|
434
489
|
// Strip orphan tool-fence blocks that the LLM may have emitted as
|
|
435
490
|
// a "no-more-tools" marker (e.g. empty ```json ``` or '''json ''').
|
|
436
491
|
// They leaked into the chat panel as visible noise.
|
|
437
|
-
|
|
492
|
+
//
|
|
493
|
+
// Also combine Round 1 prose with synthesis output when a synthesis
|
|
494
|
+
// round actually happened, so the user sees BOTH the model's intro
|
|
495
|
+
// ("Leggerò l'email…") AND the synthesized result, instead of one
|
|
496
|
+
// overwriting the other.
|
|
497
|
+
const round1Clean = stripOrphanFences(round1Prose || '');
|
|
498
|
+
const synthClean = stripOrphanFences(fullResponse || '');
|
|
499
|
+
let cleanFullResponse;
|
|
500
|
+
if (toolResults.length > 0 && round1Clean && synthClean && round1Clean !== synthClean) {
|
|
501
|
+
cleanFullResponse = `${round1Clean}\n\n${synthClean}`;
|
|
502
|
+
} else {
|
|
503
|
+
cleanFullResponse = synthClean || round1Clean;
|
|
504
|
+
}
|
|
438
505
|
|
|
439
|
-
// Persist to conversation
|
|
506
|
+
// Persist to conversation. Honour retry/edit flags so the tree forks
|
|
507
|
+
// correctly instead of duplicating the user message in the active path.
|
|
508
|
+
// - isRetry: add the new response as a sibling of the last assistant
|
|
509
|
+
// under the same user node (no new user node).
|
|
510
|
+
// - isEdit: add the new user message as a sibling of an existing
|
|
511
|
+
// user node, then chain the assistant under the new branch.
|
|
512
|
+
// - default: addMessages (creates user+assistant pair).
|
|
440
513
|
if (body.conversationId) {
|
|
441
514
|
try {
|
|
442
515
|
const conv = loadConversation(body.conversationId);
|
|
443
516
|
if (conv) {
|
|
444
|
-
|
|
517
|
+
if (body.isRetry) {
|
|
518
|
+
// Find the most recent user node in the active path — that's
|
|
519
|
+
// the parent we're regenerating from.
|
|
520
|
+
const path = getHistory(conv, 100);
|
|
521
|
+
const lastUser = [...path].reverse().find(n => n.role === 'user');
|
|
522
|
+
if (lastUser?.id) {
|
|
523
|
+
addRetryResponse(conv, lastUser.id, cleanFullResponse);
|
|
524
|
+
} else {
|
|
525
|
+
addMessages(conv, msg, cleanFullResponse);
|
|
526
|
+
}
|
|
527
|
+
} else if (body.isEdit && typeof body.editFromIdx === 'number') {
|
|
528
|
+
// Active path is a flat list; index editFromIdx in the UI maps
|
|
529
|
+
// 1:1 to the same index in the active path. Branch from there.
|
|
530
|
+
const path = getHistory(conv, 100);
|
|
531
|
+
const target = path[body.editFromIdx];
|
|
532
|
+
if (target?.id && target.role === 'user') {
|
|
533
|
+
const newUserId = editMessage(conv, target.id, msg);
|
|
534
|
+
if (newUserId) addRetryResponse(conv, newUserId, cleanFullResponse);
|
|
535
|
+
else addMessages(conv, msg, cleanFullResponse);
|
|
536
|
+
} else {
|
|
537
|
+
addMessages(conv, msg, cleanFullResponse);
|
|
538
|
+
}
|
|
539
|
+
} else {
|
|
540
|
+
addMessages(conv, msg, cleanFullResponse);
|
|
541
|
+
}
|
|
445
542
|
}
|
|
446
543
|
} catch {}
|
|
447
544
|
}
|
|
@@ -455,7 +455,15 @@ TOOLS:
|
|
|
455
455
|
Only call this if you need to refresh or the section is missing.
|
|
456
456
|
|
|
457
457
|
66. imap_read(messageId: string)
|
|
458
|
-
Read a full email message from the local DB by its id. Returns subject, from, to, body_text, body_html,
|
|
458
|
+
Read a full email message from the local DB by its id. Returns subject, from, to, body_text, body_html, and a numbered ATTACHMENTS list.
|
|
459
|
+
If the email has attachments, follow up with imap_attachment_read to read each one's content.
|
|
460
|
+
|
|
461
|
+
66b. imap_attachment_read(messageId: string, filename?: string, index?: number, attachmentId?: string)
|
|
462
|
+
Download and parse an attachment of a given email. messageId is required; pick the attachment by filename (substring match,
|
|
463
|
+
case-insensitive), 1-based index, or attachmentId (exact). Returns extracted text for PDF (text-based POs/quotes/invoices),
|
|
464
|
+
DOCX (Word), and any text/* type. For image-based PDFs or unsupported binary types, returns metadata and instructs the
|
|
465
|
+
user to share the relevant section as text. Use this whenever the user says "leggi l'allegato", "read the attachment",
|
|
466
|
+
"estrai dati dall'allegato", "what's in the PDF", etc.
|
|
459
467
|
|
|
460
468
|
67. imap_send(accountId: string, to: string, subject: string, bodyHtml: string, cc?: string, inReplyTo?: string)
|
|
461
469
|
Send an email via SMTP from a configured IMAP account. ALWAYS confirm with user before sending.
|
|
@@ -946,6 +954,83 @@ export function stripOrphanFences(text) {
|
|
|
946
954
|
/**
|
|
947
955
|
* Format an ISO timestamp into a human-readable time string.
|
|
948
956
|
*/
|
|
957
|
+
// ── Attachment Parsers (zero-deps, best-effort) ────────────────────────────
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Extract text from a PDF buffer using a naïve pattern scan. Catches text
|
|
961
|
+
* inside `BT ... (text) Tj ... ET` blocks of uncompressed content streams.
|
|
962
|
+
* Won't work on PDFs whose content streams are FlateDecode-compressed — those
|
|
963
|
+
* need a real parser (pdfjs-dist). For typical ERP-generated POs/quotes the
|
|
964
|
+
* content stream is usually plain enough that this catches the line items.
|
|
965
|
+
*/
|
|
966
|
+
function _naivePdfText(buf) {
|
|
967
|
+
if (!Buffer.isBuffer(buf)) return '';
|
|
968
|
+
// PDFs can store text in (...) strings, sometimes split across multiple Tj
|
|
969
|
+
// calls. We collect them all, decode the basic escapes, and join with spaces.
|
|
970
|
+
const raw = buf.toString('latin1');
|
|
971
|
+
const out = [];
|
|
972
|
+
// BT ... ET text blocks. Inside: (text) Tj or [(a)(b)] TJ.
|
|
973
|
+
const blockRe = /BT[\s\S]*?ET/g;
|
|
974
|
+
let m;
|
|
975
|
+
while ((m = blockRe.exec(raw))) {
|
|
976
|
+
const block = m[0];
|
|
977
|
+
const strRe = /\(((?:\\.|[^\\)])*)\)/g;
|
|
978
|
+
let sm;
|
|
979
|
+
const parts = [];
|
|
980
|
+
while ((sm = strRe.exec(block))) {
|
|
981
|
+
const s = sm[1]
|
|
982
|
+
.replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/\\t/g, '\t')
|
|
983
|
+
.replace(/\\\(/g, '(').replace(/\\\)/g, ')').replace(/\\\\/g, '\\')
|
|
984
|
+
.replace(/\\([0-7]{1,3})/g, (_, oct) => String.fromCharCode(parseInt(oct, 8)));
|
|
985
|
+
parts.push(s);
|
|
986
|
+
}
|
|
987
|
+
if (parts.length) out.push(parts.join(' '));
|
|
988
|
+
}
|
|
989
|
+
// Cleanup: collapse whitespace, drop control chars.
|
|
990
|
+
return out.join('\n').replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, '').replace(/[ \t]+/g, ' ').trim();
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
/**
|
|
994
|
+
* Extract text from a DOCX buffer. DOCX = zip with `word/document.xml`. We
|
|
995
|
+
* use Node's built-in zlib to decompress the central directory, find the
|
|
996
|
+
* document.xml entry, decompress it, and pull <w:t>...</w:t> text runs.
|
|
997
|
+
*/
|
|
998
|
+
async function _naiveDocxText(buf) {
|
|
999
|
+
if (!Buffer.isBuffer(buf)) return '';
|
|
1000
|
+
const zlib = await import('zlib');
|
|
1001
|
+
const { promisify } = await import('util');
|
|
1002
|
+
const inflateRaw = promisify(zlib.inflateRaw);
|
|
1003
|
+
// ZIP local file headers start with 0x504b0304. We scan for them and pick
|
|
1004
|
+
// out the entry whose filename is "word/document.xml".
|
|
1005
|
+
let i = 0;
|
|
1006
|
+
while (i < buf.length - 30) {
|
|
1007
|
+
if (buf.readUInt32LE(i) !== 0x04034b50) { i++; continue; }
|
|
1008
|
+
const compMethod = buf.readUInt16LE(i + 8);
|
|
1009
|
+
const compSize = buf.readUInt32LE(i + 18);
|
|
1010
|
+
const nameLen = buf.readUInt16LE(i + 26);
|
|
1011
|
+
const extraLen = buf.readUInt16LE(i + 28);
|
|
1012
|
+
const name = buf.slice(i + 30, i + 30 + nameLen).toString('utf8');
|
|
1013
|
+
const dataStart = i + 30 + nameLen + extraLen;
|
|
1014
|
+
if (name === 'word/document.xml') {
|
|
1015
|
+
const compData = buf.slice(dataStart, dataStart + compSize);
|
|
1016
|
+
let xml = '';
|
|
1017
|
+
try {
|
|
1018
|
+
if (compMethod === 0) xml = compData.toString('utf8');
|
|
1019
|
+
else if (compMethod === 8) xml = (await inflateRaw(compData)).toString('utf8');
|
|
1020
|
+
else return '';
|
|
1021
|
+
} catch { return ''; }
|
|
1022
|
+
// Extract <w:t>...</w:t> runs (and the xml: space="preserve" variant).
|
|
1023
|
+
const parts = [];
|
|
1024
|
+
const re = /<w:t[^>]*>([\s\S]*?)<\/w:t>/g;
|
|
1025
|
+
let m;
|
|
1026
|
+
while ((m = re.exec(xml))) parts.push(m[1].replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, "'"));
|
|
1027
|
+
return parts.join(' ').replace(/[ \t]+/g, ' ').trim();
|
|
1028
|
+
}
|
|
1029
|
+
i = dataStart + compSize;
|
|
1030
|
+
}
|
|
1031
|
+
return '';
|
|
1032
|
+
}
|
|
1033
|
+
|
|
949
1034
|
export function formatTime(isoStr) {
|
|
950
1035
|
try {
|
|
951
1036
|
const d = new Date(isoStr);
|
|
@@ -1352,7 +1437,76 @@ export async function executeTool(action, params, config) {
|
|
|
1352
1437
|
imapMarkRead(params.messageId, true);
|
|
1353
1438
|
const to = (() => { try { const a = JSON.parse(msg.to_addresses || '[]'); return a.map(x => x.address || x).join(', '); } catch { return msg.to_addresses || ''; } })();
|
|
1354
1439
|
const body = msg.body_reply_only || msg.body_text || msg.body_preview || '(empty)';
|
|
1355
|
-
|
|
1440
|
+
// Surface attachments in the tool response so the LLM can decide whether
|
|
1441
|
+
// to follow up with imap_attachment_read. Without this it has no way to
|
|
1442
|
+
// know an attachment exists.
|
|
1443
|
+
const atts = (msg.attachments || []).map((a, i) =>
|
|
1444
|
+
`[${i + 1}] "${a.filename || 'unnamed'}" — ${a.content_type || 'application/octet-stream'} — ${Math.round((a.size_bytes || 0) / 1024)} KB — id:${a.id}`
|
|
1445
|
+
).join('\n');
|
|
1446
|
+
const attBlock = atts
|
|
1447
|
+
? `\n\n--- ATTACHMENTS (${msg.attachments.length}) ---\n${atts}\n\nTo read the content of an attachment, call: imap_attachment_read with messageId="${msg.id}" and either filename or index.`
|
|
1448
|
+
: '';
|
|
1449
|
+
return `Subject: ${msg.subject}\nFrom: ${msg.from_name ? msg.from_name + ' <' + msg.from_address + '>' : msg.from_address}\nTo: ${to}\nDate: ${msg.internal_date}\n\n${body.slice(0, 3000)}${attBlock}`;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
case 'imap_attachment_read': {
|
|
1453
|
+
if (!params.messageId) return 'messageId required. Use imap_read first to get the messageId and the list of attachments.';
|
|
1454
|
+
const { getMessage: imapGetMsgForAtt } = await import('./email-db.mjs');
|
|
1455
|
+
const msg = imapGetMsgForAtt(params.messageId);
|
|
1456
|
+
if (!msg) return 'Message not found.';
|
|
1457
|
+
const attachments = msg.attachments || [];
|
|
1458
|
+
if (!attachments.length) return 'This message has no attachments.';
|
|
1459
|
+
// Resolution: explicit attachmentId > filename match > index > first
|
|
1460
|
+
let chosen = null;
|
|
1461
|
+
if (params.attachmentId) {
|
|
1462
|
+
chosen = attachments.find(a => a.id === params.attachmentId);
|
|
1463
|
+
} else if (params.filename) {
|
|
1464
|
+
const needle = String(params.filename).toLowerCase();
|
|
1465
|
+
chosen = attachments.find(a => (a.filename || '').toLowerCase().includes(needle));
|
|
1466
|
+
} else if (typeof params.index === 'number') {
|
|
1467
|
+
chosen = attachments[Math.max(0, params.index - 1)] || null;
|
|
1468
|
+
}
|
|
1469
|
+
if (!chosen) chosen = attachments[0];
|
|
1470
|
+
if (!chosen) return 'Could not resolve which attachment to read.';
|
|
1471
|
+
const { fetchAttachmentContent } = await import('./email-imap.mjs');
|
|
1472
|
+
let result;
|
|
1473
|
+
try {
|
|
1474
|
+
result = await fetchAttachmentContent(msg.account_id, msg.imap_folder_path, msg.uid, chosen.part_id);
|
|
1475
|
+
} catch (e) {
|
|
1476
|
+
return `Failed to fetch attachment "${chosen.filename}" from server: ${e.message}`;
|
|
1477
|
+
}
|
|
1478
|
+
if (!result?.buffer) return `Attachment "${chosen.filename}" returned no content.`;
|
|
1479
|
+
const buf = result.buffer;
|
|
1480
|
+
const ct = (chosen.content_type || result.contentType || '').toLowerCase();
|
|
1481
|
+
const head = `Attachment: ${chosen.filename}\nType: ${ct || 'unknown'}\nSize: ${Math.round(buf.length / 1024)} KB\n\n`;
|
|
1482
|
+
|
|
1483
|
+
// Text-ish — return up to 10k chars of UTF-8.
|
|
1484
|
+
if (/^text\/|application\/(json|xml|csv|x-yaml)/i.test(ct) || /\.(txt|csv|json|xml|log|md|html)$/i.test(chosen.filename || '')) {
|
|
1485
|
+
return head + buf.toString('utf8').slice(0, 10000);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
// PDF — naïve text extraction from the raw stream. Catches text-based
|
|
1489
|
+
// PDFs (invoices, purchase orders, quotes generated by ERP software).
|
|
1490
|
+
// Doesn't handle scanned/OCR PDFs — for those the model gets a clear
|
|
1491
|
+
// "image-based PDF" hint so it can ask the user.
|
|
1492
|
+
if (/pdf/i.test(ct) || /\.pdf$/i.test(chosen.filename || '')) {
|
|
1493
|
+
const text = _naivePdfText(buf);
|
|
1494
|
+
if (text && text.length > 30) {
|
|
1495
|
+
return head + `--- Extracted text (best-effort, ${text.length} chars) ---\n${text.slice(0, 10000)}`;
|
|
1496
|
+
}
|
|
1497
|
+
return head + `PDF appears to be image-based or compressed (no extractable text found). ` +
|
|
1498
|
+
`Tell the user the PDF can't be auto-read — they can open it manually or share the relevant section as text.`;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
// DOCX — minimal text extraction from word/document.xml inside the zip.
|
|
1502
|
+
if (/wordprocessingml|msword/i.test(ct) || /\.docx?$/i.test(chosen.filename || '')) {
|
|
1503
|
+
const text = await _naiveDocxText(buf);
|
|
1504
|
+
if (text) return head + `--- Extracted text (${text.length} chars) ---\n${text.slice(0, 10000)}`;
|
|
1505
|
+
return head + 'Could not extract text from DOCX (possibly malformed or password-protected).';
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// Unsupported — return metadata only.
|
|
1509
|
+
return head + `Tipo "${ct}" non supportato per lettura automatica. Allegato disponibile nella casella email; chiedi all'utente di condividere il contenuto rilevante come testo.`;
|
|
1356
1510
|
}
|
|
1357
1511
|
|
|
1358
1512
|
case 'imap_send': {
|
|
@@ -59,10 +59,10 @@ The agent works in a loop: read → plan → modify → verify → fix if needed
|
|
|
59
59
|
`),n=``,r=!1,i=!1,a=!1,o=``,s=``,c=0,l=()=>{r&&=(n+=`</ul>`,!1),i&&=(n+=`</ol>`,!1)};for(;c<t.length;){let e=t[c],u=e.trim();if(u.startsWith("```")){a?(n+=ye(o)+`</code></pre>`,a=!1,o=``):(l(),a=!0,o=``,s=u.slice(3).trim(),n+=`<pre><code${s?` class="language-${ye(s)}"`:``}>`),c++;continue}if(a){o+=e+`
|
|
60
60
|
`,c++;continue}{let e=u.match(/^(#{1,6}) (.+)/);if(e){l();let t=e[1].length;n+=`<h${t}>${be(e[2])}</h${t}>`,c++;continue}}if(/^-{3,}$/.test(u)||/^\*{3,}$/.test(u)||/^_{3,}$/.test(u)){l(),n+=`<hr>`,c++;continue}if(u.startsWith(`|`)){l();let e=[];for(;c<t.length;){let n=t[c],r=n.trim();if(r.startsWith(`|`)||/^[|\-: ]+$/.test(r)&&r.includes(`-`)&&r.includes(`|`))e.push(n),c++;else break}e.length>0&&(n+=xe(e));continue}if(u.startsWith(`> `)){l(),n+=`<blockquote><p>${be(u.slice(2))}</p></blockquote>`,c++;continue}if(/^[-*+] /.test(u)){i&&=(n+=`</ol>`,!1),r||=(n+=`<ul>`,!0),n+=`<li>${be(u.slice(2))}</li>`,c++;continue}{let e=u.match(/^(\d+)[.)]\s(.+)/);if(e){r&&=(n+=`</ul>`,!1),i||=(n+=`<ol>`,!0),n+=`<li>${be(e[2])}</li>`,c++;continue}}if(l(),u===``){n+=`<div style="height:6px"></div>`,c++;continue}n+=`<p>${be(u)}</p>`,c++}return l(),a&&(n+=ye(o)+`</code></pre>`),n}var N={root:`_root_npowj_1`,convSidebar:`_convSidebar_npowj_8`,convSidebarHeader:`_convSidebarHeader_npowj_18`,newConvBtn:`_newConvBtn_npowj_23`,convList:`_convList_npowj_36`,convItem:`_convItem_npowj_41`,convItemActive:`_convItemActive_npowj_48`,convTitle:`_convTitle_npowj_53`,convMeta:`_convMeta_npowj_61`,convDelete:`_convDelete_npowj_69`,chatMain:`_chatMain_npowj_76`,chatToolbar:`_chatToolbar_npowj_85`,convTitleBar:`_convTitleBar_npowj_94`,toolbarBtn:`_toolbarBtn_npowj_103`,toolbarBtnDim:`_toolbarBtnDim_npowj_116`,toolbarBtnCanvas:`_toolbarBtnCanvas_npowj_128`,messages:`_messages_npowj_137`,empty:`_empty_npowj_146`,emptyIcon:`_emptyIcon_npowj_158`,emptyTitle:`_emptyTitle_npowj_159`,emptySub:`_emptySub_npowj_160`,emptyHint:`_emptyHint_npowj_161`,suggGroups:`_suggGroups_npowj_163`,suggGroup:`_suggGroup_npowj_163`,suggGroupTitle:`_suggGroupTitle_npowj_165`,suggBtns:`_suggBtns_npowj_166`,suggBtn:`_suggBtn_npowj_166`,message:`_message_npowj_137`,user:`_user_npowj_178`,assistant:`_assistant_npowj_179`,msgLabel:`_msgLabel_npowj_181`,bubble:`_bubble_npowj_188`,sentinelBubble:`_sentinelBubble_npowj_211`,cursor:`_cursor_npowj_216`,blink:`_blink_npowj_1`,msgActions:`_msgActions_npowj_231`,msgActionBtn:`_msgActionBtn_npowj_240`,editBox:`_editBox_npowj_252`,editInput:`_editInput_npowj_259`,editActions:`_editActions_npowj_272`,editSaveBtn:`_editSaveBtn_npowj_273`,editCancelBtn:`_editCancelBtn_npowj_277`,toolActivity:`_toolActivity_npowj_284`,toolActivityItem:`_toolActivityItem_npowj_290`,active:`_active_npowj_303`,toolPulse:`_toolPulse_npowj_1`,done:`_done_npowj_308`,error:`_error_npowj_309`,thinkingIndicator:`_thinkingIndicator_npowj_317`,thinkingDots:`_thinkingDots_npowj_331`,thinkingDot:`_thinkingDot_npowj_331`,thinkBounce:`_thinkBounce_npowj_1`,attachBar:`_attachBar_npowj_349`,attachClear:`_attachClear_npowj_360`,inputBar:`_inputBar_npowj_371`,inputTools:`_inputTools_npowj_381`,iconBtn:`_iconBtn_npowj_387`,iconBtnActive:`_iconBtnActive_npowj_398`,thinkBtn:`_thinkBtn_npowj_400`,thinkBtnOn:`_thinkBtnOn_npowj_412`,inputRow:`_inputRow_npowj_417`,input:`_input_npowj_371`,btn:`_btn_npowj_436`,send:`_send_npowj_447`,stop:`_stop_npowj_454`,canvasPanel:`_canvasPanel_npowj_461`,canvasPanelHeader:`_canvasPanelHeader_npowj_476`,canvasPanelActions:`_canvasPanelActions_npowj_488`,canvasPanelBtn:`_canvasPanelBtn_npowj_494`,canvasPanelClose:`_canvasPanelClose_npowj_505`,canvasFrame:`_canvasFrame_npowj_516`},Ce={body:`_body_ctbrf_4`,mdCursorBlink:`_mdCursorBlink_ctbrf_1`,compact:`_compact_ctbrf_197`};function we(e){let t=e.replace(/```(?:json|tool|data|xml|csv)[^\n]*\n[\s\S]*?```/g,``).replace(/```[^\n]*\n\s*[{\[]([\s\S]*?)```/g,``).replace(/^```\s*$/gm,``),n=``,r=0,i=!1;for(let e=0;e<t.length;e++){let a=t[e];a===`{`&&(r++,r===1&&/"action"\s*:/.test(t.slice(e,e+80))&&(i=!0)),i||(n+=a),a===`}`&&(r=Math.max(0,r-1),i&&r===0&&(i=!1))}return n.replace(/\n{3,}/g,`
|
|
61
61
|
|
|
62
|
-
`).trim()}var Te={browser_open:`Opening page`,browser_screenshot:`Taking screenshot`,browser_click:`Clicking element`,browser_type:`Typing text`,browser_extract:`Extracting content`,browser_js:`Running JavaScript`,browser_wait:`Waiting for element`,browser_scroll:`Scrolling page`,browser_key:`Pressing key`,browser_close:`Closing browser`,web_search:`Searching the web`,fetch_url:`Fetching URL`,gmail_list:`Searching emails`,gmail_read:`Reading email`,gmail_send:`Sending email`,calendar_today:`Loading calendar`,calendar_create:`Creating event`};function Ee(){let e=j(),[t,n]=(0,_.useState)([]),[r,i]=(0,_.useState)(null),[a,o]=(0,_.useState)([]),[s,c]=(0,_.useState)(()=>localStorage.getItem(`nha_conv_sidebar`)!==`hidden`),[l,u]=(0,_.useState)(``),[d,f]=(0,_.useState)(!1),p=(0,_.useRef)(null),[m,h]=(0,_.useState)(null),[g,v]=(0,_.useState)(null),y=(0,_.useRef)(null),b=(0,_.useRef)(null),[x,S]=(0,_.useState)(!1),[C,w]=(0,_.useState)(!1),ee=(0,_.useRef)(null),[T,ne]=(0,_.useState)(null),[ie,O]=(0,_.useState)(!1),[ae,A]=(0,_.useState)(null),[oe,se]=(0,_.useState)(``),[ce,le]=(0,_.useState)([]),[ue,de]=(0,_.useState)(!1),[M,fe]=(0,_.useState)(!1),pe=(0,_.useRef)(null),me=(0,_.useRef)(null),he=(0,_.useRef)(null);(0,_.useEffect)(()=>{pe.current?.scrollIntoView({behavior:`smooth`})},[a]),(0,_.useEffect)(()=>{E(`/api/config`).then(e=>{e&&(e.thinking===!0||e.thinking===`on`||e.thinking===`true`)&&S(!0)}),ge().then(e=>{e&&e.length>0?_e(e[0].id):ve()});try{let e=sessionStorage.getItem(`nha_chat_prefill`)??sessionStorage.getItem(`nha_studio_import`);e&&(u(e),sessionStorage.removeItem(`nha_chat_prefill`),sessionStorage.removeItem(`nha_studio_import`),setTimeout(()=>me.current?.focus(),100))}catch{}},[]);let ge=(0,_.useCallback)(async()=>{let e=(await E(`/api/conversations`))?.conversations??[];return n(e),e},[]),_e=(0,_.useCallback)(async e=>{let t=await E(`/api/conversations/${e}`);t?.conversation&&(i(t.conversation.id),o(t.conversation.messages??[]))},[]),ve=(0,_.useCallback)(async()=>{let e=await D(`/api/conversations`,{});e?.conversation&&(i(e.conversation.id),o([]),ge())},[ge]),ye=(0,_.useCallback)(async e=>{let t=te.getState().apiBase;await fetch(`${t}/api/conversations/${e}`,{method:`DELETE`}),ge().then(t=>{e===r&&(t.length>0?_e(t[0].id):ve())})},[r,ge,_e,ve]),be=()=>{r&&window.open(`/api/conversations/${r}/export?format=md`,`_blank`)},xe=()=>{let e=!x;S(e),D(`/api/config`,{key:`thinking`,value:e?`on`:`off`}).catch(()=>{})},Ee=()=>{c(e=>{let t=!e;return localStorage.setItem(`nha_conv_sidebar`,t?`visible`:`hidden`),t})},P=e=>{let t=e.target.files?.[0];if(!t)return;let n=t.name.toLowerCase().endsWith(`.pdf`)||t.type===`application/pdf`,r=new FileReader;n?(r.onload=e=>{let n=(e.target?.result).split(`,`)[1];h({name:t.name,size:t.size,base64:n,mimeType:`application/pdf`,isPDF:!0}),v(null)},r.readAsDataURL(t)):(r.onload=e=>{h({name:t.name,size:t.size,content:e.target?.result}),v(null)},r.readAsText(t))},De=e=>{let t=e.target.files?.[0];if(!t)return;let n=new FileReader;n.onload=e=>{let n=(e.target?.result).split(`,`)[1];v({name:t.name,size:t.size,base64:n,mimeType:t.type||`image/jpeg`}),h(null)},n.readAsDataURL(t)},Oe=()=>{h(null),v(null),y.current&&(y.current.value=``),b.current&&(b.current.value=``)},ke=m?`[file] ${m.name} (${Math.round(m.size/1024)}KB)`:g?`[img] ${g.name} (${Math.round(g.size/1024)}KB)`:null,F=()=>{let e=window.SpeechRecognition??window.webkitSpeechRecognition;if(!e){alert(`Speech recognition not supported in this browser.`);return}if(C&&ee.current){ee.current.stop(),w(!1);return}let t=new e;ee.current=t,t.lang=`it-IT`,t.continuous=!1,t.interimResults=!1,t.onresult=e=>{let t=e.results[0][0].transcript;u(e=>e?e+` `+t:t)},t.onend=()=>w(!1),t.onerror=()=>w(!1),t.start(),w(!0)},I=(0,_.useCallback)(async()=>{let t=l.trim(),n=!!(m||g);if(!t&&!n||d)return;let i={role:`user`,content:m?(t?t+` `:``)+`[File: ${m.name}]`:g?(t?t+` `:``)+`[Image: ${g.name}]`:t};if(o(e=>[...e,i]),u(``),n){let n={message:t||`Analyze this attachment`,history:a.map(e=>({role:e.role,content:e.content}))};m?.isPDF&&m.base64?(n.pdfBase64=m.base64,n.pdfName=m.name):m?.content&&(n.fileContent=m.content,n.fileName=m.name),g?.base64&&(n.imageBase64=g.base64,n.imageMimeType=g.mimeType),Oe(),o(t=>[...t,{role:`assistant`,content:e(`chat.thinking`),streaming:!0}]),f(!0);try{let e=await D(`/api/chat`,n);o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:e?.response??(e?.error?`Error: `+e.error:`Error`),streaming:!1}),n}),ge()}catch(e){o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:`Error: `+e.message,streaming:!1}),n})}finally{f(!1)}return}Oe(),f(!0),le([]),de(!1),fe(!0);let s=new AbortController;p.current=s,o(e=>[...e,{role:`assistant`,content:``,streaming:!0}]);let c=a.map(e=>({role:e.role,content:e.content})),h;if(c.length>10){let e=c.slice(0,c.length-10);h=[{role:`user`,content:e.reduce((t,n,r)=>n.role===`user`?t+`\nUser: ${n.content.slice(0,120)}`:r>0&&e[r-1]?.role===`user`?t+` → ${n.content.slice(0,150)}`:t,`[Earlier conversation summary]:`)},{role:`assistant`,content:`Understood, I have context from our earlier conversation.`},...c.slice(-10)]}else h=c;try{let e=``,n=!1,
|
|
62
|
+
`).trim()}var Te={browser_open:`Opening page`,browser_screenshot:`Taking screenshot`,browser_click:`Clicking element`,browser_type:`Typing text`,browser_extract:`Extracting content`,browser_js:`Running JavaScript`,browser_wait:`Waiting for element`,browser_scroll:`Scrolling page`,browser_key:`Pressing key`,browser_close:`Closing browser`,web_search:`Searching the web`,fetch_url:`Fetching URL`,gmail_list:`Searching emails`,gmail_read:`Reading email`,gmail_send:`Sending email`,calendar_today:`Loading calendar`,calendar_create:`Creating event`};function Ee(){let e=j(),[t,n]=(0,_.useState)([]),[r,i]=(0,_.useState)(null),[a,o]=(0,_.useState)([]),[s,c]=(0,_.useState)(()=>localStorage.getItem(`nha_conv_sidebar`)!==`hidden`),[l,u]=(0,_.useState)(``),[d,f]=(0,_.useState)(!1),p=(0,_.useRef)(null),[m,h]=(0,_.useState)(null),[g,v]=(0,_.useState)(null),y=(0,_.useRef)(null),b=(0,_.useRef)(null),[x,S]=(0,_.useState)(!1),[C,w]=(0,_.useState)(!1),ee=(0,_.useRef)(null),[T,ne]=(0,_.useState)(null),[ie,O]=(0,_.useState)(!1),[ae,A]=(0,_.useState)(null),[oe,se]=(0,_.useState)(``),[ce,le]=(0,_.useState)([]),[ue,de]=(0,_.useState)(!1),[M,fe]=(0,_.useState)(!1),pe=(0,_.useRef)(null),me=(0,_.useRef)(null),he=(0,_.useRef)(null);(0,_.useEffect)(()=>{pe.current?.scrollIntoView({behavior:`smooth`})},[a]),(0,_.useEffect)(()=>{E(`/api/config`).then(e=>{e&&(e.thinking===!0||e.thinking===`on`||e.thinking===`true`)&&S(!0)}),ge().then(e=>{e&&e.length>0?_e(e[0].id):ve()});try{let e=sessionStorage.getItem(`nha_chat_prefill`)??sessionStorage.getItem(`nha_studio_import`);e&&(u(e),sessionStorage.removeItem(`nha_chat_prefill`),sessionStorage.removeItem(`nha_studio_import`),setTimeout(()=>me.current?.focus(),100))}catch{}},[]);let ge=(0,_.useCallback)(async()=>{let e=(await E(`/api/conversations`))?.conversations??[];return n(e),e},[]),_e=(0,_.useCallback)(async e=>{let t=await E(`/api/conversations/${e}`);t?.conversation&&(i(t.conversation.id),o(t.conversation.messages??[]))},[]),ve=(0,_.useCallback)(async()=>{let e=await D(`/api/conversations`,{});e?.conversation&&(i(e.conversation.id),o([]),ge())},[ge]),ye=(0,_.useCallback)(async e=>{let t=te.getState().apiBase;await fetch(`${t}/api/conversations/${e}`,{method:`DELETE`}),ge().then(t=>{e===r&&(t.length>0?_e(t[0].id):ve())})},[r,ge,_e,ve]),be=()=>{r&&window.open(`/api/conversations/${r}/export?format=md`,`_blank`)},xe=()=>{let e=!x;S(e),D(`/api/config`,{key:`thinking`,value:e?`on`:`off`}).catch(()=>{})},Ee=()=>{c(e=>{let t=!e;return localStorage.setItem(`nha_conv_sidebar`,t?`visible`:`hidden`),t})},P=e=>{let t=e.target.files?.[0];if(!t)return;let n=t.name.toLowerCase().endsWith(`.pdf`)||t.type===`application/pdf`,r=new FileReader;n?(r.onload=e=>{let n=(e.target?.result).split(`,`)[1];h({name:t.name,size:t.size,base64:n,mimeType:`application/pdf`,isPDF:!0}),v(null)},r.readAsDataURL(t)):(r.onload=e=>{h({name:t.name,size:t.size,content:e.target?.result}),v(null)},r.readAsText(t))},De=e=>{let t=e.target.files?.[0];if(!t)return;let n=new FileReader;n.onload=e=>{let n=(e.target?.result).split(`,`)[1];v({name:t.name,size:t.size,base64:n,mimeType:t.type||`image/jpeg`}),h(null)},n.readAsDataURL(t)},Oe=()=>{h(null),v(null),y.current&&(y.current.value=``),b.current&&(b.current.value=``)},ke=m?`[file] ${m.name} (${Math.round(m.size/1024)}KB)`:g?`[img] ${g.name} (${Math.round(g.size/1024)}KB)`:null,F=()=>{let e=window.SpeechRecognition??window.webkitSpeechRecognition;if(!e){alert(`Speech recognition not supported in this browser.`);return}if(C&&ee.current){ee.current.stop(),w(!1);return}let t=new e;ee.current=t,t.lang=`it-IT`,t.continuous=!1,t.interimResults=!1,t.onresult=e=>{let t=e.results[0][0].transcript;u(e=>e?e+` `+t:t)},t.onend=()=>w(!1),t.onerror=()=>w(!1),t.start(),w(!0)},I=(0,_.useCallback)(async()=>{let t=l.trim(),n=!!(m||g);if(!t&&!n||d)return;let i={role:`user`,content:m?(t?t+` `:``)+`[File: ${m.name}]`:g?(t?t+` `:``)+`[Image: ${g.name}]`:t};if(o(e=>[...e,i]),u(``),n){let n={message:t||`Analyze this attachment`,history:a.map(e=>({role:e.role,content:e.content}))};m?.isPDF&&m.base64?(n.pdfBase64=m.base64,n.pdfName=m.name):m?.content&&(n.fileContent=m.content,n.fileName=m.name),g?.base64&&(n.imageBase64=g.base64,n.imageMimeType=g.mimeType),Oe(),o(t=>[...t,{role:`assistant`,content:e(`chat.thinking`),streaming:!0}]),f(!0);try{let e=await D(`/api/chat`,n);o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:e?.response??(e?.error?`Error: `+e.error:`Error`),streaming:!1}),n}),ge()}catch(e){o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:`Error: `+e.message,streaming:!1}),n})}finally{f(!1)}return}Oe(),f(!0),le([]),de(!1),fe(!0);let s=new AbortController;p.current=s,o(e=>[...e,{role:`assistant`,content:``,streaming:!0}]);let c=a.map(e=>({role:e.role,content:e.content})),h;if(c.length>10){let e=c.slice(0,c.length-10);h=[{role:`user`,content:e.reduce((t,n,r)=>n.role===`user`?t+`\nUser: ${n.content.slice(0,120)}`:r>0&&e[r-1]?.role===`user`?t+` → ${n.content.slice(0,150)}`:t,`[Earlier conversation summary]:`)},{role:`assistant`,content:`Understood, I have context from our earlier conversation.`},...c.slice(-10)]}else h=c;try{let e=``,n=``,i=!1,a=[];await re(`/api/chat/stream`,{message:t,history:h,conversationId:r},t=>{if(t.type===`processing`&&fe(!0),t.type===`token`&&typeof t.data.content==`string`){fe(!1),e+=t.data.content;let r=we(e.replace(/<think>[\s\S]*?<\/think>/g,``)),a=e.includes(`<think>`)&&!e.includes(`</think>`);if(de(a),a)return;let s=i&&n?`${n}\n\n${r}`:r;o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:s}),t})}if(t.type===`tool`){let n=t.data.action,r=t.data.status,i=Te[n]??n,a=r===`executing`?`active`:r===`error`?`error`:`done`;le(e=>{let t=e.findIndex(e=>e.action===n&&e.status===`active`);if(t>=0){let r=[...e];return r[t]={action:n,label:i,status:a},r}return[...e,{action:n,label:i,status:a}]}),r===`executing`&&(e=we(e))}if(t.type===`tool_synthesis`&&(n=we(e.replace(/<think>[\s\S]*?<\/think>/g,``)).trim(),e=``,i=!0,de(!1),fe(!0)),t.type===`screenshot`&&typeof t.data.url==`string`&&a.push(t.data.url),t.type===`canvas`&&typeof t.data.markers==`string`){let e=t.data.markers.match(/\[CANVAS_RENDER\]([\s\S]*?)\[\/CANVAS_RENDER\]/);if(e)try{ne(JSON.parse(e[1]).html),O(!0)}catch{}}if(t.type===`done`){de(!1),fe(!1),le(e=>e.map(e=>e.status===`active`?{...e,status:`done`}:e));let n=t.data.content,r=!!t.data.__sentinel_blocked,i=(n??e).replace(/<think>[\s\S]*?<\/think>/g,``),s=i.match(/\[CANVAS_RENDER\]([\s\S]*?)\[\/CANVAS_RENDER\]/);if(s)try{ne(JSON.parse(s[1]).html),O(!0)}catch{ne(s[1]),O(!0)}if(!s){let e=i.match(/```html\n([\s\S]*?)```/);e&&e[1].includes(`<`)&&(ne(e[1]),O(!0))}let c=a.length>0?`
|
|
63
63
|
|
|
64
|
-
`+
|
|
65
|
-
`):``,l=we(a.replace(/\[CANVAS_RENDER\][\s\S]*?\[\/CANVAS_RENDER\]/g,``).replace(/```html[\s\S]*?```/g,`[Canvas HTML — click Panel to view]`))+c;o(r?e=>{let t=[...e],n=t.findIndex((e,n)=>n===t.length-1&&e.role===`assistant`);return n>=0&&(t[n]={role:`assistant`,content:l||`Message blocked by SENTINEL.`,sentinelBlocked:!0,streaming:!1}),t}:e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:l,streaming:!1}),t}),ge()}t.type===`error`&&o(e=>{let n=[...e],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:`Error: `+(t.data.message??`Unknown`),streaming:!1}),n})},s.signal)}catch(e){e.name!==`AbortError`&&o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:n.content||`Error connecting to server.`,streaming:!1}),t})}finally{de(!1),fe(!1),o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&n.streaming&&(t[t.length-1]={...n,streaming:!1}),t}),f(!1),p.current=null,setTimeout(()=>le([]),2e3)}},[l,a,d,m,g,r,ge]),Ae=()=>{p.current?.abort(),f(!1)},je=e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),I())},Me=e=>{navigator.clipboard.writeText(e.replace(/\[CANVAS_RENDER\][\s\S]*?\[\/CANVAS_RENDER\]/g,``).trim()).catch(()=>{})},Ne=(0,_.useCallback)(async t=>{if(d)return;let n=t-1;if(n<0||a[n]?.role!==`user`)return;let i=a[n],s=a.slice(0,n).map(e=>({role:e.role,content:e.content}));o(e=>{let n=[...e];return n[t]={role:`assistant`,content:``,streaming:!0},n.slice(0,t+1)}),f(!0);let c=new AbortController;p.current=c;let l=``;try{await re(`/api/chat/stream`,{message:i.content,history:s,conversationId:r},t=>{if(t.type===`token`&&typeof t.data.content==`string`){l+=t.data.content;let n=l;n=n.includes(`<think>`)&&!n.includes(`</think>`)?`💭 `+e(`chat.thinking`):we(n.replace(/<think>[\s\S]*?<\/think>/g,``)),o(e=>{let t=[...e],r=t[t.length-1];return r?.role===`assistant`&&(t[t.length-1]={...r,content:n}),t})}if(t.type===`tool_synthesis`&&(l=``,o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:``}),t})),t.type===`done`){let e=we((t.data.content??l).replace(/<think>[\s\S]*?<\/think>/g,``));o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:e,streaming:!1}),n}),ge()}},c.signal)}catch{}finally{f(!1),p.current=null}},[d,a,r,ge,e]),Pe=e=>{d||(A(e),se(a[e].content))},Fe=(0,_.useCallback)(async()=>{if(ae===null)return;let t=oe.trim();if(!t)return;let n=a.slice(0,ae).map(e=>({role:e.role,content:e.content}));o(e=>{let n=e.slice(0,ae);return n.push({role:`user`,content:t}),n.push({role:`assistant`,content:``,streaming:!0}),n}),A(null),se(``),f(!0);let i=new AbortController;p.current=i;let s=``;try{await re(`/api/chat/stream`,{message:t,history:n,conversationId:r},t=>{if(t.type===`token`&&typeof t.data.content==`string`){s+=t.data.content;let n=s;n=n.includes(`<think>`)&&!n.includes(`</think>`)?`💭 `+e(`chat.thinking`):we(n.replace(/<think>[\s\S]*?<\/think>/g,``)),o(e=>{let t=[...e],r=t[t.length-1];return r?.role===`assistant`&&(t[t.length-1]={...r,content:n}),t})}if(t.type===`tool_synthesis`&&(s=``,o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:``}),t})),t.type===`done`){let e=we((t.data.content??s).replace(/<think>[\s\S]*?<\/think>/g,``));o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:e,streaming:!1}),n}),ge()}},i.signal)}catch{}finally{f(!1),p.current=null}},[ae,oe,a,r,ge,e]);return(0,k.jsxs)(`div`,{className:N.root,children:[s&&(0,k.jsxs)(`div`,{className:N.convSidebar,children:[(0,k.jsx)(`div`,{className:N.convSidebarHeader,children:(0,k.jsxs)(`button`,{className:N.newConvBtn,onClick:ve,children:[`+ `,e(`chat.newChat`)]})}),(0,k.jsx)(`div`,{className:N.convList,children:t.map(t=>{let n=Math.floor(t.messageCount/2),i=t.id===r;return(0,k.jsxs)(`div`,{className:`${N.convItem} ${i?N.convItemActive:``}`,onClick:()=>_e(t.id),children:[(0,k.jsx)(`div`,{className:N.convTitle,children:t.title||e(`chat.newChat`)}),(0,k.jsxs)(`div`,{className:N.convMeta,children:[(0,k.jsxs)(`span`,{children:[n,` turns`]}),!i&&(0,k.jsx)(`span`,{className:N.convDelete,onClick:e=>{e.stopPropagation(),ye(t.id)},children:`del`})]})]},t.id)})})]}),(0,k.jsxs)(`div`,{className:N.chatMain,children:[(0,k.jsxs)(`div`,{className:N.chatToolbar,children:[(0,k.jsx)(`button`,{className:N.toolbarBtn,onClick:Ee,title:`Toggle conversations`,children:`💬 Chats`}),(0,k.jsx)(`span`,{className:N.convTitleBar,children:t.find(e=>e.id===r)?.title||e(`chat.newChat`)}),(0,k.jsx)(`button`,{className:N.toolbarBtn,onClick:ve,children:`+ New`}),(0,k.jsx)(`button`,{className:N.toolbarBtnDim,onClick:be,title:`Export Markdown`,children:`Export`}),T&&(0,k.jsx)(`button`,{className:`${N.toolbarBtn} ${N.toolbarBtnCanvas}`,onClick:()=>O(e=>!e),title:`Toggle canvas panel`,children:ie?`▣ Panel ✕`:`▣ Panel`})]}),(0,k.jsxs)(`div`,{className:N.messages,ref:he,children:[a.length===0&&(0,k.jsxs)(`div`,{className:N.empty,children:[(0,k.jsx)(`div`,{className:N.emptyIcon,children:`💬`}),(0,k.jsx)(`div`,{className:N.emptyTitle,children:`NHA Chat`}),(0,k.jsx)(`div`,{className:N.emptySub,children:`Personal Operations Assistant · 80 Tools · 38 Agents · Free AI`}),(0,k.jsxs)(`div`,{className:N.suggGroups,children:[(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`⚡ Quick Actions`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`Show my unread emails and summarize the most important ones`,`What's on my calendar today? Any meetings I need to prepare for?`,`List my pending tasks sorted by priority`,`Check my GitHub notifications and summarize open issues`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]}),(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`🌐 Web & Research`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`Search the web for the latest AI news and summarize the top 5 stories`,`Open google.com and take a screenshot of the homepage`,`Search for the best restaurants near me and create a summary`,`Research the latest developments in quantum computing and write a report`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]}),(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`🛠️ Productivity`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`Draft a professional reply to my last email`,`Create a new calendar event for tomorrow at 10am with reminder`,`Summarize my notes and create a to-do list from action items`,`Find contacts named Mario and show their details`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]}),(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`📈 Finance`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`What is the current price of Bitcoin and its 24h performance?`,`Analyze the current macro environment and suggest 3 trading opportunities`,`What is the current market regime? Risk-on or risk-off?`,`Give me a technical analysis of AAPL with key support/resistance levels`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]})]})]}),a.map((e,t)=>(0,k.jsxs)(`div`,{className:`${N.message} ${N[e.role]}`,children:[(0,k.jsx)(`div`,{className:N.msgLabel,children:e.role===`user`?`You`:`NHA`}),e.role===`assistant`&&e.streaming&&(0,k.jsxs)(`div`,{className:N.toolActivity,children:[(M||e.content===``&&!ue&&ce.length===0)&&(0,k.jsxs)(`div`,{className:N.thinkingIndicator,children:[(0,k.jsxs)(`div`,{className:N.thinkingDots,children:[(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot})]}),ue?`Deep thinking...`:`Generating...`]}),ue&&!M&&(0,k.jsxs)(`div`,{className:N.thinkingIndicator,children:[(0,k.jsxs)(`div`,{className:N.thinkingDots,children:[(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot})]}),`Deep thinking...`]}),ce.map((e,t)=>(0,k.jsxs)(`div`,{className:`${N.toolActivityItem} ${N[e.status]}`,children:[e.status===`active`?`⏳`:e.status===`error`?`❌`:`✅`,` `,e.label,e.status===`active`&&`...`]},t))]}),e.role===`user`&&ae===t?(0,k.jsxs)(`div`,{className:N.editBox,children:[(0,k.jsx)(`textarea`,{className:N.editInput,value:oe,onChange:e=>se(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),Fe()),e.key===`Escape`&&A(null)},autoFocus:!0,rows:3}),(0,k.jsxs)(`div`,{className:N.editActions,children:[(0,k.jsx)(`button`,{className:N.editSaveBtn,onClick:Fe,children:`Send ↵`}),(0,k.jsx)(`button`,{className:N.editCancelBtn,onClick:()=>A(null),children:`Cancel`})]})]}):e.role===`assistant`?e.content!==``&&(0,k.jsx)(`div`,{className:`${N.bubble} ${Ce.body} ${e.sentinelBlocked?N.sentinelBubble:``}`,dangerouslySetInnerHTML:{__html:Se(e.content)}}):(0,k.jsx)(`div`,{className:N.bubble,children:e.content}),e.streaming&&(0,k.jsx)(`span`,{className:N.cursor}),!e.streaming&&ae!==t&&(0,k.jsxs)(`div`,{className:N.msgActions,children:[(0,k.jsx)(`button`,{className:N.msgActionBtn,onClick:()=>Me(e.content),children:`Copy`}),e.role===`user`&&!d&&(0,k.jsx)(`button`,{className:N.msgActionBtn,onClick:()=>Pe(t),children:`Edit`}),e.role===`assistant`&&!d&&(0,k.jsx)(`button`,{className:N.msgActionBtn,onClick:()=>Ne(t),children:`Retry`})]})]},t)),(0,k.jsx)(`div`,{ref:pe})]}),ke&&(0,k.jsxs)(`div`,{className:N.attachBar,children:[(0,k.jsx)(`span`,{children:ke}),(0,k.jsx)(`button`,{className:N.attachClear,onClick:Oe,children:`×`})]}),(0,k.jsxs)(`div`,{className:N.inputBar,children:[(0,k.jsxs)(`div`,{className:N.inputTools,children:[(0,k.jsx)(`button`,{className:`${N.iconBtn} ${C?N.iconBtnActive:``}`,onClick:F,title:`Voice input`,children:`🎤`}),(0,k.jsx)(`button`,{className:N.iconBtn,onClick:()=>y.current?.click(),title:`Attach file`,children:`📎`}),(0,k.jsx)(`button`,{className:N.iconBtn,onClick:()=>b.current?.click(),title:`Attach image`,children:`🖼`}),(0,k.jsx)(`input`,{ref:y,type:`file`,style:{display:`none`},onChange:P}),(0,k.jsx)(`input`,{ref:b,type:`file`,accept:`image/*`,style:{display:`none`},onChange:De}),(0,k.jsx)(`span`,{style:{flex:1}}),(0,k.jsxs)(`button`,{className:`${N.thinkBtn} ${x?N.thinkBtnOn:``}`,onClick:xe,title:`Extended Thinking`,children:[`Think: `,x?`on`:`off`]}),T&&(0,k.jsx)(`button`,{className:N.toolbarBtn,onClick:()=>O(e=>!e),title:`Canvas panel`,children:`▣ Panel`})]}),(0,k.jsxs)(`div`,{className:N.inputRow,children:[(0,k.jsx)(`textarea`,{ref:me,className:N.input,value:l,onChange:e=>u(e.target.value),onKeyDown:je,placeholder:e(`chat.placeholder`),rows:1,disabled:d}),d?(0,k.jsxs)(`button`,{className:`${N.btn} ${N.stop}`,onClick:Ae,children:[`■ `,e(`chat.stopGeneration`)]}):(0,k.jsx)(`button`,{className:`${N.btn} ${N.send}`,onClick:I,disabled:!l.trim()&&!m&&!g,children:`Send ↵`})]})]})]}),ie&&T&&(0,k.jsxs)(`div`,{className:N.canvasPanel,children:[(0,k.jsxs)(`div`,{className:N.canvasPanelHeader,children:[(0,k.jsx)(`span`,{children:`Canvas`}),(0,k.jsxs)(`div`,{className:N.canvasPanelActions,children:[(0,k.jsx)(`button`,{className:N.canvasPanelBtn,onClick:()=>{let e=new Blob([T],{type:`text/html`}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`NHA-Canvas.html`,n.click(),setTimeout(()=>URL.revokeObjectURL(t),5e3)},children:`↓ Download`}),(0,k.jsx)(`button`,{className:N.canvasPanelBtn,onClick:()=>navigator.clipboard.writeText(T).catch(()=>{}),children:`Copy HTML`}),(0,k.jsx)(`button`,{className:N.canvasPanelClose,onClick:()=>O(!1),children:`×`})]})]}),(0,k.jsx)(`iframe`,{className:N.canvasFrame,sandbox:`allow-scripts`,srcDoc:T,title:`Canvas`})]})]})}var P={root:`_root_1899x_1`,header:`_header_1899x_8`,headerLeft:`_headerLeft_1899x_19`,title:`_title_1899x_21`,subtitle:`_subtitle_1899x_28`,headerActions:`_headerActions_1899x_34`,tokenBar:`_tokenBar_1899x_41`,tokIn:`_tokIn_1899x_49`,tokOut:`_tokOut_1899x_50`,tokTotal:`_tokTotal_1899x_51`,tokDim:`_tokDim_1899x_52`,sessionsBtn:`_sessionsBtn_1899x_54`,pdfBtn:`_pdfBtn_1899x_66`,clearBtn:`_clearBtn_1899x_76`,sessionsDrawer:`_sessionsDrawer_1899x_89`,noSessions:`_noSessions_1899x_104`,sessionItem:`_sessionItem_1899x_111`,sessionInfo:`_sessionInfo_1899x_121`,sessionTask:`_sessionTask_1899x_127`,sessionMeta:`_sessionMeta_1899x_137`,sessionBtns:`_sessionBtns_1899x_143`,importBtn:`_importBtn_1899x_149`,delSessionBtn:`_delSessionBtn_1899x_159`,sessionsFooter:`_sessionsFooter_1899x_169`,clearAllSessionsBtn:`_clearAllSessionsBtn_1899x_176`,inputArea:`_inputArea_1899x_189`,inputRow:`_inputRow_1899x_198`,taskInput:`_taskInput_1899x_204`,inputControls:`_inputControls_1899x_219`,runBtn:`_runBtn_1899x_225`,stopBtn:`_stopBtn_1899x_238`,attachBtn:`_attachBtn_1899x_249`,attachBadge:`_attachBadge_1899x_262`,clearAttach:`_clearAttach_1899x_275`,examples:`_examples_1899x_284`,exampleBtn:`_exampleBtn_1899x_290`,body:`_body_1899x_308`,agentChip:`_agentChip_1899x_321`,chip_running:`_chip_running_1899x_332`,charCardPulse:`_charCardPulse_1899x_1`,chip_done:`_chip_done_1899x_338`,chip_error:`_chip_error_1899x_339`,chip_waiting:`_chip_waiting_1899x_340`,chipIcon:`_chipIcon_1899x_341`,chipLabel:`_chipLabel_1899x_342`,chipDots:`_chipDots_1899x_343`,chipCheck:`_chipCheck_1899x_344`,chipErr:`_chipErr_1899x_345`,officeSceneWrap:`_officeSceneWrap_1899x_348`,pipeline:`_pipeline_1899x_358`,pipelineWrap:`_pipelineWrap_1899x_373`,pipelineRunning:`_pipelineRunning_1899x_383`,scanSweep:`_scanSweep_1899x_1`,pipelineTitle:`_pipelineTitle_1899x_409`,pipelineNodes:`_pipelineNodes_1899x_417`,pipelineStep:`_pipelineStep_1899x_424`,arrow:`_arrow_1899x_430`,arrowActive:`_arrowActive_1899x_439`,arrowPulse:`_arrowPulse_1899x_1`,agentChar:`_agentChar_1899x_451`,charWaiting:`_charWaiting_1899x_466`,charActive:`_charActive_1899x_471`,charDone:`_charDone_1899x_479`,charError:`_charError_1899x_484`,orbitRing1:`_orbitRing1_1899x_495`,orbitRing2:`_orbitRing2_1899x_496`,orbitSpin1:`_orbitSpin1_1899x_1`,orbitSpin2:`_orbitSpin2_1899x_1`,charAvatar:`_charAvatar_1899x_542`,charIcon:`_charIcon_1899x_557`,iconBob:`_iconBob_1899x_1`,charCheck:`_charCheck_1899x_574`,badgePop:`_badgePop_1899x_1`,charErr:`_charErr_1899x_484`,charPulse:`_charPulse_1899x_618`,charPulse2:`_charPulse2_1899x_619`,expandRing:`_expandRing_1899x_1`,charLabel:`_charLabel_1899x_638`,charStatus:`_charStatus_1899x_650`,charStatusDots:`_charStatusDots_1899x_663`,dot1:`_dot1_1899x_664`,dot2:`_dot2_1899x_664`,dot3:`_dot3_1899x_664`,dotFade:`_dotFade_1899x_1`,twoCol:`_twoCol_1899x_678`,panelTitle:`_panelTitle_1899x_685`,logPanel:`_logPanel_1899x_695`,logBody:`_logBody_1899x_707`,logEntry:`_logEntry_1899x_715`,logTime:`_logTime_1899x_725`,logIcon:`_logIcon_1899x_726`,logAgent:`_logAgent_1899x_727`,logText:`_logText_1899x_728`,log_system:`_log_system_1899x_730`,log_error:`_log_error_1899x_731`,liveOutputPanel:`_liveOutputPanel_1899x_734`,liveBlock:`_liveBlock_1899x_741`,blockSlideIn:`_blockSlideIn_1899x_1`,liveBlockActive:`_liveBlockActive_1899x_755`,liveBlockScan:`_liveBlockScan_1899x_1`,liveBlockHeader:`_liveBlockHeader_1899x_780`,liveBlockIcon:`_liveBlockIcon_1899x_789`,liveBlockLabel:`_liveBlockLabel_1899x_791`,outputStatus:`_outputStatus_1899x_799`,status_done:`_status_done_1899x_810`,status_running:`_status_running_1899x_811`,status_error:`_status_error_1899x_812`,status_waiting:`_status_waiting_1899x_813`,liveBlockBody:`_liveBlockBody_1899x_816`,liveBlockWorking:`_liveBlockWorking_1899x_954`,workingDot:`_workingDot_1899x_961`,workingBounce:`_workingBounce_1899x_1`,workingLabel:`_workingLabel_1899x_978`,workingFade:`_workingFade_1899x_1`,studioBlinkCursor:`_studioBlinkCursor_1899x_1`,resultAccordion:`_resultAccordion_1899x_1007`,resultAccordionSummary:`_resultAccordionSummary_1899x_1014`,resultAccordionBody:`_resultAccordionBody_1899x_1031`,financeSection:`_financeSection_1899x_1065`,financeSectionTitle:`_financeSectionTitle_1899x_1073`,financePresets:`_financePresets_1899x_1082`,financeBtn:`_financeBtn_1899x_1088`,canvasToggleBtn:`_canvasToggleBtn_1899x_1106`,canvasPanel:`_canvasPanel_1899x_1122`,canvasPanelHeader:`_canvasPanelHeader_1899x_1137`,canvasPanelActions:`_canvasPanelActions_1899x_1149`,canvasPanelBtn:`_canvasPanelBtn_1899x_1155`,canvasPanelClose:`_canvasPanelClose_1899x_1167`,canvasFrame:`_canvasFrame_1899x_1178`,pipelineLiveTag:`_pipelineLiveTag_1899x_1186`,liveTagBlink:`_liveTagBlink_1899x_1`,reasonRow:`_reasonRow_1899x_1200`,reasonChip:`_reasonChip_1899x_1209`,reasonIcon:`_reasonIcon_1899x_1222`,reasonText:`_reasonText_1899x_1223`,liveBlockReason:`_liveBlockReason_1899x_1226`,councilWrapper:`_councilWrapper_1899x_1236`,councilPanel:`_councilPanel_1899x_1241`,councilHeader:`_councilHeader_1899x_1249`,councilHeaderLeft:`_councilHeaderLeft_1899x_1260`,councilHeaderRight:`_councilHeaderRight_1899x_1266`,councilIcon:`_councilIcon_1899x_1272`,councilTitle:`_councilTitle_1899x_1274`,councilConvergedBadge:`_councilConvergedBadge_1899x_1283`,councilDivergedBadge:`_councilDivergedBadge_1899x_1295`,councilPhaseTag:`_councilPhaseTag_1899x_1307`,councilPhaseActive:`_councilPhaseActive_1899x_1313`,phaseGlow:`_phaseGlow_1899x_1`,councilPhaseDone:`_councilPhaseDone_1899x_1322`,councilMetrics:`_councilMetrics_1899x_1325`,convRow:`_convRow_1899x_1333`,convLabel:`_convLabel_1899x_1339`,convTrack:`_convTrack_1899x_1347`,convFill:`_convFill_1899x_1355`,convPct:`_convPct_1899x_1361`,councilNodes:`_councilNodes_1899x_1371`,councilSectionTitle:`_councilSectionTitle_1899x_1376`,councilNode:`_councilNode_1899x_1371`,councilNodeHeader:`_councilNodeHeader_1899x_1393`,councilNodeIcon:`_councilNodeIcon_1899x_1406`,councilNodeLabel:`_councilNodeLabel_1899x_1407`,councilNodeToggle:`_councilNodeToggle_1899x_1408`,councilNodeBody:`_councilNodeBody_1899x_1410`,councilSynthesis:`_councilSynthesis_1899x_1420`,councilSynthesisHeader:`_councilSynthesisHeader_1899x_1424`,heraldIcon:`_heraldIcon_1899x_1433`,heraldLabel:`_heraldLabel_1899x_1435`,heraldStreaming:`_heraldStreaming_1899x_1443`,councilSynthesisBody:`_councilSynthesisBody_1899x_1445`,councilSkipped:`_councilSkipped_1899x_1475`,councilSkipIcon:`_councilSkipIcon_1899x_1486`,charSpriteRunning:`_charSpriteRunning_1899x_1499`,spriteWalk:`_spriteWalk_1899x_1`,charSpriteDone:`_charSpriteDone_1899x_1508`,charScanline:`_charScanline_1899x_1512`,scanlineScroll:`_scanlineScroll_1899x_1`,auraAnim:`_auraAnim_1899x_1532`,auraGlow:`_auraGlow_1899x_1`,parliamentPrompt:`_parliamentPrompt_1899x_1539`,parliamentPromptIcon:`_parliamentPromptIcon_1899x_1549`,parliamentPromptContent:`_parliamentPromptContent_1899x_1550`,parliamentPromptTitle:`_parliamentPromptTitle_1899x_1551`,parliamentPromptDesc:`_parliamentPromptDesc_1899x_1552`,parliamentPromptMeta:`_parliamentPromptMeta_1899x_1553`,parliamentPromptBtns:`_parliamentPromptBtns_1899x_1554`,parliamentActivateBtn:`_parliamentActivateBtn_1899x_1555`,parliamentSkipBtn:`_parliamentSkipBtn_1899x_1562`,panelTabs:`_panelTabs_1899x_1570`,panelTabBtn:`_panelTabBtn_1899x_1571`,panelTabActive:`_panelTabActive_1899x_1578`,panelEmpty:`_panelEmpty_1899x_1580`,browserPanel:`_browserPanel_1899x_1589`,browserBar:`_browserBar_1899x_1590`,browserInput:`_browserInput_1899x_1591`,browserGo:`_browserGo_1899x_1598`,liveBlockClickable:`_liveBlockClickable_1899x_1605`,liveBlockBodyClamped:`_liveBlockBodyClamped_1899x_1614`,expandHint:`_expandHint_1899x_1621`,blockModalOverlay:`_blockModalOverlay_1899x_1630`,blockModal:`_blockModal_1899x_1630`,blockModalHeader:`_blockModalHeader_1899x_1655`,blockModalTitle:`_blockModalTitle_1899x_1665`,blockModalClose:`_blockModalClose_1899x_1673`,blockModalBody:`_blockModalBody_1899x_1685`},De=[{label:`📈 Full Trading Strategy`,task:`You are a team of senior quantitative analysts and macro traders. Build a complete, actionable trading strategy with the following structure:
|
|
64
|
+
`+a.map(e=>``).join(`
|
|
65
|
+
`):``,l=we(i.replace(/\[CANVAS_RENDER\][\s\S]*?\[\/CANVAS_RENDER\]/g,``).replace(/```html[\s\S]*?```/g,`[Canvas HTML — click Panel to view]`))+c;o(r?e=>{let t=[...e],n=t.findIndex((e,n)=>n===t.length-1&&e.role===`assistant`);return n>=0&&(t[n]={role:`assistant`,content:l||`Message blocked by SENTINEL.`,sentinelBlocked:!0,streaming:!1}),t}:e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:l,streaming:!1}),t}),ge()}t.type===`error`&&o(e=>{let n=[...e],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:`Error: `+(t.data.message??`Unknown`),streaming:!1}),n})},s.signal)}catch(e){e.name!==`AbortError`&&o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:n.content||`Error connecting to server.`,streaming:!1}),t})}finally{de(!1),fe(!1),o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&n.streaming&&(t[t.length-1]={...n,streaming:!1}),t}),f(!1),p.current=null,setTimeout(()=>le([]),2e3)}},[l,a,d,m,g,r,ge]),Ae=()=>{p.current?.abort(),f(!1)},je=e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),I())},Me=e=>{navigator.clipboard.writeText(e.replace(/\[CANVAS_RENDER\][\s\S]*?\[\/CANVAS_RENDER\]/g,``).trim()).catch(()=>{})},Ne=(0,_.useCallback)(async t=>{if(d)return;let n=t-1;if(n<0||a[n]?.role!==`user`)return;let i=a[n],s=a.slice(0,n).map(e=>({role:e.role,content:e.content}));o(e=>{let n=[...e];return n[t]={role:`assistant`,content:``,streaming:!0},n.slice(0,t+1)}),f(!0);let c=new AbortController;p.current=c;let l=``,u=``,m=!1;try{await re(`/api/chat/stream`,{message:i.content,history:s,conversationId:r,isRetry:!0},t=>{if(t.type===`token`&&typeof t.data.content==`string`){l+=t.data.content;let n=we(l.replace(/<think>[\s\S]*?<\/think>/g,``)),r=l.includes(`<think>`)&&!l.includes(`</think>`)?`💭 `+e(`chat.thinking`):m&&u?`${u}\n\n${n}`:n;o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:r}),t})}if(t.type===`tool_synthesis`&&(u=we(l.replace(/<think>[\s\S]*?<\/think>/g,``)).trim(),l=``,m=!0),t.type===`done`){let e=we((t.data.content??l).replace(/<think>[\s\S]*?<\/think>/g,``));o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:e,streaming:!1}),n}),ge()}},c.signal)}catch{}finally{f(!1),p.current=null}},[d,a,r,ge,e]),Pe=e=>{d||(A(e),se(a[e].content))},Fe=(0,_.useCallback)(async()=>{if(ae===null)return;let t=oe.trim();if(!t)return;let n=a.slice(0,ae).map(e=>({role:e.role,content:e.content}));o(e=>{let n=e.slice(0,ae);return n.push({role:`user`,content:t}),n.push({role:`assistant`,content:``,streaming:!0}),n}),A(null),se(``),f(!0);let i=new AbortController;p.current=i;let s=``,c=``,l=!1;try{await re(`/api/chat/stream`,{message:t,history:n,conversationId:r,isEdit:!0,editFromIdx:ae},t=>{if(t.type===`token`&&typeof t.data.content==`string`){s+=t.data.content;let n=we(s.replace(/<think>[\s\S]*?<\/think>/g,``)),r=s.includes(`<think>`)&&!s.includes(`</think>`)?`💭 `+e(`chat.thinking`):l&&c?`${c}\n\n${n}`:n;o(e=>{let t=[...e],n=t[t.length-1];return n?.role===`assistant`&&(t[t.length-1]={...n,content:r}),t})}if(t.type===`tool_synthesis`&&(c=we(s.replace(/<think>[\s\S]*?<\/think>/g,``)).trim(),s=``,l=!0),t.type===`done`){let e=we((t.data.content??s).replace(/<think>[\s\S]*?<\/think>/g,``));o(t=>{let n=[...t],r=n[n.length-1];return r?.role===`assistant`&&(n[n.length-1]={...r,content:e,streaming:!1}),n}),ge()}},i.signal)}catch{}finally{f(!1),p.current=null}},[ae,oe,a,r,ge,e]);return(0,k.jsxs)(`div`,{className:N.root,children:[s&&(0,k.jsxs)(`div`,{className:N.convSidebar,children:[(0,k.jsx)(`div`,{className:N.convSidebarHeader,children:(0,k.jsxs)(`button`,{className:N.newConvBtn,onClick:ve,children:[`+ `,e(`chat.newChat`)]})}),(0,k.jsx)(`div`,{className:N.convList,children:t.map(t=>{let n=Math.floor(t.messageCount/2),i=t.id===r;return(0,k.jsxs)(`div`,{className:`${N.convItem} ${i?N.convItemActive:``}`,onClick:()=>_e(t.id),children:[(0,k.jsx)(`div`,{className:N.convTitle,children:t.title||e(`chat.newChat`)}),(0,k.jsxs)(`div`,{className:N.convMeta,children:[(0,k.jsxs)(`span`,{children:[n,` turns`]}),!i&&(0,k.jsx)(`span`,{className:N.convDelete,onClick:e=>{e.stopPropagation(),ye(t.id)},children:`del`})]})]},t.id)})})]}),(0,k.jsxs)(`div`,{className:N.chatMain,children:[(0,k.jsxs)(`div`,{className:N.chatToolbar,children:[(0,k.jsx)(`button`,{className:N.toolbarBtn,onClick:Ee,title:`Toggle conversations`,children:`💬 Chats`}),(0,k.jsx)(`span`,{className:N.convTitleBar,children:t.find(e=>e.id===r)?.title||e(`chat.newChat`)}),(0,k.jsx)(`button`,{className:N.toolbarBtn,onClick:ve,children:`+ New`}),(0,k.jsx)(`button`,{className:N.toolbarBtnDim,onClick:be,title:`Export Markdown`,children:`Export`}),T&&(0,k.jsx)(`button`,{className:`${N.toolbarBtn} ${N.toolbarBtnCanvas}`,onClick:()=>O(e=>!e),title:`Toggle canvas panel`,children:ie?`▣ Panel ✕`:`▣ Panel`})]}),(0,k.jsxs)(`div`,{className:N.messages,ref:he,children:[a.length===0&&(0,k.jsxs)(`div`,{className:N.empty,children:[(0,k.jsx)(`div`,{className:N.emptyIcon,children:`💬`}),(0,k.jsx)(`div`,{className:N.emptyTitle,children:`NHA Chat`}),(0,k.jsx)(`div`,{className:N.emptySub,children:`Personal Operations Assistant · 80 Tools · 38 Agents · Free AI`}),(0,k.jsxs)(`div`,{className:N.suggGroups,children:[(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`⚡ Quick Actions`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`Show my unread emails and summarize the most important ones`,`What's on my calendar today? Any meetings I need to prepare for?`,`List my pending tasks sorted by priority`,`Check my GitHub notifications and summarize open issues`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]}),(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`🌐 Web & Research`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`Search the web for the latest AI news and summarize the top 5 stories`,`Open google.com and take a screenshot of the homepage`,`Search for the best restaurants near me and create a summary`,`Research the latest developments in quantum computing and write a report`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]}),(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`🛠️ Productivity`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`Draft a professional reply to my last email`,`Create a new calendar event for tomorrow at 10am with reminder`,`Summarize my notes and create a to-do list from action items`,`Find contacts named Mario and show their details`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]}),(0,k.jsxs)(`div`,{className:N.suggGroup,children:[(0,k.jsx)(`div`,{className:N.suggGroupTitle,children:`📈 Finance`}),(0,k.jsx)(`div`,{className:N.suggBtns,children:[`What is the current price of Bitcoin and its 24h performance?`,`Analyze the current macro environment and suggest 3 trading opportunities`,`What is the current market regime? Risk-on or risk-off?`,`Give me a technical analysis of AAPL with key support/resistance levels`].map(e=>(0,k.jsx)(`button`,{className:N.suggBtn,onClick:()=>u(e),children:e},e))})]})]})]}),a.map((e,t)=>(0,k.jsxs)(`div`,{className:`${N.message} ${N[e.role]}`,children:[(0,k.jsx)(`div`,{className:N.msgLabel,children:e.role===`user`?`You`:`NHA`}),e.role===`assistant`&&e.streaming&&(0,k.jsxs)(`div`,{className:N.toolActivity,children:[(M||e.content===``&&!ue&&ce.length===0)&&(0,k.jsxs)(`div`,{className:N.thinkingIndicator,children:[(0,k.jsxs)(`div`,{className:N.thinkingDots,children:[(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot})]}),ue?`Deep thinking...`:`Generating...`]}),ue&&!M&&(0,k.jsxs)(`div`,{className:N.thinkingIndicator,children:[(0,k.jsxs)(`div`,{className:N.thinkingDots,children:[(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot}),(0,k.jsx)(`div`,{className:N.thinkingDot})]}),`Deep thinking...`]}),ce.map((e,t)=>(0,k.jsxs)(`div`,{className:`${N.toolActivityItem} ${N[e.status]}`,children:[e.status===`active`?`⏳`:e.status===`error`?`❌`:`✅`,` `,e.label,e.status===`active`&&`...`]},t))]}),e.role===`user`&&ae===t?(0,k.jsxs)(`div`,{className:N.editBox,children:[(0,k.jsx)(`textarea`,{className:N.editInput,value:oe,onChange:e=>se(e.target.value),onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),Fe()),e.key===`Escape`&&A(null)},autoFocus:!0,rows:3}),(0,k.jsxs)(`div`,{className:N.editActions,children:[(0,k.jsx)(`button`,{className:N.editSaveBtn,onClick:Fe,children:`Send ↵`}),(0,k.jsx)(`button`,{className:N.editCancelBtn,onClick:()=>A(null),children:`Cancel`})]})]}):e.role===`assistant`?e.content!==``&&(0,k.jsx)(`div`,{className:`${N.bubble} ${Ce.body} ${e.sentinelBlocked?N.sentinelBubble:``}`,dangerouslySetInnerHTML:{__html:Se(e.content)}}):(0,k.jsx)(`div`,{className:N.bubble,children:e.content}),e.streaming&&(0,k.jsx)(`span`,{className:N.cursor}),!e.streaming&&ae!==t&&(0,k.jsxs)(`div`,{className:N.msgActions,children:[(0,k.jsx)(`button`,{className:N.msgActionBtn,onClick:()=>Me(e.content),children:`Copy`}),e.role===`user`&&!d&&(0,k.jsx)(`button`,{className:N.msgActionBtn,onClick:()=>Pe(t),children:`Edit`}),e.role===`assistant`&&!d&&(0,k.jsx)(`button`,{className:N.msgActionBtn,onClick:()=>Ne(t),children:`Retry`})]})]},t)),(0,k.jsx)(`div`,{ref:pe})]}),ke&&(0,k.jsxs)(`div`,{className:N.attachBar,children:[(0,k.jsx)(`span`,{children:ke}),(0,k.jsx)(`button`,{className:N.attachClear,onClick:Oe,children:`×`})]}),(0,k.jsxs)(`div`,{className:N.inputBar,children:[(0,k.jsxs)(`div`,{className:N.inputTools,children:[(0,k.jsx)(`button`,{className:`${N.iconBtn} ${C?N.iconBtnActive:``}`,onClick:F,title:`Voice input`,children:`🎤`}),(0,k.jsx)(`button`,{className:N.iconBtn,onClick:()=>y.current?.click(),title:`Attach file`,children:`📎`}),(0,k.jsx)(`button`,{className:N.iconBtn,onClick:()=>b.current?.click(),title:`Attach image`,children:`🖼`}),(0,k.jsx)(`input`,{ref:y,type:`file`,style:{display:`none`},onChange:P}),(0,k.jsx)(`input`,{ref:b,type:`file`,accept:`image/*`,style:{display:`none`},onChange:De}),(0,k.jsx)(`span`,{style:{flex:1}}),(0,k.jsxs)(`button`,{className:`${N.thinkBtn} ${x?N.thinkBtnOn:``}`,onClick:xe,title:`Extended Thinking`,children:[`Think: `,x?`on`:`off`]}),T&&(0,k.jsx)(`button`,{className:N.toolbarBtn,onClick:()=>O(e=>!e),title:`Canvas panel`,children:`▣ Panel`})]}),(0,k.jsxs)(`div`,{className:N.inputRow,children:[(0,k.jsx)(`textarea`,{ref:me,className:N.input,value:l,onChange:e=>u(e.target.value),onKeyDown:je,placeholder:e(`chat.placeholder`),rows:1,disabled:d}),d?(0,k.jsxs)(`button`,{className:`${N.btn} ${N.stop}`,onClick:Ae,children:[`■ `,e(`chat.stopGeneration`)]}):(0,k.jsx)(`button`,{className:`${N.btn} ${N.send}`,onClick:I,disabled:!l.trim()&&!m&&!g,children:`Send ↵`})]})]})]}),ie&&T&&(0,k.jsxs)(`div`,{className:N.canvasPanel,children:[(0,k.jsxs)(`div`,{className:N.canvasPanelHeader,children:[(0,k.jsx)(`span`,{children:`Canvas`}),(0,k.jsxs)(`div`,{className:N.canvasPanelActions,children:[(0,k.jsx)(`button`,{className:N.canvasPanelBtn,onClick:()=>{let e=new Blob([T],{type:`text/html`}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`NHA-Canvas.html`,n.click(),setTimeout(()=>URL.revokeObjectURL(t),5e3)},children:`↓ Download`}),(0,k.jsx)(`button`,{className:N.canvasPanelBtn,onClick:()=>navigator.clipboard.writeText(T).catch(()=>{}),children:`Copy HTML`}),(0,k.jsx)(`button`,{className:N.canvasPanelClose,onClick:()=>O(!1),children:`×`})]})]}),(0,k.jsx)(`iframe`,{className:N.canvasFrame,sandbox:`allow-scripts`,srcDoc:T,title:`Canvas`})]})]})}var P={root:`_root_1899x_1`,header:`_header_1899x_8`,headerLeft:`_headerLeft_1899x_19`,title:`_title_1899x_21`,subtitle:`_subtitle_1899x_28`,headerActions:`_headerActions_1899x_34`,tokenBar:`_tokenBar_1899x_41`,tokIn:`_tokIn_1899x_49`,tokOut:`_tokOut_1899x_50`,tokTotal:`_tokTotal_1899x_51`,tokDim:`_tokDim_1899x_52`,sessionsBtn:`_sessionsBtn_1899x_54`,pdfBtn:`_pdfBtn_1899x_66`,clearBtn:`_clearBtn_1899x_76`,sessionsDrawer:`_sessionsDrawer_1899x_89`,noSessions:`_noSessions_1899x_104`,sessionItem:`_sessionItem_1899x_111`,sessionInfo:`_sessionInfo_1899x_121`,sessionTask:`_sessionTask_1899x_127`,sessionMeta:`_sessionMeta_1899x_137`,sessionBtns:`_sessionBtns_1899x_143`,importBtn:`_importBtn_1899x_149`,delSessionBtn:`_delSessionBtn_1899x_159`,sessionsFooter:`_sessionsFooter_1899x_169`,clearAllSessionsBtn:`_clearAllSessionsBtn_1899x_176`,inputArea:`_inputArea_1899x_189`,inputRow:`_inputRow_1899x_198`,taskInput:`_taskInput_1899x_204`,inputControls:`_inputControls_1899x_219`,runBtn:`_runBtn_1899x_225`,stopBtn:`_stopBtn_1899x_238`,attachBtn:`_attachBtn_1899x_249`,attachBadge:`_attachBadge_1899x_262`,clearAttach:`_clearAttach_1899x_275`,examples:`_examples_1899x_284`,exampleBtn:`_exampleBtn_1899x_290`,body:`_body_1899x_308`,agentChip:`_agentChip_1899x_321`,chip_running:`_chip_running_1899x_332`,charCardPulse:`_charCardPulse_1899x_1`,chip_done:`_chip_done_1899x_338`,chip_error:`_chip_error_1899x_339`,chip_waiting:`_chip_waiting_1899x_340`,chipIcon:`_chipIcon_1899x_341`,chipLabel:`_chipLabel_1899x_342`,chipDots:`_chipDots_1899x_343`,chipCheck:`_chipCheck_1899x_344`,chipErr:`_chipErr_1899x_345`,officeSceneWrap:`_officeSceneWrap_1899x_348`,pipeline:`_pipeline_1899x_358`,pipelineWrap:`_pipelineWrap_1899x_373`,pipelineRunning:`_pipelineRunning_1899x_383`,scanSweep:`_scanSweep_1899x_1`,pipelineTitle:`_pipelineTitle_1899x_409`,pipelineNodes:`_pipelineNodes_1899x_417`,pipelineStep:`_pipelineStep_1899x_424`,arrow:`_arrow_1899x_430`,arrowActive:`_arrowActive_1899x_439`,arrowPulse:`_arrowPulse_1899x_1`,agentChar:`_agentChar_1899x_451`,charWaiting:`_charWaiting_1899x_466`,charActive:`_charActive_1899x_471`,charDone:`_charDone_1899x_479`,charError:`_charError_1899x_484`,orbitRing1:`_orbitRing1_1899x_495`,orbitRing2:`_orbitRing2_1899x_496`,orbitSpin1:`_orbitSpin1_1899x_1`,orbitSpin2:`_orbitSpin2_1899x_1`,charAvatar:`_charAvatar_1899x_542`,charIcon:`_charIcon_1899x_557`,iconBob:`_iconBob_1899x_1`,charCheck:`_charCheck_1899x_574`,badgePop:`_badgePop_1899x_1`,charErr:`_charErr_1899x_484`,charPulse:`_charPulse_1899x_618`,charPulse2:`_charPulse2_1899x_619`,expandRing:`_expandRing_1899x_1`,charLabel:`_charLabel_1899x_638`,charStatus:`_charStatus_1899x_650`,charStatusDots:`_charStatusDots_1899x_663`,dot1:`_dot1_1899x_664`,dot2:`_dot2_1899x_664`,dot3:`_dot3_1899x_664`,dotFade:`_dotFade_1899x_1`,twoCol:`_twoCol_1899x_678`,panelTitle:`_panelTitle_1899x_685`,logPanel:`_logPanel_1899x_695`,logBody:`_logBody_1899x_707`,logEntry:`_logEntry_1899x_715`,logTime:`_logTime_1899x_725`,logIcon:`_logIcon_1899x_726`,logAgent:`_logAgent_1899x_727`,logText:`_logText_1899x_728`,log_system:`_log_system_1899x_730`,log_error:`_log_error_1899x_731`,liveOutputPanel:`_liveOutputPanel_1899x_734`,liveBlock:`_liveBlock_1899x_741`,blockSlideIn:`_blockSlideIn_1899x_1`,liveBlockActive:`_liveBlockActive_1899x_755`,liveBlockScan:`_liveBlockScan_1899x_1`,liveBlockHeader:`_liveBlockHeader_1899x_780`,liveBlockIcon:`_liveBlockIcon_1899x_789`,liveBlockLabel:`_liveBlockLabel_1899x_791`,outputStatus:`_outputStatus_1899x_799`,status_done:`_status_done_1899x_810`,status_running:`_status_running_1899x_811`,status_error:`_status_error_1899x_812`,status_waiting:`_status_waiting_1899x_813`,liveBlockBody:`_liveBlockBody_1899x_816`,liveBlockWorking:`_liveBlockWorking_1899x_954`,workingDot:`_workingDot_1899x_961`,workingBounce:`_workingBounce_1899x_1`,workingLabel:`_workingLabel_1899x_978`,workingFade:`_workingFade_1899x_1`,studioBlinkCursor:`_studioBlinkCursor_1899x_1`,resultAccordion:`_resultAccordion_1899x_1007`,resultAccordionSummary:`_resultAccordionSummary_1899x_1014`,resultAccordionBody:`_resultAccordionBody_1899x_1031`,financeSection:`_financeSection_1899x_1065`,financeSectionTitle:`_financeSectionTitle_1899x_1073`,financePresets:`_financePresets_1899x_1082`,financeBtn:`_financeBtn_1899x_1088`,canvasToggleBtn:`_canvasToggleBtn_1899x_1106`,canvasPanel:`_canvasPanel_1899x_1122`,canvasPanelHeader:`_canvasPanelHeader_1899x_1137`,canvasPanelActions:`_canvasPanelActions_1899x_1149`,canvasPanelBtn:`_canvasPanelBtn_1899x_1155`,canvasPanelClose:`_canvasPanelClose_1899x_1167`,canvasFrame:`_canvasFrame_1899x_1178`,pipelineLiveTag:`_pipelineLiveTag_1899x_1186`,liveTagBlink:`_liveTagBlink_1899x_1`,reasonRow:`_reasonRow_1899x_1200`,reasonChip:`_reasonChip_1899x_1209`,reasonIcon:`_reasonIcon_1899x_1222`,reasonText:`_reasonText_1899x_1223`,liveBlockReason:`_liveBlockReason_1899x_1226`,councilWrapper:`_councilWrapper_1899x_1236`,councilPanel:`_councilPanel_1899x_1241`,councilHeader:`_councilHeader_1899x_1249`,councilHeaderLeft:`_councilHeaderLeft_1899x_1260`,councilHeaderRight:`_councilHeaderRight_1899x_1266`,councilIcon:`_councilIcon_1899x_1272`,councilTitle:`_councilTitle_1899x_1274`,councilConvergedBadge:`_councilConvergedBadge_1899x_1283`,councilDivergedBadge:`_councilDivergedBadge_1899x_1295`,councilPhaseTag:`_councilPhaseTag_1899x_1307`,councilPhaseActive:`_councilPhaseActive_1899x_1313`,phaseGlow:`_phaseGlow_1899x_1`,councilPhaseDone:`_councilPhaseDone_1899x_1322`,councilMetrics:`_councilMetrics_1899x_1325`,convRow:`_convRow_1899x_1333`,convLabel:`_convLabel_1899x_1339`,convTrack:`_convTrack_1899x_1347`,convFill:`_convFill_1899x_1355`,convPct:`_convPct_1899x_1361`,councilNodes:`_councilNodes_1899x_1371`,councilSectionTitle:`_councilSectionTitle_1899x_1376`,councilNode:`_councilNode_1899x_1371`,councilNodeHeader:`_councilNodeHeader_1899x_1393`,councilNodeIcon:`_councilNodeIcon_1899x_1406`,councilNodeLabel:`_councilNodeLabel_1899x_1407`,councilNodeToggle:`_councilNodeToggle_1899x_1408`,councilNodeBody:`_councilNodeBody_1899x_1410`,councilSynthesis:`_councilSynthesis_1899x_1420`,councilSynthesisHeader:`_councilSynthesisHeader_1899x_1424`,heraldIcon:`_heraldIcon_1899x_1433`,heraldLabel:`_heraldLabel_1899x_1435`,heraldStreaming:`_heraldStreaming_1899x_1443`,councilSynthesisBody:`_councilSynthesisBody_1899x_1445`,councilSkipped:`_councilSkipped_1899x_1475`,councilSkipIcon:`_councilSkipIcon_1899x_1486`,charSpriteRunning:`_charSpriteRunning_1899x_1499`,spriteWalk:`_spriteWalk_1899x_1`,charSpriteDone:`_charSpriteDone_1899x_1508`,charScanline:`_charScanline_1899x_1512`,scanlineScroll:`_scanlineScroll_1899x_1`,auraAnim:`_auraAnim_1899x_1532`,auraGlow:`_auraGlow_1899x_1`,parliamentPrompt:`_parliamentPrompt_1899x_1539`,parliamentPromptIcon:`_parliamentPromptIcon_1899x_1549`,parliamentPromptContent:`_parliamentPromptContent_1899x_1550`,parliamentPromptTitle:`_parliamentPromptTitle_1899x_1551`,parliamentPromptDesc:`_parliamentPromptDesc_1899x_1552`,parliamentPromptMeta:`_parliamentPromptMeta_1899x_1553`,parliamentPromptBtns:`_parliamentPromptBtns_1899x_1554`,parliamentActivateBtn:`_parliamentActivateBtn_1899x_1555`,parliamentSkipBtn:`_parliamentSkipBtn_1899x_1562`,panelTabs:`_panelTabs_1899x_1570`,panelTabBtn:`_panelTabBtn_1899x_1571`,panelTabActive:`_panelTabActive_1899x_1578`,panelEmpty:`_panelEmpty_1899x_1580`,browserPanel:`_browserPanel_1899x_1589`,browserBar:`_browserBar_1899x_1590`,browserInput:`_browserInput_1899x_1591`,browserGo:`_browserGo_1899x_1598`,liveBlockClickable:`_liveBlockClickable_1899x_1605`,liveBlockBodyClamped:`_liveBlockBodyClamped_1899x_1614`,expandHint:`_expandHint_1899x_1621`,blockModalOverlay:`_blockModalOverlay_1899x_1630`,blockModal:`_blockModal_1899x_1630`,blockModalHeader:`_blockModalHeader_1899x_1655`,blockModalTitle:`_blockModalTitle_1899x_1665`,blockModalClose:`_blockModalClose_1899x_1673`,blockModalBody:`_blockModalBody_1899x_1685`},De=[{label:`📈 Full Trading Strategy`,task:`You are a team of senior quantitative analysts and macro traders. Build a complete, actionable trading strategy with the following structure:
|
|
66
66
|
|
|
67
67
|
1. MACRO REGIME ANALYSIS
|
|
68
68
|
- Current macro cycle phase (expansion/peak/contraction/trough) with supporting indicators (yield curve, PMI, CPI trajectory, Fed/ECB policy stance)
|
package/src/ui-dist/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
9
9
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
10
10
|
<title>NHA — NotHumanAllowed</title>
|
|
11
|
-
<script type="module" crossorigin src="/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/assets/index-C4d3pl8K.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-DnJMrYkq.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|