diff --git a/crates/pod/src/entrypoint.rs b/crates/pod/src/entrypoint.rs index 054a1acf..b7750370 100644 --- a/crates/pod/src/entrypoint.rs +++ b/crates/pod/src/entrypoint.rs @@ -39,10 +39,6 @@ struct Cli { #[arg(long, value_name = "PATH")] project: Option, - /// Internal typed pod-name override for session restore launched by the TUI. - #[arg(long, value_name = "NAME", requires = "session", hide = true)] - session_pod_name: Option, - /// Internal resolved manifest config for delegated child Pod spawning. #[arg( long, @@ -85,7 +81,7 @@ struct Cli { /// concurrent writers are prevented by the pod-registry. /// Mutually exclusive with `--adopt` (spawned children always start /// fresh). - #[arg(long, value_name = "UUID", conflicts_with_all = ["adopt", "pod"])] + #[arg(long, value_name = "UUID", conflicts_with_all = ["adopt"])] session: Option, } @@ -101,9 +97,8 @@ fn runtime_workspace_root(cli: &Cli) -> Result { } fn runtime_pod_name(cli: &Cli, workspace_root: &Path) -> String { - cli.session_pod_name + cli.pod .as_deref() - .or(cli.pod.as_deref()) .map(str::to_string) .unwrap_or_else(|| default_pod_name_for_workspace(workspace_root)) } @@ -171,7 +166,7 @@ where } fn apply_session_restore_overrides(manifest: &mut PodManifest, cli: &Cli) -> Result<(), String> { - if let Some(pod_name) = cli.session_pod_name.as_deref().or(cli.pod.as_deref()) { + if let Some(pod_name) = cli.pod.as_deref() { manifest.pod.name = pod_name.to_string(); } Ok(()) @@ -733,12 +728,28 @@ permission = "write" } #[test] - fn pod_flag_conflicts_with_session() { - let segment_id = session_store::new_segment_id(); - let segment_id = segment_id.to_string(); - let err = Cli::try_parse_from(["yoi pod", "--pod", "agent", "--session", &segment_id]) - .unwrap_err(); - assert_eq!(err.kind(), clap::error::ErrorKind::ArgumentConflict); + fn pod_flag_is_runtime_identity_for_session_restore() { + let tmp = TempDir::new().unwrap(); + let workspace = tmp.path().join("explicit-workspace"); + let store = tmp.path().join("sessions"); + std::fs::create_dir(&workspace).unwrap(); + let segment_id = session_store::new_segment_id().to_string(); + let cli = Cli::try_parse_from([ + "yoi pod", + "--workspace", + workspace.to_str().unwrap(), + "--session", + &segment_id, + "--pod", + "explicit-name", + "--store", + store.to_str().unwrap(), + ]) + .unwrap(); + + assert_eq!(cli.session.unwrap().to_string(), segment_id); + assert_eq!(cli.pod.as_deref(), Some("explicit-name")); + assert_eq!(runtime_pod_name(&cli, &workspace), "explicit-name"); } #[test] @@ -835,6 +846,20 @@ permission = "write" assert_eq!(cli.pod.as_deref(), Some("agent")); } + #[test] + fn old_session_pod_name_identity_alias_is_rejected() { + let segment_id = session_store::new_segment_id().to_string(); + let err = Cli::try_parse_from([ + "yoi pod", + "--session", + &segment_id, + "--session-pod-name", + "agent", + ]) + .unwrap_err(); + assert_eq!(err.kind(), clap::error::ErrorKind::UnknownArgument); + } + #[test] fn removed_profile_pod_name_alias_is_rejected() { let err = Cli::try_parse_from(["yoi pod", "--profile-pod-name", "agent"]).unwrap_err(); diff --git a/crates/tui/src/lib.rs b/crates/tui/src/lib.rs index b9bede35..8dfd8c53 100644 --- a/crates/tui/src/lib.rs +++ b/crates/tui/src/lib.rs @@ -54,7 +54,10 @@ pub enum LaunchMode { Resume, /// `yoi --session `: skip the picker, go straight to the /// resume name dialog with `id` baked in. - ResumeWithSession(SegmentId), + ResumeWithSession { + id: SegmentId, + pod_name: Option, + }, /// `yoi panel`: open the workspace panel from the current workspace. Panel, } @@ -93,8 +96,8 @@ pub async fn launch(options: LaunchOptions) -> ExitCode { socket_override, } => single_pod::run_pod_name(pod_name, socket_override, runtime_command).await, LaunchMode::Resume => single_pod::run_resume(runtime_command).await, - LaunchMode::ResumeWithSession(id) => { - single_pod::run_spawn(Some(id), None, None, runtime_command).await + LaunchMode::ResumeWithSession { id, pod_name } => { + single_pod::run_spawn(Some(id), pod_name, None, runtime_command).await } LaunchMode::Panel => single_pod::run_panel(runtime_command).await, }; diff --git a/crates/yoi/src/main.rs b/crates/yoi/src/main.rs index edbbb7cf..d0805cfb 100644 --- a/crates/yoi/src/main.rs +++ b/crates/yoi/src/main.rs @@ -297,11 +297,6 @@ fn parse_args_slice(args: &[String]) -> Result { "--profile can only be used for fresh spawn".to_string(), )); } - if pod_name.is_some() && session.is_some() { - return Err(ParseError( - "--pod and --session are mutually exclusive".to_string(), - )); - } if pod_name.is_some() && resume { return Err(ParseError( "--pod and --resume are mutually exclusive".to_string(), @@ -324,6 +319,12 @@ fn parse_args_slice(args: &[String]) -> Result { } let pod_name = pod_name.or(positional); + if socket_override.is_some() && session.is_some() { + return Err(ParseError( + "--socket can only be used with --pod attach mode".to_string(), + )); + } + if let Some(profile) = profile { return Ok(Mode::Tui { mode: LaunchMode::Spawn { @@ -333,6 +334,12 @@ fn parse_args_slice(args: &[String]) -> Result { workspace_root, }); } + if let Some(id) = session { + return Ok(Mode::Tui { + mode: LaunchMode::ResumeWithSession { id, pod_name }, + workspace_root, + }); + } if let Some(pod_name) = pod_name { return Ok(Mode::Tui { mode: LaunchMode::PodName { @@ -348,13 +355,6 @@ fn parse_args_slice(args: &[String]) -> Result { workspace_root, }); } - if let Some(id) = session { - return Ok(Mode::Tui { - mode: LaunchMode::ResumeWithSession(id), - workspace_root, - }); - } - Ok(Mode::Tui { mode: LaunchMode::Spawn { pod_name: None, @@ -563,13 +563,29 @@ mod tests { } #[test] - fn parse_rejects_pod_and_session() { - let segment_id = session_store::new_segment_id().to_string(); - let err = parse_args_from(["--pod", "agent", "--session", &segment_id]).unwrap_err(); - assert_eq!( - err.to_string(), - "--pod and --session are mutually exclusive" - ); + fn parse_session_accepts_explicit_runtime_pod_identity() { + let segment_id = session_store::new_segment_id(); + match parse_args_from([ + "--session", + &segment_id.to_string(), + "--pod", + "explicit-name", + ]) + .unwrap() + { + Mode::Tui { + mode: + LaunchMode::ResumeWithSession { + id, + pod_name: Some(pod_name), + }, + .. + } => { + assert_eq!(id, segment_id); + assert_eq!(pod_name, "explicit-name"); + } + _ => panic!("expected ResumeWithSession mode with explicit pod name"), + } } #[test]