nothumanallowed 14.4.0 → 14.4.2

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.0",
3
+ "version": "14.4.2",
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.0';
8
+ export const VERSION = '14.4.2';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -38,6 +38,92 @@ function deleteWorkflow(id) {
38
38
  if (fs.existsSync(p)) fs.unlinkSync(p);
39
39
  }
40
40
 
41
+ /** Seed example workflows on first run */
42
+ function seedExamples() {
43
+ ensureDir();
44
+ const marker = path.join(WORKFLOWS_DIR, '.examples-seeded');
45
+ if (fs.existsSync(marker)) return;
46
+
47
+ const examples = [
48
+ {
49
+ id: 'ex_email_digest', name: '📧 Daily Email Digest',
50
+ enabled: false,
51
+ nodes: [
52
+ { id: 'n1', defId: 'trigger_cron', x: 40, y: 80, config: { schedule: '0 8 * * *' } },
53
+ { id: 'n2', defId: 'ai_summarize', x: 200, y: 80, config: { prompt: 'Summarize the last 10 unread emails concisely: {{output}}' } },
54
+ { id: 'n3', defId: 'action_slack', x: 400, y: 40, config: { channel: '#general', text: '📧 Morning Digest:\n{{output}}' } },
55
+ { id: 'n4', defId: 'action_notify', x: 400, y: 140, config: { message: 'Email digest ready', channel: 'system' } },
56
+ ],
57
+ edges: [{ from: 'n1', to: 'n2' }, { from: 'n2', to: 'n3' }, { from: 'n2', to: 'n4' }],
58
+ },
59
+ {
60
+ id: 'ex_smart_router', name: '🔀 Smart Email Router',
61
+ enabled: false,
62
+ nodes: [
63
+ { id: 'n1', defId: 'trigger_email', x: 40, y: 100, config: { filter: 'is:unread' } },
64
+ { id: 'n2', defId: 'ai_classify', x: 200, y: 100, config: { categories: 'urgent, meeting, newsletter, spam', prompt: 'Classify this email: {{output}}' } },
65
+ { id: 'n3', defId: 'logic_if', x: 380, y: 100, config: { condition: 'output.includes("urgent")' } },
66
+ { id: 'n4', defId: 'action_notify', x: 560, y: 40, config: { message: '🚨 Urgent email: {{output}}', channel: 'telegram' } },
67
+ { id: 'n5', defId: 'action_task', x: 560, y: 160, config: { title: 'Review: {{output}}', priority: 'low' } },
68
+ ],
69
+ edges: [
70
+ { from: 'n1', to: 'n2' }, { from: 'n2', to: 'n3' },
71
+ { from: 'n3', to: 'n4', fromPort: 'true' },
72
+ { from: 'n3', to: 'n5', fromPort: 'false' },
73
+ ],
74
+ },
75
+ {
76
+ id: 'ex_content_pipeline', name: '📝 Content Pipeline',
77
+ enabled: false,
78
+ nodes: [
79
+ { id: 'n1', defId: 'trigger_manual', x: 40, y: 100, config: { input: 'Write a blog post about AI agents' } },
80
+ { id: 'n2', defId: 'ai_agent', x: 200, y: 100, config: { agent: 'quill', prompt: 'Write a professional blog post about: {{output}}' } },
81
+ { id: 'n3', defId: 'ai_translate', x: 400, y: 40, config: { lang: 'Italian', prompt: '{{output}}' } },
82
+ { id: 'n4', defId: 'action_drive', x: 600, y: 40, config: { name: 'blog-it.md', content: '{{output}}' } },
83
+ { id: 'n5', defId: 'action_drive', x: 400, y: 160, config: { name: 'blog-en.md', content: '{{output}}' } },
84
+ ],
85
+ edges: [{ from: 'n1', to: 'n2' }, { from: 'n2', to: 'n3' }, { from: 'n2', to: 'n5' }, { from: 'n3', to: 'n4' }],
86
+ },
87
+ {
88
+ id: 'ex_meeting_prep', name: '📅 Meeting Prep Automation',
89
+ enabled: false,
90
+ nodes: [
91
+ { id: 'n1', defId: 'trigger_cron', x: 40, y: 100, config: { schedule: '0 7 * * 1-5' } },
92
+ { id: 'n2', defId: 'ai_agent', x: 200, y: 100, config: { agent: 'herald', prompt: 'List my meetings for today with details' } },
93
+ { id: 'n3', defId: 'logic_if', x: 380, y: 100, config: { condition: 'output.length > 20' } },
94
+ { id: 'n4', defId: 'ai_summarize', x: 540, y: 40, config: { prompt: 'Prepare a brief for each meeting. Include talking points: {{output}}' } },
95
+ { id: 'n5', defId: 'action_email', x: 720, y: 40, config: { to: 'me', subject: '📅 Meeting Prep — Today', body: '{{output}}' } },
96
+ ],
97
+ edges: [
98
+ { from: 'n1', to: 'n2' }, { from: 'n2', to: 'n3' },
99
+ { from: 'n3', to: 'n4', fromPort: 'true' },
100
+ ],
101
+ },
102
+ {
103
+ id: 'ex_web_monitor', name: '🌐 Website Monitor + Alert',
104
+ enabled: false,
105
+ nodes: [
106
+ { id: 'n1', defId: 'trigger_cron', x: 40, y: 100, config: { schedule: '*/30 * * * *' } },
107
+ { id: 'n2', defId: 'action_webhook', x: 200, y: 100, config: { url: 'https://nothumanallowed.com', method: 'GET' } },
108
+ { id: 'n3', defId: 'logic_if', x: 380, y: 100, config: { condition: 'output.includes("Error") || output.length < 100' } },
109
+ { id: 'n4', defId: 'action_notify', x: 560, y: 40, config: { message: '🚨 Website down or error detected!', channel: 'telegram' } },
110
+ { id: 'n5', defId: 'logic_error', x: 560, y: 160, config: { retries: '2', fallback: 'Check failed — site may be unreachable' } },
111
+ ],
112
+ edges: [
113
+ { from: 'n1', to: 'n2' }, { from: 'n2', to: 'n3' },
114
+ { from: 'n3', to: 'n4', fromPort: 'true' },
115
+ { from: 'n3', to: 'n5', fromPort: 'false' },
116
+ ],
117
+ },
118
+ ];
119
+
120
+ for (const wf of examples) {
121
+ const p = path.join(WORKFLOWS_DIR, `${wf.id}.json`);
122
+ if (!fs.existsSync(p)) fs.writeFileSync(p, JSON.stringify(wf, null, 2));
123
+ }
124
+ fs.writeFileSync(marker, new Date().toISOString());
125
+ }
126
+
41
127
  /** Substitute {{varName}} placeholders in a string using a context map */
