Skip to content

Add /idle endpoint for hosting platform idle tracking#13146

Closed
mslynch wants to merge 2 commits intoposit-dev:mainfrom
mslynch:idle-tracking-endpoint
Closed

Add /idle endpoint for hosting platform idle tracking#13146
mslynch wants to merge 2 commits intoposit-dev:mainfrom
mslynch:idle-tracking-endpoint

Conversation

@mslynch
Copy link
Copy Markdown
Member

@mslynch mslynch commented Apr 22, 2026

Summary

Adds a /idle HTTP endpoint on the Positron server/REH build that Posit Cloud can query to determine how long the user has been idle.

Architecture

The existing IUserActivityService keeps track of DOM events (e.g. keydown, mousedown, touchstart. A new browser-side workbench contribution, PositronIdleReporterContribution, registers a callback to watch activity changes, upon which it forwards timestamps to a new IPC channel every 30s. A new service, PositronIdleTrackingService, keeps the most recent timestamp monotonically and exposes the result via the HTTP endpoint.

Response format

GET /idle?tkn=<connection-token>

{
  "seconds_idle": 142,
  "last_activity_epoch_ms": 1718900000000
}

Behavior notes

Since timestamps are sent every 30 seconds, the idle time may be reported up to 30s even while Positron is in use.

Opening a tab counts as activity for ~60-70s. IUserActivityService initializes isActive = true on construction, treating the act of opening the window as an implicit activity signal (see the service's own comment). The bundled DomActivityTracker then verifies continued activity via DOM events: after 2 poll intervals (~60s) with no keydown/mousedown/touchstart, plus a 10s debounce, it flips to isActive = false.

In practice: if a user opens a tab and walks away without interacting, seconds_idle will report 0 for approximately 60-70 seconds before it begins to climb. This is expected and acceptable for session-management use cases where idle timeouts are on the order of minutes or hours, but it's worth noting for any consumer that expects sub-minute precision.

Release Notes

New Features

  • N/A (internal server/REH feature; no user-visible change)

Bug Fixes

  • N/A

QA Notes

@:sessions

This feature only activates in the server/REH build and requires Linux (license manager is Linux-only).

Automated tests

```bash
./scripts/test.sh --run src/vs/platform/positronIdleTracking/test/node/positronIdleTrackingService.test.ts
./scripts/test.sh --run src/vs/platform/positronIdleTracking/test/common/positronIdleTrackingIpc.test.ts
```

Manual verification (Linux only)

  1. Build and start the server:
    ```bash
    npm run build-start && npm run build-check
    ./scripts/code-server.sh --connection-token test-token --license-key-file /path/to/license.lic
    ```
  2. Open the URL printed by the server in a browser.
  3. Wait ~10s, then query `/idle`:
    ```bash
    curl -s "http://localhost:/idle?tkn=test-token" | jq .
    ```
  4. Verify:
    • `seconds_idle` near 0 when interacting
    • `seconds_idle` oscillates between 0 and ~30s when actively interacting (heartbeat interval)
    • `seconds_idle` grows unboundedly when the user stops interacting (after the ~60-70s grace period described above)
    • HTTP 403 when `?tkn=` is missing or wrong

🤖 Generated with Claude Code

mslynch and others added 2 commits April 22, 2026 10:36
Adds a /idle HTTP endpoint on the Positron server/REH build that hosting
platforms (e.g. Posit Cloud) can query to determine how long the user has
been idle. The response includes seconds_idle, last_activity_epoch_ms,
and connected_clients.

Activity signals originate from the existing IUserActivityService in the
browser (DOM events: keydown, mousedown, touchstart). A new browser-side
workbench contribution forwards activity timestamps to the server via a
dedicated IPC channel. A new node-side service aggregates timestamps
across connected clients (taking the most recent) and exposes the
resulting idle info via the HTTP endpoint.

Includes unit tests for the service and IPC channel pair.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the per-client Map<string, number> with a single monotonic
lastActivityEpochMs. Drop the connectedClients field from the response,
the clientId parameter from reportActivity, and the removeClient method.

Rationale: the core signal (max activity timestamp across all clients)
is naturally preserved by monotonic updates. Per-client tracking added
complexity without meaningful benefit for Posit Cloud's use case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@mslynch mslynch marked this pull request as ready for review April 22, 2026 16:54
@juliasilge
Copy link
Copy Markdown
Contributor

FYI we'll need to treat this like a community-contributed PR and apply the changes in a new, non-fork PR because of the problems outlined in #6628.

@jmcphers
Copy link
Copy Markdown
Collaborator

This checks user activity but not kernel activity; i.e. if you start a long-running computation and close the browser tab, your session will quickly begin reporting as idle even though Python or R are still doing work. Is that intended behavior for this endpoint?

@mslynch
Copy link
Copy Markdown
Member Author

mslynch commented Apr 23, 2026

This checks user activity but not kernel activity; i.e. if you start a long-running computation and close the browser tab, your session will quickly begin reporting as idle even though Python or R are still doing work. Is that intended behavior for this endpoint?

Yes - we're planning on calling the Kallichore API as well for that.

@isabelizimm
Copy link
Copy Markdown
Contributor

Opened #13169 as a non-fork PR for repo secret purposes. I'll close this one out!

@github-actions github-actions Bot locked and limited conversation to collaborators Apr 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants