nothumanallowed 13.5.76 → 13.5.78
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 +1 -1
- package/src/commands/ui.mjs +36 -7
- package/src/services/web-ui.mjs +41 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.78",
|
|
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/commands/ui.mjs
CHANGED
|
@@ -4051,6 +4051,30 @@ ${completedHeadings ? `## SECTIONS ALREADY WRITTEN (headings only):\n${completed
|
|
|
4051
4051
|
return;
|
|
4052
4052
|
}
|
|
4053
4053
|
|
|
4054
|
+
// POST /api/studio/webcraft/skills/:name/delete { name } → delete a single skill/log file
|
|
4055
|
+
if (pathname.match(/^\/api\/studio\/webcraft\/skills\/[^/]+\/delete$/) && method === 'POST') {
|
|
4056
|
+
const projName = decodeURIComponent(pathname.replace('/api/studio/webcraft/skills/', '').replace('/delete', '')).replace(/[^a-zA-Z0-9_-]/g, '');
|
|
4057
|
+
const body = await parseBody(req);
|
|
4058
|
+
const fname = (body.name || '').replace(/[^a-zA-Z0-9_. -]/g, '_');
|
|
4059
|
+
if (!fname || !projName) { sendJSON(res, 400, { error: 'invalid' }); return; }
|
|
4060
|
+
// Protect the 3 default .md files from deletion
|
|
4061
|
+
const PROTECTED = new Set(['memory.md', 'liara.md', 'skills.md']);
|
|
4062
|
+
if (PROTECTED.has(fname)) { sendJSON(res, 400, { error: 'protected file' }); return; }
|
|
4063
|
+
const skillsDir = path.join(os.homedir(), '.nha', 'webcraft', projName, 'skills');
|
|
4064
|
+
const filePath = path.join(skillsDir, fname);
|
|
4065
|
+
try { if (fs.existsSync(filePath)) fs.unlinkSync(filePath); } catch(_) {}
|
|
4066
|
+
// Remove from _index.json too
|
|
4067
|
+
const idxPath = path.join(skillsDir, '_index.json');
|
|
4068
|
+
try {
|
|
4069
|
+
let idx = JSON.parse(fs.readFileSync(idxPath, 'utf8'));
|
|
4070
|
+
delete idx[fname];
|
|
4071
|
+
fs.writeFileSync(idxPath, JSON.stringify(idx), 'utf8');
|
|
4072
|
+
} catch(_) {}
|
|
4073
|
+
sendJSON(res, 200, { ok: true });
|
|
4074
|
+
logRequest(method, pathname, 200, Date.now() - start);
|
|
4075
|
+
return;
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4054
4078
|
// GET /api/studio/webcraft/projects/load/:name → { projectName, description, files[] }
|
|
4055
4079
|
if (pathname.startsWith('/api/studio/webcraft/projects/load/') && method === 'GET') {
|
|
4056
4080
|
const projName = decodeURIComponent(pathname.replace('/api/studio/webcraft/projects/load/', '')).replace(/[^a-zA-Z0-9_-]/g, '');
|
|
@@ -4582,15 +4606,18 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
|
|
|
4582
4606
|
sendLog(`✅ Sandbox pronta!`);
|
|
4583
4607
|
|
|
4584
4608
|
// Write sandbox log to skills/ so the agent can read it as context
|
|
4609
|
+
// Always overwrite the same file (latest.log) — no accumulation across restarts
|
|
4585
4610
|
try {
|
|
4586
4611
|
const _nl = '\n';
|
|
4587
|
-
const
|
|
4588
|
-
const
|
|
4612
|
+
const _now = new Date();
|
|
4613
|
+
const _pad = n => String(n).padStart(2,'0');
|
|
4614
|
+
const logTs = _now.getFullYear()+'-'+_pad(_now.getMonth()+1)+'-'+_pad(_now.getDate())+' '+_pad(_now.getHours())+':'+_pad(_now.getMinutes())+':'+_pad(_now.getSeconds());
|
|
4615
|
+
const logName = projName + '-latest.log';
|
|
4589
4616
|
const logsDir = path.join(sandboxDir, 'skills');
|
|
4590
4617
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
4591
|
-
//
|
|
4592
|
-
const
|
|
4593
|
-
|
|
4618
|
+
// Clean up old timestamped log files (migration from previous format)
|
|
4619
|
+
const oldLogs = fs.readdirSync(logsDir).filter(f => f.endsWith('.log') && f.startsWith(projName + '-') && f !== logName);
|
|
4620
|
+
oldLogs.forEach(f => { try { fs.unlinkSync(path.join(logsDir, f)); } catch(_) {} });
|
|
4594
4621
|
const logContent = '# Sandbox Log — ' + projName + _nl + 'Avviato: ' + logTs + _nl + 'Porta: ' + freePort + _nl + _nl + _sbLogLines.join(_nl);
|
|
4595
4622
|
fs.writeFileSync(path.join(logsDir, logName), logContent, 'utf8');
|
|
4596
4623
|
// Also update _index.json so the UI knows the type
|
|
@@ -4606,8 +4633,10 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
|
|
|
4606
4633
|
// Write error log too
|
|
4607
4634
|
try {
|
|
4608
4635
|
const _nl = '\n';
|
|
4609
|
-
const
|
|
4610
|
-
const
|
|
4636
|
+
const _now2 = new Date();
|
|
4637
|
+
const _pad2 = n => String(n).padStart(2,'0');
|
|
4638
|
+
const logTs = _now2.getFullYear()+'-'+_pad2(_now2.getMonth()+1)+'-'+_pad2(_now2.getDate())+' '+_pad2(_now2.getHours())+':'+_pad2(_now2.getMinutes())+':'+_pad2(_now2.getSeconds());
|
|
4639
|
+
const logName = projName + '-latest.log';
|
|
4611
4640
|
const logsDir = path.join(sandboxDir, 'skills');
|
|
4612
4641
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
4613
4642
|
const logContent = '# Sandbox Log — ' + projName + ' [ERRORE]' + _nl + 'Avviato: ' + logTs + _nl + _nl + _sbLogLines.join(_nl) + _nl + _nl + '❌ ERRORE: ' + e.message;
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -6568,14 +6568,19 @@ function renderWebCraft(el) {
|
|
|
6568
6568
|
? '<div id="wcFileTabsRow" style="display:flex;gap:0;overflow-x:auto;border-bottom:1px solid var(--border);margin-bottom:0;flex-shrink:0;scrollbar-width:none">' +
|
|
6569
6569
|
wcState.generatedFiles.map(function(f,i){
|
|
6570
6570
|
var active = i === wcState.activeFile;
|
|
6571
|
-
|
|
6571
|
+
var hasErr = !!f._error;
|
|
6572
|
+
var tabColor = hasErr ? (active ? '#f87171' : '#7f4040') : (active ? 'var(--green)' : 'var(--dim)');
|
|
6573
|
+
var tabBorder = hasErr ? (active ? '#f87171' : 'transparent') : (active ? 'var(--green3)' : 'transparent');
|
|
6574
|
+
return '<button id="wcTab'+i+'" onclick="wcSetFile('+i+')" style="padding:6px 14px;font-size:11px;font-family:var(--mono);font-weight:'+(active?'700':'400')+';background:'+(active?'var(--bg3)':'transparent')+';border:none;border-bottom:2px solid '+tabBorder+';color:'+tabColor+';cursor:pointer;white-space:nowrap;flex-shrink:0">'+(hasErr?'⚠ ':'')+wcEsc(f.name)+'</button>';
|
|
6572
6575
|
}).join('') +
|
|
6573
6576
|
'</div>'
|
|
6574
6577
|
: '';
|
|
6575
6578
|
|
|
6576
|
-
var
|
|
6579
|
+
var _activeFile = wcState.generatedFiles[wcState.activeFile];
|
|
6580
|
+
var codeHtml = wcState.generatedFiles.length > 0 && _activeFile
|
|
6577
6581
|
? '<div id="wcCodeWrap" style="flex:1;overflow:auto;background:var(--bg3);border-radius:0 0 8px 8px">' +
|
|
6578
|
-
'<
|
|
6582
|
+
(_activeFile._error ? '<div style="padding:8px 14px;background:rgba(239,68,68,0.12);border-bottom:1px solid rgba(239,68,68,0.3);font-size:11px;color:#f87171;display:flex;align-items:center;gap:6px">⚠ Generazione fallita — chiedi al modello di rigenerare questo file</div>' : '') +
|
|
6583
|
+
'<pre style="margin:0;padding:14px 16px;font-size:11px;line-height:1.6;color:'+(_activeFile._error?'#f87171':'var(--text)')+';font-family:var(--mono);white-space:pre-wrap;word-break:break-all">'+wcEsc(_activeFile.content)+'</pre>' +
|
|
6579
6584
|
'</div>'
|
|
6580
6585
|
: '<div style="flex:1;display:flex;align-items:center;justify-content:center;color:var(--dim);font-size:12px;flex-direction:column;gap:8px">' +
|
|
6581
6586
|
'<span style="font-size:36px;opacity:.25">🛠</span>' +
|
|
@@ -6786,6 +6791,22 @@ function wcSkillsPanelHtml() {
|
|
|
6786
6791
|
function wcSkillModalHtml() {
|
|
6787
6792
|
if (!wcSkillModal) return '';
|
|
6788
6793
|
var m = wcSkillModal;
|
|
6794
|
+
// Log files: read-only viewer
|
|
6795
|
+
if (m.mode === 'view') {
|
|
6796
|
+
return '<div onclick="wcCloseSkillModal(event)" style="position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:9999;display:flex;align-items:center;justify-content:center">' +
|
|
6797
|
+
'<div onclick="event.stopPropagation()" style="background:var(--bg2);border:1px solid var(--border);border-radius:14px;width:680px;max-width:96vw;max-height:88vh;display:flex;flex-direction:column;overflow:hidden">' +
|
|
6798
|
+
'<div style="padding:14px 20px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px">' +
|
|
6799
|
+
'<span style="font-size:14px">📄</span>' +
|
|
6800
|
+
'<span style="font-size:13px;font-weight:700;color:var(--text);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">'+wcEsc(m.name)+'</span>' +
|
|
6801
|
+
'<span style="font-size:10px;background:#333;color:#aaa;padding:2px 8px;border-radius:10px">log</span>' +
|
|
6802
|
+
'<button onclick="wcCloseSkillModal()" style="background:none;border:none;color:var(--dim);font-size:18px;cursor:pointer;line-height:1;margin-left:4px">×</button>' +
|
|
6803
|
+
'</div>' +
|
|
6804
|
+
'<div style="flex:1;overflow:auto;padding:14px 18px">' +
|
|
6805
|
+
'<pre style="margin:0;font-size:11px;line-height:1.7;color:var(--text);font-family:var(--mono);white-space:pre-wrap;word-break:break-all">'+wcEsc(m.content || '')+'</pre>' +
|
|
6806
|
+
'</div>' +
|
|
6807
|
+
'</div>' +
|
|
6808
|
+
'</div>';
|
|
6809
|
+
}
|
|
6789
6810
|
var isNew = m.mode === 'new';
|
|
6790
6811
|
var charCount = (m.content || '').length;
|
|
6791
6812
|
// Length guidance per type
|
|
@@ -6878,7 +6899,8 @@ function wcNewSkill() {
|
|
|
6878
6899
|
function wcOpenSkill(si) {
|
|
6879
6900
|
var s = wcSkills[si];
|
|
6880
6901
|
if (!s) return;
|
|
6881
|
-
|
|
6902
|
+
var mode = (s.type === 'log') ? 'view' : 'edit';
|
|
6903
|
+
wcSkillModal = { mode: mode, idx: si, name: s.name, content: s.content, type: s.type || 'skill', generating: false };
|
|
6882
6904
|
renderWebCraft(document.getElementById('content'));
|
|
6883
6905
|
}
|
|
6884
6906
|
|
|
@@ -6964,7 +6986,19 @@ async function wcSaveSkill() {
|
|
|
6964
6986
|
}
|
|
6965
6987
|
|
|
6966
6988
|
async function wcDeleteSkill(si) {
|
|
6967
|
-
|
|
6989
|
+
var s = wcSkills[si];
|
|
6990
|
+
if (!s) return;
|
|
6991
|
+
if (!confirm('Eliminare "' + s.name + '"?')) return;
|
|
6992
|
+
// Delete the file on disk via the delete-skill endpoint
|
|
6993
|
+
try {
|
|
6994
|
+
await fetch(API + '/api/studio/webcraft/skills/' + encodeURIComponent(wcState.projectName) + '/delete', {
|
|
6995
|
+
method: 'POST',
|
|
6996
|
+
headers: {'Content-Type':'application/json'},
|
|
6997
|
+
body: JSON.stringify({ name: s.name })
|
|
6998
|
+
});
|
|
6999
|
+
} catch(_) {}
|
|
7000
|
+
wcSkills.splice(si, 1);
|
|
7001
|
+
renderWebCraft(document.getElementById('content'));
|
|
6968
7002
|
}
|
|
6969
7003
|
|
|
6970
7004
|
async function wcPersistSkills() {
|
|
@@ -7872,7 +7906,7 @@ async function wcGenerate() {
|
|
|
7872
7906
|
renderWebCraft(document.getElementById('content'));
|
|
7873
7907
|
} catch(e) {
|
|
7874
7908
|
if (e && e.name === 'AbortError') break;
|
|
7875
|
-
wcState.generatedFiles.push({ name: fp.name, content: '// Error generating this file: ' + (e.message || 'unknown error'), lang: fp.lang });
|
|
7909
|
+
wcState.generatedFiles.push({ name: fp.name, content: '// Error generating this file: ' + (e.message || 'unknown error'), lang: fp.lang, _error: true });
|
|
7876
7910
|
if (fi === 0) wcState.activeFile = 0;
|
|
7877
7911
|
renderWebCraft(document.getElementById('content'));
|
|
7878
7912
|
}
|
|
@@ -8066,7 +8100,7 @@ async function wcStartSandbox() {
|
|
|
8066
8100
|
headers: {'Content-Type':'application/json'},
|
|
8067
8101
|
body: JSON.stringify({
|
|
8068
8102
|
projectName: wcState.projectName || 'webcraft-sandbox',
|
|
8069
|
-
files: wcState.generatedFiles
|
|
8103
|
+
files: wcState.generatedFiles.filter(function(f){ return !f._error; })
|
|
8070
8104
|
})
|
|
8071
8105
|
});
|
|
8072
8106
|
if (!r.ok || !r.body) throw new Error('Sandbox error ' + r.status);
|