use objectiveai_sdk::cli::command::agents::selector::AgentSelector;
use objectiveai_sdk::cli::command::agents::wait::{Request, Response};
use crate::context::Context;
use crate::error::Error;
pub async fn execute(ctx: &Context, request: Request) -> Result<Response, Error> {
wait(ctx, request.agent).await
}
async fn wait(ctx: &Context, agent: AgentSelector) -> Result<Response, Error> {
let state_dir = ctx.filesystem.state_dir();
let hierarchy = match agent {
AgentSelector::Instance {
parent_agent_instance_hierarchy,
agent_instance,
} => {
let parent = parent_agent_instance_hierarchy
.as_deref()
.unwrap_or(&ctx.config.agent_instance_hierarchy);
format!("{parent}/{agent_instance}")
}
AgentSelector::Tag { agent_tag } => {
match crate::db::tags::lookup(ctx.db_client().await?, &agent_tag).await? {
crate::db::tags::LookupState::Bound {
agent_instance_hierarchy,
} => agent_instance_hierarchy,
crate::db::tags::LookupState::Grouped { .. } => {
match wait_for_tag_upgrade(ctx, &state_dir, agent_tag).await? {
Some(agent_instance_hierarchy) => agent_instance_hierarchy,
None => return Ok(Response::Ok),
}
}
crate::db::tags::LookupState::Absent => {
return Err(Error::TagNotFound(agent_tag));
}
}
}
AgentSelector::Ref { .. } => return Err(Error::WaitRefTarget),
};
let (dir, key) = super::locks::agent_instance_lock(&state_dir, &hierarchy);
objectiveai_sdk::lockfile::wait_released(&dir, &key)
.await
.map_err(|source| Error::Lockfile { key, source })?;
Ok(Response::Ok)
}
async fn wait_for_tag_upgrade(
ctx: &Context,
state_dir: &std::path::Path,
agent_tag: String,
) -> Result<Option<String>, Error> {
let (dir, key) = super::locks::agent_tag_lock(state_dir, &agent_tag);
if objectiveai_sdk::lockfile::try_held(&dir, &key).await {
objectiveai_sdk::lockfile::wait_released(&dir, &key)
.await
.map_err(|source| Error::Lockfile { key, source })?;
match crate::db::tags::lookup(ctx.db_client().await?, &agent_tag).await? {
crate::db::tags::LookupState::Bound {
agent_instance_hierarchy,
} => Ok(Some(agent_instance_hierarchy)),
crate::db::tags::LookupState::Grouped { .. } => {
Err(Error::TagLockDroppedWithoutUpgrade { tag: agent_tag })
}
crate::db::tags::LookupState::Absent => Err(Error::TagNotFound(agent_tag)),
}
} else {
match crate::db::tags::lookup(ctx.db_client().await?, &agent_tag).await? {
crate::db::tags::LookupState::Bound {
agent_instance_hierarchy,
} => Ok(Some(agent_instance_hierarchy)),
crate::db::tags::LookupState::Grouped { .. } => Ok(None),
crate::db::tags::LookupState::Absent => Err(Error::TagNotFound(agent_tag)),
}
}
}
pub mod request_schema {
use objectiveai_sdk::cli::command::agents::wait as sdk;
use objectiveai_sdk::cli::command::agents::wait::request_schema::{Request, Response};
use crate::context::Context;
use crate::error::Error;
pub async fn execute(_ctx: &Context, _request: Request) -> Result<Response, Error> {
Ok(objectiveai_sdk::cli::command::ResponseSchema(schemars::schema_for!(sdk::Request)))
}
}
pub mod response_schema {
use objectiveai_sdk::cli::command::agents::wait as sdk;
use objectiveai_sdk::cli::command::agents::wait::response_schema::{Request, Response};
use crate::context::Context;
use crate::error::Error;
pub async fn execute(_ctx: &Context, _request: Request) -> Result<Response, Error> {
Ok(objectiveai_sdk::cli::command::ResponseSchema(schemars::schema_for!(sdk::Response)))
}
}