Skip to content

feat: add event log#124

Open
szdziedzic wants to merge 11 commits into
EvanBacon:mainfrom
expo:szdziedzic-codex/event-log
Open

feat: add event log#124
szdziedzic wants to merge 11 commits into
EvanBacon:mainfrom
expo:szdziedzic-codex/event-log

Conversation

@szdziedzic

@szdziedzic szdziedzic commented Jul 2, 2026

Copy link
Copy Markdown

Why

serve-sim did not have one place to inspect the actions routed through the preview or CLI. When debugging agent-driven sessions, it is useful to see recent simulator actions in order: touches, gestures, hardware buttons, app installs, media drops, UI setting changes, screenshots, and related commands.

For EAS and other automation consumers, JSON events also need a stable message field. Adding a Bunyan-style msg field lets logs from serve-sim and other tools be gathered together without every consumer knowing serve-sim-specific display fields.

How

  • Added a bounded in-memory event log for simulator events, exposed through JSON and SSE endpoints.
  • Record HID input at the central DeviceSession ingress, plus recognized host-side simulator commands from /exec and UI setting updates.
  • Coalesce touch sequences into readable tap and drag entries instead of logging every move event.
  • Redact printable key values so text typed into the simulator is not exposed through the event log.
  • Added msg to every JSON event entry while keeping summary as a compatibility/display alias.
  • Added a compact Event Log section to the Tools panel that streams new events live.
  • Added serve-sim event-log [-d udid] [--json] [--limit n] for CLI and automation consumers.
  • Skip upload/base64 plumbing commands so the log shows the user-level action instead of implementation noise.

Test Plan

  • bunx tsc --noEmit
  • bun test packages/serve-sim/src/__tests__
  • bun run packages/serve-sim/build.ts
