aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-aiassist.js
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-05-27 06:00:43 +0200
committerAgando <roduccomm@gmail.com>2026-05-27 06:00:43 +0200
commit212708b464c2bdbdd9670c00804623dca0729d2c (patch)
treeee190cbb0d1524350baea641df65aa19817744b5 /modules/core/module-aiassist.js
parentf4d934d341056142da1212c845eeeb170fd452c2 (diff)
auto: 2026-05-27_06:00 changes
Diffstat (limited to 'modules/core/module-aiassist.js')
-rw-r--r--modules/core/module-aiassist.js49
1 files changed, 39 insertions, 10 deletions
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js
index f9e1e98..e983e6a 100644
--- a/modules/core/module-aiassist.js
+++ b/modules/core/module-aiassist.js
@@ -538,6 +538,22 @@ RULES:
}
return null;
}
+ _trackToolFailure(toolName, error) {
+ try {
+ const key = 'webx11_tool_failures';
+ const raw = localStorage.getItem(key) || '{}';
+ const map = JSON.parse(raw);
+ if (!map[toolName]) map[toolName] = { count: 0, last: '', errors: [] };
+ map[toolName].count++;
+ map[toolName].last = new Date().toISOString();
+ map[toolName].errors.push(error);
+ if (map[toolName].errors.length > 5) map[toolName].errors.shift();
+ localStorage.setItem(key, JSON.stringify(map));
+ if (map[toolName].count >= 3) {
+ this.terminal.print(`⚠️ Tool '${toolName}' has failed ${map[toolName].count} times. Consider creating a workaround skill.`, 'warning');
+ }
+ } catch (e) { /* ignore */ }
+ }
async agenticLoop(messages) {
let toolTurns = 0;
while (toolTurns < this.MAX_TOOL_TURNS) {
@@ -579,8 +595,11 @@ RULES:
const obs = this._summarizeObservation(toolResult, 150);
const err = this._isToolError(toolResult);
if (err) {
+ this.terminal.log('WARN', 'AI', `Tool ${fn.name} failed: ${err} (${t1}s)`);
+ this._trackToolFailure(fn.name, err);
this.terminal.print(`📊 Result (${t1}s): ⚠️ Error: ${err}`, 'warning');
} else {
+ this.terminal.log('INFO', 'AI', `Tool ${fn.name} ok (${t1}s)`);
this.terminal.print(`📊 Result (${t1}s): ${obs}`, 'info');
}
messages.push({ role: 'tool', content: toolResult });
@@ -598,8 +617,11 @@ RULES:
const dObs = this._summarizeObservation(toolResult, 150);
const dErr = this._isToolError(toolResult);
if (dErr) {
+ this.terminal.log('WARN', 'AI', `Tool ${fn.name} failed: ${dErr} (${t1}s)`);
+ this._trackToolFailure(fn.name, dErr);
this.terminal.print(`📊 Result (${t1}s): ⚠️ Error: ${dErr}`, 'warning');
} else {
+ this.terminal.log('INFO', 'AI', `Tool ${fn.name} ok (${t1}s)`);
this.terminal.print(`📊 Result (${t1}s): ${dObs}`, 'info');
}
messages.push({ role: 'tool', content: toolResult });
@@ -803,8 +825,9 @@ RULES:
return name === 'write_file' || name === 'delete_file' || name === 'run_command' || name === 'make_directory' || name === 'edit_module';
}
async runTool(name, argsStr) {
+ let a = {};
try {
- const a = typeof argsStr === 'object' ? argsStr : (argsStr ? JSON.parse(argsStr) : {});
+ a = typeof argsStr === 'object' ? argsStr : (argsStr ? JSON.parse(argsStr) : {});
switch (name) {
case 'list_files': {
const originalPath = a.path || '';
@@ -1058,7 +1081,7 @@ RULES:
for (const [name, meta] of Object.entries(index)) {
const score = (name.includes(query) ? 3 : 0) + (meta.description.toLowerCase().includes(query) ? 2 : 0) + ((meta.tags || []).some(t => t.toLowerCase().includes(query)) ? 2 : 0);
if (score > 0) {
- const content = fs.fsRead(`/skills/${name}.md`) || '';
+ const content = fs.readFile(`/skills/${name}.md`) || '';
matches.push({ name, description: meta.description, category: meta.category, score, content: content.substring(0, 2000) });
}
}
@@ -1078,7 +1101,7 @@ RULES:
}
const fs = this.terminal.fs;
fs.mkdirRecursive('/skills');
- fs.fsWrite(`/skills/${name}.md`, content);
+ fs.writeFile(`/skills/${name}.md`, content);
const index = fs.fsReadJSON('/skills/index.json') || {};
index[name] = { name, description, tags, category, created: index[name]?.created || new Date().toISOString(), updated: new Date().toISOString() };
fs.fsWriteJSON('/skills/index.json', index);
@@ -1093,7 +1116,7 @@ RULES:
const fs = this.terminal.fs;
const index = fs.fsReadJSON('/skills/index.json') || {};
if (!index[pname]) return JSON.stringify({ error: `Skill "${pname}" not found` });
- fs.fsWrite(`/skills/${pname}.md`, pcontent);
+ fs.writeFile(`/skills/${pname}.md`, pcontent);
index[pname].updated = new Date().toISOString();
// Re-parse frontmatter for metadata updates
const metaMatch = pcontent.match(/^---\n([\s\S]*?)\n---/);
@@ -1134,8 +1157,10 @@ RULES:
}
}
async runModuleTool(name, argsStr) {
- const a = typeof argsStr === 'object' ? argsStr : (argsStr ? JSON.parse(argsStr) : {});
- switch (name) {
+ let a = {};
+ try {
+ a = typeof argsStr === 'object' ? argsStr : (argsStr ? JSON.parse(argsStr) : {});
+ switch (name) {
case 'view_module': {
const modName = a.name || '';
const entry = this.terminal.moduleManager.moduleRegistry.find(m => m.name === modName);
@@ -1211,6 +1236,10 @@ RULES:
return JSON.stringify({ modules, total: modules.length, hasLocalEdits: hasMods });
}
default: return JSON.stringify({ error: `Unknown module tool: ${name}` });
+ }
+ } catch (e) {
+ this._errorLog.push({ tool: name, args: a, error: e.message, timestamp: Date.now() });
+ return JSON.stringify({ error: e.message, stack: e.stack?.substring(0, 200) });
}
}
clearContext() {
@@ -1358,11 +1387,11 @@ category: productivity
- User says "map out", "diagram", "brainstorm", "organize thoughts"
- Visualizing project structure or task decomposition`;
- fs.fsWrite('/skills/mindmap-user-guide.md', mindmapSkill);
+ fs.writeFile('/skills/mindmap-user-guide.md', mindmapSkill);
const existingIndex = fs.fsReadJSON('/skills/index.json') || {};
existingIndex['mindmap-user-guide'] = { name: 'mindmap-user-guide', description: 'How to create, view, and manage brainstorming mindmaps using the mindmap terminal module', tags: ['mindmap', 'brainstorming', 'organization', 'planning'], category: 'productivity', created: existingIndex['mindmap-user-guide']?.created || new Date().toISOString(), updated: new Date().toISOString() };
fs.fsWriteJSON('/skills/index.json', existingIndex);
- fs.fsWrite('/skills/_seeded', '1');
+ fs.writeFile('/skills/_seeded', '1');
}
_trackPattern(userMessage) {
const lower = userMessage.toLowerCase();
@@ -1381,7 +1410,7 @@ category: productivity
for (const [tool, errors] of Object.entries(grouped)) {
if (errors.length >= 3) {
const skillName = 'tool-' + tool + '-workaround';
- const existing = this.terminal.fs.fsRead('/skills/' + skillName + '.md');
+ const existing = this.terminal.fs.readFile('/skills/' + skillName + '.md');
if (existing) continue;
const steps = errors.map((e, i) => (i + 1) + '. When calling ' + tool + ', avoid: "' + JSON.stringify(e.args) + '" which caused: ' + e.error).join('\n');
const content = '---\nname: ' + skillName + '\ndescription: Workarounds for ' + tool + ' failures\ntags: [' + tool + ', error, workaround]\ncategory: system\n---\n## Steps\n' + steps;
@@ -1397,7 +1426,7 @@ category: productivity
const now = Date.now();
const issues = [];
for (const [name, meta] of Object.entries(index)) {
- const content = fs.fsRead('/skills/' + name + '.md');
+ const content = fs.readFile('/skills/' + name + '.md');
if (!content || content.length < 50) {
issues.push({ name, issue: 'empty or too short' });
continue;