The agent's status is the CLI's word, not whether a process runs
Desktop said "running" as soon as `lembas service run` was started, while the CLI was still dialling, waiting for a terminal that holds the link, or refused by the server -- the reason went only to agent.log. Now the supervisor reads what the CLI itself writes: `service.json` in its state directory (connecting, linked, waiting + why, stopped + why) for the pid it started, the line it printed before that, and its last line when it ends. A service the app did not start is described the same way. A run the CLI ends with 0 because trying again will not help (a refused token, no login) is no longer restarted every second: it waits five minutes, or until linking again starts it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4 files changed
+323
-20
No files matched your search
+26
-4
@@ -9,12 +9,35 @@ const WORDS = {
|
||||
off: () => t("agent off"),
|
||||
not_linked: () => t("not linked"),
|
||||
starting: () => t("agent starting…"),
|
||||
connecting: () => t("agent connecting…"),
|
||||
running: () => t("agent running"),
|
||||
waiting: () => t("agent waiting"),
|
||||
refused: () => t("agent refused"),
|
||||
elsewhere: () => t("agent running (service)"),
|
||||
elsewhere_waiting: () => t("agent waiting"),
|
||||
failed: () => t("agent stopped"),
|
||||
no_folders: () => t("agent: no folders"),
|
||||
}
|
||||
|
||||
/**
|
||||
* The pill's state: what the CLI says of its link, not whether a process runs. Linked but allowed
|
||||
* into no folder is said too -- a green light would say it works when it cannot.
|
||||
*/
|
||||
export function pillState(s) {
|
||||
const a = s.agent
|
||||
const noFolders = s.remote && !(s.remote.enabled && s.remote.roots.length)
|
||||
const linked = a.state === "running" || (a.state === "elsewhere" && a.detail?.linked)
|
||||
if (linked && noFolders) return "no_folders"
|
||||
if (a.state === "elsewhere" && !a.detail?.linked) return "elsewhere_waiting"
|
||||
return a.state
|
||||
}
|
||||
|
||||
/** Why the agent is not working, in the CLI's words, when it said. */
|
||||
export function agentWhy(a) {
|
||||
if (a.state === "elsewhere") return a.detail?.why || ""
|
||||
return typeof a.detail === "string" ? a.detail : ""
|
||||
}
|
||||
|
||||
export function renderBar(s) {
|
||||
let host = ""
|
||||
try {
|
||||
@@ -22,12 +45,11 @@ export function renderBar(s) {
|
||||
} catch {}
|
||||
$("host").textContent = host
|
||||
$("host").title = s.server || ""
|
||||
// Connected but allowed into no folder: a green light would say it works when it cannot.
|
||||
const noFolders = s.remote && !(s.remote.enabled && s.remote.roots.length)
|
||||
const state = s.agent.state === "running" && noFolders ? "no_folders" : s.agent.state
|
||||
const state = pillState(s)
|
||||
const reason = agentWhy(s.agent)
|
||||
$("agent").dataset.state = state
|
||||
$("agent-text").textContent = WORDS[state] ? WORDS[state]() : state
|
||||
$("agent").title = state === "failed" ? t("Agent stopped: %(why)s", { why: s.agent.detail }) : t("Agent")
|
||||
$("agent").title = reason ? t("Agent: %(why)s", { why: reason }) : t("Agent")
|
||||
$("update").hidden = !s.update
|
||||
$("update").textContent = s.update ? t("update %(version)s", { version: s.update }) : t("update")
|
||||
$("update").title = s.update ? t("LLeMbas %(version)s is available (this is %(current)s)", { version: s.update, current: s.version }) : ""
|
||||
|
||||
Reference in new issue
Block a user