Screen.Recording.2026-07-02.at.17.27.46.mov
➜  serve-sim git:(szdziedzic-codex/event-log) node packages/serve-sim/dist/serve-sim.js event-log --json -n 5
{
  "events": [
    {
      "device": "AC78FEE5-C665-4295-889B-F6BCB1A618D5",
      "source": "ui",
      "kind": "ui-setting",
      "action": "appearance",
      "status": "ok",
      "summary": "UI appearance dark",
      "details": {
        "option": "appearance",
        "value": "dark"
      },
      "id": 30,
      "timestamp": "2026-07-02T15:28:28.025Z",
      "msg": "UI appearance dark"
    },
    {
      "device": "AC78FEE5-C665-4295-889B-F6BCB1A618D5",
      "source": "hid",
      "kind": "tap",
      "action": "tap",
      "summary": "Tap 0.225,0.637",
      "details": {
        "type": "tap",
        "start": {
          "x": 0.22482827944379294,
          "y": 0.636982430905168
        },
        "current": {
          "x": 0.22482827944379294,
          "y": 0.636982430905168
        },
        "moveCount": 0,
        "screen": {
          "width": 1206,
          "height": 2622
        }
      },
      "id": 31,
      "timestamp": "2026-07-02T15:28:37.584Z",
      "msg": "Tap 0.225,0.637"
    },
    {
      "device": "AC78FEE5-C665-4295-889B-F6BCB1A618D5",
      "source": "hid",
      "kind": "drag",
      "action": "drag",
      "summary": "Drag 0.736,0.672 -> 0.128,0.66",
      "details": {
        "type": "drag",
        "phase": "end",
        "start": {
          "x": 0.7359133299826883,
          "y": 0.6715041611014075
        },
        "current": {
          "x": 0.12832970346791758,
          "y": 0.659996917702661
        },
        "moveCount": 11,
        "screen": {
          "width": 1206,
          "height": 2622
        }
      },
      "id": 32,
      "timestamp": "2026-07-02T15:28:38.288Z",
      "msg": "Drag 0.736,0.672 -> 0.128,0.66"
    },
    {
      "device": "AC78FEE5-C665-4295-889B-F6BCB1A618D5",
      "source": "hid",
      "kind": "tap",
      "action": "tap",
      "summary": "Tap 0.346,0.624",
      "details": {
        "type": "tap",
        "start": {
          "x": 0.34634500474674706,
          "y": 0.6238312955923148
        },
        "current": {
          "x": 0.34634500474674706,
          "y": 0.6238312955923148
        },
        "moveCount": 0,
        "screen": {
          "width": 1206,
          "height": 2622
        }
      },
      "id": 33,
      "timestamp": "2026-07-02T15:28:39.151Z",
      "msg": "Tap 0.346,0.624"
    },
    {
      "device": "AC78FEE5-C665-4295-889B-F6BCB1A618D5",
      "source": "exec",
      "kind": "button",
      "action": "home",
      "status": "ok",
      "summary": "Home",
      "details": {
        "command": "xcrun simctl launch AC78FEE5-C665-4295-889B-F6BCB1A618D5 com.apple.springboard",
        "exitCode": 0,
        "bundleId": "com.apple.springboard"
      },
      "id": 34,
      "timestamp": "2026-07-02T15:28:40.136Z",
      "msg": "Home"
    }
  ]
}
➜  serve-sim git:(szdziedzic-codex/event-log) node packages/serve-sim/dist/serve-sim.js event-log           
05:27:39 PM  iPhone 17 Pro  Key down Left Command
05:27:41 PM  iPhone 17 Pro  Key down Left Shift
05:27:48 PM  iPhone 17 Pro  Key up Left Command
05:27:48 PM  iPhone 17 Pro  Key up Left Shift
05:27:50 PM  iPhone 17 Pro  Tap at 0.30, 0.66
05:27:52 PM  iPhone 17 Pro  Tap at 0.30, 0.66
05:27:53 PM  iPhone 17 Pro  Drag from 0.20, 0.67 to 0.00, 0.70
05:27:55 PM  iPhone 17 Pro  Drag from 0.01, 0.70 to 0.16, 0.66
05:28:01 PM  iPhone 17 Pro  Home
05:28:02 PM  iPhone 17 Pro  Screenshot
05:28:05 PM  iPhone 17 Pro  Tap at 0.61, 0.94
05:28:06 PM  iPhone 17 Pro  Tap at 0.47, 0.94
05:28:07 PM  iPhone 17 Pro  Key down character
05:28:07 PM  iPhone 17 Pro  Key up character
05:28:08 PM  iPhone 17 Pro  Key down character
05:28:08 PM  iPhone 17 Pro  Key up character
05:28:08 PM  iPhone 17 Pro  Key down character
05:28:09 PM  iPhone 17 Pro  Key up character
05:28:09 PM  iPhone 17 Pro  Key down character
05:28:09 PM  iPhone 17 Pro  Key up character
05:28:10 PM  iPhone 17 Pro  Key down character
05:28:10 PM  iPhone 17 Pro  Key up character
05:28:10 PM  iPhone 17 Pro  Key down character
05:28:11 PM  iPhone 17 Pro  Key up character
05:28:15 PM  iPhone 17 Pro  Home
05:28:21 PM  iPhone 17 Pro  Rotate landscape left
05:28:22 PM  iPhone 17 Pro  Rotate portrait upside down
05:28:23 PM  iPhone 17 Pro  Rotate landscape right
05:28:24 PM  iPhone 17 Pro  Rotate portrait
05:28:28 PM  iPhone 17 Pro  UI appearance dark
05:28:37 PM  iPhone 17 Pro  Tap at 0.22, 0.64
05:28:38 PM  iPhone 17 Pro  Drag from 0.74, 0.67 to 0.13, 0.66
05:28:39 PM  iPhone 17 Pro  Tap at 0.35, 0.62
05:28:40 PM  iPhone 17 Pro  Home

