Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ First development changelog. dsprrr is experimental; the API may change.
`refine(best_of_n(mod))`) compose their ids cleanly instead of crashing with
a duplicate-argument error (#dsprrr-pcd, #dsprrr-wx6).

* `pin_module_config()` now errors clearly for pipelines and other unsupported
module types instead of silently serialising them as an empty `PredictModule`
and dropping every step on restore (#dsprrr-07u).

## Internal

* Tests now isolate the on-disk cache to a temporary directory, so running
Expand Down
9 changes: 9 additions & 0 deletions R/orchestration.R
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ restore_module_config <- function(config, signature = NULL) {
}

serialize_module_config_v2 <- function(module) {
if (inherits(module, "PipelineModule")) {
cli::cli_abort(c(
"Pipeline persistence is not yet supported",
"x" = "{.fn pin_module_config} cannot serialise a {.cls PipelineModule}",
"i" = "Persisting it here would silently drop every step and its demos",
"i" = "Pin each step module individually, or rebuild the pipeline from source"
))
}

kind <- module_kind(module)
supported <- c("predict", "react", "chain_of_thought", "multichain")
if (!kind %in% supported) {
Expand Down
6 changes: 5 additions & 1 deletion R/run.R
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,11 @@ module_kind <- function(module) {
"ReactModule" = "react",
"MultiChainComparisonModule" = "multichain",
"PredictModule" = "predict",
"predict"
# Fall back to the actual class name rather than silently claiming
# "predict" -- otherwise unsupported module types (pipelines, ensembles,
# RAG, ...) pass the persistence allow-list and serialize as a bare
# PredictModule, losing all of their structure.
class(module)[1]
)
}

Expand Down
17 changes: 17 additions & 0 deletions tests/testthat/test-orchestration.R
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,20 @@ test_that("module config round-trips correctly", {
expect_true(restored$is_compiled())
expect_equal(restored$state$best_score, 0.92)
})

test_that("pin_module_config refuses to silently destroy pipelines (dsprrr-07u)", {
skip_if_not_installed("pins")

m1 <- module(signature("question -> thought"), type = "predict")
m2 <- module(signature("thought -> answer"), type = "predict")
pipe <- pipeline(m1, m2)
board <- pins::board_temp()

# Regression: module_kind() collapsed unknown classes to "predict", so a
# pipeline pinned without error and restored as a single empty PredictModule,
# silently losing every step and its bootstrapped demos.
expect_error(
pin_module_config(board, "pipe", pipe),
"[Pp]ipeline"
)
})
Loading