aboutsummaryrefslogtreecommitdiff
path: root/modules/core/core-bundle.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/core/core-bundle.js')
-rw-r--r--modules/core/core-bundle.js46
1 files changed, 46 insertions, 0 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js
index d1793b2..449a80c 100644
--- a/modules/core/core-bundle.js
+++ b/modules/core/core-bundle.js
@@ -5455,6 +5455,7 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
'errors': 'errors [n] — Show last n ERROR log entries (default: 20)',
'doctor': 'doctor — Run all health checks, rank issues, show top 3 warnings',
'bug-report': 'bug-report — Generate a markdown bug report to /tmp/ for debugging',
+ 'bug': 'bug <title> — File a structured bug report (stored server-side, visible in BUG-REPORT.html)',
'preview': 'preview <file.html> — Render an HTML file from the VFS in a preview pane',
'reset': 'reset [mem|vfs|config|all] — Global reset command (default: mem)',
'factory-reset': 'factory-reset — Alias for reset all',
@@ -5745,6 +5746,48 @@ Only output XML function calls for tool tasks. If no tool is needed, answer norm
}
};
+ // v4.6.37: bug — file a structured report to the backend (Part A)
+ this.commands['bug'] = async (args) => {
+ const title = (args || []).join(' ').trim() || 'Untitled bug report';
+ const diag = {
+ version: window.NEWOS4_VERSION || 'unknown',
+ url: location.href,
+ ua: navigator.userAgent,
+ online: navigator.onLine,
+ modules: Object.keys(this.terminal.moduleManager.modules).length,
+ errors: [],
+ };
+ try {
+ const raw = JSON.parse(localStorage.getItem('webx11_debug_db') || '[]');
+ const list = Array.isArray(raw) ? raw : (raw.errors || []);
+ diag.errors = list.slice(-20).map(e => ({
+ message: String(e.message || e.msg || '').slice(0, 300),
+ source: String(e.source || e.url || '').slice(0, 200),
+ count: Number(e.count) || 1,
+ }));
+ } catch (_e) {}
+ try {
+ diag.recent_commands = JSON.parse(localStorage.getItem('webx11_command_history') || '[]')
+ .slice(-10)
+ .map(c => String(c).replace(/(password|token|secret|api[_-]?key)\S*/ig, '$1:[redacted]'));
+ } catch (_e) {}
+
+ this.terminal.print('📮 Filing bug report…', 'info');
+ let res = null, err = null;
+ try {
+ const r = await fetch('/spaces/newos4/api/debug/report.php', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ title, diagnostics: diag }),
+ });
+ res = await r.json();
+ if (!r.ok) err = res.error || ('HTTP ' + r.status);
+ } catch (e) { err = e.message; }
+ if (err) { this.terminal.print('❌ Report failed: ' + err, 'error'); return; }
+ this.terminal.print('✅ Report filed: ' + res.id + (res.duplicate ? ' (already known)' : ''), 'success');
+ this.terminal.print(' View: /spaces/newos4/downloads/bugs/BUG-REPORT.html', 'info');
+ };
+
this.commands['preview'] = (args) => this.terminal.openPreview(args);
// v4.5.64: reset — unified reset command superseding factory-reset, reset-vfs, reset-mem, config-reset
@@ -19764,6 +19807,9 @@ class DebugSupervisorModule {
window.fetch = function() {
const args = arguments;
const url = typeof args[0] === 'string' ? args[0] : (args[0]?.url || '?');
+ // Never record failures of the debug-sync endpoint itself: that produced a
+ // self-referential loop (38,495 identical "Fetch failed …/ingest.php" entries).
+ if (url.indexOf('/api/debug/') !== -1) return self._originalFetch.apply(window, args);
return self._originalFetch.apply(window, args).catch(function(err) {
self._recordError('Fetch failed: ' + url + ' — ' + (err.message || err), url, err.stack);
throw err;