Summary by CodeRabbit

  • New Features
    • Added a real-time event log tool to the simulator Tools panel.
    • Introduced a serve-sim event-log CLI subcommand to view recent events (formatted or JSON), with optional device filtering.
    • Added new browser-accessible event-log endpoints, including an SSE stream, for live updates.
  • Bug Fixes
    • Improved event readability with localized timestamps, clearer device labels, and human-friendly tap/drag and key/rotation details.
    • Touch gestures are now logged as tap vs drag, including drag update behavior.
  • Documentation
    • Updated the serve-sim README to reflect the new tool/CLI capabilities.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a simulator event log across server, CLI, and client paths, with in-memory storage, HID/command capture, JSON/SSE endpoints, an event-log command, and a browser tools panel.

Changes

Simulator event log feature

Layer / File(s) Summary
Event log store and type contracts
packages/serve-sim/src/event-log.ts, packages/serve-sim/src/__tests__/event-log.test.ts
Defines event-log types, the in-memory store, HID/command event mapping helpers, and tests for recording, reading, subscribing, and mapping behavior.
Event line formatting and humanization
packages/serve-sim/src/event-log-format.ts, packages/serve-sim/src/__tests__/event-log-format.test.ts
Adds event-log line formatting helpers and tests for tap, drag, key, and rotation summaries.
HID and command event capture
packages/serve-sim/src/device-session.ts, packages/serve-sim/src/exec-ws.ts, packages/serve-sim/src/__tests__/exec-ws.test.ts
Records HID gesture/activity events and completed shell commands into the event log, with tests covering device filtering and SSE payload handling.
Middleware endpoints and command/UI event recording
packages/serve-sim/src/middleware.ts, packages/serve-sim/src/__tests__/middleware-selection.test.ts, packages/serve-sim/src/client/client.tsx, packages/serve-sim/src/client/components/tools-panel.tsx, packages/serve-sim/src/client/utils/sim-endpoint.ts
Adds /api/event-log JSON and SSE routes, records UI-setting and command events, extends preview config with event-log endpoints, and wires the new endpoint prop through the client.
CLI event-log subcommand
packages/serve-sim/src/index.ts, packages/serve-sim/README.md
Adds serve-sim event-log and documents the new command in the README.
Client EventLogTool panel
packages/serve-sim/src/client/components/event-log-tool.tsx
Adds the event-log tools panel UI that streams and renders recent events.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • EvanBacon/serve-sim#59: Both PRs touch packages/serve-sim/src/index.ts to add or extend serve-sim CLI subcommands.
  • EvanBacon/serve-sim#86: Both PRs modify the exec WebSocket control-channel wiring used by createExecUpgradeHandler.
  • EvanBacon/serve-sim#91: Both PRs modify preview config plumbing in middleware.ts and client/utils/sim-endpoint.ts.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding an event log feature.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@szdziedzic szdziedzic marked this pull request as ready for review July 2, 2026 14:37
@szdziedzic szdziedzic marked this pull request as draft July 2, 2026 14:50
@szdziedzic szdziedzic marked this pull request as ready for review July 2, 2026 14:50
@szdziedzic szdziedzic marked this pull request as draft July 2, 2026 14:52
@szdziedzic szdziedzic marked this pull request as ready for review July 2, 2026 14:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
packages/serve-sim/src/device-session.ts (2)

67-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate of formatPoint/formatNumber from event-log.ts.

formatEventLogPoint/formatEventLogNumber are copy-pasted, byte-for-byte, from the private formatPoint/formatNumber helpers in event-log.ts. Exporting those from event-log.ts (or a shared util) and importing here would avoid drift between the two implementations as either evolves.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/device-session.ts` around lines 67 - 74, The helpers
formatEventLogPoint and formatEventLogNumber in device-session.ts are duplicated
from the private formatPoint and formatNumber logic in event-log.ts; replace the
copy-paste with a shared source of truth by exporting those helpers from
event-log.ts or moving them into a common utility and importing them here. Keep
the behavior identical, but ensure device-session.ts uses the shared
formatPoint/formatNumber symbols so the implementations cannot drift.

400-480: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

No test coverage for the tap/drag gesture coalescing logic.

recordTouchEvent has several stateful branches (begin/move/end, threshold-based tap-vs-drag classification, create-vs-update of the log entry). Given its complexity and that it's the primary HID capture path for the new feature, it would benefit from unit tests (mocking recordEventLogEvent/updateEventLogEvent or the module) before merge.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/device-session.ts` around lines 400 - 480, Add unit
tests for recordTouchEvent in device-session.ts to cover the stateful
begin/move/end flow and the tap-vs-drag threshold behavior. Mock
recordEventLogEvent and updateEventLogEvent (or the event-log module) and verify
that a begin initializes touchGestureLog, move coalesces into a drag and
switches from create to update when eventId exists, and end emits either a tap
or drag based on touchGestureMoved. Use the recordTouchEvent method and
touchGestureLog-related helpers as anchors when locating the logic.
packages/serve-sim/src/__tests__/event-log.test.ts (1)

