mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-17 10:00:46 -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-status-bar-style" content="black-translucent" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
||||||
<title>Multi Roomba Rover</title>
|
<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">
|
<link rel="stylesheet" crossorigin href="/assets/index-C_i0uH-D.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ let status = {
|
|||||||
lastOutcome: null,
|
lastOutcome: null,
|
||||||
lastReason: null,
|
lastReason: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
|
lastErrorDetails: null,
|
||||||
lastPromptReadAt: null,
|
lastPromptReadAt: null,
|
||||||
lastPromptChars: 0,
|
lastPromptChars: 0,
|
||||||
lastSystemPrompt: null,
|
lastSystemPrompt: null,
|
||||||
@@ -205,11 +206,67 @@ function clearRuntimeHistory() {
|
|||||||
lastPostedText: null,
|
lastPostedText: null,
|
||||||
lastPostedAt: null,
|
lastPostedAt: null,
|
||||||
lastError: null,
|
lastError: null,
|
||||||
|
lastErrorDetails: null,
|
||||||
lastOutcome: 'cleared',
|
lastOutcome: 'cleared',
|
||||||
lastReason: 'admin requested clear history',
|
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 = {}) {
|
function isChargingFromSensors(sensors = {}) {
|
||||||
const label = String(sensors?.chargingState?.label || '').toLowerCase();
|
const label = String(sensors?.chargingState?.label || '').toLowerCase();
|
||||||
if (label === 'waiting' || label === 'full charging' || label === 'trickle charging') {
|
if (label === 'waiting' || label === 'full charging' || label === 'trickle charging') {
|
||||||
@@ -686,11 +743,18 @@ async function runTick() {
|
|||||||
lastPostedAt: Date.now(),
|
lastPostedAt: Date.now(),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} 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({
|
updateStatus({
|
||||||
lastOutcome: 'failed',
|
lastOutcome: 'failed',
|
||||||
lastReason: 'exception',
|
lastReason: failure.reason,
|
||||||
lastError: err.message,
|
lastError: failure.message,
|
||||||
|
lastErrorDetails: failure.details,
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
inFlight = false;
|
inFlight = false;
|
||||||
|
|||||||
@@ -351,6 +351,14 @@ function LlmCommentaryPanel({ status, onClearHistory, clearingHistory }) {
|
|||||||
Error: {status.lastError}
|
Error: {status.lastError}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : 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 ? (
|
{status.lastGeneratedText ? (
|
||||||
<div className="surface text-xs text-slate-200 break-words">
|
<div className="surface text-xs text-slate-200 break-words">
|
||||||
Generated: {status.lastGeneratedText}
|
Generated: {status.lastGeneratedText}
|
||||||
|
|||||||
Reference in New Issue
Block a user