commit bf5114b28674e28c465e5c3e43c1f78d660d765e
parent 22253d833097dd81edbcea1121097906f6d580f5
Author: triesap <tyson@radroots.org>
Date: Thu, 9 Apr 2026 16:58:27 +0000
runtime: resolve hyf startup paths
Diffstat:
4 files changed, 263 insertions(+), 0 deletions(-)
diff --git a/src/hyf_runtime/env.mojo b/src/hyf_runtime/env.mojo
@@ -0,0 +1,30 @@
+from std.os import getenv
+
+from hyf_runtime.profile import interactive_user_profile
+
+
+comptime _HYF_PATHS_PROFILE_ENV = "HYF_PATHS_PROFILE"
+comptime _HYF_PATHS_REPO_LOCAL_ROOT_ENV = "HYF_PATHS_REPO_LOCAL_ROOT"
+
+
+def hyf_paths_profile_env_name() -> String:
+ return _HYF_PATHS_PROFILE_ENV
+
+
+def hyf_paths_repo_local_root_env_name() -> String:
+ return _HYF_PATHS_REPO_LOCAL_ROOT_ENV
+
+
+def configured_paths_profile_from_env() -> String:
+ var value = getenv(_HYF_PATHS_PROFILE_ENV, "")
+ if value != "":
+ return value
+ return interactive_user_profile()
+
+
+def configured_repo_local_root_from_env() -> String:
+ return getenv(_HYF_PATHS_REPO_LOCAL_ROOT_ENV, "")
+
+
+def configured_user_home_from_env() -> String:
+ return getenv("HOME", "")
diff --git a/src/hyf_runtime/startup.mojo b/src/hyf_runtime/startup.mojo
@@ -0,0 +1,136 @@
+from std.collections import List
+from std.sys import argv
+
+from hyf_runtime.env import (
+ configured_paths_profile_from_env,
+ configured_repo_local_root_from_env,
+ configured_user_home_from_env,
+)
+from hyf_runtime.errors import raise_runtime_contract_error
+from hyf_runtime.paths import RuntimePaths, hyf_runtime_paths_for_unix_profile
+
+
+@fieldwise_init
+struct RuntimeStartupContext(Copyable, Movable):
+ var paths_profile: String
+ var repo_local_base_root: String
+ var user_home: String
+ var paths: RuntimePaths
+
+
+@fieldwise_init
+struct RuntimeStartupInput(Copyable, Movable):
+ var env_paths_profile: String
+ var env_repo_local_base_root: String
+ var user_home: String
+ var argv: List[String]
+
+
+@fieldwise_init
+struct _StartupOverrides(Copyable, Movable):
+ var paths_profile: String
+ var repo_local_base_root: String
+
+
+def _require_flag_value(
+ args: List[String], value_index: Int, flag_name: String
+) raises -> String:
+ if value_index >= len(args):
+ raise_runtime_contract_error(flag_name + " requires a value")
+ var value = String(String(args[value_index]).strip())
+ if value == "":
+ raise_runtime_contract_error(flag_name + " requires a non-empty value")
+ if value.startswith("-"):
+ raise_runtime_contract_error(
+ flag_name + " value must not be another flag"
+ )
+ return value^
+
+
+def _parse_startup_overrides(args: List[String]) raises -> _StartupOverrides:
+ var overrides = _StartupOverrides(paths_profile="", repo_local_base_root="")
+ var index = 0
+ while index < len(args):
+ var arg = String(args[index])
+
+ if arg == "--paths-profile":
+ overrides.paths_profile = _require_flag_value(
+ args, index + 1, "--paths-profile"
+ )
+ index += 2
+ continue
+
+ if arg.startswith("--paths-profile="):
+ overrides.paths_profile = String(
+ arg[byte = len("--paths-profile=") :]
+ )
+ if overrides.paths_profile == "":
+ raise_runtime_contract_error("--paths-profile requires a value")
+ index += 1
+ continue
+
+ if arg == "--repo-local-root":
+ overrides.repo_local_base_root = _require_flag_value(
+ args, index + 1, "--repo-local-root"
+ )
+ index += 2
+ continue
+
+ if arg.startswith("--repo-local-root="):
+ overrides.repo_local_base_root = String(
+ arg[byte = len("--repo-local-root=") :]
+ )
+ if overrides.repo_local_base_root == "":
+ raise_runtime_contract_error(
+ "--repo-local-root requires a value"
+ )
+ index += 1
+ continue
+
+ raise_runtime_contract_error("unknown startup argument '" + arg + "'")
+
+ return overrides^
+
+
+def resolve_startup_context(
+ input: RuntimeStartupInput,
+) raises -> RuntimeStartupContext:
+ var profile = String(input.env_paths_profile)
+ if profile == "":
+ raise_runtime_contract_error("env paths profile must not be empty")
+
+ var repo_local_base_root = String(input.env_repo_local_base_root)
+ var overrides = _parse_startup_overrides(input.argv)
+ if overrides.paths_profile != "":
+ profile = String(overrides.paths_profile)
+ if overrides.repo_local_base_root != "":
+ repo_local_base_root = String(overrides.repo_local_base_root)
+
+ var paths = hyf_runtime_paths_for_unix_profile(
+ profile, input.user_home, repo_local_base_root
+ )
+ return RuntimeStartupContext(
+ paths_profile=profile,
+ repo_local_base_root=repo_local_base_root,
+ user_home=String(input.user_home),
+ paths=paths^,
+ )
+
+
+def process_startup_args() -> List[String]:
+ var raw_args = argv()
+ var args = List[String]()
+ for index in range(1, len(raw_args)):
+ args.append(String(raw_args[index]))
+ return args^
+
+
+def resolve_startup_context_from_process() raises -> RuntimeStartupContext:
+ return resolve_startup_context(
+ RuntimeStartupInput(
+ env_paths_profile=configured_paths_profile_from_env(),
+ env_repo_local_base_root=configured_repo_local_root_from_env(),
+ user_home=configured_user_home_from_env(),
+ argv=process_startup_args(),
+ )
+ )
diff --git a/src/main.mojo b/src/main.mojo
@@ -1,5 +1,8 @@
+from hyf_runtime.startup import resolve_startup_context_from_process
from hyf_stdio.server import run_stdio_server
def main() raises:
+ var startup_context = resolve_startup_context_from_process()
+ _ = startup_context.paths.config_path
run_stdio_server()
diff --git a/tests/test_runtime_paths.mojo b/tests/test_runtime_paths.mojo
@@ -1,10 +1,16 @@
+from std.collections import List
from std.testing import TestSuite, assert_equal, assert_raises
+from hyf_runtime.env import (
+ hyf_paths_profile_env_name,
+ hyf_paths_repo_local_root_env_name,
+)
from hyf_runtime.paths import (
hyf_runtime_paths_for_unix_profile,
runtime_paths_for_namespace,
)
from hyf_runtime.roots import runtime_roots_from_base_root
+from hyf_runtime.startup import RuntimeStartupInput, resolve_startup_context
def test_runtime_paths_repo_local_contract_vector() raises:
@@ -80,5 +86,93 @@ def test_runtime_paths_reject_invalid_profile_namespace_and_base_root() raises:
)
+def _startup_argv() -> List[String]:
+ return List[String]()
+
+
+def _startup_argv2(first: String, second: String) -> List[String]:
+ var args = List[String]()
+ args.append(first)
+ args.append(second)
+ return args^
+
+
+def test_runtime_env_contract_names_are_frozen() raises:
+ assert_equal(hyf_paths_profile_env_name(), "HYF_PATHS_PROFILE")
+ assert_equal(
+ hyf_paths_repo_local_root_env_name(), "HYF_PATHS_REPO_LOCAL_ROOT"
+ )
+
+
+def test_startup_context_defaults_from_env_and_home() raises:
+ var context = resolve_startup_context(
+ RuntimeStartupInput(
+ env_paths_profile="interactive_user",
+ env_repo_local_base_root="",
+ user_home="/home/hyf-test",
+ argv=_startup_argv(),
+ )
+ )
+
+ assert_equal(context.paths_profile, "interactive_user")
+ assert_equal(
+ context.paths.config_path,
+ "/home/hyf-test/.radroots/config/services/hyf/config.toml",
+ )
+
+
+def test_startup_context_cli_flags_override_env() raises:
+ var context = resolve_startup_context(
+ RuntimeStartupInput(
+ env_paths_profile="service_host",
+ env_repo_local_base_root="",
+ user_home="/home/ignored",
+ argv=_startup_argv2(
+ "--paths-profile=repo_local",
+ "--repo-local-root=/tmp/hyf-runtime",
+ ),
+ )
+ )
+
+ assert_equal(context.paths_profile, "repo_local")
+ assert_equal(context.repo_local_base_root, "/tmp/hyf-runtime")
+ assert_equal(
+ context.paths.config_path,
+ "/tmp/hyf-runtime/config/services/hyf/config.toml",
+ )
+
+
+def test_startup_context_rejects_missing_root_unknown_flag_and_flag_as_value() raises:
+ with assert_raises():
+ _ = resolve_startup_context(
+ RuntimeStartupInput(
+ env_paths_profile="repo_local",
+ env_repo_local_base_root="",
+ user_home="/home/ignored",
+ argv=_startup_argv(),
+ )
+ )
+
+ with assert_raises():
+ _ = resolve_startup_context(
+ RuntimeStartupInput(
+ env_paths_profile="interactive_user",
+ env_repo_local_base_root="",
+ user_home="/home/ignored",
+ argv=_startup_argv2("--profile", "repo_local"),
+ )
+ )
+
+ with assert_raises():
+ _ = resolve_startup_context(
+ RuntimeStartupInput(
+ env_paths_profile="interactive_user",
+ env_repo_local_base_root="",
+ user_home="/home/ignored",
+ argv=_startup_argv2("--paths-profile", "--repo-local-root"),
+ )
+ )
+
+
def main() raises:
TestSuite.discover_tests[__functions_in_module()]().run()