16-192: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No test for the 500-entry eviction cap.

The suite covers ordering, filtering, since/limit reads, subscriptions, and command/HID mapping well, but doesn't exercise EVENT_LOG_MAX_ENTRIES eviction (i.e., recording >500 entries and verifying the oldest are dropped). This is a core invariant of the store worth pinning down.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/__tests__/event-log.test.ts` around lines 16 - 192,
Add a test in event-log.test.ts to cover EVENT_LOG_MAX_ENTRIES eviction in the
event log store. In the existing describe("event log store") suite, use
recordEventLogEvent to create more than 500 entries, then verify readEventLog
only returns the newest 500 and that the oldest IDs/entries are dropped while
order is preserved. Reference the store APIs recordEventLogEvent and
readEventLog so the behavior stays pinned down if implementation details change.
packages/serve-sim/src/exec-ws.ts (1)

181-184: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Silent catch around onCommandResult has no rationale/logging, unlike the analogous pattern in event-log.ts.

notifyEventLogSubscribers in event-log.ts documents why subscriber errors are swallowed. Here, onCommandResult errors are also swallowed but without comment or any diagnostic trail, which could hide real bugs in the new event-log mapping logic during development.

🔍 Add a comment / minimal diagnostic
       try {
         opts.onCommandResult?.(command, result);
-      } catch {}
+      } catch {
+        // Event-log capture is a diagnostic side-channel; a failure here
+        // must not break the exec response path.
+      }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/exec-ws.ts` around lines 181 - 184, The try/catch
around onCommandResult in exec-ws.ts is swallowing errors without any rationale
or diagnostics. Update the onCommandResult callback handling in the command
result path to match the documented pattern used by notifyEventLogSubscribers in
event-log.ts: either add a brief comment explaining why subscriber errors are
ignored, or log a minimal diagnostic before swallowing so failures in the
event-log mapping are visible during development.
packages/serve-sim/src/__tests__/exec-ws.test.ts (1)

191-199: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

SSE retry only attempts once.

If the control channel emits more than one non-data frame before the actual data: payload, this will fail since it only retries a single time. Consider looping with a small bound instead of a single conditional retry to reduce CI flakiness.

♻️ Suggested loop-based retry
-    let reply = await channel.next();
-    let data = /^data: (.*)$/m.exec(reply.data ?? "")?.[1];
-    if (!data) {
-      reply = await channel.next();
-      data = /^data: (.*)$/m.exec(reply.data ?? "")?.[1];
-    }
+    let reply = await channel.next();
+    let data = /^data: (.*)$/m.exec(reply.data ?? "")?.[1];
+    for (let attempts = 0; !data && attempts < 5; attempts++) {
+      reply = await channel.next();
+      data = /^data: (.*)$/m.exec(reply.data ?? "")?.[1];
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/__tests__/exec-ws.test.ts` around lines 191 - 199, The
SSE test in exec-ws.test.ts only retries once when parsing the control channel
response, so it can still fail if multiple non-data frames arrive before the
first data payload. Update the parsing logic around connect(), channel.next(),
and the /^data: (.*)$/m extraction to use a small bounded loop instead of a
single if retry, so it keeps advancing until it finds data or reaches the limit.
packages/serve-sim/src/index.ts (1)

