Skip to content

Run rstudioapi::jobRunScript() in a new background console - #1460

Merged
juliasilge merged 3 commits into
mainfrom
feat/jobrunscript-new-session
Nov 7, 2026
Merged

juliasilge merged 3 commits into
mainfrom
feat/jobrunscript-new-session

Conversation

@juliasilge

@juliasilge juliasilge commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

rstudioapi::jobRunScript() now works in Positron. ark asks Positron to start a new R console session in the background, and that session runs the script with source(). The caller's console stays free while the script runs. For example, targets::tar_make(as_job = TRUE) now runs the pipeline in its own console.

Before this change, the call failed with "Function runScriptJob not found in RStudio", because ark did not define .rs.api.runScriptJob().

Changes

  • Add the execute_code_in_new_session frontend method to the UI comm. crates/amalthea/src/comm/ui_comm.rs is generated from the Positron contract.
  • Add .ps.ui.executeCodeInNewSession(code, sessionName). It parses code first. If the code does not parse, it stops with an error in the caller's session, and no session starts. It returns the ID of the new session.
  • Add .rs.api.runScriptJob() with the same arguments as in RStudio, so that the callFun() of rstudioapi accepts it:
    • path, name, encoding, and workingDir must each be a single string.
    • The script must exist. If name is NULL or empty, the session name is the file name. If workingDir is NULL, the working directory is the folder of the script. The working directory must exist.
    • ark normalizes both paths in the caller's session, so relative paths use the working directory of the caller.
    • importEnv = TRUE and a non-empty exportEnv are not supported. Each one gives a warning, and the job still runs.
    • The function returns the session ID invisibly.

The new session runs this code:

{
    setwd("/path/to/working/dir")
    source("/path/to/script.R", encoding = "unknown")
}

ark makes each value with deparse(), so quotes and backslashes in paths are safe. The braces make one expression. Positron can split console input into statements and continue after an error. Without the braces, a failed setwd() would let source() run in the wrong folder.

Why not setWorkingDirectory()

I originally wanted to use ILanguageRuntimeSession.setWorkingDirectory() from Positron, but it is not a good fit here:

  • For R, it sends setwd() directly to the kernel, outside the console queue. It does not wait for the result, and it continues after an error. The order of setwd() and source() running would then depend on timing.
  • It escapes only \ and " while deparse() escapes all special characters.
  • The supervisor rejects it for kernels that do not implement it, such as Python.
  • It runs after the session starts, so .Rprofile and renv still use the workspace folder. A real fix needs a working directory at session start, and Positron does not have this option yet.

Known limitations

  • The caller's console is busy until the new session starts and the code is in the queue. This takes some seconds, or even more with a complicated .Rprofile or renv. ark needs the reply to return the session ID and to report start errors.
  • If the user interrupts the caller during this wait, R returns, but the job still starts.
  • The .ps.ui.* functions need an active execute request, so a call from a later::later() callback fails. This limit is the same for all .ps.ui.* functions currently.
  • The other rstudioapi job functions (jobAdd(), jobGetState(), and more) are not part of this change.

Testing

  • New integration tests in crates/ark/tests/integration/rstudioapi.rs cover the request that ark sends (with a path that contains a space and a quote), name and workingDir, relative paths, a missing file or folder, bad argument types, the warnings, and code that does not parse. Tests that call rstudioapi::jobRunScript() skip when rstudioapi is not installed. Tests that call .rs.api.runScriptJob() directly always run.
  • Run them with cargo nextest run -p ark --test integration -E 'test(rstudioapi::)'. They need nextest, because each test needs its own R session.
  • The expected paths remove the \\?\ prefix that canonicalize() adds on Windows. I did not run the tests on Windows, so so we'll want to especially check the Windows CI result.
  • To do a manual test in Positron (with the companion PR):
    1. Make foo.R with Sys.sleep(10); print(getwd()).
    2. In the R console, run rstudioapi::jobRunScript("foo.R").
    3. After some seconds, the call returns. A new console named foo.R shows in the session list, and the original console stays selected. You can type in the original console while the script runs, and the new console prints the folder of the script.

Positron Release Notes

New Features

Bug Fixes

  • N/A

@juliasilge
juliasilge marked this pull request as ready for review November 2, 2026 00:37
@juliasilge
juliasilge requested a review from jmcphers November 5, 2026 20:53

@jmcphers jmcphers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM!

@juliasilge
juliasilge merged commit 70885c7 into main Nov 7, 2026
18 of 19 checks passed
@juliasilge
juliasilge deleted the feat/jobrunscript-new-session branch November 7, 2026 01:51
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 7, 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.

2 participants