No error is a dead end: crash, click, and your agent is already looking
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -710,6 +710,77 @@ ShellRoot {
|
||||
function onReloadFailed(error: string): void {
|
||||
console.warn("Panama shell reload failed:", error);
|
||||
Quickshell.inhibitReloadPopup();
|
||||
root.offerReloadDiagnosis(error);
|
||||
}
|
||||
}
|
||||
|
||||
// ── The reload-failure rung of the escalation ladder ─────────────────────
|
||||
//
|
||||
// This is the failure most likely to happen while somebody is customizing
|
||||
// the desktop, and the one they are least equipped to read: a QML parse
|
||||
// error in the journal, and a shell that silently keeps running the old
|
||||
// configuration. That "keeps running" is what makes the rung possible --
|
||||
// the shell that failed to load the change is not the shell answering
|
||||
// here, so it can still say so and still offer the log to an agent.
|
||||
//
|
||||
// Sent through notify-send rather than constructed in-process on purpose:
|
||||
// it takes the same delivery path, the same per-application rules and the
|
||||
// same `panama-exec` click as every other rung, so there is one mechanism
|
||||
// to keep working rather than two.
|
||||
//
|
||||
// Everything below is guarded. A handler that throws on a failed reload
|
||||
// turns one bad save into a broken desktop, so a fault in the offer must
|
||||
// cost nothing beyond the offer.
|
||||
function offerReloadDiagnosis(error: string): void {
|
||||
try {
|
||||
if (DesktopPreferences.get("reloadFailureOffer") !== true)
|
||||
return;
|
||||
|
||||
// No agent chosen is the shipped default, and it means exactly
|
||||
// what it says: the desktop stays quiet rather than volunteering a
|
||||
// tool nobody asked for. The old actionless behaviour, verbatim.
|
||||
const agent = String(DesktopPreferences.get("preferredAgent") ?? "none");
|
||||
if (agent === "" || agent === "none")
|
||||
return;
|
||||
|
||||
const spec = PreferenceSchema.spec("preferredAgent");
|
||||
const option = (spec?.options ?? []).find(entry => entry.value === agent);
|
||||
const label = option ? option.label : agent;
|
||||
|
||||
// The failing message goes to the launcher as ONE single-quoted
|
||||
// argument, so nothing a QML parse error can contain -- and they
|
||||
// contain plenty of punctuation -- ends the quoting and starts a
|
||||
// command of its own. `panama-agent-reload` reads the rest of the
|
||||
// context out of the journal itself.
|
||||
const summary = String(error ?? "").replace(/\s+/g, " ").trim().slice(0, 500);
|
||||
|
||||
// The launcher is reached by path rather than by name: the shell
|
||||
// is started by systemd, whose environment does not carry the
|
||||
// repo's bin directory on PATH. Same expansion the
|
||||
// panama-crash-watch unit uses.
|
||||
const command = '"${PANAMA_PATH:-$HOME/.local/share/Panama}/bin/panama-agent-reload" '
|
||||
+ root.shellQuote(summary);
|
||||
|
||||
// Ordinary urgency, the same as the crash rung's. A critical
|
||||
// notification never expires and can break through Do Not Disturb,
|
||||
// which is a louder desktop than anybody asked for in exchange for
|
||||
// an offer that keeps in history until it is read anyway.
|
||||
Quickshell.execDetached([
|
||||
"notify-send", "--app-name=Panama",
|
||||
"--icon=dialog-error-symbolic",
|
||||
"--hint=string:panama-exec:" + command,
|
||||
"The shell could not reload your change",
|
||||
"The previous configuration is still running. Click to hand the failure to "
|
||||
+ label + "."
|
||||
]);
|
||||
} catch (problem) {
|
||||
console.warn("Panama shell reload failure offer skipped:", problem);
|
||||
}
|
||||
}
|
||||
|
||||
// POSIX single-quoting: everything between the quotes is literal, and the
|
||||
// only character that needs care is the quote itself.
|
||||
function shellQuote(text: string): string {
|
||||
return "'" + String(text).replace(/'/g, "'\\''") + "'";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user