get_nexus_info and a server-side attention roll-up #155

Open
opened 2026-09-15 18:24:45 +02:00 by lz · 0 comments
Owner

The tool that answers "is anything waiting on me?" from a phone without opening Nexus. Arguably the highest-value tool in the set, and the only one needing new derivation rather than a wrapper over an existing service call.

Depends on #154. Scope: nexus:read.

Contents

/api/state phase, quota, and the fleet-wide attention roll-up.

The roll-up is the work

nexus/src/lib/attention.ts derives a session's mark client-side today and only ever paints the web UI. Exposing it is what makes the tool useful.

It has three inputs, and the third is the one people drop (AGENTS.md fact #26): the roster row, its health probe, and whether the workspace is running at all. stopWorker writes workers.status and never touches a session row, so every session of a deliberately stopped workspace still reads status: 'running' while its probe reports the container down. Derived without the third input, a workspace stopped on purpose reports its whole fleet entry as failing.

Read health.health, never health.claudeRunning. The field is three-valued, and its 'unknown' arm (container gone, session row gone) ships claudeRunning: false as a placeholder rather than an observation — so the boolean turns "we could not look" into "claude is dead". It also decides the opposite way from unhealthyReason in Sessions.svelte, which gates on the same field.

Within a running workspace the split is: the probe owns whether claude is alive, attention owns what a live agent is doing. An absent claude stays errored except when the row reported ended, which only SessionEnd can say and which never fires for a crash. The converse matters as much: a live claude makes an ended report stale, so it is ignored rather than believed.

attention_state being null is not idle — it means the feature has not reported yet.

Structure

Lift the derivation so client and server share one implementation, rather than reimplementing it server-side. A second copy will diverge, and the failure is a phone that disagrees with the browser about whether you are needed — which is worse than no tool at all.

Note convergeSessions nulls attention for a workspace that is not running, so seeded or fake rows lose their state within a poll. Stub the roster when testing.

Unknown is not falsy

Three signals in this area disagree and none may be inferred from a falsy value (fact #19): rate_limits is an absent key until the first inference call; context_window.used_percentage is null while its sibling total_input_tokens is 0; per-session cost is simply missing after a Nexus restart. A quota window whose resets_at has passed is unknown, not zero — getAccountQuota prunes it as a read-time filter, and the tool must serialize that as unknown rather than fabricating a number.

Done when

Asking Claude "does anything need me?" from a phone gives the same answer the sidebar gives in a browser, including for a deliberately stopped workspace, and the shared derivation is proven by a test that fails if either side is changed alone.

The tool that answers **"is anything waiting on me?"** from a phone without opening Nexus. Arguably the highest-value tool in the set, and the only one needing new derivation rather than a wrapper over an existing service call. Depends on #154. Scope: `nexus:read`. ## Contents `/api/state` phase, quota, and the **fleet-wide attention roll-up**. ## The roll-up is the work `nexus/src/lib/attention.ts` derives a session's mark client-side today and only ever paints the web UI. Exposing it is what makes the tool useful. **It has three inputs, and the third is the one people drop** (AGENTS.md fact #26): the roster row, its health probe, and **whether the workspace is running at all**. `stopWorker` writes `workers.status` and never touches a session row, so every session of a deliberately stopped workspace still reads `status: 'running'` while its probe reports the container down. Derived without the third input, a workspace stopped on purpose reports its whole fleet entry as failing. **Read `health.health`, never `health.claudeRunning`.** The field is three-valued, and its `'unknown'` arm (container gone, session row gone) ships `claudeRunning: false` as a *placeholder* rather than an observation — so the boolean turns "we could not look" into "claude is dead". It also decides the opposite way from `unhealthyReason` in `Sessions.svelte`, which gates on the same field. Within a running workspace the split is: the **probe** owns whether claude is alive, **attention** owns what a live agent is doing. An absent claude stays `errored` *except* when the row reported `ended`, which only `SessionEnd` can say and which never fires for a crash. The converse matters as much: a live claude makes an `ended` report stale, so it is ignored rather than believed. `attention_state` being null is **not** idle — it means the feature has not reported yet. ## Structure Lift the derivation so client and server share one implementation, rather than reimplementing it server-side. A second copy will diverge, and the failure is a phone that disagrees with the browser about whether you are needed — which is worse than no tool at all. Note `convergeSessions` nulls attention for a workspace that is not running, so seeded or fake rows lose their state within a poll. Stub the roster when testing. ## Unknown is not falsy Three signals in this area disagree and none may be inferred from a falsy value (fact #19): `rate_limits` is an **absent key** until the first inference call; `context_window.used_percentage` is **`null`** while its sibling `total_input_tokens` is `0`; per-session cost is simply **missing** after a Nexus restart. A quota window whose `resets_at` has passed is **unknown**, not zero — `getAccountQuota` prunes it as a read-time filter, and the tool must serialize that as unknown rather than fabricating a number. ## Done when Asking Claude "does anything need me?" from a phone gives the same answer the sidebar gives in a browser, including for a deliberately stopped workspace, and the shared derivation is proven by a test that fails if either side is changed alone.
lz added this to the MCP support (#140) milestone 2026-09-15 18:24:45 +02:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lz/agent-nexus#155
No description provided.