diff --git a/crates/execution/assets/v8-bridge.source.js b/crates/execution/assets/v8-bridge.source.js index 82414ef2..8ab77440 100644 --- a/crates/execution/assets/v8-bridge.source.js +++ b/crates/execution/assets/v8-bridge.source.js @@ -8262,6 +8262,10 @@ var __bridge = (() => { function getRuntimeHomeDir() { return globalThis.process?.env?.HOME || config.homedir; } + function getRuntimeUserHomeDir() { + const virtualHome = getRuntimeVirtualOs().homedir; + return typeof virtualHome === "string" && virtualHome.length > 0 ? virtualHome : config.homedir; + } function getRuntimeTmpDir() { return globalThis.process?.env?.TMPDIR || config.tmpdir; } @@ -8533,7 +8537,7 @@ var __bridge = (() => { uid: getRuntimeUid(), gid: getRuntimeGid(), shell: getRuntimeShell(), - homedir: getRuntimeHomeDir() + homedir: getRuntimeUserHomeDir() }; }, // CPU information diff --git a/crates/execution/src/node_import_cache.rs b/crates/execution/src/node_import_cache.rs index 5caab0d0..a5257c2c 100644 --- a/crates/execution/src/node_import_cache.rs +++ b/crates/execution/src/node_import_cache.rs @@ -17,7 +17,7 @@ const NODE_IMPORT_CACHE_MATERIALIZE_TIMEOUT_MS_ENV: &str = "AGENTOS_NODE_IMPORT_CACHE_MATERIALIZE_TIMEOUT_MS"; const NODE_IMPORT_CACHE_SCHEMA_VERSION: &str = "1"; const NODE_IMPORT_CACHE_LOADER_VERSION: &str = "8"; -const NODE_IMPORT_CACHE_ASSET_VERSION: &str = "70"; +const NODE_IMPORT_CACHE_ASSET_VERSION: &str = "71"; const NODE_IMPORT_CACHE_DIR_PREFIX: &str = "agentos-node-import-cache"; const DEFAULT_NODE_IMPORT_CACHE_MATERIALIZE_TIMEOUT: Duration = Duration::from_secs(30); const PYODIDE_DIST_DIR: &str = "pyodide-dist"; @@ -7392,6 +7392,9 @@ function createGuestOsModule(osModule) { (globalThis.__agentOSVirtualOs||{}).shell, DEFAULT_VIRTUAL_OS_SHELL, ); + function runtimeHomeDir() { + return resolveVirtualPath(globalThis.process?.env?.HOME, virtualHomeDir); + } const virtualCpuInfo = Object.freeze( Array.from({ length: VIRTUAL_OS_CPU_COUNT }, () => Object.freeze({ @@ -7435,7 +7438,7 @@ function createGuestOsModule(osModule) { cpus: () => virtualCpuInfo.map((cpu) => cloneVirtualCpuInfo(cpu)), freemem: () => VIRTUAL_OS_FREEMEM, getPriority: () => 0, - homedir: () => virtualHomeDir, + homedir: () => runtimeHomeDir(), hostname: () => VIRTUAL_OS_HOSTNAME, loadavg: () => [0, 0, 0], machine: () => VIRTUAL_OS_MACHINE, diff --git a/crates/sidecar/tests/builtin_conformance.rs b/crates/sidecar/tests/builtin_conformance.rs index ae8ea765..4e450654 100644 --- a/crates/sidecar/tests/builtin_conformance.rs +++ b/crates/sidecar/tests/builtin_conformance.rs @@ -1943,6 +1943,67 @@ fn os_resource_limits_are_vm_scoped() { run_isolated_builtin_conformance_test("os-resource-limits"); } +fn os_homedir_follows_effective_home_env_impl() { + assert_node_available(); + + let cwd = temp_dir("builtin-conformance-os-homedir-home-env"); + let entrypoint = cwd.join("entry.mjs"); + write_fixture( + &entrypoint, + r#" +import os from "node:os"; + +const initial = { + envHome: process.env.HOME, + homedir: os.homedir(), + userInfoHome: os.userInfo().homedir, +}; + +process.env.HOME = "/tmp/runtime-home"; + +console.log(JSON.stringify({ + initial, + afterMutation: { + envHome: process.env.HOME, + homedir: os.homedir(), + userInfoHome: os.userInfo().homedir, + }, +})); +"#, + ); + + let host = run_host_probe_with_env(&cwd, &entrypoint, &[("HOME", "/home/foo")]); + let guest = run_guest_probe_with_config( + "os-homedir-home-env", + &cwd, + &entrypoint, + HashMap::from([(String::from("env.HOME"), String::from("/home/foo"))]), + wire_permissions_allow_all(), + ALLOWED_NODE_BUILTINS, + ); + + assert_eq!(guest["initial"]["envHome"], "/home/foo"); + assert_eq!(guest["initial"]["homedir"], host["initial"]["homedir"]); + assert_eq!(guest["initial"]["homedir"], guest["initial"]["envHome"]); + assert_eq!(guest["initial"]["userInfoHome"], "/home/agentos"); + + assert_eq!(guest["afterMutation"]["envHome"], "/tmp/runtime-home"); + assert_eq!( + guest["afterMutation"]["homedir"], + host["afterMutation"]["homedir"] + ); + assert_eq!( + guest["afterMutation"]["homedir"], + guest["afterMutation"]["envHome"] + ); + assert_eq!(guest["afterMutation"]["userInfoHome"], "/home/agentos"); +} + +#[test] +fn os_homedir_follows_effective_home_env() { + run_isolated_builtin_conformance_test("os-homedir-home-env"); +} + fn dns_conformance_matches_host_node() { assert_node_available(); @@ -4036,6 +4097,7 @@ fn __builtin_conformance_extra_test_runner() { "perf-hooks-observer" => perf_hooks_observer_and_histogram_match_host_node_impl(), "process-runtime-stats" => process_runtime_stats_are_live_impl(), "os-resource-limits" => os_resource_limits_are_vm_scoped_impl(), + "os-homedir-home-env" => os_homedir_follows_effective_home_env_impl(), "timer-handle-ref-refresh" => timer_handle_ref_refresh_matches_host_node_impl(), "timer-unref-exit" => unrefd_timeout_does_not_keep_guest_process_alive_impl(), other => panic!("unknown builtin conformance extra test: {other}"),