nothumanallowed 13.5.76 → 13.5.77
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 +30 -2
- package/src/services/web-ui.mjs +31 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nothumanallowed",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.77",
|
|
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, '');
|
|
@@ -4584,7 +4608,9 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
|
|
|
4584
4608
|
// Write sandbox log to skills/ so the agent can read it as context
|
|
4585
4609
|
try {
|
|
4586
4610
|
const _nl = '\n';
|
|
4587
|
-
const
|
|
4611
|
+
const _now = new Date();
|
|
4612
|
+
const _pad = n => String(n).padStart(2,'0');
|
|
4613
|
+
const logTs = _now.getFullYear()+'-'+_pad(_now.getMonth()+1)+'-'+_pad(_now.getDate())+' '+_pad(_now.getHours())+':'+_pad(_now.getMinutes())+':'+_pad(_now.getSeconds());
|
|
4588
4614
|
const logName = projName + '-' + logTs.replace(/[: ]/g, '-') + '.log';
|
|
4589
4615
|
const logsDir = path.join(sandboxDir, 'skills');
|
|
4590
4616
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
@@ -4606,7 +4632,9 @@ module.exports = { validateEmail, sanitizeText, validatePassword, validateUserna
|
|
|
4606
4632
|
// Write error log too
|
|
4607
4633
|
try {
|
|
4608
4634
|
const _nl = '\n';
|
|
4609
|
-
const
|
|
4635
|
+
const _now2 = new Date();
|
|
4636
|
+
const _pad2 = n => String(n).padStart(2,'0');
|
|
4637
|
+
const logTs = _now2.getFullYear()+'-'+_pad2(_now2.getMonth()+1)+'-'+_pad2(_now2.getDate())+' '+_pad2(_now2.getHours())+':'+_pad2(_now2.getMinutes())+':'+_pad2(_now2.getSeconds());
|
|
4610
4638
|
const logName = projName + '-' + logTs.replace(/[: ]/g, '-') + '-ERROR.log';
|
|
4611
4639
|
const logsDir = path.join(sandboxDir, 'skills');
|
|
4612
4640
|
fs.mkdirSync(logsDir, { recursive: true });
|
package/src/services/web-ui.mjs
CHANGED
|
@@ -6786,6 +6786,22 @@ function wcSkillsPanelHtml() {
|
|
|
6786
6786
|
function wcSkillModalHtml() {
|
|
6787
6787
|
if (!wcSkillModal) return '';
|
|
6788
6788
|
var m = wcSkillModal;
|
|
6789
|
+
// Log files: read-only viewer
|
|
6790
|
+
if (m.mode === 'view') {
|
|
6791
|
+
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">' +
|
|
6792
|
+
'<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">' +
|
|
6793
|
+
'<div style="padding:14px 20px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px">' +
|
|
6794
|
+
'<span style="font-size:14px">📄</span>' +
|
|
6795
|
+
'<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>' +
|
|
6796
|
+
'<span style="font-size:10px;background:#333;color:#aaa;padding:2px 8px;border-radius:10px">log</span>' +
|
|
6797
|
+
'<button onclick="wcCloseSkillModal()" style="background:none;border:none;color:var(--dim);font-size:18px;cursor:pointer;line-height:1;margin-left:4px">×</button>' +
|
|
6798
|
+
'</div>' +
|
|
6799
|
+
'<div style="flex:1;overflow:auto;padding:14px 18px">' +
|
|
6800
|
+
'<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>' +
|
|
6801
|
+
'</div>' +
|
|
6802
|
+
'</div>' +
|
|
6803
|
+
'</div>';
|
|
6804
|
+
}
|
|
6789
6805
|
var isNew = m.mode === 'new';
|
|
6790
6806
|
var charCount = (m.content || '').length;
|
|
6791
6807
|
// Length guidance per type
|
|
@@ -6878,7 +6894,8 @@ function wcNewSkill() {
|
|
|
6878
6894
|
function wcOpenSkill(si) {
|
|
6879
6895
|
var s = wcSkills[si];
|
|
6880
6896
|
if (!s) return;
|
|
6881
|
-
|
|
6897
|
+
var mode = (s.type === 'log') ? 'view' : 'edit';
|
|
6898
|
+
wcSkillModal = { mode: mode, idx: si, name: s.name, content: s.content, type: s.type || 'skill', generating: false };
|
|
6882
6899
|
renderWebCraft(document.getElementById('content'));
|
|
6883
6900
|
}
|
|
6884
6901
|
|
|
@@ -6964,7 +6981,19 @@ async function wcSaveSkill() {
|
|
|
6964
6981
|
}
|
|
6965
6982
|
|
|
6966
6983
|
async function wcDeleteSkill(si) {
|
|
6967
|
-
|
|
6984
|
+
var s = wcSkills[si];
|
|
6985
|
+
if (!s) return;
|
|
6986
|
+
if (!confirm('Eliminare "' + s.name + '"?')) return;
|
|
6987
|
+
// Delete the file on disk via the delete-skill endpoint
|
|
6988
|
+
try {
|
|
6989
|
+
await fetch(API + '/api/studio/webcraft/skills/' + encodeURIComponent(wcState.projectName) + '/delete', {
|
|
6990
|
+
method: 'POST',
|
|
6991
|
+
headers: {'Content-Type':'application/json'},
|
|
6992
|
+
body: JSON.stringify({ name: s.name })
|
|
6993
|
+
});
|
|
6994
|
+
} catch(_) {}
|
|
6995
|
+
wcSkills.splice(si, 1);
|
|
6996
|
+
renderWebCraft(document.getElementById('content'));
|
|
6968
6997
|
}
|
|
6969
6998
|
|
|
6970
6999
|
async function wcPersistSkills() {
|