nothumanallowed 13.5.54 → 13.5.55

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": "13.5.54",
3
+ "version": "13.5.55",
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": {
@@ -3913,11 +3913,59 @@ ${completedHeadings ? `## SECTIONS ALREADY WRITTEN (headings only):\n${completed
3913
3913
  // Write meta
3914
3914
  const meta = { projectName: projName, description: body.description || '', files: (body.files || []).map(f => f.name), createdAt: new Date().toISOString() };
3915
3915
  fs.writeFileSync(path.join(projDir, 'webcraft-meta.json'), JSON.stringify(meta, null, 2), 'utf8');
3916
+ // Write agent memory file — always included as first context for WebCraft Agent
3917
+ const agentMd = [
3918
+ '# WebCraft Agent Memory — ' + projName,
3919
+ '> Auto-generated. Edit to give the agent persistent context about this project.',
3920
+ '',
3921
+ '## Progetto',
3922
+ '- **Nome**: ' + projName,
3923
+ '- **Descrizione**: ' + (body.description || ''),
3924
+ '- **Creato**: ' + new Date().toISOString(),
3925
+ '',
3926
+ '## Stack',
3927
+ '- Server: Express.js (Node.js)',
3928
+ '- Auth: JWT (access 15min, refresh 7d httpOnly cookie) + bcryptjs cost 12',
3929
+ '- DB: PostgreSQL (sandbox: in-memory shim in server/db.js)',
3930
+ '- CSS: BEM methodology',
3931
+ '- Security: helmet, express-rate-limit, custom sentinel WAF middleware',
3932
+ '',
3933
+ '## File principali',
3934
+ (body.files || []).map(f => '- ' + f.name).join('\n'),
3935
+ '',
3936
+ '## Note agente',
3937
+ '(aggiungi qui note per sessioni future — es. "usa Tailwind invece di BEM", "API key in .env.local")',
3938
+ ].join('\n');
3939
+ fs.writeFileSync(path.join(projDir, 'webcraft-agent.md'), agentMd, 'utf8');
3916
3940
  sendJSON(res, 200, { ok: true, dir: projDir });
3917
3941
  logRequest(method, pathname, 200, Date.now() - start);
3918
3942
  return;
3919
3943
  }
3920
3944
 
3945
+ // POST /api/studio/webcraft/projects/chat/save { projectName, chat[] }
3946
+ if (pathname === '/api/studio/webcraft/projects/chat/save' && method === 'POST') {
3947
+ const body = await parseBody(req, 2 * 1024 * 1024);
3948
+ const projName = (body.projectName || '').replace(/[^a-zA-Z0-9_-]/g, '-');
3949
+ if (!projName) { sendJSON(res, 400, { error: 'projectName required' }); return; }
3950
+ const projDir = path.join(os.homedir(), '.nha', 'webcraft', projName);
3951
+ fs.mkdirSync(projDir, { recursive: true });
3952
+ fs.writeFileSync(path.join(projDir, 'webcraft-chat.json'), JSON.stringify(body.chat || [], null, 2), 'utf8');
3953
+ sendJSON(res, 200, { ok: true });
3954
+ logRequest(method, pathname, 200, Date.now() - start);
3955
+ return;
3956
+ }
3957
+
3958
+ // GET /api/studio/webcraft/projects/chat/load/:name
3959
+ if (pathname.startsWith('/api/studio/webcraft/projects/chat/load/') && method === 'GET') {
3960
+ const projName = decodeURIComponent(pathname.replace('/api/studio/webcraft/projects/chat/load/', '')).replace(/[^a-zA-Z0-9_-]/g, '');
3961
+ const chatPath = path.join(os.homedir(), '.nha', 'webcraft', projName, 'webcraft-chat.json');
3962
+ if (!fs.existsSync(chatPath)) { sendJSON(res, 200, { chat: [] }); return; }
3963
+ const chat = JSON.parse(fs.readFileSync(chatPath, 'utf8'));
3964
+ sendJSON(res, 200, { chat });
3965
+ logRequest(method, pathname, 200, Date.now() - start);
3966
+ return;
3967
+ }
3968
+
3921
3969
  // GET /api/studio/webcraft/projects/load/:name → { projectName, description, files[] }
3922
3970
  if (pathname.startsWith('/api/studio/webcraft/projects/load/') && method === 'GET') {
3923
3971
  const projName = decodeURIComponent(pathname.replace('/api/studio/webcraft/projects/load/', '')).replace(/[^a-zA-Z0-9_-]/g, '');
@@ -4147,6 +4195,13 @@ module.exports = { get, set, del, exists };
4147
4195
  [/require\(['"]\.\/config\/database['"]\)/g, "require('./db')"],
4148
4196
  [/require\(['"]\.\.\/config\/db['"]\)/g, "require('../db')"],
4149
4197
  [/require\(['"]\.\/config\/db['"]\)/g, "require('./db')"],
4198
+ // email utils: LLM puts utils/email but file is in services/email
4199
+ [/require\(['"]\.\.\/utils\/email['"]\)/g, "require('../services/email')"],
4200
+ [/require\(['"]\.\/utils\/email['"]\)/g, "require('./services/email')"],
4201
+ // config module: LLM generates require('../../config') or require('../config')
4202
+ [/require\(['"]\.\.\/\.\.\/config['"]\)/g, "{env:process.env}"],
4203
+ [/require\(['"]\.\.\/config['"]\)/g, "{env:process.env}"],
4204
+ [/require\(['"]\.\/config['"]\)/g, "{env:process.env}"],
4150
4205
  ];
4151
4206
  function patchJsFiles(dir) {
4152
4207
  if (!fs.existsSync(dir)) return;
@@ -4350,6 +4405,10 @@ module.exports = { get, set, del, exists };
4350
4405
  const sendEv = (data) => { try { res.write(`data: ${JSON.stringify(data)}\n\n`); } catch {} };
4351
4406
 
4352
4407
  try {
4408
+ // Always read agent memory file first if present
4409
+ const agentMemoryPath = path.join(sandboxDir, 'webcraft-agent.md');
4410
+ const agentMemory = fs.existsSync(agentMemoryPath) ? fs.readFileSync(agentMemoryPath, 'utf8') : '';
4411
+
4353
4412
  // Read all project files to give agent full context
4354
4413
  const allFiles = [];
4355
4414
  if (fs.existsSync(sandboxDir)) {
@@ -4407,7 +4466,7 @@ Il tuo lavoro e di correggere, migliorare ed espandere il codice del progetto sa
4407
4466
 
4408
4467
  PROGETTO ATTIVO: ${projectName}
4409
4468
  PERCORSO: ${sandboxDir}
4410
-
4469
+ ${agentMemory ? '\nMEMORIA PROGETTO:\n' + agentMemory + '\n' : ''}
4411
4470
  FILE DISPONIBILI:
4412
4471
  ${fileList}
4413
4472
 
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '13.5.54';
8
+ export const VERSION = '13.5.55';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -6572,10 +6572,13 @@ async function wcChatSend() {
6572
6572
  }
6573
6573
  } else if (ev.type === 'done') {
6574
6574
  wcChatRunning = false;
6575
- if (ev.changed) {
6576
- // Reload project files from disk
6577
- wcReloadProjectFiles();
6578
- }
6575
+ if (ev.changed) { wcReloadProjectFiles(); }
6576
+ // Persist chat to disk
6577
+ fetch(API + '/api/studio/webcraft/projects/chat/save', {
6578
+ method: 'POST',
6579
+ headers: {'Content-Type':'application/json'},
6580
+ body: JSON.stringify({ projectName: wcState.projectName, chat: wcChat })
6581
+ }).catch(function(){});
6579
6582
  } else if (ev.type === 'restart_sandbox') {
6580
6583
  wcStartSandbox();
6581
6584
  } else if (ev.type === 'error') {
@@ -6731,7 +6734,13 @@ async function wcLoadProject(pi) {
6731
6734
  wcState.activeFile = 0;
6732
6735
  wcMainTab = 'new';
6733
6736
  wcRightTab = 'files';
6737
+ // Load persisted chat history
6738
+ try {
6739
+ var cr = await fetch(API + '/api/studio/webcraft/projects/chat/load/' + encodeURIComponent(wcState.projectName));
6740
+ if (cr.ok) { var cd = await cr.json(); wcChat = cd.chat || []; }
6741
+ } catch(_) { wcChat = []; }
6734
6742
  renderWebCraft(document.getElementById('content'));
6743
+ wcScrollChatToBottom();
6735
6744
  }
6736
6745
 
6737
6746
  async function wcDeleteProject(pi) {