feat: add standalone resume picker

This commit is contained in:
2026-08-30 13:46:24 +09:00
parent c5fd9c01e5
commit 133feb8c76
8 changed files with 373 additions and 11 deletions
+4 -3
View File
@@ -37,9 +37,10 @@ pub use backend_workspace::{
};
pub use runtime_command::WorkerRuntimeCommand;
pub use target::{
BackendTarget, Dashboard, LocalTarget, ResolvedTarget, StandaloneTarget, Target, TargetError,
TargetKind, WorkerByName, WorkerConnection, WorkerConnectionSelector, WorkerList,
WorkerListRequest, WorkerResume, WorkerSpawn,
BackendTarget, Dashboard, LocalTarget, ResolvedTarget, StandaloneSessionListIntent,
StandaloneSessionResumeIntent, StandaloneTarget, Target, TargetError, TargetKind, WorkerByName,
WorkerConnection, WorkerConnectionSelector, WorkerList, WorkerListRequest, WorkerResume,
WorkerSpawn,
};
pub use spawn::{
+79
View File
@@ -132,6 +132,19 @@ pub struct WorkerResume {
pub runtime_command: WorkerRuntimeCommand,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StandaloneSessionListIntent {
pub state_dir: PathBuf,
pub cwd: PathBuf,
pub include_all: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StandaloneSessionResumeIntent {
pub state_dir: PathBuf,
pub session_id: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Dashboard {
Local {
@@ -204,6 +217,26 @@ pub trait Target: fmt::Debug + Send + Sync {
fn resume_worker(&self) -> Result<WorkerResume, TargetError>;
fn standalone_session_list(
&self,
_include_all: bool,
) -> Result<StandaloneSessionListIntent, TargetError> {
Err(TargetError::unsupported(
"standalone session listing",
self.kind(),
))
}
fn standalone_session_resume(
&self,
_session_id: String,
) -> Result<StandaloneSessionResumeIntent, TargetError> {
Err(TargetError::unsupported(
"standalone session restore",
self.kind(),
))
}
fn dashboard(&self) -> Result<Dashboard, TargetError>;
fn list_workers(&self, request: WorkerListRequest) -> Result<WorkerList, TargetError>;
@@ -312,6 +345,29 @@ impl Target for StandaloneTarget {
Err(TargetError::unsupported("Worker restore", self.kind()))
}
fn standalone_session_list(
&self,
include_all: bool,
) -> Result<StandaloneSessionListIntent, TargetError> {
let cwd = std::env::current_dir()
.map_err(|error| TargetError::invalid(self.kind(), error.to_string()))?;
Ok(StandaloneSessionListIntent {
state_dir: self.state_dir.clone(),
cwd,
include_all,
})
}
fn standalone_session_resume(
&self,
session_id: String,
) -> Result<StandaloneSessionResumeIntent, TargetError> {
Ok(StandaloneSessionResumeIntent {
state_dir: self.state_dir.clone(),
session_id,
})
}
fn dashboard(&self) -> Result<Dashboard, TargetError> {
Err(TargetError::unsupported("Worker dashboard", self.kind()))
}
@@ -575,6 +631,29 @@ mod tests {
);
}
#[test]
fn standalone_target_builds_explicit_session_intents() {
let target = StandaloneTarget::new("/tmp/yoi-client-sessions");
let list = target.standalone_session_list(true).unwrap();
assert_eq!(list.state_dir, PathBuf::from("/tmp/yoi-client-sessions"));
assert!(list.include_all);
assert!(list.cwd.is_absolute());
let resume = target
.standalone_session_resume("019d1234-0000-7000-8000-000000000000".to_string())
.unwrap();
assert_eq!(resume.state_dir, list.state_dir);
assert_eq!(resume.session_id, "019d1234-0000-7000-8000-000000000000");
assert!(
LocalTarget::new()
.standalone_session_list(false)
.unwrap_err()
.to_string()
.contains("not supported")
);
}
#[test]
fn local_target_builds_local_worker_list() {
let target = LocalTarget::new();