mirror of
https://github.com/robcholz/vibebox.git
synced 2026-05-21 06:56:48 +02:00
refactor: organize all the params.
This commit is contained in:
+5
-1
@@ -43,7 +43,11 @@
|
||||
6. [x] VM should be separated by a per-session VM daemon process (only accepts if to shut down vm and itself).
|
||||
7. [x] setup vibebox commands
|
||||
8. [ ] setup cli commands.
|
||||
9. [ ] fix ui overlap.
|
||||
1. [x] Organize all the params.
|
||||
2. [ ] Remove old cli.
|
||||
3. [ ] add an actual config file.
|
||||
4. [ ] set up the cli.
|
||||
9. [ ] fix ui overlap, and consistency issue.
|
||||
10. [ ] intensive integration test.
|
||||
|
||||
## Publish
|
||||
|
||||
+5
-5
@@ -20,14 +20,14 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
commands,
|
||||
session_manager::{INSTANCE_DIR_NAME, INSTANCE_TOML_FILENAME},
|
||||
session_manager::{INSTANCE_DIR_NAME, INSTANCE_FILENAME},
|
||||
tui::AppState,
|
||||
vm::{self, LoginAction, VmInput},
|
||||
};
|
||||
|
||||
const SSH_KEY_NAME: &str = "ssh_key";
|
||||
#[allow(dead_code)]
|
||||
const SERIAL_LOG_NAME: &str = "serial.log";
|
||||
pub(crate) const SERIAL_LOG_NAME: &str = "serial.log";
|
||||
const DEFAULT_SSH_USER: &str = "vibecoder";
|
||||
const SSH_CONNECT_RETRIES: usize = 30;
|
||||
const SSH_CONNECT_DELAY_MS: u64 = 500;
|
||||
@@ -126,7 +126,7 @@ pub(crate) fn ensure_ssh_keypair(
|
||||
pub(crate) fn load_or_create_instance_config(
|
||||
instance_dir: &Path,
|
||||
) -> Result<InstanceConfig, Box<dyn std::error::Error>> {
|
||||
let config_path = instance_dir.join(INSTANCE_TOML_FILENAME);
|
||||
let config_path = instance_dir.join(INSTANCE_FILENAME);
|
||||
let mut config = if config_path.exists() {
|
||||
let raw = fs::read_to_string(&config_path)?;
|
||||
toml::from_str::<InstanceConfig>(&raw)?
|
||||
@@ -167,7 +167,7 @@ pub fn touch_last_active(instance_dir: &Path) -> Result<(), Box<dyn std::error::
|
||||
let mut config = load_or_create_instance_config(instance_dir)?;
|
||||
let now = OffsetDateTime::now_utc().format(&Rfc3339)?;
|
||||
config.last_active = Some(now);
|
||||
write_instance_config(&instance_dir.join(INSTANCE_TOML_FILENAME), &config)?;
|
||||
write_instance_config(&instance_dir.join(INSTANCE_FILENAME), &config)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ fn spawn_ssh_io(
|
||||
let ssh_ready = Arc::new(AtomicBool::new(false));
|
||||
let input_tx_holder: Arc<Mutex<Option<Sender<VmInput>>>> = Arc::new(Mutex::new(None));
|
||||
|
||||
let instance_path = instance_dir.join(INSTANCE_TOML_FILENAME);
|
||||
let instance_path = instance_dir.join(INSTANCE_FILENAME);
|
||||
let config_for_output = config.clone();
|
||||
let log_for_output = log_file.clone();
|
||||
let ssh_connected_for_output = ssh_connected.clone();
|
||||
|
||||
+20
-16
@@ -11,8 +11,7 @@ use crate::config::CONFIG_FILENAME;
|
||||
pub const INSTANCE_DIR_NAME: &str = ".vibebox";
|
||||
pub const GLOBAL_CACHE_DIR_NAME: &str = "vibebox";
|
||||
pub const GLOBAL_DIR_NAME: &str = ".vibebox";
|
||||
pub const INSTANCE_TOML_FILENAME: &str = "instance.toml";
|
||||
pub const SESSION_TEMP_PREFIX: &str = "sessions";
|
||||
pub const INSTANCE_FILENAME: &str = "instance.toml";
|
||||
pub const SESSION_TOML_SUFFIX: &str = ".toml";
|
||||
const SESSIONS_DIR_NAME: &str = "sessions";
|
||||
|
||||
@@ -100,7 +99,8 @@ impl SessionManager {
|
||||
} else {
|
||||
tracing::warn!(
|
||||
directory = %directory.display(),
|
||||
"missing session id in instance.toml"
|
||||
file = INSTANCE_FILENAME,
|
||||
"missing session id in instance file"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@ impl SessionManager {
|
||||
}
|
||||
|
||||
fn session_path_for(&self, id: &str) -> PathBuf {
|
||||
let filename = format!("{id}.toml");
|
||||
let filename = format!("{id}{SESSION_TOML_SUFFIX}");
|
||||
self.sessions_dir.join(filename)
|
||||
}
|
||||
|
||||
@@ -225,9 +225,7 @@ fn read_session_file(path: &Path) -> Result<SessionEntry, SessionError> {
|
||||
}
|
||||
|
||||
fn read_instance_metadata(directory: &Path) -> Result<InstanceMetadata, SessionError> {
|
||||
let instance_path = directory
|
||||
.join(INSTANCE_DIR_NAME)
|
||||
.join(INSTANCE_TOML_FILENAME);
|
||||
let instance_path = directory.join(INSTANCE_DIR_NAME).join(INSTANCE_FILENAME);
|
||||
if !instance_path.exists() {
|
||||
return Ok(InstanceMetadata::default());
|
||||
}
|
||||
@@ -256,7 +254,7 @@ fn atomic_write(path: &Path, content: &[u8]) -> io::Result<()> {
|
||||
|
||||
fs::create_dir_all(parent)?;
|
||||
let mut temp = tempfile::Builder::new()
|
||||
.prefix(SESSION_TEMP_PREFIX)
|
||||
.prefix(SESSIONS_DIR_NAME)
|
||||
.suffix(SESSION_TOML_SUFFIX)
|
||||
.tempfile_in(parent)?;
|
||||
temp.write_all(content)?;
|
||||
@@ -285,7 +283,7 @@ mod tests {
|
||||
let instance_dir = project_dir.join(INSTANCE_DIR_NAME);
|
||||
fs::create_dir_all(&instance_dir).unwrap();
|
||||
let content = format!("id = \"{id}\"\nlast_active = \"{last_active}\"\n");
|
||||
fs::write(instance_dir.join(INSTANCE_TOML_FILENAME), content).unwrap();
|
||||
fs::write(instance_dir.join(INSTANCE_FILENAME), content).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -306,9 +304,10 @@ mod tests {
|
||||
assert_eq!(dirs[0], project_dir.canonicalize().unwrap());
|
||||
assert!(mgr.index_path().exists());
|
||||
|
||||
let session_path = mgr
|
||||
.index_path()
|
||||
.join("019bf290-cccc-7c23-ba1d-dce7e6d40693.toml");
|
||||
let session_path = mgr.index_path().join(format!(
|
||||
"019bf290-cccc-7c23-ba1d-dce7e6d40693{}",
|
||||
SESSION_TOML_SUFFIX
|
||||
));
|
||||
assert!(session_path.exists());
|
||||
}
|
||||
|
||||
@@ -329,9 +328,10 @@ mod tests {
|
||||
let sessions = mgr.list_sessions().unwrap();
|
||||
assert!(sessions.is_empty());
|
||||
|
||||
let session_path = mgr
|
||||
.index_path()
|
||||
.join("019bf290-cccc-7c23-ba1d-dce7e6d40693.toml");
|
||||
let session_path = mgr.index_path().join(format!(
|
||||
"019bf290-cccc-7c23-ba1d-dce7e6d40693{}",
|
||||
SESSION_TOML_SUFFIX
|
||||
));
|
||||
assert!(!session_path.exists());
|
||||
}
|
||||
|
||||
@@ -340,7 +340,11 @@ mod tests {
|
||||
let temp = TempDir::new().unwrap();
|
||||
let mgr = manager(&temp);
|
||||
fs::create_dir_all(mgr.index_path()).unwrap();
|
||||
fs::write(mgr.index_path().join("bad.toml"), "not toml").unwrap();
|
||||
fs::write(
|
||||
mgr.index_path().join(format!("bad{SESSION_TOML_SUFFIX}")),
|
||||
"not toml",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let err = mgr.list_sessions().unwrap_err();
|
||||
assert!(matches!(err, SessionError::TomlDe(_)));
|
||||
|
||||
@@ -43,6 +43,10 @@ const START_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
const DEFAULT_EXPECT_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
const LOGIN_EXPECT_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
const PROVISION_SCRIPT: &str = include_str!("provision.sh");
|
||||
const PROVISION_SCRIPT_NAME: &str = "provision.sh";
|
||||
const DEFAULT_RAW_NAME: &str = "default.raw";
|
||||
const INSTANCE_RAW_NAME: &str = "instance.raw";
|
||||
const BASE_DISK_RAW_NAME: &str = "disk.raw";
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum LoginAction {
|
||||
@@ -158,8 +162,8 @@ where
|
||||
basename_compressed.trim_end_matches(".tar.xz")
|
||||
));
|
||||
|
||||
let default_raw = cache_dir.join("default.raw");
|
||||
let instance_raw = instance_dir.join("instance.raw");
|
||||
let default_raw = cache_dir.join(DEFAULT_RAW_NAME);
|
||||
let instance_raw = instance_dir.join(INSTANCE_RAW_NAME);
|
||||
|
||||
// Prepare system-wide directories
|
||||
fs::create_dir_all(&cache_dir)?;
|
||||
@@ -212,11 +216,6 @@ where
|
||||
for share in [
|
||||
DirectoryShare::new(home.join(".codex"), "/usr/local/codex".into(), false),
|
||||
DirectoryShare::new(home.join(".claude"), "/usr/local/claude".into(), false),
|
||||
DirectoryShare::new(
|
||||
"/Users/zhangjie/Documents/Code/CompletePrograms/vibebox/.ssh".into(),
|
||||
"/usr/local/ssh".into(),
|
||||
true,
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
@@ -629,7 +628,11 @@ fn ensure_base_image(
|
||||
|
||||
println!("Decompressing base image...");
|
||||
let status = Command::new("tar")
|
||||
.args(["-xOf", &base_compressed.to_string_lossy(), "disk.raw"])
|
||||
.args([
|
||||
"-xOf",
|
||||
&base_compressed.to_string_lossy(),
|
||||
BASE_DISK_RAW_NAME,
|
||||
])
|
||||
.stdout(std::fs::File::create(base_raw)?)
|
||||
.status()?;
|
||||
|
||||
@@ -655,7 +658,7 @@ fn ensure_default_image(
|
||||
println!("Configuring base image...");
|
||||
fs::copy(base_raw, default_raw)?;
|
||||
|
||||
let provision_command = script_command_from_content("provision.sh", PROVISION_SCRIPT)?;
|
||||
let provision_command = script_command_from_content(PROVISION_SCRIPT_NAME, PROVISION_SCRIPT)?;
|
||||
run_vm(
|
||||
default_raw,
|
||||
&[Send(provision_command)],
|
||||
|
||||
+7
-5
@@ -15,16 +15,18 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
instance::SERIAL_LOG_NAME,
|
||||
instance::{
|
||||
InstanceConfig, build_ssh_login_actions, ensure_instance_dir, ensure_ssh_keypair,
|
||||
extract_ipv4, load_or_create_instance_config, write_instance_config,
|
||||
},
|
||||
session_manager::GLOBAL_DIR_NAME,
|
||||
session_manager::{GLOBAL_DIR_NAME, INSTANCE_FILENAME},
|
||||
vm::{self, DirectoryShare, LoginAction, VmInput},
|
||||
};
|
||||
|
||||
const VM_MANAGER_SOCKET_NAME: &str = "vm.sock";
|
||||
const VM_MANAGER_LOCK_NAME: &str = "vm.lock";
|
||||
const VM_MANAGER_LOG_NAME: &str = "vm_manager.log";
|
||||
|
||||
pub fn ensure_manager(
|
||||
raw_args: &[std::ffi::OsString],
|
||||
@@ -132,7 +134,7 @@ fn spawn_manager_process(
|
||||
cmd.env("VIBEBOX_LOG_NO_COLOR", "1");
|
||||
cmd.env("VIBEBOX_AUTO_SHUTDOWN_MS", auto_shutdown_ms.to_string());
|
||||
tracing::info!(auto_shutdown_ms, "vm manager process spawn requested");
|
||||
let log_path = instance_dir.join("vm_manager.log");
|
||||
let log_path = instance_dir.join(VM_MANAGER_LOG_NAME);
|
||||
let log_file = fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
@@ -280,7 +282,7 @@ fn spawn_manager_io(
|
||||
vm_output_fd: std::os::unix::io::OwnedFd,
|
||||
vm_input_fd: std::os::unix::io::OwnedFd,
|
||||
) -> vm::IoContext {
|
||||
let log_path = instance_dir.join("serial.log");
|
||||
let log_path = instance_dir.join(SERIAL_LOG_NAME);
|
||||
let log_file = fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
@@ -289,7 +291,7 @@ fn spawn_manager_io(
|
||||
.ok()
|
||||
.map(|file| Arc::new(Mutex::new(file)));
|
||||
|
||||
let instance_path = instance_dir.join("instance.toml");
|
||||
let instance_path = instance_dir.join(INSTANCE_FILENAME);
|
||||
let config_for_output = config.clone();
|
||||
let log_for_output = log_file.clone();
|
||||
let mut line_buf = String::new();
|
||||
@@ -465,7 +467,7 @@ fn run_manager_with(
|
||||
let mut config = load_or_create_instance_config(&instance_dir)?;
|
||||
if config.vm_ipv4.is_some() {
|
||||
config.vm_ipv4 = None;
|
||||
write_instance_config(&instance_dir.join("instance.toml"), &config)?;
|
||||
write_instance_config(&instance_dir.join(INSTANCE_FILENAME), &config)?;
|
||||
}
|
||||
let config = Arc::new(Mutex::new(config));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user