mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
failmodeling
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
||||
<title>Multi Roomba Rover</title>
|
||||
<script type="module" crossorigin src="/assets/index-CkACp-FG.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CS__Wyws.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-C_i0uH-D.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -66,6 +66,7 @@ let status = {
|
||||
lastOutcome: null,
|
||||
lastReason: null,
|
||||
lastError: null,
|
||||
lastErrorDetails: null,
|
||||
lastPromptReadAt: null,
|
||||
lastPromptChars: 0,
|
||||
lastSystemPrompt: null,
|
||||
@@ -205,11 +206,67 @@ function clearRuntimeHistory() {
|
||||
lastPostedText: null,
|
||||
lastPostedAt: null,
|
||||
lastError: null,
|
||||
lastErrorDetails: null,
|
||||
lastOutcome: 'cleared',
|
||||
lastReason: 'admin requested clear history',
|
||||
});
|
||||
}
|
||||
|
||||
function buildFailureInfo(err) {
|
||||
const details = {};
|
||||
if (err && typeof err === 'object') {
|
||||
if (err.name) details.name = String(err.name);
|
||||
if (err.code != null) details.code = String(err.code);
|
||||
if (err.errno != null) details.errno = String(err.errno);
|
||||
if (err.type) details.type = String(err.type);
|
||||
if (err.status != null) details.status = Number(err.status);
|
||||
if (err.statusCode != null) details.statusCode = Number(err.statusCode);
|
||||
if (err.status_code != null) details.status_code = Number(err.status_code);
|
||||
if (err.error) details.error = typeof err.error === 'string' ? err.error : JSON.stringify(err.error);
|
||||
if (err.cause) {
|
||||
if (typeof err.cause === 'string') {
|
||||
details.cause = err.cause;
|
||||
} else if (typeof err.cause === 'object') {
|
||||
details.cause = {
|
||||
name: err.cause.name || null,
|
||||
message: err.cause.message || null,
|
||||
code: err.cause.code || null,
|
||||
status: err.cause.status ?? err.cause.statusCode ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (err.response && typeof err.response === 'object') {
|
||||
const response = {};
|
||||
if (err.response.status != null) response.status = Number(err.response.status);
|
||||
if (err.response.statusText) response.statusText = String(err.response.statusText);
|
||||
if (err.response.url) response.url = String(err.response.url);
|
||||
if (Object.keys(response).length) {
|
||||
details.response = response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const message =
|
||||
(err && typeof err === 'object' && typeof err.message === 'string' && err.message.trim()) ||
|
||||
details.error ||
|
||||
String(err || 'Unknown error');
|
||||
|
||||
const reasonParts = [];
|
||||
if (details.name) reasonParts.push(details.name);
|
||||
const code = details.code || details.errno || details.type;
|
||||
if (code) reasonParts.push(String(code));
|
||||
const status =
|
||||
details.status ??
|
||||
details.statusCode ??
|
||||
details.status_code ??
|
||||
details.response?.status ??
|
||||
null;
|
||||
if (status != null) reasonParts.push(`status ${status}`);
|
||||
const reason = reasonParts.length ? reasonParts.join(' | ') : 'exception';
|
||||
|
||||
return { reason, message, details: Object.keys(details).length ? details : null };
|
||||
}
|
||||
|
||||
function isChargingFromSensors(sensors = {}) {
|
||||
const label = String(sensors?.chargingState?.label || '').toLowerCase();
|
||||
if (label === 'waiting' || label === 'full charging' || label === 'trickle charging') {
|
||||
@@ -686,11 +743,18 @@ async function runTick() {
|
||||
lastPostedAt: Date.now(),
|
||||
});
|
||||
} catch (err) {
|
||||
logger.warn('Commentary tick failed', { tickId, error: err.message });
|
||||
const failure = buildFailureInfo(err);
|
||||
logger.warn('Commentary tick failed', {
|
||||
tickId,
|
||||
reason: failure.reason,
|
||||
error: failure.message,
|
||||
details: failure.details,
|
||||
});
|
||||
updateStatus({
|
||||
lastOutcome: 'failed',
|
||||
lastReason: 'exception',
|
||||
lastError: err.message,
|
||||
lastReason: failure.reason,
|
||||
lastError: failure.message,
|
||||
lastErrorDetails: failure.details,
|
||||
});
|
||||
} finally {
|
||||
inFlight = false;
|
||||
|
||||
@@ -351,6 +351,14 @@ function LlmCommentaryPanel({ status, onClearHistory, clearingHistory }) {
|
||||
Error: {status.lastError}
|
||||
</div>
|
||||
) : null}
|
||||
{status.lastErrorDetails ? (
|
||||
<details className="surface text-xs text-red-200">
|
||||
<summary className="cursor-pointer select-none text-red-300">Failure details</summary>
|
||||
<pre className="mt-0.5 whitespace-pre-wrap break-words text-[0.72rem] text-red-200">
|
||||
{JSON.stringify(status.lastErrorDetails, null, 2)}
|
||||
</pre>
|
||||
</details>
|
||||
) : null}
|
||||
{status.lastGeneratedText ? (
|
||||
<div className="surface text-xs text-slate-200 break-words">
|
||||
Generated: {status.lastGeneratedText}
|
||||
|
||||
Reference in New Issue
Block a user