From ed6aef82ecdafeed35619b15b67127e85da15b1a Mon Sep 17 00:00:00 2001 From: Simon Couch Date: Thu, 27 Aug 2026 14:43:52 -0700 Subject: [PATCH 1/4] enable temporary package installation --- pkg-r/R/run-r.R | 5 +++++ pkg-r/tests/testthat/test-run-r.R | 13 +++++++++++++ 2 files changed, 18 insertions(+) diff --git a/pkg-r/R/run-r.R b/pkg-r/R/run-r.R index 0caede0..f61d5fc 100644 --- a/pkg-r/R/run-r.R +++ b/pkg-r/R/run-r.R @@ -55,6 +55,8 @@ tool_run_r <- function(private) { "summaries (head(), summary()) over large outputs.", if (identical(private$worker$network, "none")) { "\n- The session has no network access." + } else { + "\n- You can install R packages with install.packages()." }, "\n- The session can only write to its own temporary directory." ), @@ -856,6 +858,9 @@ worker_init <- function( ) { setwd(work_dir) options(width = 80, cli.num_colors = 1) + worker_lib <- file.path(work_dir, "library") + dir.create(worker_lib) + .libPaths(c(worker_lib, .libPaths())) if (!protection %in% c("sandbox", "guardrails")) { stop("unknown run_r protection mode: ", protection) } diff --git a/pkg-r/tests/testthat/test-run-r.R b/pkg-r/tests/testthat/test-run-r.R index cbe0b9e..1738cc8 100644 --- a/pkg-r/tests/testthat/test-run-r.R +++ b/pkg-r/tests/testthat/test-run-r.R @@ -53,6 +53,19 @@ test_that("run_r session state persists across calls, and handles sync lazily", expect_match(res@value, "48") }) +test_that("run_r prepends a worker-local package library", { + worker <- local_guardrail_worker() + worker_ensure(worker) + + paths <- worker$rs$run(function() { + list(libraries = .libPaths(), bit64 = find.package("bit64")) + }) + + expect_equal(basename(paths$libraries[[1]]), "library") + expect_true(dir.exists(paths$libraries[[1]])) + expect_false(startsWith(paths$bit64, paths$libraries[[1]])) +}) + test_that("run_r loads integer64 methods for stored handles", { skip_if_not_installed("bit64") worker <- local_worker() From 08d4057d4864156ad23bce9ef967101b12fc9fed Mon Sep 17 00:00:00 2001 From: Simon Couch Date: Thu, 27 Aug 2026 14:47:18 -0700 Subject: [PATCH 2/4] clarify temporary package library --- pkg-r/R/run-r.R | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg-r/R/run-r.R b/pkg-r/R/run-r.R index f61d5fc..51da4c0 100644 --- a/pkg-r/R/run-r.R +++ b/pkg-r/R/run-r.R @@ -56,7 +56,10 @@ tool_run_r <- function(private) { if (identical(private$worker$network, "none")) { "\n- The session has no network access." } else { - "\n- You can install R packages with install.packages()." + paste( + "\n- The temporary directory has been added to libPaths, so you", + "can use install.packages() normally." + ) }, "\n- The session can only write to its own temporary directory." ), From 60f555a7d7271a9550cfaa3ba7b8f06fe767168e Mon Sep 17 00:00:00 2001 From: Simon Couch Date: Thu, 27 Aug 2026 14:47:57 -0700 Subject: [PATCH 3/4] order package sandbox guidance --- pkg-r/R/run-r.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg-r/R/run-r.R b/pkg-r/R/run-r.R index 51da4c0..a261a9d 100644 --- a/pkg-r/R/run-r.R +++ b/pkg-r/R/run-r.R @@ -55,13 +55,14 @@ tool_run_r <- function(private) { "summaries (head(), summary()) over large outputs.", if (identical(private$worker$network, "none")) { "\n- The session has no network access." - } else { + }, + "\n- The session can only write to its own temporary directory.", + if (identical(private$worker$network, "full")) { paste( "\n- The temporary directory has been added to libPaths, so you", "can use install.packages() normally." ) - }, - "\n- The session can only write to its own temporary directory." + } ), arguments = list( code = ellmer::type_string("The R code to run.") From c89aef8541c482a122f257a799fca4a9b6fe3adc Mon Sep 17 00:00:00 2001 From: Simon Couch Date: Thu, 27 Aug 2026 14:49:17 -0700 Subject: [PATCH 4/4] keep network guidance together --- pkg-r/R/run-r.R | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg-r/R/run-r.R b/pkg-r/R/run-r.R index a261a9d..fa4e16f 100644 --- a/pkg-r/R/run-r.R +++ b/pkg-r/R/run-r.R @@ -53,11 +53,10 @@ tool_run_r <- function(private) { "\n- Do not use this tool to talk to the user; explanations belong in your reply.", "\n- Return results implicitly (`x`, not `print(x)`) and prefer brief", "summaries (head(), summary()) over large outputs.", + "\n- The session can only write to its own temporary directory.", if (identical(private$worker$network, "none")) { "\n- The session has no network access." - }, - "\n- The session can only write to its own temporary directory.", - if (identical(private$worker$network, "full")) { + } else { paste( "\n- The temporary directory has been added to libPaths, so you", "can use install.packages() normally."