You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The `request_client()` function allows R to call client-side functions synchronously by sending a **JSON-RPC Request** (with an `id`) over the WebSocket. This is primarily used to emulate the RStudio API:
50
+
The `request_client()` function allows R to call client-side functions synchronously by sending a **JSON-RPC Request** (with an `id`) over the WebSocket. This is primarily used to emulate the RStudio API.
51
51
52
-
1. R sends a request with `method` set to the action name (e.g., `"active_editor_context"`).
53
-
2. R enters a `while` loop that calls `httpuv::service()`.
54
-
3. The client processes the action and sends back a **JSON-RPC Response** (with the same id) via the WebSocket.
55
-
4. R retrieves the `result` (or `error`) and returns it.
52
+
**Coordinate Handling**: The `sess` protocol uses **1-indexed** coordinates for all rows (lines) and columns (characters) on the wire. This aligns with R's internal representation. The client (e.g., VS Code extension) is responsible for converting these to its internal 0-indexed representation if necessary.
56
53
57
-
**Coordinate Handling**: The emulation layer automatically converts between R (1-indexed) and IPC (0-indexed) coordinates. Locations and ranges sent to the client are 0-indexed, while data received from the client (e.g., in `document_context`) is converted back to 1-indexed R objects.
Below are all the JSON-RPC methods sent from R to the client to emulate RStudio API functionality:
58
+
Below are the JSON-RPC methods sent from R to the client to emulate RStudio API functionality:
60
59
61
60
-**`active_editor_context`**: Requests the current context of the active editor.
62
61
-**`replace_text_in_current_selection`**: Replaces text in the current selection (params: `text`, `id`).
@@ -129,15 +128,21 @@ Returns the most recent static plot captured by the R session.
129
128
130
129
---
131
130
132
-
## 3. Hook Registration
131
+
## 3. Hook Registration & Options
133
132
134
133
By default, the package does not inject hooks into the R session on load. Calling `sess::sess_app()` will start the server and automatically call `sess::register_hooks()` to enable features like automatic `View()` interception or plot redirection.
135
134
136
-
If you need to manually register hooks without starting the full app environment (or re-register them if they were overridden), you can call:
137
-
```r
138
-
sess::register_hooks()
139
-
```
140
-
This rebinds internal functions (like `utils::View`) and sets `options()` for browsers, viewers, and devices to route through the IPC server.
135
+
### Intercepted Functions
136
+
-**`utils::View()`**: Redirects data to the client's data viewer. Supports `data.frame`, `matrix`, `list`, and `ArrowTabular` objects.
137
+
-**`browser()`**, **`viewer()`**, **`page_viewer()`**: Redirects URLs and HTML files to the client's browser or webview.
138
+
-**Help System**: Intercepts help topic printing to route HTML help to the client.
139
+
140
+
### Global Options
141
+
-**`sess.row_limit`**: Limits the number of rows sent to the data viewer (default: 100). Set to 0 for no limit.
142
+
-**`sess.dataview`**: Target viewer column for data (default: `"Two"`).
143
+
-**`sess.browser`**: Target viewer for browser (default: `"Active"`).
144
+
-**`sess.webview`**: Target viewer for webview (default: `"Two"`).
145
+
-**`sess.helpPanel`**: Target viewer for help (default: `"Two"`).
141
146
142
147
## 4. Comparison with Legacy IPC
143
148
@@ -153,37 +158,8 @@ The `sess` package replaces the legacy file-based IPC mechanism with a modern, i
153
158
|**Transport Reliability**| OS-level File System Watchers |**WebSocket & HTTP streams**|
-**Old Approach:** R intercepted commands and appended custom JSON structures to a `request.log` file, then updated the timestamp on a `request.lock` file. The client OS file watcher detected the `.lock` file change, read the `.log` file, and processed the pending commands.
160
-
-**New Approach (`sess`):** R directly pushes an instantaneous **JSON-RPC Notification** (e.g., `method: "dataview"`, `method: "help"`) over the persistent WebSocket connection. The client receives and processes the payload instantly, bypassing disk I/O and file system watchers entirely.
161
-
162
-
**2. Synchronous RStudio API Emulation**
163
-
-**Old Approach:** R wrote a command to `request.log`, and then entered a blocking `while` loop aggressively polling for the creation of a `response.lock` file by the client.
164
-
-**New Approach (`sess`):** R sends a **JSON-RPC Request** over the WebSocket with an `id`. It enters a `while` loop calling `httpuv::service()`, maintaining a responsive background state, and waits for a corresponding **JSON-RPC Response** with the matching `id` over the same WebSocket.
165
-
166
-
**3. Workspace State (Global Environment)**
167
-
-**Old Approach:** An R task callback ran after every top-level console execution, eagerly evaluating and serializing the entire Global Environment to a `workspace.json` file, followed by touching a `workspace.lock` file. The client watched for the lock file change to read the JSON file. This caused constant overhead and disk writes, even when the client's workspace pane was hidden.
168
-
-**New Approach (`sess`):** Adopts a "Pull" architecture. The workspace is *only* evaluated and serialized when the client explicitly sends an **HTTP POST Request** to `/rpc` with `method: "workspace"`. This happens on-demand (e.g., when the UI pane is visible), saving significant R processing time and disk I/O.
169
-
170
-
**4. Static Plots**
171
-
-**Old Approach:** Plotting commands (via custom devices or hooks) generated a `plot.png` file on disk and updated a `plot.lock` file. The client watcher noticed the lock change, read the new PNG file from disk, and displayed it.
172
-
-**New Approach (`sess`):** When a new plot is generated to a temporary file, R sends a lightweight **JSON-RPC Notification** (`method: "plot_updated"`) via the WebSocket. The client then pulls the actual image data by sending an **HTTP POST Request** to `/rpc` (`method: "plot_latest"`), which returns the base64-encoded image over the network stream.
173
-
174
-
**5. Client Queries (Hover, Completion)**
175
-
-**Old Approach:** R ran an internal `httpuv` server using custom JSON structures and ad-hoc request types (like `{ "type": "hover" }`).
176
-
-**New Approach (`sess`):** Unified under the **JSON-RPC 2.0** standard. The client sends structured requests with strict `id` and `params` formatting to the single `/rpc` HTTP endpoint, receiving standardized JSON-RPC responses.
177
-
178
161
### Architectural Shifts
179
162
180
-
1.**Elimination of File Watchers**: The legacy system relied heavily on OS-level file system watchers (`fs.watch`) monitoring lock files to trigger client updates. This approach could be unreliable or slow across different platforms, network drives, and remote container environments. `sess` replaces this entirely with persistent WebSocket connections for instantaneous, reliable event pushing.
181
-
2.**On-Demand vs. Eager Evaluation**: Previously, R would eagerly evaluate and serialize the entire Global Environment to `workspace.json` frequently (e.g., via task callbacks), incurring significant continuous disk I/O and processing overhead. `sess` shifts this to a "Pull" model. The client requests the workspace state only when needed, significantly reducing R's background workload.
182
-
3.**Unified Standard**: Instead of maintaining separate, disparate mechanisms for command logs, lock-file polling loops, JSON dumps, and custom HTTP query payloads, `sess` unifies all structured communication under the ubiquitous **JSON-RPC 2.0** standard across WebSocket and HTTP transports.
183
-
184
-
### Responsiveness and the Event Loop
185
-
186
-
Because R is fundamentally single-threaded, both IPC mechanisms are constrained by the R event loop, but they surface this limitation differently to the client:
187
-
188
-
-**The "Busy" State**: If R is executing a long-running computation, the `httpuv` server running inside the session cannot process incoming HTTP requests (such as a request for `/rpc``workspace` or `completion`).
189
-
-**Active vs. Passive Waiting**: In the legacy system, the client passively waited for `workspace.lock` to change, effectively ignoring the busy state until the operation completed. With the `sess` HTTP RPC model, the client actively requests data. Therefore, the client *must* implement short, aggressive timeouts (e.g., 500ms) for these HTTP requests. If a timeout occurs, the client gracefully interprets this as "R is busy" and can display a loading state without locking up the IDE's UI thread.
163
+
1.**Elimination of File Watchers**: Replaces unreliable OS-level file system watchers with persistent WebSocket connections for instantaneous event pushing.
164
+
2.**On-Demand Evaluation**: Evaluations of the Global Environment are now performed only when requested by the client ("Pull" model), reducing R's background workload.
165
+
3.**Unified Standard**: Unifies all structured communication under the **JSON-RPC 2.0** standard across WebSocket and HTTP transports.
0 commit comments