Skip to content

Commit c32ed5a

Browse files
wan9chicodex
andcommitted
feat(ipc): runner ↔ tool IPC channel with disableCache
Add the runner-aware IPC protocol, embedded Node client addon, execution-time server lifecycle, and disableCache handling. getEnv and getEnvs intentionally return unset/empty values until the follow-up env-tracking PR can fingerprint served values. Co-Authored-By: OpenAI <codex@openai.com>
1 parent b886a13 commit c32ed5a

42 files changed

Lines changed: 2489 additions & 68 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Changelog
22

3+
- **Added** Runner-aware tools can now opt the current task run out of caching through the new IPC channel; Vite dev server integration uses this automatically ([#441](https://github.com/voidzero-dev/vite-task/pull/441))
34
- **Fixed** Prefix environment assignments like `PATH=... command` now affect executable lookup during task planning, so tools provided only by the prefixed `PATH` can be resolved correctly ([#440](https://github.com/voidzero-dev/vite-task/pull/440))
45
- **Changed** Cache misses caused by a tracked env var now name the env var inline, for example `cache miss: env 'NODE_ENV' changed`, instead of the generic `envs changed` message ([#438](https://github.com/voidzero-dev/vite-task/pull/438))
56
- **Fixed** The task cache is now stored in a per-schema-version subdirectory (e.g. `node_modules/.vite/task-cache/v13/`), so switching between branches that pin different Vite+ versions no longer fails with `Unrecognized database version`. Each version keeps its own cache directory; a cache from a different version is ignored rather than aborting the run ([#433](https://github.com/voidzero-dev/vite-task/pull/433))

Cargo.lock

Lines changed: 142 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ libc = "0.2.185"
8686
libtest-mimic = "0.8.2"
8787
memmap2 = "0.9.7"
8888
monostate = "1.0.2"
89+
napi = "3"
90+
napi-build = "2"
91+
napi-derive = "3"
8992
native_str = { path = "crates/native_str" }
9093
nix = { version = "0.31.2", features = ["dir", "signal"] }
9194
ntapi = "0.4.1"
@@ -150,8 +153,12 @@ vite_shell = { path = "crates/vite_shell" }
150153
vite_str = { path = "crates/vite_str" }
151154
vite_task = { path = "crates/vite_task" }
152155
vite_task_bin = { path = "crates/vite_task_bin" }
156+
vite_task_client = { path = "crates/vite_task_client" }
157+
vite_task_client_napi = { path = "crates/vite_task_client_napi", artifact = "cdylib", target = "target" }
153158
vite_task_graph = { path = "crates/vite_task_graph" }
159+
vite_task_ipc_shared = { path = "crates/vite_task_ipc_shared" }
154160
vite_task_plan = { path = "crates/vite_task_plan" }
161+
vite_task_server = { path = "crates/vite_task_server" }
155162
vite_workspace = { path = "crates/vite_workspace" }
156163
vt100 = "0.16.2"
157164
wax = "0.7.0"
@@ -169,6 +176,7 @@ ignored = [
169176
# These are artifact dependencies. They are not directly `use`d in Rust code.
170177
"fspy_preload_unix",
171178
"fspy_preload_windows",
179+
"vite_task_client_napi",
172180
]
173181

174182
[profile.dev]

crates/native_str/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use wincode::{
3737
/// **Not portable across platforms.** The binary representation is platform-specific.
3838
/// Deserializing a `NativeStr` serialized on a different platform leads to unspecified
3939
/// behavior (garbage data), but is not unsafe. Designed for same-platform IPC only.
40-
#[derive(TransparentWrapper, PartialEq, Eq)]
40+
#[derive(TransparentWrapper, PartialEq, Eq, Hash)]
4141
#[repr(transparent)]
4242
pub struct NativeStr {
4343
// On unix, this is the raw bytes of the OsStr.

crates/vite_task/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,27 @@ tokio = { workspace = true, features = [
4343
tokio-util = { workspace = true }
4444
tracing = { workspace = true }
4545
twox-hash = { workspace = true }
46+
materialized_artifact = { workspace = true }
4647
uuid = { workspace = true, features = ["v4"] }
4748
vite_path = { workspace = true }
4849
vite_select = { workspace = true }
4950
vite_str = { workspace = true }
5051
vite_task_graph = { workspace = true }
52+
vite_task_ipc_shared = { workspace = true }
5153
vite_task_plan = { workspace = true }
54+
vite_task_server = { workspace = true }
5255
vite_workspace = { workspace = true }
5356
wax = { workspace = true }
5457
zstd = { workspace = true }
5558

59+
# Artifact build-deps must be unconditional: cargo's resolver panics when
60+
# `artifact = "cdylib"` deps live under a `[target.cfg.build-dependencies]`
61+
# block on cross-compile.
62+
[build-dependencies]
63+
anyhow = { workspace = true }
64+
materialized_artifact_build = { workspace = true }
65+
vite_task_client_napi = { workspace = true }
66+
5667
[dev-dependencies]
5768
tempfile = { workspace = true }
5869

crates/vite_task/build.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
#![expect(
2+
clippy::disallowed_types,
3+
clippy::disallowed_macros,
4+
reason = "build.rs interfaces with std::path and cargo's env-var API"
5+
)]
6+
7+
use std::{env, path::Path};
8+
9+
use anyhow::Context;
10+
111
// Why `cfg(fspy)` instead of matching on `target_os` directly at each use site:
212
// "fspy is available" is a single semantic predicate, but the underlying reason
313
// (the `fspy` crate builds on windows/macos/linux) is a three-OS list that
@@ -7,12 +17,18 @@
717
// over OSes. The OS allowlist lives in two spots that must stay in sync: this
818
// file (for the rustc cfg) and the target-scoped dep block in Cargo.toml
919
// (which Cargo resolves before build.rs runs, so it can't reuse this cfg).
10-
fn main() {
20+
fn main() -> anyhow::Result<()> {
1121
println!("cargo::rustc-check-cfg=cfg(fspy)");
1222
println!("cargo::rerun-if-changed=build.rs");
1323

14-
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
24+
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
1525
if matches!(target_os.as_str(), "windows" | "macos" | "linux") {
1626
println!("cargo::rustc-cfg=fspy");
1727
}
28+
29+
let env_name = "CARGO_CDYLIB_FILE_VITE_TASK_CLIENT_NAPI";
30+
println!("cargo:rerun-if-env-changed={env_name}");
31+
let dylib_path = env::var_os(env_name).with_context(|| format!("{env_name} not set"))?;
32+
materialized_artifact_build::register("vite_task_client_napi", Path::new(&dylib_path));
33+
Ok(())
1834
}

crates/vite_task/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod cli;
22
mod collections;
3+
mod napi_client;
34
pub mod session;
45

56
// Public exports for vite_task_bin
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//! The `vite_task_client_napi` cdylib is embedded into the `vp` binary and
2+
//! materialized to disk on first use so tools can `require()` it at runtime.
3+
4+
use std::{env, fs, sync::LazyLock};
5+
6+
use materialized_artifact::artifact;
7+
use vite_path::{AbsolutePath, AbsolutePathBuf};
8+
9+
/// Path to the materialized `vite_task_client_napi` `.node` addon.
10+
///
11+
/// The file is written to a process-wide temp directory on first call and
12+
/// reused on every subsequent call (content-addressed filename; no re-writes).
13+
///
14+
/// # Panics
15+
///
16+
/// Panics if the materialization fails on first call — this mirrors fspy's
17+
/// `SPY_IMPL` and the same reasoning applies: if we can't write into the
18+
/// system temp dir, the runner can't run tasks anyway.
19+
#[must_use]
20+
pub fn napi_client_path() -> &'static AbsolutePath {
21+
static PATH: LazyLock<AbsolutePathBuf> = LazyLock::new(|| {
22+
let dir = env::temp_dir().join("vite_task_client_napi");
23+
let _ = fs::create_dir(&dir);
24+
let path = artifact!("vite_task_client_napi")
25+
.materialize()
26+
.suffix(".node")
27+
.at(&dir)
28+
.expect("materialize vite_task_client_napi");
29+
AbsolutePathBuf::new(path).expect("system temp dir yields an absolute path")
30+
});
31+
PATH.as_absolute_path()
32+
}

0 commit comments

Comments
 (0)