Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions crates/openshell-cli/src/completers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::time::Duration;

use clap_complete::engine::CompletionCandidate;
use openshell_bootstrap::{list_gateways, load_active_gateway, load_gateway_metadata};
use openshell_core::ObjectName;
use openshell_core::proto::open_shell_client::OpenShellClient;
use openshell_core::proto::{ListProvidersRequest, ListSandboxesRequest};
use tonic::transport::{Channel, Endpoint};
Expand All @@ -33,6 +34,7 @@ pub fn complete_sandbox_names(_prefix: &OsStr) -> Vec<CompletionCandidate> {
.list_sandboxes(ListSandboxesRequest {
limit: 200,
offset: 0,
label_selector: String::new(),
})
.await
.ok()?;
Expand All @@ -41,7 +43,7 @@ pub fn complete_sandbox_names(_prefix: &OsStr) -> Vec<CompletionCandidate> {
.into_inner()
.sandboxes
.into_iter()
.map(|s| CompletionCandidate::new(s.name))
.map(|s| CompletionCandidate::new(s.object_name()))
.collect(),
)
})
Expand All @@ -64,7 +66,7 @@ pub fn complete_provider_names(_prefix: &OsStr) -> Vec<CompletionCandidate> {
.into_inner()
.providers
.into_iter()
.map(|p| CompletionCandidate::new(p.name))
.map(|p| CompletionCandidate::new(p.object_name()))
.collect(),
)
})
Expand Down
35 changes: 34 additions & 1 deletion crates/openshell-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,10 @@ enum SandboxCommands {
#[arg(long, overrides_with = "auto_providers")]
no_auto_providers: bool,

/// Attach labels to the sandbox (key=value format, repeatable).
#[arg(long = "label")]
labels: Vec<String>,

/// Command to run after "--" (defaults to an interactive shell).
#[arg(trailing_var_arg = true)]
command: Vec<String>,
Expand Down Expand Up @@ -1232,6 +1236,10 @@ enum SandboxCommands {
/// Print only sandbox names (one per line).
#[arg(long, conflicts_with = "ids")]
names: bool,

/// Filter sandboxes by label selector (key1=value1,key2=value2).
#[arg(long)]
selector: Option<String>,
},

/// Delete a sandbox by name.
Expand Down Expand Up @@ -2293,6 +2301,7 @@ async fn main() -> Result<()> {
no_bootstrap,
auto_providers,
no_auto_providers,
labels,
command,
} => {
// Resolve --tty / --no-tty into an Option<bool> override.
Expand Down Expand Up @@ -2323,6 +2332,19 @@ async fn main() -> Result<()> {
None // prompt or auto-detect
};

// Parse --label flags into a HashMap<String, String>.
let mut labels_map = std::collections::HashMap::new();
for label_str in &labels {
let parts: Vec<&str> = label_str.splitn(2, '=').collect();
if parts.len() != 2 {
return Err(miette::miette!(
"invalid label format '{}', expected key=value",
label_str
));
}
labels_map.insert(parts[0].to_string(), parts[1].to_string());
}

// Parse --upload spec into (local_path, sandbox_path, git_ignore).
let upload_spec = upload.as_deref().map(|s| {
let (local, remote) = parse_upload_spec(s);
Expand Down Expand Up @@ -2373,6 +2395,7 @@ async fn main() -> Result<()> {
tty_override,
Some(false),
auto_providers_override,
&labels_map,
&tls,
))
.await?;
Expand Down Expand Up @@ -2474,8 +2497,18 @@ async fn main() -> Result<()> {
offset,
ids,
names,
selector,
} => {
run::sandbox_list(endpoint, limit, offset, ids, names, &tls).await?;
run::sandbox_list(
endpoint,
limit,
offset,
ids,
names,
selector.as_deref(),
&tls,
)
.await?;
}
SandboxCommands::Delete { names, all } => {
run::sandbox_delete(endpoint, &names, all, &tls, &ctx.name).await?;
Expand Down
Loading
Loading