nothumanallowed 14.1.79 → 14.1.80
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": "14.1.
|
|
3
|
+
"version": "14.1.80",
|
|
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 = '14.1.
|
|
8
|
+
export const VERSION = '14.1.80';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -851,56 +851,112 @@ ${prevContext ? `Recent files generated (for consistency):\n${prevContext}\n\n`
|
|
|
851
851
|
let syntaxError = null;
|
|
852
852
|
const fileTokensIn = countTokens(fileSys) + countTokens(filePrompt);
|
|
853
853
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
854
|
+
// Retry loop — up to 2 attempts per file
|
|
855
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
856
|
+
try {
|
|
857
|
+
// Stream chunks to browser in real-time during generation
|
|
858
|
+
let rawOutput = '';
|
|
859
|
+
await callLLMStream(config, fileSys, filePrompt, (chunk) => {
|
|
860
|
+
rawOutput += chunk;
|
|
861
|
+
// Real-time streaming to browser
|
|
862
|
+
emit({ type: 'file_chunk', name: fileSpec.name, chunk, fi: fi + 1, total: filePlan.length });
|
|
863
|
+
}, { max_tokens: maxTokens });
|
|
864
|
+
|
|
865
|
+
// Strip markdown fences if LLM wrapped the output
|
|
866
|
+
rawOutput = rawOutput
|
|
867
|
+
.replace(/^```[\w]*\n/, '').replace(/\n```$/, '')
|
|
868
|
+
.replace(/^```[\w]*\r\n/, '').replace(/\r\n```$/, '').trim();
|
|
869
|
+
|
|
870
|
+
// Continuation loop — up to 3 rounds if file appears truncated
|
|
871
|
+
for (let contRound = 0; contRound < 3 && isFileTruncated(rawOutput, fileSpec.name); contRound++) {
|
|
872
|
+
emit({ type: 'file_chunk', name: fileSpec.name, chunk: `\n/* ... continuing (${contRound + 1}) ... */\n`, fi: fi + 1, total: filePlan.length });
|
|
873
|
+
const contPrompt = `The file ${fileSpec.name} was truncated. Continue EXACTLY from the last line. Output ONLY the remaining code (no repetition, no explanation):
|
|
874
|
+
|
|
875
|
+
LAST 600 CHARS OF WHAT WAS WRITTEN:
|
|
876
|
+
${rawOutput.slice(-600)}
|
|
877
|
+
|
|
878
|
+
Continue from here:`;
|
|
879
|
+
let continuation = '';
|
|
880
|
+
await callLLMStream(config, fileSys, contPrompt, (chunk) => {
|
|
881
|
+
continuation += chunk;
|
|
882
|
+
emit({ type: 'file_chunk', name: fileSpec.name, chunk, fi: fi + 1, total: filePlan.length });
|
|
883
|
+
}, { max_tokens: Math.min(maxTokens, 8192) });
|
|
884
|
+
continuation = continuation
|
|
885
|
+
.replace(/^```[\w]*\n/, '').replace(/\n```$/, '').trim();
|
|
886
|
+
if (continuation.length > 20) {
|
|
887
|
+
rawOutput = rawOutput + '\n' + continuation;
|
|
888
|
+
} else {
|
|
889
|
+
break; // continuation too short — likely done
|
|
890
|
+
}
|
|
891
|
+
}
|
|
880
892
|
|
|
881
|
-
|
|
893
|
+
fileContent = rawOutput;
|
|
894
|
+
syntaxError = null;
|
|
882
895
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
});
|
|
896
|
+
const fileTokensOut = countTokens(fileContent);
|
|
897
|
+
totalTokensIn += fileTokensIn;
|
|
898
|
+
totalTokensOut += fileTokensOut;
|
|
887
899
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
900
|
+
// Quick syntax check for JS/TS files
|
|
901
|
+
if (fileSpec.name.endsWith('.js') || fileSpec.name.endsWith('.mjs')) {
|
|
902
|
+
try { new Function(fileContent); } catch (e) { syntaxError = e.message.replace(/\n.*/s, ''); }
|
|
903
|
+
}
|
|
904
|
+
// HTML completeness check
|
|
905
|
+
if (fileSpec.name.endsWith('.html') && !fileContent.includes('</html>')) {
|
|
906
|
+
syntaxError = 'Missing </html> closing tag';
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
const abs = path.join(projectDir, fileSpec.name);
|
|
910
|
+
ensureDir(path.dirname(abs));
|
|
911
|
+
fs.writeFileSync(abs, fileContent, 'utf-8');
|
|
912
|
+
generatedFiles.push({ name: fileSpec.name, content: fileContent });
|
|
913
|
+
emit({ type: 'file_done', name: fileSpec.name, fi: fi + 1, total: filePlan.length, syntaxError, tokOut: fileTokensOut, cumTokIn: totalTokensIn, cumTokOut: totalTokensOut });
|
|
914
|
+
break; // success — exit retry loop
|
|
891
915
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
916
|
+
} catch (e) {
|
|
917
|
+
if (attempt === 0) {
|
|
918
|
+
emit({ type: 'file_chunk', name: fileSpec.name, chunk: `\n/* Retry: ${e.message.slice(0, 100)} */\n`, fi: fi + 1, total: filePlan.length });
|
|
919
|
+
continue; // retry once
|
|
920
|
+
}
|
|
921
|
+
emit({ type: 'file_error', name: fileSpec.name, error: e.message });
|
|
895
922
|
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
896
925
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
926
|
+
// ── Post-generation integrity check ──────────────────────────────────────
|
|
927
|
+
const brokenFiles = generatedFiles.filter((f) => {
|
|
928
|
+
if (!f.content || f.content.length < 20) return true;
|
|
929
|
+
if (f.name.endsWith('.html') && !f.content.includes('</html>')) return true;
|
|
930
|
+
if ((f.name.endsWith('.js') || f.name.endsWith('.mjs'))) {
|
|
931
|
+
try { new Function(f.content); } catch { return true; }
|
|
932
|
+
}
|
|
933
|
+
if (f.name.endsWith('.json')) {
|
|
934
|
+
try { JSON.parse(f.content); } catch { return true; }
|
|
935
|
+
}
|
|
936
|
+
return isFileTruncated(f.content, f.name);
|
|
937
|
+
});
|
|
938
|
+
|
|
939
|
+
if (brokenFiles.length > 0 && brokenFiles.length <= 10) {
|
|
940
|
+
emit({ type: 'phase', phase: 'autofix', msg: `Post-generation fix: ${brokenFiles.length} file(s) need repair...` });
|
|
941
|
+
for (const broken of brokenFiles) {
|
|
942
|
+
try {
|
|
943
|
+
emit({ type: 'status', msg: `Regenerating ${broken.name}...` });
|
|
944
|
+
let fixedContent = '';
|
|
945
|
+
const fixPrompt = `Regenerate this file COMPLETELY. It was truncated or has errors.\n\nFile: ${broken.name}\nProject: ${projectName}\nDescription: ${description}\nFull file list: ${allFileNames}\n\nOutput the COMPLETE file content only, no explanation.`;
|
|
946
|
+
await callLLMStream(config, fileSys, fixPrompt, (chunk) => {
|
|
947
|
+
fixedContent += chunk;
|
|
948
|
+
}, { max_tokens: 16384 });
|
|
949
|
+
fixedContent = fixedContent
|
|
950
|
+
.replace(/^```[\w]*\n/, '').replace(/\n```$/, '').trim();
|
|
951
|
+
if (fixedContent.length > broken.content.length) {
|
|
952
|
+
broken.content = fixedContent;
|
|
953
|
+
const abs = path.join(projectDir, broken.name);
|
|
954
|
+
fs.writeFileSync(abs, fixedContent, 'utf-8');
|
|
955
|
+
emit({ type: 'status', msg: `Fixed ${broken.name} (${fixedContent.length} chars)` });
|
|
956
|
+
}
|
|
957
|
+
} catch (e) {
|
|
958
|
+
emit({ type: 'status', msg: `Could not fix ${broken.name}: ${e.message.slice(0, 100)}` });
|
|
959
|
+
}
|
|
904
960
|
}
|
|
905
961
|
}
|
|
906
962
|
|
|
@@ -678,7 +678,7 @@ FRONTEND:
|
|
|
678
678
|
- apply.html: Application modal/page — job summary header, form (Full Name / Email / Phone / LinkedIn URL / Portfolio URL / Cover Letter textarea with character count / Resume paste textarea), Submit button with loading state, success page with application reference number
|
|
679
679
|
- public/css/main.css: Modern job board design — tag/badge system (Remote=blue, Onsite=green, Urgent=red), salary range display, company logo placeholder styles, filter sidebar collapse on mobile, job card hover effects, application form validation styles`}],ln=[{key:`auth`,label:`Auth (register/login/JWT)`,icon:`🔒`},{key:`cookieBanner`,label:`GDPR Cookie Banner`,icon:`🍪`},{key:`securityMiddleware`,label:`Security Middleware`,icon:`🛡️`},{key:`emailVerification`,label:`Email Verification`,icon:`✉️`}],un={js:`📄`,ts:`📄`,css:`🎨`,html:`🌐`,json:`📋`,md:`📑`,sql:`🗂`,env:`🔐`,conf:`⚙`,lock:`🔒`};function dn(e){return un[e.split(`.`).pop()?.toLowerCase()??``]??`📄`}function fn(e){let t=new TextEncoder().encode(e).length;return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(2)} MB`}function pn(e){return e===`memory`?`🧠`:e===`provider`?`🤖`:e===`log`?`📄`:`📋`}function mn(){let e=P(),[t,n]=(0,_.useState)(`new`),[r,i]=(0,_.useState)(`files`),[a,o]=(0,_.useState)(``),[s,c]=(0,_.useState)(``),[l,u]=(0,_.useState)({auth:!0,cookieBanner:!0,securityMiddleware:!0,emailVerification:!0}),[d,f]=(0,_.useState)([{label:`Email`,type:`email`,required:!0},{label:`Password`,type:`password`,required:!0},{label:`Name`,type:`text`,required:!0}]),[p,m]=(0,_.useState)([]),[h,g]=(0,_.useState)(0),[v,y]=(0,_.useState)(null),[b,x]=(0,_.useState)(null),[S,C]=(0,_.useState)(null),[w,T]=(0,_.useState)(!1),[E,ee]=(0,_.useState)(!1),[D,te]=(0,_.useState)(0),[ne,A]=(0,_.useState)(0),[re,M]=(0,_.useState)(``),[N,ie]=(0,_.useState)({fi:0,total:0,name:``}),[ae,oe]=(0,_.useState)({tokIn:0,tokOut:0}),[se,ce]=(0,_.useState)(null),[F,le]=(0,_.useState)([]),[ue,de]=(0,_.useState)(``),[fe,pe]=(0,_.useState)(!1),[me,he]=(0,_.useState)([]),[ge,_e]=(0,_.useState)(null),[ve,ye]=(0,_.useState)([]),[I,be]=(0,_.useState)(!1),[xe,Se]=(0,_.useState)(null),[Ce,L]=(0,_.useState)([]),[we,Te]=(0,_.useState)(!1),[Ee,R]=(0,_.useState)(``),[z,De]=(0,_.useState)([]),[Oe,ke]=(0,_.useState)([]),[Ae,je]=(0,_.useState)([]),[Me,Ne]=(0,_.useState)(null),[Pe,Fe]=(0,_.useState)(!1),[Ie,B]=(0,_.useState)([]),[Le,Re]=(0,_.useState)(null),[ze,Be]=(0,_.useState)(!0),Ve=(0,_.useRef)(null),[He,Ue]=(0,_.useState)(`0s`),[We,Ge]=(0,_.useState)(`0s`),Ke=(0,_.useRef)(0),qe=(0,_.useRef)(0),Je=(0,_.useRef)(null),Ye=(0,_.useRef)(null),Xe=(0,_.useRef)(null),Ze=(0,_.useRef)(null),Qe=(0,_.useRef)(null),$e=(0,_.useRef)(null);function et(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function tt(e){let t=Math.floor((Date.now()-e)/1e3),n=Math.floor(t/60);return(n>0?`${n}m `:``)+`${t%60}s`}(0,_.useEffect)(()=>(w||E?Je.current=setInterval(()=>{w&&Ue(tt(Ke.current)),E&&Ge(tt(qe.current))},1e3):Je.current&&=(clearInterval(Je.current),null),()=>{Je.current&&clearInterval(Je.current)}),[w,E]);function nt(){Xe.current&&(Xe.current.scrollTop=Xe.current.scrollHeight)}(0,_.useEffect)(()=>{nt()},[F]),(0,_.useEffect)(()=>{a&&!I&&(be(!0),O(`/api/studio/webcraft/skills/${encodeURIComponent(a)}`).then(e=>{e?.skills&&ye(e.skills)}).catch(()=>{}))},[a,I]);async function rt(e,t){if(w||!e||e.length<5)return;T(!0),m([]),g(0),y(null),ie({fi:0,total:0,name:``}),oe({tokIn:0,tokOut:0}),Ke.current=Date.now(),Ue(`0s`),Ye.current=new AbortController;let n=Date.now();try{let r=await fetch(`/api/studio/webcraft/generate`,{method:`POST`,headers:{"Content-Type":`application/json`},signal:Ye.current.signal,body:JSON.stringify({projectName:t,description:e,blocks:l,authFields:d})});if(!r.ok||!r.body){T(!1);return}let i=r.body.getReader(),a=new TextDecoder,o=``,s=[];for(;;){let{done:e,value:t}=await i.read();if(e)break;o+=a.decode(t,{stream:!0});let r=o.split(`
|
|
680
680
|
|
|
681
|
-
`);o=r.pop()??``;for(let e of r){let t=e.replace(/^data: /,``).trim();if(t)try{let e=JSON.parse(t);if(e.type===`processing`||e.type===`planning`)ie(t=>({...t,name:e.type===`planning`?`📋 Pianificazione struttura...`:e.msg||`Avvio...`}));else if(e.type===`file_start`)s.push({name:e.name,content:``,_pending:!0}),m([...s]),ie({fi:e.fi,total:e.total,name:e.name}),g(s.length-1),y(``);else if(e.type===`file_chunk`){let t=s.find(t=>t.name===e.name);t&&(t.content+=e.chunk,t._pending=!1),m([...s]),y(t?t.content:null)}else if(e.type===`file_done`){let t=s.find(t=>t.name===e.name);t&&(t._pending=!1,e.syntaxError&&(t._syntaxError=e.syntaxError)),m([...s]),ie({fi:e.fi,total:e.total,name:e.name}),(e.cumTokIn||e.cumTokOut)&&oe({tokIn:e.cumTokIn||0,tokOut:e.cumTokOut||0})}else if(e.type===`file_error`){let t=s.find(t=>t.name===e.name);t&&(t._error=!0,t._pending=!1),m([...s])}else e.type===`done`&&(ce({seconds:Math.round((Date.now()-n)/1e3),tokIn:e.tokIn??0,tokOut:e.tokOut??0,files:s.length}),y(null),T(!1),be(!1),ye([]),s.some(e=>e._error||e._syntaxError)?setTimeout(()=>Qe.current?.(),800):setTimeout(()=>$e.current?.(),800))}catch{}}}}catch(e){e.name!==`AbortError`&&le(t=>[...t,{role:`system`,text:`Errore generazione: `+e.message}]),T(!1)}}async function it(){let e=ue.trim();if(!(a&&p.length>0)){if(!e||e.length<5)return;let t=a||`MyProject`;o(t),c(e),de(``),await rt(e,t);return}if(!e&&me.length===0||fe||w)return;let t=[...me];if(he([]),de(``),e.toLowerCase().startsWith(`/plan `)||e.toLowerCase().startsWith(`piano: `)){let t=e.replace(/^\/plan[ ]*/i,``).replace(/^piano:[ ]*/i,``);le(t=>[...t,{role:`user`,text:e}]),await at(`[MODALITA PIANO] Descrivi cosa modificheresti per: "${t}". Elenca i file e cosa faresti. NON applicare modifiche ancora. Rispondi con il piano in bullet list.`,t,[]);return}le(n=>[...n,{role:`user`,text:e,attachments:t}]),await at(e,null,t)}async function at(e,t,n){if(fe)return;pe(!0);let r={};p.forEach(e=>{r[e.name]=e.content});try{let i=await fetch(`/api/studio/webcraft/agent`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({projectName:a,message:e,attachments:n.map(e=>({name:e.name,mimeType:e.mimeType,base64:e.base64}))})});if(!i.ok||!i.body){le(e=>[...e,{role:`agent`,text:`Errore: ${i.status}`,tools:[]}]),pe(!1);return}let o={role:`agent`,text:``,tools:[]};le(e=>[...e,o]);let s=i.body.getReader(),c=new TextDecoder,l=``,u=!1;for(;;){let{done:e,value:n}=await s.read();if(e)break;l+=c.decode(n,{stream:!0});let i=l.split(`
|
|
681
|
+
`);o=r.pop()??``;for(let e of r){let t=e.replace(/^data: /,``).trim();if(t)try{let e=JSON.parse(t);if(e.type===`processing`||e.type===`planning`)ie(t=>({...t,name:e.type===`planning`?`📋 Pianificazione struttura...`:e.msg||`Avvio...`}));else if(e.type===`file_start`)s.push({name:e.name,content:``,_pending:!0}),m([...s]),ie({fi:e.fi,total:e.total,name:e.name}),g(s.length-1),y(``);else if(e.type===`file_chunk`){let t=s.find(t=>t.name===e.name);t&&(t.content+=e.chunk,t._pending=!1),m([...s]),y(t?t.content:null)}else if(e.type===`file_done`){let t=s.find(t=>t.name===e.name);t&&(t._pending=!1,e.syntaxError&&(t._syntaxError=e.syntaxError)),m([...s]),ie({fi:e.fi,total:e.total,name:e.name}),(e.cumTokIn||e.cumTokOut)&&oe({tokIn:e.cumTokIn||0,tokOut:e.cumTokOut||0})}else if(e.type===`file_error`){let t=s.find(t=>t.name===e.name);t&&(t._error=!0,t._pending=!1),m([...s])}else e.type===`phase`||e.type===`status`&&!e.op?ie(t=>({...t,name:e.msg||e.phase||``})):e.type===`done`&&(ce({seconds:Math.round((Date.now()-n)/1e3),tokIn:e.tokIn??0,tokOut:e.tokOut??0,files:s.length}),y(null),T(!1),be(!1),ye([]),s.some(e=>e._error||e._syntaxError)?setTimeout(()=>Qe.current?.(),800):setTimeout(()=>$e.current?.(),800))}catch{}}}}catch(e){e.name!==`AbortError`&&le(t=>[...t,{role:`system`,text:`Errore generazione: `+e.message}]),T(!1)}}async function it(){let e=ue.trim();if(!(a&&p.length>0)){if(!e||e.length<5)return;let t=a||`MyProject`;o(t),c(e),de(``),await rt(e,t);return}if(!e&&me.length===0||fe||w)return;let t=[...me];if(he([]),de(``),e.toLowerCase().startsWith(`/plan `)||e.toLowerCase().startsWith(`piano: `)){let t=e.replace(/^\/plan[ ]*/i,``).replace(/^piano:[ ]*/i,``);le(t=>[...t,{role:`user`,text:e}]),await at(`[MODALITA PIANO] Descrivi cosa modificheresti per: "${t}". Elenca i file e cosa faresti. NON applicare modifiche ancora. Rispondi con il piano in bullet list.`,t,[]);return}le(n=>[...n,{role:`user`,text:e,attachments:t}]),await at(e,null,t)}async function at(e,t,n){if(fe)return;pe(!0);let r={};p.forEach(e=>{r[e.name]=e.content});try{let i=await fetch(`/api/studio/webcraft/agent`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({projectName:a,message:e,attachments:n.map(e=>({name:e.name,mimeType:e.mimeType,base64:e.base64}))})});if(!i.ok||!i.body){le(e=>[...e,{role:`agent`,text:`Errore: ${i.status}`,tools:[]}]),pe(!1);return}let o={role:`agent`,text:``,tools:[]};le(e=>[...e,o]);let s=i.body.getReader(),c=new TextDecoder,l=``,u=!1;for(;;){let{done:e,value:n}=await s.read();if(e)break;l+=c.decode(n,{stream:!0});let i=l.split(`
|
|
682
682
|
|
|
683
683
|
`);l=i.pop()??``;for(let e of i){let n=e.replace(/^data: /,``).trim();if(n)try{let e=JSON.parse(n);e.type===`text`?(o.text+=e.token,le(e=>{let t=[...e];return t[t.length-1]={...o},t})):e.type===`tool`?(o.tools.push({op:e.op,path:e.path,result:e.result,oldSnippet:e.oldSnippet??``,newSnippet:e.newSnippet??``}),(e.op===`edit`||e.op===`write`)&&e.result===`ok`&&(u=!0),le(e=>{let t=[...e];return t[t.length-1]={...o},t})):e.type===`done`?(t&&!u&&_e({plan:o.text,originalMessage:t}),pe(!1),e.changed&&await ot((o.tools??[]).filter(e=>e.op===`edit`||e.op===`write`).map(e=>e.path),r)):e.type===`error`&&(o.text+=`
|
|
684
684
|
Errore: `+e.msg,pe(!1))}catch{}}}}catch(e){le(t=>[...t,{role:`agent`,text:`Errore di rete: `+e.message,tools:[]}])}pe(!1)}async function ot(e,t){if(!a)return;let n=await O(`/api/studio/webcraft/projects/load/${encodeURIComponent(a)}`);if(n?.files&&(m(n.files),e.length>0)){let r=e.map(e=>{let r=n.files.find(t=>t.name===e);return r?{file:e,before:t[e]??``,after:r.content}:null}).filter(Boolean);ke(e=>[...e,...r])}}function st(){Ye.current&&=(Ye.current.abort(),null),T(!1),pe(!1),le(e=>[...e,{role:`system`,text:`⏹ Generazione interrotta.`}])}async function ct(){return a?(await k(`/api/studio/webcraft/snapshot`,{projectName:a}))?.snapshot??null:null}async function lt(){let e=await ct();e&&(le(t=>[...t,{role:`system`,text:`💾 Snapshot salvato (${e.slice(0,16).replace(`T`,` `)})`}]),V())}async function V(){if(!a)return;let e=await O(`/api/studio/webcraft/snapshots/${encodeURIComponent(a)}`);e?.snapshots&&L(e.snapshots)}async function ut(e){confirm(`Ripristinare lo snapshot del ${e.replace(`T`,` `).slice(0,16)}? I file attuali verranno sovrascritti.`)&&await k(`/api/studio/webcraft/restore`,{projectName:a,ts:e})!==null&&(le(t=>[...t,{role:`agent`,text:`Snapshot ripristinato (${e}). Ricarico i file...`}]),ot([],{}))}async function dt(){if(!a)return;let e=await k(`/api/studio/webcraft/syntax-check`,{projectName:a});if(e?.results){let t=e.results.filter(e=>!e.ok);t.length>0?le(e=>[...e,{role:`system`,text:`⚠ Syntax check: ${t.length} errore/i trovato/i.`,syntaxErrors:t}]):le(e=>[...e,{role:`system`,text:`✓ Syntax check: tutti i file JS sono validi.`}])}}async function ft(){let e=p.filter(e=>e._error||e._syntaxError);if(e.length===0){$e.current?.();return}ee(!0),te(0),A(e.length),qe.current=Date.now(),Ge(`0s`);for(let t=0;t<e.length;t++){let n=e[t];M(n.name),te(t),await at(`REPAIR FILE: ${n.name}\nErrore: ${n._syntaxError??`generazione fallita`}\nRigenera il file correttamente. Output SOLO il contenuto del file, nessuna spiegazione.`,null,[])}te(e.length),M(``),ee(!1),setTimeout(()=>$e.current?.(),500)}let pt={cleanup:`🧹`,shims:`🔌`,deps:`📦`,start:`🚀`,autofix:`🔧`,ready:`✅`};function mt(e,t=`info`){let n=new Date().toLocaleTimeString();B(r=>[...r,`${t===`phase`?`
|
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-BxGt2gxR.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-UUUprsdb.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|