feat: add client_connected telemetry and surface/client labels for the IDE funnel

Merged
AN
1d ago
+190-0

Issue for this PR

Closes #

Type of change

  • New feature

What does this PR do?

Makes the IDE-extension onboarding funnel measurable from backend telemetry.

Context: ~92% of installs run the VS Code extension (telemetry source="datamates"), which runs altimate serve as its backend. On that process we emit startup_ready and then nothing until session_start (the first model prompt), so the large launch -> first-message drop was invisible.

Two additions:

  • New client_connected event. Emitted once per process the first time an authenticated client subscribes to the event stream (GET /event or /global/event). It lives in a .use middleware after basic-auth in Server.createApp, so unauthenticated probes/health checks don't count. This splits the launch->session drop into "backend launched but no client connected" vs "connected but no message sent". Added to ANCHOR_EVENTS so it flushes immediately. It fires for every surface (serve, run, tui); the IDE-funnel read filters surface=="serve", and the other surfaces give a baseline to compare against.
  • startup_ready gains surface. surface mirrors the existing command field, but client_connected has no command, so surface is the single key that joins the two funnel stages in queries.

Telemetry-only, fail-safe (dynamic import + .catch), non-blocking. The server.ts change is wrapped in altimate_change markers (upstream-shared file); the telemetry module is under src/altimate/** (altimate-owned, no markers required).

Not carrying a separate client field (review note): an earlier revision also added client = ALTIMATE_CLI_CLIENT to both events. The independent review pointed out toAppInsightsEnvelopes already stamps source = ALTIMATE_CLI_CLIENT onto every event that has no source of its own — so client was an exact duplicate of source (dashboards can already filter on source=datamates). It was dropped.

How did you verify your code works?

  • Unit (telemetry): bun test on the telemetry suites — 394 pass, 0 fail. Asserts startup_ready carries surface, and client_connected fires exactly once per process across repeated calls.
  • Server wiring (new, test/server/altimate-client-connected-wiring.test.ts): drives real requests through Server.createApp and asserts the middleware calls Telemetry.clientConnected() for GET /event and GET /global/event, and not for other paths or non-GET methods. Verified non-vacuous by mutating the path literal (positive cases then fail). The one case not exercised — "move the hook above basic-auth so unauthenticated probes count" — is called out in the test file: Flag.OPENCODE_SERVER_PASSWORD is a module-level const frozen at load and CI runs the package in one process, so a runtime password toggle can't drive a 401; the ordering is enforced structurally by registering the hook immediately after the basic-auth .use.
  • Typecheck: bun run typecheck on the opencode package — clean (exit 0).

Marker placement checked by hand against script/upstream/utils/config.ts (the --markers guard currently no-ops against the v2 upstream baseline).

Screenshots / recordings

N/A (backend telemetry only).

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

[!NOTE]
Low Risk
Telemetry-only changes with fail-safe dynamic import; server middleware adds a lightweight post-handler on event-stream routes without altering stream behavior.

Overview
Adds IDE onboarding funnel telemetry so launch → first-message drop can be split into “server up but no client” vs “client connected but no prompt.”

client_connected fires once per process when a real client opens the SSE bus on GET /event or GET /global/event. Server middleware runs after auth, only on 2xx, and dynamically calls Telemetry.clientConnected(). The event is an anchor (immediate flush). startup_ready now includes surface (same value as command) so dashboards can join funnel stages on one key.

The in-process trace consumer sets x-altimate-trace-consumer so its default /event subscription is not counted as an external client on serve startups.

Tests cover the telemetry latch, surface on startup_ready, and server middleware wiring (paths, GET-only, header skip, non-event routes).

Reviewed by Cursor Bugbot for commit 45fc7441fdd1bcd9ff18c00ceaee83b5c00a8ea7. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Telemetry now records when a client connects, including the command surface and time since startup. Connection events are reported once per process when an event stream is requested.
    • Startup-ready telemetry now includes the command surface, providing additional context for startup activity.