nothumanallowed 14.4.15 → 14.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "14.4.
|
|
3
|
+
"version": "14.4.16",
|
|
4
4
|
"description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/src/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.4.
|
|
8
|
+
export const VERSION = '14.4.16';
|
|
9
9
|
export const BASE_URL = 'https://nothumanallowed.com/cli';
|
|
10
10
|
export const API_BASE = 'https://nothumanallowed.com/api/v1';
|
|
11
11
|
|
|
@@ -1711,11 +1711,24 @@ export function register(router) {
|
|
|
1711
1711
|
router.post('/api/studio/webcraft/generate', async (req, res) => {
|
|
1712
1712
|
const body = await parseBody(req, 1_048_576);
|
|
1713
1713
|
const config = loadConfig();
|
|
1714
|
-
|
|
1714
|
+
let { projectName, description, blocks = {}, authFields = [] } = body;
|
|
1715
1715
|
if (!projectName || !description) return sendError(res, 400, 'projectName and description required');
|
|
1716
1716
|
|
|
1717
|
+
// Prevent overwriting existing projects — add (1), (2), etc.
|
|
1718
|
+
const baseName = projectName;
|
|
1719
|
+
let suffix = 0;
|
|
1720
|
+
while (fs.existsSync(ProjectStore.dir(projectName))) {
|
|
1721
|
+
// Check if directory has actual project files (not just .nha-context)
|
|
1722
|
+
const files = fs.readdirSync(ProjectStore.dir(projectName)).filter((f) => !f.startsWith('.nha-'));
|
|
1723
|
+
if (files.length === 0) break; // empty project dir — safe to reuse
|
|
1724
|
+
suffix++;
|
|
1725
|
+
projectName = `${baseName} (${suffix})`;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1717
1728
|
const sse = sendSSE(res);
|
|
1718
|
-
//
|
|
1729
|
+
// Notify frontend of the final project name (may differ from input)
|
|
1730
|
+
if (suffix > 0) sse.send({ type: 'project_renamed', name: projectName });
|
|
1731
|
+
|
|
1719
1732
|
const ac = new AbortController();
|
|
1720
1733
|
req.on('close', () => ac.abort());
|
|
1721
1734
|
res.on('close', () => ac.abort());
|
|
@@ -761,9 +761,9 @@ FRONTEND:
|
|
|
761
761
|
- index.html: Job board homepage — (1) Hero: gradient background, large search widget (keyword input + location input + category select + Search button), quick stats bar (12,847 Jobs / 3,420 Companies / 45K Candidates). (2) Featured jobs: horizontal scroll row of 4 "Featured" cards with company logo (colored emoji), job title, company name, location + type badge + salary range + "Easy Apply" button. (3) Main layout: left sidebar filters (Job Type checkboxes, Salary Range slider, Category checkboxes, Location input, Posted Within select, Remote Only toggle) + right: jobs list (job row cards with company logo/title/company/location/type/salary/time-ago posted/Save bookmark/Apply button). (4) "Load More" button + results count "Showing 12 of 247 jobs". (5) Top companies section: 8 company cards with logo/name/industry/openings count. (6) Category browsing: 6 category cards with icon/name/count/link. (7) Job seeker CTA banner. (8) Newsletter.
|
|
762
762
|
- job.html: Job detail page — company header (logo + name + industry + website + size + "Follow" button), job title + badges (Remote, Senior, Urgent), salary + location + posted date, Apply Now button (sticky on scroll), job description (markdown-rendered sections: About/Responsibilities/Requirements/Nice-to-Have/Benefits), company sidebar card (description + stats), similar jobs list (4 cards)
|
|
763
763
|
- 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
|
|
764
|
-
- 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`}],RT=[{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:`✉️`}],zT={js:`📄`,ts:`📄`,css:`🎨`,html:`🌐`,json:`📋`,md:`📑`,sql:`🗂`,env:`🔐`,conf:`⚙`,lock:`🔒`};function BT(e){return zT[e.split(`.`).pop()?.toLowerCase()??``]??`📄`}function VT(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 HT(e){return e===`memory`?`🧠`:e===`provider`?`🤖`:e===`log`?`📄`:`📋`}function UT(){let e=j(),[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)(new Set),[w,ee]=(0,_.useState)(!1),[te,T]=(0,_.useState)(``),[ne,re]=(0,_.useState)(``),[ie,O]=(0,_.useState)(!1),[ae,A]=(0,_.useState)(null),[oe,se]=(0,_.useState)(!1),ce=(0,_.useRef)(null),le=(0,_.useRef)(null),ue=(0,_.useRef)(!0),de=(0,_.useRef)(null),M=(0,_.useRef)(null),fe=(0,_.useRef)(null),pe=(0,_.useRef)(null),[me,he]=(0,_.useState)(null),[ge,_e]=(0,_.useState)(!1),[ve,ye]=(0,_.useState)(!1),[be,xe]=(0,_.useState)(0),[Se,N]=(0,_.useState)(0),[Ce,we]=(0,_.useState)(``),[Te,Ee]=(0,_.useState)({fi:0,total:0,name:``}),[P,De]=(0,_.useState)({tokIn:0,tokOut:0}),[Oe,ke]=(0,_.useState)(null),[F,I]=(0,_.useState)([]),[Ae,je]=(0,_.useState)(``),[Me,Ne]=(0,_.useState)(!1),[Pe,Fe]=(0,_.useState)([]),[Ie,Le]=(0,_.useState)(null),[Re,ze]=(0,_.useState)([]),[L,Be]=(0,_.useState)(!1),[Ve,He]=(0,_.useState)(null),[Ue,We]=(0,_.useState)([]),[Ge,Ke]=(0,_.useState)(!1),[qe,Je]=(0,_.useState)(``),[Ye,Xe]=(0,_.useState)([]),[Ze,Qe]=(0,_.useState)([]),[$e,et]=(0,_.useState)([]),[tt,nt]=(0,_.useState)(null),[rt,it]=(0,_.useState)(!1),[at,ot]=(0,_.useState)(null),[st,ct]=(0,_.useState)(`0s`),[lt,ut]=(0,_.useState)(`0s`),dt=(0,_.useRef)(0),ft=(0,_.useRef)(0),R=(0,_.useRef)(null),pt=(0,_.useRef)(null),mt=(0,_.useRef)(null),ht=(0,_.useRef)(null),gt=(0,_.useRef)(null),_t=(0,_.useRef)(null);(0,_.useEffect)(()=>{let e=e=>{if((e.metaKey||e.ctrlKey)&&e.key===`f`&&(e.preventDefault(),ee(e=>!e)),(e.metaKey||e.ctrlKey)&&e.key===`s`&&(e.preventDefault(),b!==null&&p[h])){let e=p[h];m(e=>e.map((e,t)=>t===h?{...e,content:b}:e)),D(`/api/studio/webcraft/file/write`,{projectName:a,path:e.name,content:b}),x(null),C(t=>{let n=new Set(t);return n.delete(e.name),n})}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[b,h,p,a]),(0,_.useEffect)(()=>{let e=()=>{let e=b===null?fe.current:M.current;e&&pe.current&&(pe.current.scrollTop=e.scrollTop)},t=b===null?fe.current:M.current;return t&&t.addEventListener(`scroll`,e),()=>{t&&t.removeEventListener(`scroll`,e)}},[b,h]);function vt(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function yt(e){let t=Math.floor((Date.now()-e)/1e3),n=Math.floor(t/60);return(n>0?`${n}m `:``)+`${t%60}s`}(0,_.useEffect)(()=>(ge||ve?R.current=setInterval(()=>{ge&&ct(yt(dt.current)),ve&&ut(yt(ft.current))},1e3):R.current&&=(clearInterval(R.current),null),()=>{R.current&&clearInterval(R.current)}),[ge,ve]);function z(){mt.current&&(mt.current.scrollTop=mt.current.scrollHeight)}(0,_.useEffect)(()=>{z()},[F]),(0,_.useEffect)(()=>{a&&!L&&(Be(!0),E(`/api/studio/webcraft/skills/${encodeURIComponent(a)}`).then(e=>{e?.skills&&ze(e.skills)}).catch(()=>{}))},[a,L]);async function bt(e,t){if(ge||!e||e.length<5)return;_e(!0),m([]),g(0),y(null),Ee({fi:0,total:0,name:``}),De({tokIn:0,tokOut:0}),dt.current=Date.now(),ct(`0s`),pt.current=new AbortController;let n=Date.now();try{let r=await fetch(`/api/studio/webcraft/generate`,{method:`POST`,headers:{"Content-Type":`application/json`},signal:pt.current.signal,body:JSON.stringify({projectName:t,description:e,blocks:l,authFields:d})});if(!r.ok||!r.body){_e(!1);return}let i=r.body.getReader(),a=pt.current,
|
|
764
|
+
- 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`}],RT=[{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:`✉️`}],zT={js:`📄`,ts:`📄`,css:`🎨`,html:`🌐`,json:`📋`,md:`📑`,sql:`🗂`,env:`🔐`,conf:`⚙`,lock:`🔒`};function BT(e){return zT[e.split(`.`).pop()?.toLowerCase()??``]??`📄`}function VT(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 HT(e){return e===`memory`?`🧠`:e===`provider`?`🤖`:e===`log`?`📄`:`📋`}function UT(){let e=j(),[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)(new Set),[w,ee]=(0,_.useState)(!1),[te,T]=(0,_.useState)(``),[ne,re]=(0,_.useState)(``),[ie,O]=(0,_.useState)(!1),[ae,A]=(0,_.useState)(null),[oe,se]=(0,_.useState)(!1),ce=(0,_.useRef)(null),le=(0,_.useRef)(null),ue=(0,_.useRef)(!0),de=(0,_.useRef)(null),M=(0,_.useRef)(null),fe=(0,_.useRef)(null),pe=(0,_.useRef)(null),[me,he]=(0,_.useState)(null),[ge,_e]=(0,_.useState)(!1),[ve,ye]=(0,_.useState)(!1),[be,xe]=(0,_.useState)(0),[Se,N]=(0,_.useState)(0),[Ce,we]=(0,_.useState)(``),[Te,Ee]=(0,_.useState)({fi:0,total:0,name:``}),[P,De]=(0,_.useState)({tokIn:0,tokOut:0}),[Oe,ke]=(0,_.useState)(null),[F,I]=(0,_.useState)([]),[Ae,je]=(0,_.useState)(``),[Me,Ne]=(0,_.useState)(!1),[Pe,Fe]=(0,_.useState)([]),[Ie,Le]=(0,_.useState)(null),[Re,ze]=(0,_.useState)([]),[L,Be]=(0,_.useState)(!1),[Ve,He]=(0,_.useState)(null),[Ue,We]=(0,_.useState)([]),[Ge,Ke]=(0,_.useState)(!1),[qe,Je]=(0,_.useState)(``),[Ye,Xe]=(0,_.useState)([]),[Ze,Qe]=(0,_.useState)([]),[$e,et]=(0,_.useState)([]),[tt,nt]=(0,_.useState)(null),[rt,it]=(0,_.useState)(!1),[at,ot]=(0,_.useState)(null),[st,ct]=(0,_.useState)(`0s`),[lt,ut]=(0,_.useState)(`0s`),dt=(0,_.useRef)(0),ft=(0,_.useRef)(0),R=(0,_.useRef)(null),pt=(0,_.useRef)(null),mt=(0,_.useRef)(null),ht=(0,_.useRef)(null),gt=(0,_.useRef)(null),_t=(0,_.useRef)(null);(0,_.useEffect)(()=>{let e=e=>{if((e.metaKey||e.ctrlKey)&&e.key===`f`&&(e.preventDefault(),ee(e=>!e)),(e.metaKey||e.ctrlKey)&&e.key===`s`&&(e.preventDefault(),b!==null&&p[h])){let e=p[h];m(e=>e.map((e,t)=>t===h?{...e,content:b}:e)),D(`/api/studio/webcraft/file/write`,{projectName:a,path:e.name,content:b}),x(null),C(t=>{let n=new Set(t);return n.delete(e.name),n})}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[b,h,p,a]),(0,_.useEffect)(()=>{let e=()=>{let e=b===null?fe.current:M.current;e&&pe.current&&(pe.current.scrollTop=e.scrollTop)},t=b===null?fe.current:M.current;return t&&t.addEventListener(`scroll`,e),()=>{t&&t.removeEventListener(`scroll`,e)}},[b,h]);function vt(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function yt(e){let t=Math.floor((Date.now()-e)/1e3),n=Math.floor(t/60);return(n>0?`${n}m `:``)+`${t%60}s`}(0,_.useEffect)(()=>(ge||ve?R.current=setInterval(()=>{ge&&ct(yt(dt.current)),ve&&ut(yt(ft.current))},1e3):R.current&&=(clearInterval(R.current),null),()=>{R.current&&clearInterval(R.current)}),[ge,ve]);function z(){mt.current&&(mt.current.scrollTop=mt.current.scrollHeight)}(0,_.useEffect)(()=>{z()},[F]),(0,_.useEffect)(()=>{a&&!L&&(Be(!0),E(`/api/studio/webcraft/skills/${encodeURIComponent(a)}`).then(e=>{e?.skills&&ze(e.skills)}).catch(()=>{}))},[a,L]);async function bt(e,t){if(ge||!e||e.length<5)return;_e(!0),m([]),g(0),y(null),Ee({fi:0,total:0,name:``}),De({tokIn:0,tokOut:0}),dt.current=Date.now(),ct(`0s`),pt.current=new AbortController;let n=Date.now();try{let r=await fetch(`/api/studio/webcraft/generate`,{method:`POST`,headers:{"Content-Type":`application/json`},signal:pt.current.signal,body:JSON.stringify({projectName:t,description:e,blocks:l,authFields:d})});if(!r.ok||!r.body){_e(!1);return}let i=r.body.getReader(),a=pt.current,s=new TextDecoder,c=``,u=[];for(;;){if(a?.signal?.aborted){try{i.cancel()}catch{}break}let{done:e,value:t}=await i.read();if(e)break;c+=s.decode(t,{stream:!0});let r=c.split(`
|
|
765
765
|
|
|
766
|
-
`);
|
|
766
|
+
`);c=r.pop()??``;for(let e of r){let t=e.replace(/^data: /,``).trim();if(t)try{let e=JSON.parse(t);if(e.type===`project_renamed`)o(e.name);else if(e.type===`processing`||e.type===`planning`)Ee(t=>({...t,name:e.type===`planning`?`📋 Pianificazione struttura...`:e.msg||`Avvio...`}));else if(e.type===`file_start`)u.push({name:e.name,content:``,_pending:!0}),m([...u]),Ee({fi:e.fi,total:e.total,name:e.name}),ce.current=u.length-1,g(u.length-1),y(``),ue.current=!0;else if(e.type===`file_chunk`){let t=u.find(t=>t.name===e.name);t&&(t.content+=e.chunk,t._pending=!1),m([...u]);let n=u.findIndex(t=>t.name===e.name);n>=0&&(ce.current=n,y(t?t.content:null))}else if(e.type===`file_done`){let t=u.find(t=>t.name===e.name);t&&(t._pending=!1,e.syntaxError&&(t._syntaxError=e.syntaxError)),m([...u]),Ee({fi:e.fi,total:e.total,name:e.name}),(e.cumTokIn||e.cumTokOut)&&De({tokIn:e.cumTokIn||0,tokOut:e.cumTokOut||0})}else if(e.type===`file_error`){let t=u.find(t=>t.name===e.name);t&&(t._error=!0,t._pending=!1),m([...u])}else e.type===`phase`||e.type===`status`&&!e.op?Ee(t=>({...t,name:e.msg||e.phase||``})):e.type===`done`&&(ke({seconds:Math.round((Date.now()-n)/1e3),tokIn:e.tokIn??0,tokOut:e.tokOut??0,files:u.length}),y(null),_e(!1),ce.current=null,le.current&&=(clearTimeout(le.current),null),se(!0),Be(!1),ze([]),u.some(e=>e._error||e._syntaxError)?setTimeout(()=>gt.current?.(),800):setTimeout(()=>_t.current?.(),800))}catch{}}}}catch(e){e.name!==`AbortError`&&I(t=>[...t,{role:`system`,text:`Errore generazione: `+e.message}]),_e(!1)}}async function xt(){let e=Ae.trim();if(!(a&&p.length>0)){if(!e||e.length<5)return;let t=a||`MyProject`;o(t),c(e),je(``),await bt(e,t);return}if(!e&&Pe.length===0||Me||ge)return;let t=[...Pe];if(Fe([]),je(``),e.toLowerCase().startsWith(`/plan `)||e.toLowerCase().startsWith(`piano: `)){let t=e.replace(/^\/plan[ ]*/i,``).replace(/^piano:[ ]*/i,``);I(t=>[...t,{role:`user`,text:e}]),await St(`[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}I(n=>[...n,{role:`user`,text:e,attachments:t}]),await St(e,null,t)}async function St(e,t,n){if(Me)return;Ne(!0),a&&p.length>0&&D(`/api/studio/webcraft/snapshot`,{projectName:a}).catch(()=>{});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){I(e=>[...e,{role:`agent`,text:`Errore: ${i.status}`,tools:[]}]),Ne(!1);return}let o={role:`agent`,text:``,tools:[]};I(e=>[...e,o]);let s=i.body.getReader(),c=new TextDecoder,l=``,u=!1,d=``;for(;;){let{done:e,value:n}=await s.read();if(e)break;l+=c.decode(n,{stream:!0});let i=l.split(`
|
|
767
767
|
|
|
768
768
|
`);l=i.pop()??``;for(let e of i){let n=e.replace(/^data: /,``).trim();if(n)try{let e=JSON.parse(n);if(e.type===`text`){d+=e.token;let t=d.lastIndexOf(`<`),n;t>=0&&!d.slice(t).includes(`>`)?(n=d.slice(0,t),d=d.slice(t)):(n=d.replace(/<tool>[\s\S]*?<\/tool>/g,``).replace(/<done\s*\/>/g,``),d=``),n&&(o.text+=n,I(e=>{let t=[...e];return t[t.length-1]={...o},t}))}else if(e.type===`step`)o.text+=`\n\n**[Step ${e.step}/${e.max}]** `,I(e=>{let t=[...e];return t[t.length-1]={...o},t});else if(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`||e.result===`ok_repaired`)&&(u=!0),I(e=>{let t=[...e];return t[t.length-1]={...o},t});else if(e.type===`files_changed`)e.files?.length&&await Ct(e.files,r);else if(e.type===`syntax_errors`)e.errors?.length&&(o.syntaxErrors=e.errors,I(e=>{let t=[...e];return t[t.length-1]={...o},t}));else if(e.type===`sandbox_restart`)o.text+=`
|
|
769
769
|
|
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-CZWTJyRN.js"></script>
|
|
12
12
|
<link rel="stylesheet" crossorigin href="/assets/index-R2XRhcPq.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|