feat(LUKE-58): observe Cursor cloud agent sessions
Merged
DA
2mo ago+980+980+012345678901234567890123456789-33-33-01234567890123456789
Summary
- Add a
CursorSessionAdapteronCloudSessionAdapter(LUKE-58), so a Cursor API key saved in Settings — or read fromCURSOR_API_KEY— lets Luke observe cloud agents the way it already observes Conductor sessions. Without a key it reports nothing and issues no request, and every other provider keeps working without one. The id is core'sPROVIDER_ID.CURSOR, so the credential row, the session row, and the mark all name the same provider. - A pass is one bounded
GET /v1/agentscall plus one read of the run each observed agent names as its latest. A Cursor agent is a standing definition whose own status reports only whether the user filed it away, so the state Luke shows exists only on the run; that is the fan-out the issue allows "unless a status needs it". An archived agent and one that has never run are already settled and cost no second request. - Map run states as the issue specifies:
RUNNINGto working without freshness decay, since a run state is stamped with the moment it was entered rather than with a heartbeat;FINISHEDto waiting throughstatusWhileRecent;CANCELLEDandEXPIREDto complete;CREATING,ERROR, or a state this build does not know to unknown rather than a state Luke cannot verify. - Stamp each observation with the run's
updatedAt, so a turn that just ended reads as waiting however long the run took. The agent's own timestamps would date a 40-minute run from when it started and call the finished turn stale at the one moment the user is being waited on. - Label each session by
repos[].urlthroughrepositoryLabel(). An agent'sname,summary, the run'sresult, and the branch Cursor opens are all written from the opening prompt, so the label has no fallback to any of them; a test plantsSECRET_PROMPT_TEXTin all four and asserts none of it reaches an observation. - Show Cursor's brand mark on Cursor sessions, reproduced from Simple Icons (CC0-1.0, sourced from cursor.com/brand) as inline path data like the other marks. Cursor publishes one silhouette rather than a colour pair, so it is drawn in the light form the brand uses on a dark surface. The smoke fixture gains a Cursor session so the mark appears in generated evidence, as every other provider's does.
- Move the guard for reading a state a provider reported into the shared cloud adapter as
knownValue, now that a second provider needs it. Both adapters had written it out with their own pair of casts; matching against the known values needs none.
Evidence
- Platform-independent checks:
./scripts/check.sh— passed (repository contract checks, Biome, typecheck, 94 desktop tests including 19 new Cursor tests, 33 sidecar-core tests, 5 harness tests, and both builds) - macOS Electron verification (
./scripts/verify.sh):not runlocally — this workspace is a Linux cloud sandbox; the macOS CI job runs it on this PR, and its evidence now carries a Cursor row - Live account verification: the adapter itself was run against a real Cursor account on macOS, decrypting the stored key in process. One pass issued exactly two requests —
GET /v1/agents?limit=100andGET /v1/agents/{id}/runs/{latestRunId}— and produced one row,waiting · Cursor: luke, stamped2026-08-12T22:33:45Z, the moment that run finished. Agents last touched outside the 24-hour window were dropped, and no prompt-derived text appeared in the observation. - Re-run after the shared-guard cleanup: the same two requests, the same row and timestamp, by then reported as
unknownbecause the run had finished twenty minutes earlier —statusWhileRecentholding the waiting state only while it is recent.
Automated visual evidence
Download the deterministic macOS evidence · workflow run
- Commit:
4648b68c579e3445bea2f99eb533113a91c4735c - Scenario:
smoke - Physical-notch check: not performed by CI
Physical-device evidence
- Screenshot or screen recording:
not attached— the deterministic CI evidence covers the new mark in the panel - Physical-notch check:
not performed - Device/display configuration:
not recorded
Notes
- Rebased onto main for the panel revamp (#18) and the provider marks (#17). The three earlier commits collapsed into two: the adapter, and the mark, matching how Conductor's mark landed separately.
- The issue describes the
/v0/agentspayload, which is still served and returnssource.repository,source.ref, and a run-levelstatusin one call. This PR uses/v1/agentsinstead because v0 carries no per-run timestamp: its only date is when the agent was created, so a finished turn would decay to unknown minutes after a long run ended. The status mapping the issue specifies is unchanged; it moved to the object that actually reports it. - Blockers or follow-up verification: None