nothumanallowed 14.1.41 → 14.1.43

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.41",
3
+ "version": "14.1.43",
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.41';
8
+ export const VERSION = '14.1.43';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11
 
@@ -19,7 +19,7 @@ import { createServer } from 'net';
19
19
  import { promisify } from 'util';
20
20
  import { sendJSON, sendError, parseBody, sendSSE } from '../index.mjs';
21
21
  import { loadConfig } from '../../config.mjs';
22
- import { callLLM, callLLMStream } from '../../services/llm.mjs';
22
+ import { callLLM, callLLMStream, fixQwen3BPE } from '../../services/llm.mjs';
23
23
  import { NHA_DIR } from '../../constants.mjs';
24
24
 
25
25
  const execAsync = promisify(exec);
@@ -443,11 +443,34 @@ RULES:
443
443
  - After each tool use, continue explaining what you did
444
444
  `;
445
445
 
446
+ // Load memory.md and skills.md for context
447
+ const ctxDir = SkillStore.dir(projectName);
448
+ let skillContext = '';
449
+ try {
450
+ const memPath = path.join(ctxDir, 'memory.md');
451
+ const skillsPath = path.join(ctxDir, 'skills.md');
452
+ const providerPath = path.join(ctxDir, `${config.llm?.provider || 'nha'}.md`);
453
+
454
+ if (fs.existsSync(memPath)) {
455
+ const memContent = fs.readFileSync(memPath, 'utf-8');
456
+ skillContext += `\n### MEMORY:\n${memContent}\n`;
457
+ }
458
+ if (fs.existsSync(skillsPath)) {
459
+ const skillsContent = fs.readFileSync(skillsPath, 'utf-8');
460
+ skillContext += `\n### SKILLS:\n${skillsContent}\n`;
461
+ }
462
+ if (fs.existsSync(providerPath)) {
463
+ const providerContent = fs.readFileSync(providerPath, 'utf-8');
464
+ skillContext += `\n### MODEL INFO:\n${providerContent}\n`;
465
+ }
466
+ } catch {}
467
+
446
468
  const systemPrompt = [
447
469
  `You are WebCraft Agent, an expert full-stack developer. Today is ${today}. Respond in ${language}.`,
448
470
  `\n\n## PROJECT: ${projectName}`,
449
471
  `\n## FILES:\n${fileIndex}`,
450
- skillCtx ? `\n\n## CONTEXT (Skills/Memory):\n${skillCtx}` : '',
472
+ skillContext,
473
+ skillCtx ? `\n\n## ADDITIONAL CONTEXT:\n${skillCtx}` : '',
451
474
  attachments?.length ? `\n\n## ATTACHMENTS: ${attachments.map((a) => a.name).join(', ')}` : '',
452
475
  `\n\n## CURRENT FILE CONTENTS:\n${fileContents}`,
453
476
  `\n\n${toolSpec}`,
@@ -464,8 +487,10 @@ RULES:
464
487
 
465
488
  await callLLMStream(config, systemPrompt, userContent, (token) => {
466
489
  fullResponse += token;
490
+ // Apply BPE fix for better Italian text quality
491
+ const fixedToken = fixQwen3BPE(token);
467
492
  // Suppress raw <tool> blocks from text stream — only emit visible text
468
- const visibleToken = token.replace(/<tool>[\s\S]*?<\/tool>/g, '');
493
+ const visibleToken = fixedToken.replace(/<tool>[\s\S]*?<\/tool>/g, '');
469
494
  if (visibleToken) emit({ type: 'text', token: visibleToken });
470
495
  }, { max_tokens: 8192 });
471
496
 
@@ -521,6 +546,17 @@ RULES:
521
546
  }
522
547
  }
523
548
 
549
+ // Log chat interaction to changes.log.md
550
+ if (hasChanges) {
551
+ try {
552
+ const ctxDir = SkillStore.dir(projectName);
553
+ const logFile = path.join(ctxDir, 'changes.log.md');
554
+ const timestamp = new Date().toISOString();
555
+ const logEntry = `\n## ${timestamp.slice(0, 16).replace('T', ' ')} — Chat modification\n- User: ${message.slice(0, 100)}${message.length > 100 ? '...' : ''}\n- Files modified: ${fullResponse.match(/<tool>[\s\S]*?"op":"(write|edit)"[\s\S]*?"path":"([^"]+)"[\s\S]*?<\/tool>/g)?.map(m => m.match(/"path":"([^"]+)"/)?.[1]).filter(Boolean).join(', ') || 'none'}\n`;
556
+ fs.writeFileSync(logFile, (fs.existsSync(logFile) ? fs.readFileSync(logFile, 'utf-8') : '') + logEntry, 'utf-8');
557
+ } catch {}
558
+ }
559
+
524
560
  emit({ type: 'done', changed: hasChanges });
525
561
  }
526
562
 
@@ -824,8 +860,37 @@ This approach ensures agents have the right context without being overwhelmed by
824
860
  `;
825
861
  fs.writeFileSync(skillsFile, skillsContent, 'utf-8');
826
862
  }
863
+ // Initialize provider-specific file (liara.md, claude.md, etc.)
864
+ const config = loadConfig();
865
+ const provider = config.llm?.provider || 'nha';
866
+ const model = config.llm?.model || '';
867
+ const providerFile = path.join(ctxDir, `${provider}.md`);
868
+ if (!fs.existsSync(providerFile)) {
869
+ const providerContent = `# ${provider.toUpperCase()} Model Configuration
870
+
871
+ ## Current Model: ${model || 'Default'}
872
+
873
+ ### Model Characteristics
874
+ - **Provider**: ${provider}
875
+ - **Model**: ${model || 'Default model for this provider'}
876
+ - **Context Window**: Varies by model
877
+ - **Strengths**: Add specific strengths of this model
878
+ - **Limitations**: Add specific limitations to be aware of
879
+
880
+ ### Best Practices for This Model
881
+ - Write specific coding patterns this model excels at
882
+ - Note any formatting preferences
883
+ - Document prompt engineering tips that work well
884
+
885
+ ### Configuration Notes
886
+ - Add any specific configuration notes for this provider
887
+ - Document any rate limits or special considerations
888
+ `;
889
+ fs.writeFileSync(providerFile, providerContent, 'utf-8');
890
+ }
891
+
827
892
  const logFile = path.join(ctxDir, 'changes.log.md');
828
- const logEntry = `## ${new Date().toISOString().slice(0, 10)} — Initial generation\n- Generated ${generatedFiles.length} files\n- Tokens in: ${totalTokensIn} / out: ${totalTokensOut}\n- Description: ${description}\n`;
893
+ const logEntry = `## ${new Date().toISOString().slice(0, 10)} — Initial generation\n- Generated ${generatedFiles.length} files\n- Tokens in: ${totalTokensIn} / out: ${totalTokensOut}\n- Description: ${description}\n- Provider: ${provider} (${model || 'default'})\n`;
829
894
  fs.writeFileSync(logFile, (fs.existsSync(logFile) ? fs.readFileSync(logFile, 'utf-8') : '') + logEntry, 'utf-8');
830
895
 
831
896
  emit({ type: 'done', tokIn: totalTokensIn, tokOut: totalTokensOut });