Repository navigation
Add persistent multi-session R Interactive windows - #1805
Conversation
Implement independent plain R and arf agents, durable replay, native console control, session-bound language services, rich renderers, and notebook export. Include macOS storage and virtual-cell lint cache fixes with regression coverage.
|
@eitsupi Addressed your latest review in fa5b7fa.
Local validation passed 99 backend/runtime tests, 47 arf tests, 106 editor/runtime/supervision/terminal tests, and 634 sess checks. TypeScript compilation and R lint passed; ESLint reported no errors. The production VSIX was built and verified before pushing. The new CI run will cover the supported OS matrix, including Linux supervision. CI follow-up: 622dfcd removes a test-only |
Remove the Node path setting, scope Electron Node mode to agent launches, and mark Interactive settings experimental. Verify private sess calls and full editor quit/reconnect across versions.
eitsupi
left a comment
There was a problem hiding this comment.
A review with ChatGPT did not find any major remaining issues.
I only have two small nits:
- Even if the VS Code runtime is the right default, would it be worth keeping an optional (and experimental)
r.interactive.nodePathoverride?process.execPathshould work for VS Code and likely for common Code-OSS derivatives, but that behavior is not really part of the VS Code extension API contract. An explicit standalone Node path could provide an escape hatch for code-server, OpenVSCode Server, VSCodium, or other compatible IDEs. I would still keep the default fully automatic. - Do we want to keep all of the new files under
docs/?r-interactive.mdis clearly useful as user documentation, but several of the other files look more like implementation plans, PR review notes, or point-in-time validation reports. I wonder if keeping only the long-term user/architecture documentation would reduce maintenance burden and avoid stale design or test-result documents later.
|
@eitsupi Following up on your review:
|
|
As I commented on #1755, I think it would be better in the long term to create a website on GitHub Pages using SSG and discontinue the wiki. |
|
@eitsupi Agreed that a GitHub Pages site with an SSG is worth considering as a separate documentation project. I've applied the wiki move in 9c1eeb0:
Documentation links and settings were checked, and the VSIX was rebuilt before pushing. The Node-override CI regression is also fixed; all checks on 9c1eeb0 are green, including Linux, macOS, Windows, build, and lint. |
eitsupi
left a comment
There was a problem hiding this comment.
Aside from some slightly outdated descriptions remaining in the PR text, everything seems fine.
Awsome work!
|
@eitsupi Thanks for your review! |
…1837) Fixes #1836. #1764 introduced the public session API with pseudoterminal downstream clients in mind. #1805 made Workspace actions execute in their owning session, but terminal dispatch only resolves native PID associations, leaving extension-owned pseudoterminals without an execution target. Add backward-compatible `session.activate(sessionId, { terminal })` to explicitly bind a terminal. Interactive execution retains priority; terminal execution uses the session's current explicit or native association. Unassociated background sessions still reject terminal execution. Execution, readiness and terminal selection share a registry with at most one terminal per session and one session per terminal. Explicit binding replaces either endpoint's previous association, so a superseded native terminal cannot return as a fallback when the explicit terminal closes. Live explicit bindings take priority over native attach. Close and connection replacement invalidate associations; queued sends validate the exact association, and delayed native discovery cannot overwrite intervening ownership changes or a newer connection. Reconnect refreshes the selected session's connection even after same-session reselection, while preserving a newer selection of a different session; old Workspace nodes still reject execution. **Downstream follow-up:** vscode-R-console needs to pass its VS Code Terminal when activating a sess session, and repeat registration after reconnecting. Older vscode-R implementations ignore the extra argument, so downstream can retain compatibility with their existing activation API. No vscode-R-console sources or sess wire protocol are changed here.
Add native VS Code Interactive windows whose R processes survive editor reloads, application exit, and disconnection. Users can run independent background R or headless arf sessions, attach to existing arf sessions in tmux, and switch between them while retaining their environments and executed history. The implementation uses VS Code's Interactive/notebook APIs, a bundled sess bridge, languageserver, and JGD; it does not require Jupyter.
Sessions and execution
SessionBackendcontract. The shared sess backend composes plain-R and arf adapters, with private console/RPC and graphics helpers. Backend-specific preparation runs for both creation and restart; the independent agent bundle no longer shares the sess installation cache. Legacy config/protocol compatibility and current version requirements are preserved.Plots, tables, widgets, and history
mfrow = c(2, 2)produce two four-panel pages. The selected page survives updates and reconnection; Open, Save, and Fit target that page. Save opens a native SVG/PNG format picker without resizing the cell. Standard graphics images support Open and Save without offering live device resizing.:=andset()stay quiet unless explicitly displayed. Respectoptions(warn)andsuppressWarnings()during analysis. Cell snapshots retain at most 1,000 rows / 100,000 cells, subsetting before class printing or serialization. Large tables use a separate full-data handle without a deep copy: the saved row limit is not an inline browsing limit. The cell distinguishes Saved preview from Live data; exports preserve the original preview/scope. Live query caches expire after reference edits. New inline queries refresh column metadata and clear incompatible filters/sorting after schema changes; schema changes during ordinary navigation require Reset/reopen. Synthetic row-name representation differences do not clear valid queries.r.interactive.tableViewdefault setting. Text uses the class-specific R printout captured at execution time, including data.table type labels and R print options. Switching does not rerun R. Snapshots are bounded to 256 KiB, preserve Unicode and portable line endings, and fail gracefully when a custom printer errors. Explicitprint(x)remains console output.Workspace, language services, and R libraries
.lintrlinter lists require languageserver #782: released 0.3.20 forces default linters for pathless documents. The extension does not patch R package namespaces.Connection, output, and cancellation robustness
Deliver replayed history before live events received in the same socket read, so reconnecting during streaming output does not skip cells or output.
Bound rich events by their encoded JSON byte size before native IPC transmission. Oversized HTML, tables, and escaped strings produce a retained truncation notice while R keeps running.
Keep forked R workers off the parent console socket. Parallel output uses worker stdout/stderr instead of interleaving protocol frames or consuming parent input.
Interrupt slow inspections, including queries whose request has timed out. Return an interrupted RPC response while preserving the R polling loop, so subsequent code and inspections still work.
Documentation
The R Interactive wiki page contains the experimental user guide, including setup, session controls, rich output, storage limits, and troubleshooting. The current architecture/backend contract, contributor test instructions, and analysis fixtures remain beside the source. The original plans and dated reports are preserved in the PR's history; report links below refer to that fixed revision.
Validation
57ddfc0, VS Code 1.140.080b76b2The expanded public-code review added fourteen sourced R-manual examples and fixed five output problems: raster rotation/reflection/interpolation, phantom rows from matrix-column queries, missing pages through imported graphics calls, duplicate old plots after layout changes, and missing zero-count bar outlines. All 108 public/research executions passed across three configurations. Twelve new JGD plots were rendered and visually compared with ordinary-R PNGs; the runner now saves every retained page. The public-example report records sources, adaptations, reproductions and checks.
Connection/output/cancellation regressions also cover replay/live events sharing a socket read, oversized Unicode and JSON-escaped displays, concurrent mclapply output, and inspection cancellation both before and after timeout.
The installer was tested with the compiler deliberately disabled: it installed a compatible locally built native binary, handled Linux-style binary repositories without compiling, and rejected an incompatible same-version build without replacing an existing installation. A live R-universe test installed and loaded the public sess binary successfully for ordinary use and correctly rejected it for Interactive. renv and user-library isolation checks pass with both R and arf.
The large-table review records the copy audit and reproducible allocation benchmark. On a 2-million-row × 23-column data.table, the old copy alone allocated 351 MiB; the complete warmed preview now allocates 0.63 MiB in 7 ms. An exact-dimension 832,976,871 × 23 compact ALTREP data.frame previews in 52 ms and fetches its final page in 1 ms. These are local R-side measurements, not timings on the user’s remote server. The allocation regression was rerun successfully. New tests fetch the final 11 rows through the inline helper and actual notebook renderer message path, combine date/logical/text filters with descending sorting, recover from schema edits, preserve unfinished filter drafts, and verify Reset/offline/stale-response behavior.
The research review maps PR capabilities to coverage and records six findings fixed during analysis work. Reproducible workflows cover import/cleaning, joins/reshape, grouped summaries, hypothesis tests, linear/logistic/survival models, bootstrap reproducibility, diagnostic pages, faceted visualization, CSV/gzip/RDS and plot-file export, and 100,000-row previews. Native sessions retained independent models and data after reload; historical tables were paged/sorted/filtered after by-reference edits. Standard graphics was checked natively, and bulk stop retained all three disposable transcripts.
New supervisor regressions launch real plain R and arf with no tmux on PATH, verify that the agent leaves the editor process tree, terminate the launcher, and reconnect to the same R PID with retained objects. They also cover explicit-supervisor preflight, restart recovery, and launch failures without duplicate agents.
Native testing covers multiple sessions, real reload/application exit, workspace switching, restart/bulk stop, execution/input/language features, missing-arf recovery, and export. The latest pass verifies the two-page plot example, exact data.table printing, selected-page SVG save, default-view changes, and view-choice restoration after reload. Regressions also cover stopped controls, stale replies, save readiness, output lifecycle ordering, compressed-asset quotas, and Windows print-snapshot line endings.
The original ten public examples include R Graph Gallery plots, dplyr summaries, DT, and Plotly. Seven JGD plots were visually compared with independent R PNG renders; DT search/sort/paging and Plotly hover/zoom/reset were exercised through the actual asset service and iframe sandbox. See the public-example report and live-testing report for sources, reproducible fixtures, and coverage.
Backend-refactor validation used R 4.6.1, arf 0.5.3, and VS Code 1.110.0. The new tests also cover a backend with no sess library/bootstrap, dispatch/completion ordering, transport ambiguity, stale events, input/request ownership, request cancellation, early Stop, and the original arf process remaining usable after disposal. The production VSIX was rebuilt and its bundled agent, extension, sess handler and manifest verified against the workspace before pushing. Older R/OS combinations were not rerun for this refactor; their requirements are unchanged.
Requirements and limits
Requires VS Code 1.110+. The persistent Interactive runtime supports Linux and macOS and requires R, the documented R dependencies, and either compatible prebuilt sess/dependency packages or a package compiler; tmux and arf are optional. The agent uses VS Code's extension host runtime by default: Electron in Node mode on desktop, or VS Code Server's Node remotely. The optional experimental
r.interactive.nodePathsetting selects standalone Node.js 18+; no separate Node installation is required by default. macOS uses writable Application Support storage by default.Persistence preserves a running R process through editor reload/exit; host logout policies may still terminate detached processes. It does not checkpoint the R heap across process termination or host reboot. Actual Remote SSH transport and server-specific systemd policies have not been exercised locally. Windows CI verifies the compatible extension/package paths; it does not imply Windows support for the native persistent runtime.
Existing agents retain their original runtime. Start a new session to use the updated bootstrap, graphics handling, storage capabilities, printed table snapshots, reproducible data inspection, corrected fallback plot pages, and bounded large-table previews, or restart a managed session after preserving needed R objects. Editor-side plot grouping, table alignment and inline controls also apply to retained output. Sessions already providing bounded snapshots and full-data handles can keep running after the extension update/reload; older output without a full handle cannot expand a truncated snapshot. Setup, lifecycle semantics, and other known limits are in the user guide; the implementation review records the workflow comparison and regression coverage.
Screenshots