42
128
  function interpolate(str, ctx) {
43
129
  if (typeof str !== 'string') return str;
@@ -278,6 +364,7 @@ export function register(router) {
278
364
  // GET /api/workflows — list all workflows
279
365
  router.get('/api/workflows', async (req, res) => {
280
366
  try {
367
+ seedExamples();
281
368
  sendJSON(res, 200, { workflows: listWorkflows() });
282
369
  } catch (e) {
283
370
  sendError(res, 500, e.message);
@@ -1031,41 +1031,40 @@ RULES:
1031
1031
 
1032
1032
  // ── Generation pipeline (SSE) ─────────────────────────────────────────────────
1033
1033
 
1034
- const FILE_PLAN_SYSTEM = `You are the lead architect of a 200-person engineering team. Design an ENTERPRISE-GRADE file structure.
1035
- Output ONLY a JSON array: [{"name":"path/to/file.ext","purpose":"detailed description","tokens":N}]
1036
- where "tokens" is your estimate of content tokens (300-800 small, 1000-2500 medium, 2500-5000 large).
1037
-
1038
- MANDATORY STRUCTURE (every project MUST have):
1039
- - package.json (with ALL dependencies: express, helmet, cors, compression, morgan, bcryptjs, jsonwebtoken, express-rate-limit, cookie-parser, dotenv)
1040
- - .env.example (all env vars documented)
1041
- - README.md (setup guide, API docs, architecture overview)
1042
- - server.js (Express with full middleware stack)
1043
- - routes/ (separate file per resource — auth.js, api.js, pages.js)
1044
- - middleware/ (auth.js, error.js, validate.js, rateLimiter.js)
1045
- - models/ (per-entity files with validation)
1046
- - controllers/ (business logic separated from routes)
1047
- - utils/ (jwt.js, hash.js, logger.js, helpers.js)
1048
- - config/ (database.js, constants.js)
1049
- - public/index.html (hero, features, testimonials, pricing, CTA, footer — complete landing page)
1050
- - public/login.html (login + register forms with validation)
1051
- - public/dashboard.html (protected page with real UI)
1052
- - public/css/variables.css (CSS custom properties: colors, fonts, spacing, breakpoints)
1053
- - public/css/reset.css (modern CSS reset)
1054
- - public/css/layout.css (grid/flexbox layouts, nav, hero, sections)
1055
- - public/css/components.css (buttons, cards, forms, modals, toasts, badges)
1056
- - public/css/animations.css (keyframes, transitions, scroll animations)
1057
- - public/css/responsive.css (media queries, mobile nav)
1058
- - public/js/app.js (SPA router, init, dark mode toggle)
1059
- - public/js/auth.js (login/register/logout, token management)
1060
- - public/js/api.js (fetch wrapper with auth headers, error handling)
1061
- - public/js/ui.js (toasts, modals, loading spinners, form validation)
1062
- - public/js/animations.js (intersection observer, scroll effects)
1063
-
1064
- RULES:
1065
- - Generate 25-45 files — real enterprise projects have many files
1066
- - Token estimates must be realistic: CSS files 1500-3000, JS files 1000-2000, HTML pages 2000-4000
1067
- - Use relative paths only
1068
- - No explanation, no markdown, ONLY the JSON array.`;
1034
+ const FILE_PLAN_SYSTEM = `You are a senior architect. Design a MINIMAL but COMPLETE working website.
1035
+ Output ONLY a JSON array: [{"name":"path/file.ext","purpose":"description","tokens":N}]
1036
+
1037
+ CRITICAL RULES:
1038
+ - Generate 8-15 files MAXIMUM — every file must be COMPLETE and WORKING
1039
+ - Each file should be 100-300 lines substantial but not truncated
1040
+ - Token estimate per file: 500-2000 tokens (no file should need more than 2500)
1041
+ - The generated site must work IMMEDIATELY when you run "node server.js"
1042
+ - Users can add more features later via chat — start with a solid foundation
1043
+
1044
+ REQUIRED FILES:
1045
+ 1. package.json — dependencies (express, helmet, cors, compression, morgan, bcryptjs, jsonwebtoken, dotenv, cookie-parser, express-rate-limit)
1046
+ 2. .env.example environment variables
1047
+ 3. server.js — Express server with ALL middleware, routes, and static serving
1048
+ 4. public/index.html — COMPLETE landing page (hero, features, footer — all CSS inline in <style>, all JS inline in <script>)
1049
+ 5. public/login.html — Login + register page (complete with inline CSS/JS, form validation, API calls)
1050
+ 6. public/css/style.css — ONE main stylesheet (variables, reset, layout, components, responsive — everything in one file)
1051
+ 7. public/js/app.js — Main JS (SPA routing, auth, API client, dark mode, toasts, form validation)
1052
+ 8. middleware/auth.js JWT authentication middleware
1053
+ 9. routes/auth.js — Auth routes (register, login, logout, refresh)
1054
+ 10. models/user.js User model with JSON file storage
1055
+
1056
+ OPTIONAL (only if the project type requires them):
1057
+ - routes/api.js REST API routes for the specific project
1058
+ - public/dashboard.html Protected dashboard page
1059
+ - Additional pages specific to the project type
1060
+
1061
+ DO NOT generate:
1062
+ - Separate CSS files per component (put everything in style.css)
1063
+ - Separate JS files per feature (put everything in app.js)
1064
+ - README.md, .gitignore (not essential for a working site)
1065
+ - Animation/responsive separate files
1066
+
1067
+ Output ONLY the JSON array, no explanation.`;
1069
1068
 
1070
1069
  // Token counter — approximate based on character count (1 token ≈ 4 chars)
1071
1070
  function countTokens(text) {
@@ -1192,20 +1191,36 @@ function _isSeverelyTruncated(content, filename) {
1192
1191
  }
1193
1192
 
1194
1193
  async function runGenerate(config, projectName, description, blocks, authFields, emit, abortSignal) {
1195
- const blocksDesc = Object.entries(blocks)
1196
- .filter(([, enabled]) => enabled)
1197
- .map(([key]) => key)
1198
- .join(', ');
1194
+ // Blocks write to memory.md as TODO features (NOT generated now)
1195
+ const enabledBlocks = Object.entries(blocks).filter(([, enabled]) => enabled).map(([key]) => key);
1199
1196
  const authDesc = blocks.auth
1200
1197
  ? `Auth fields: ${authFields.map((f) => `${f.label}(${f.type}${f.required ? ',required' : ''})`).join(', ')}`
1201
1198
  : '';
1202
1199
 
1200
+ // Save blocks as planned features in memory.md
1201
+ SkillStore.ensureDefaults(projectName, config);
1202
+ if (enabledBlocks.length > 0) {
1203
+ const ctxDir = SkillStore.dir(projectName);
1204
+ const memPath = path.join(ctxDir, 'memory.md');
1205
+ const blockInstructions = `# ${projectName} — Project Memory
1206
+
1207
+ ## Planned Features (ask the AI agent to implement these one by one)
1208
+ ${enabledBlocks.includes('auth') ? `- [ ] **Authentication** (register/login/JWT) — ${authDesc || 'email + password'}\n` : ''}${enabledBlocks.includes('cookieBanner') ? '- [ ] **GDPR Cookie Banner** — consent modal, localStorage tracking\n' : ''}${enabledBlocks.includes('securityMiddleware') ? '- [ ] **Security Middleware** — helmet CSP, rate limiting, CORS\n' : ''}${enabledBlocks.includes('emailVerification') ? '- [ ] **Email Verification** — send verification link, confirm endpoint\n' : ''}
1209
+ ## How to implement
1210
+ Ask the AI in chat: "Add authentication" or "Add cookie banner" — the agent will modify your code.
1211
+
1212
+ ## Architecture Decisions
1213
+ _Add notes here as you build._
1214
+ `;
1215
+ fs.writeFileSync(memPath, blockInstructions, 'utf-8');
1216
+ }
1217
+
1203
1218
  const planPrompt = `Project: ${projectName}
1204
1219
  Description: ${description}
1205
- ${blocksDesc ? `Required blocks: ${blocksDesc}` : ''}
1206
- ${authDesc}
1207
1220
 
1208
- Design a COMPLETE production-ready file structure. Include ALL files needed for a fully working site: server, routes, middleware, models, public HTML/CSS/JS pages, config files, README. Minimum 20 files.`;
1221
+ Design a MINIMAL but COMPLETE file structure for a working website.
1222
+ Focus on the core: a beautiful landing page, server, and main CSS/JS.
1223
+ The user will add features like auth, cookie banner, etc. later via chat.`;
1209
1224
 
1210
1225
  // Emit immediately so the browser connection stays alive and the UI shows activity
1211
1226
  emit({ type: 'processing', msg: 'Planning file structure...' });
@@ -1285,9 +1300,9 @@ Design a COMPLETE production-ready file structure. Include ALL files needed for
1285
1300
  })
1286
1301
  .join('\n\n');
1287
1302
 
1288
- // Generous max_tokens — enterprise files are large
1289
- const estimatedTokens = fileSpec.tokens || 2000;
1290
- const maxTokens = Math.min(Math.max(estimatedTokens * 3, 4000), 16384);
1303
+ // max_tokens — generous for fewer, more complete files
1304
+ const estimatedTokens = fileSpec.tokens || 1500;
1305
+ const maxTokens = Math.min(Math.max(estimatedTokens * 3, 3000), 12000);
1291
1306
 
1292
1307
  const fileSys = `You are a team of 200 senior full-stack developers generating ENTERPRISE-GRADE production code.
1293
1308
 
@@ -1321,12 +1336,12 @@ FRONTEND STANDARDS:
1321
1336
  - Accessible: aria-labels, focus styles, keyboard navigation, alt text
1322
1337
  - Professional typography: system font stack, proper hierarchy (clamp() for fluid sizes)
1323
1338
  - CSS Grid/Flexbox layouts — no floats
1324
- - At minimum 500 lines for main CSS files, 200+ lines for page JS files`;
1339
+ - Each file must be COMPLETE and SELF-CONTAINED no truncation
1340
+ - Maximum 200 lines per file. If more content needed, split into separate files
1341
+ - HTML: external CSS/JS via link/script tags, NOT inline styles/scripts exceeding 20 lines`;
1325
1342
 
1326
1343
  const filePrompt = `Project: ${projectName}
1327
1344
  Description: ${description}
1328
- ${blocksDesc ? `Enabled blocks: ${blocksDesc}` : ''}
1329
- ${authDesc}
1330
1345
  Full project file list: ${allFileNames}
1331
1346
 
1332
1347
  NOW GENERATE: ${fileSpec.name}