680-697: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Redundant execSync shellouts per device.

getDeviceName (existing helper) re-runs xcrun simctl list devices -j and re-parses the full device list on every call. When events span multiple devices, this loop calls it once per unique device, synchronously shelling out repeatedly for data that's already available after the first call.

♻️ Fetch the device list once and reuse it
+function listSimulatorDevices(): Record<string, Array<{ udid: string; name: string; state: string }>> {
+  try {
+    const output = execSync("xcrun simctl list devices -j", { encoding: "utf-8" });
+    return (JSON.parse(output) as { devices: Record<string, Array<{ udid: string; name: string; state: string }>> }).devices;
+  } catch {
+    return {};
+  }
+}
+
 function deviceLabelsForEvents(events: EventLogEntry[]): Map<string, string> {
   const devices = [...new Set(events.map((event) => event.device).filter((device): device is string => !!device))];
   const names = new Map<string, string>();
+  const allDevices = listSimulatorDevices();
   for (const device of devices) {
-    names.set(device, getDeviceName(device) ?? device.slice(0, 8));
+    const name = Object.values(allDevices).flat().find((d) => d.udid === device)?.name;
+    names.set(device, name ?? device.slice(0, 8));
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/index.ts` around lines 680 - 697, The device label
builder is repeatedly shelling out via getDeviceName for each unique device,
which re-fetches and re-parses the full simctl device list multiple times.
Refactor deviceLabelsForEvents to fetch the device list once and reuse it for
all lookups, either by passing a cached lookup into getDeviceName or by
computing the name map up front and then building labels from that single
result. Keep the logic in deviceLabelsForEvents and the getDeviceName helper
aligned so repeated calls do not invoke execSync per device.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/serve-sim/src/event-log.ts`:
- Around line 210-223: The HID key event handling in event-log.ts is persisting
printable characters via keyLabelForUsage in the 0x06 case, which exposes typed
text in summary/details and downstream JSON/SSE/CLI output. Update the key
handling logic to avoid storing literal glyphs for printable usages: keep
special keys readable, but redact or generalize letters/numbers before
constructing the returned event object in the 0x06 case (and the matching
508-517 path) so the event log no longer contains sensitive keystrokes.

In `@packages/serve-sim/src/middleware.ts`:
- Around line 131-134: Wrap the event-log recording path in `recordCommandEvent`
so failures stay diagnostic-only and cannot break the main exec flow. Add
try/catch around the `eventLogEventForCommand` and `recordEventLogEvent` calls,
using the same defensive pattern as `notifyEventLogSubscribers`, and keep the
`/exec` completion handler and `exec-ws` `onCommandResult` callback insulated
from any throw coming out of `recordCommandEvent`.
- Around line 1257-1267: `handleUiRequest` has the same unguarded
event-recording gap for `ui-setting` as the exec path: after `setUiOption`
succeeds, the direct `recordEventLogEvent` call can throw and incorrectly fail
the whole request. Update the `ui-setting` branch in `handleUiRequest` to wrap
`recordEventLogEvent` in the same safe/error-swallowing pattern used for
exec-path recording so the request still returns `{ ok: true }` when the option
update succeeds.

---

Nitpick comments:
In `@packages/serve-sim/src/__tests__/event-log.test.ts`:
- Around line 16-192: Add a test in event-log.test.ts to cover
EVENT_LOG_MAX_ENTRIES eviction in the event log store. In the existing
describe("event log store") suite, use recordEventLogEvent to create more than
500 entries, then verify readEventLog only returns the newest 500 and that the
oldest IDs/entries are dropped while order is preserved. Reference the store
APIs recordEventLogEvent and readEventLog so the behavior stays pinned down if
implementation details change.

In `@packages/serve-sim/src/__tests__/exec-ws.test.ts`:
- Around line 191-199: The SSE test in exec-ws.test.ts only retries once when
parsing the control channel response, so it can still fail if multiple non-data
frames arrive before the first data payload. Update the parsing logic around
connect(), channel.next(), and the /^data: (.*)$/m extraction to use a small
bounded loop instead of a single if retry, so it keeps advancing until it finds
data or reaches the limit.

In `@packages/serve-sim/src/device-session.ts`:
- Around line 67-74: The helpers formatEventLogPoint and formatEventLogNumber in
device-session.ts are duplicated from the private formatPoint and formatNumber
logic in event-log.ts; replace the copy-paste with a shared source of truth by
exporting those helpers from event-log.ts or moving them into a common utility
and importing them here. Keep the behavior identical, but ensure
device-session.ts uses the shared formatPoint/formatNumber symbols so the
implementations cannot drift.
- Around line 400-480: Add unit tests for recordTouchEvent in device-session.ts
to cover the stateful begin/move/end flow and the tap-vs-drag threshold
behavior. Mock recordEventLogEvent and updateEventLogEvent (or the event-log
module) and verify that a begin initializes touchGestureLog, move coalesces into
a drag and switches from create to update when eventId exists, and end emits
either a tap or drag based on touchGestureMoved. Use the recordTouchEvent method
and touchGestureLog-related helpers as anchors when locating the logic.

In `@packages/serve-sim/src/exec-ws.ts`:
- Around line 181-184: The try/catch around onCommandResult in exec-ws.ts is
swallowing errors without any rationale or diagnostics. Update the
onCommandResult callback handling in the command result path to match the
documented pattern used by notifyEventLogSubscribers in event-log.ts: either add
a brief comment explaining why subscriber errors are ignored, or log a minimal
diagnostic before swallowing so failures in the event-log mapping are visible
during development.

In `@packages/serve-sim/src/index.ts`:
- Around line 680-697: The device label builder is repeatedly shelling out via
getDeviceName for each unique device, which re-fetches and re-parses the full
simctl device list multiple times. Refactor deviceLabelsForEvents to fetch the
device list once and reuse it for all lookups, either by passing a cached lookup
into getDeviceName or by computing the name map up front and then building
labels from that single result. Keep the logic in deviceLabelsForEvents and the
getDeviceName helper aligned so repeated calls do not invoke execSync per
device.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 12746ca3-42ff-4368-af94-fc90bdf65276

📥 Commits

Reviewing files that changed from the base of the PR and between fd545ed and 3c1f07f.

📒 Files selected for processing (15)
  • packages/serve-sim/README.md
  • packages/serve-sim/src/__tests__/event-log-format.test.ts
  • packages/serve-sim/src/__tests__/event-log.test.ts
  • packages/serve-sim/src/__tests__/exec-ws.test.ts
  • packages/serve-sim/src/__tests__/middleware-selection.test.ts
  • packages/serve-sim/src/client/client.tsx
  • packages/serve-sim/src/client/components/event-log-tool.tsx
  • packages/serve-sim/src/client/components/tools-panel.tsx
  • packages/serve-sim/src/client/utils/sim-endpoint.ts
  • packages/serve-sim/src/device-session.ts
  • packages/serve-sim/src/event-log-format.ts
  • packages/serve-sim/src/event-log.ts
  • packages/serve-sim/src/exec-ws.ts
  • packages/serve-sim/src/index.ts
  • packages/serve-sim/src/middleware.ts

Comment thread packages/serve-sim/src/event-log.ts
Comment thread packages/serve-sim/src/middleware.ts
Comment thread packages/serve-sim/src/middleware.ts Outdated
@szdziedzic szdziedzic marked this pull request as draft July 2, 2026 15:22
@szdziedzic

Copy link
Copy Markdown
Author

Thanks @coderabbitai, addressed the actionable feedback in acd9e26: printable key events now redact typed characters and omit raw printable HID usage; exec/UI-setting event-log recording is guarded so diagnostic logging cannot fail the primary request; eviction coverage, SSE retry hardening, shared point formatting, cached simulator labels, and the command-result side-channel rationale were also added.

Validation: bun test packages/serve-sim/src/__tests__, bunx tsc --noEmit, and bun run packages/serve-sim/build.ts all pass.

One note on the tap/drag coalescing test suggestion: I intentionally left direct DeviceSession.recordTouchEvent unit coverage out of this pass because DeviceSession eagerly constructs native HID/capture handles. Exercising that public path would pull native simulator state into the unit suite, so I think it is better handled later through an integration-style seam instead of contorting this PR.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/serve-sim/src/exec-ws.ts (1)

175-187: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Observer receives internal id beyond documented stdout/stderr/exitCode shape.

result includes id (the request id) in addition to stdout/stderr/exitCode, and that whole object is forwarded to opts.onCommandResult. If the event-log observer persists this object as-is (e.g. via spread), the internal exec-channel request id leaks into stored/streamed event-log entries even though it has no semantic meaning there. Consider passing a trimmed object ({ stdout, stderr, exitCode }) to the observer instead of the full result used for the websocket response.

🔧 Proposed fix
       try {
-        opts.onCommandResult?.(command, result);
+        opts.onCommandResult?.(command, {
+          stdout: result.stdout,
+          stderr: result.stderr,
+          exitCode: result.exitCode,
+        });
       } catch {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/serve-sim/src/exec-ws.ts` around lines 175 - 187, The exec command
observer is receiving the full websocket response object, including the internal
request identifier, instead of only the documented command result fields. Update
the result handling in exec-ws.ts so execCommandResult/onCommandResult is called
with a trimmed payload containing only stdout, stderr, and exitCode, while
keeping the id only for send(result) on the websocket response path. Use the
existing result construction and opts.onCommandResult callback in the exec flow
to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/serve-sim/src/exec-ws.ts`:
- Around line 175-187: The exec command observer is receiving the full websocket
response object, including the internal request identifier, instead of only the
documented command result fields. Update the result handling in exec-ws.ts so
execCommandResult/onCommandResult is called with a trimmed payload containing
only stdout, stderr, and exitCode, while keeping the id only for send(result) on
the websocket response path. Use the existing result construction and
opts.onCommandResult callback in the exec flow to locate the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 008edb20-6275-4f39-a1d4-d2408d39080c

📥 Commits

Reviewing files that changed from the base of the PR and between 77963ba and acd9e26.

📒 Files selected for processing (7)
  • packages/serve-sim/src/__tests__/event-log.test.ts
  • packages/serve-sim/src/__tests__/exec-ws.test.ts
  • packages/serve-sim/src/device-session.ts
  • packages/serve-sim/src/event-log.ts
  • packages/serve-sim/src/exec-ws.ts
  • packages/serve-sim/src/index.ts
  • packages/serve-sim/src/middleware.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/serve-sim/src/tests/event-log.test.ts
  • packages/serve-sim/src/index.ts
  • packages/serve-sim/src/tests/exec-ws.test.ts
  • packages/serve-sim/src/middleware.ts
  • packages/serve-sim/src/device-session.ts
  • packages/serve-sim/src/event-log.ts

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
git log --oneline -1 acd9e26 2>/dev/null || echo "commit not found locally"
git show --stat acd9e26 2>/dev/null | head -50

Length of output: 1005


@szdziedzic, thanks for the update — confirmed commit acd9e26 touches exactly the areas you listed (device-session.ts, event-log.ts, exec-ws.ts, middleware.ts, index.ts, plus updated test coverage), and I appreciate you calling out validation results for bun test, bunx tsc --noEmit, and the build step.

Your rationale on skipping direct DeviceSession.recordTouchEvent unit coverage makes sense — since it eagerly constructs native HID/capture handles, forcing unit-level exercise of that path would introduce native simulator dependencies into what should be a fast, isolated test suite. Deferring that to an integration-style seam is the right call rather than distorting this PR's scope.

I'll take another pass over the diff to confirm the fixes land as described.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@szdziedzic szdziedzic marked this pull request as ready for review July 2, 2026 15:27
@szdziedzic szdziedzic changed the title Add simulator event log feat: add event log Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant