Skip to content
12 changes: 5 additions & 7 deletions app/src/ai/agent_sdk/ambient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,8 @@ impl AmbientAgentRunner {
vec![]
};

let team_scope = match super::common::resolve_environment_team_scope(&args.scope, ctx) {
let team_scope =
match super::common::resolve_environment_team_scope(&args.scope, ctx) {
Ok(team_scope) => team_scope,
Err(err) => {
super::report_fatal_error(err, ctx);
Expand All @@ -404,15 +405,12 @@ impl AmbientAgentRunner {
environment_args.environment = Some(environment_id);
}

let environment_id = match EnvironmentChoice::resolve_for_create(
environment_args,
&team_scope,
ctx,
) {
let environment_id =
match EnvironmentChoice::resolve_for_create(environment_args, &team_scope, ctx) {
Ok(EnvironmentChoice::None) => {
eprintln!("Agent will run without an environment.");
None
},
}
Ok(EnvironmentChoice::Environment { id, .. }) => Some(id),
Err(ResolveConfigurationError::Canceled) => {
ctx.terminate_app(TerminationMode::ForceTerminate, None);
Expand Down
46 changes: 33 additions & 13 deletions app/src/ai/agent_sdk/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ use crate::ai::cloud_environments::CloudAmbientAgentEnvironment;
use crate::ai::llms::{LLMId, LLMPreferences, is_model_allowed_for_scope};
use crate::auth::UserUid;
use crate::auth::auth_state::AuthStateProvider;
use crate::cloud_object::model::persistence::CloudModel;
use crate::cloud_object::{CloudObject, CloudObjectLookup as _, Owner};
use crate::server::cloud_objects::update_manager::UpdateManager;
use crate::server::cloud_objects::update_manager::{InitialLoadResponse, UpdateManager};
use crate::server::ids::{ServerId, SyncId};
use crate::server::server_api::ServerApiProvider;
use crate::server::server_api::ai::AIClient;
use crate::server::team_scope::RequestTeamScope;
use crate::workspaces::update_manager::TeamUpdateManager;
use crate::workspaces::user_workspaces::team_workspace_settings::{
NotATeamMemberError, TeamScopeForCli, TeamScopeForCliError,
Expand Down Expand Up @@ -161,9 +163,11 @@ pub(super) fn resolve_environment_team_scope(
scope: &ObjectScope,
ctx: &AppContext,
) -> anyhow::Result<TeamScopeForCli> {
UserWorkspaces::as_ref(ctx)
.team_scope_for_cli_object(scope)
.map_err(|err| describe_team_resolution_error(err, ctx))
if scope.personal {
Ok(TeamScopeForCli::Personal)
} else {
resolve_team_scope(&scope.team_selection, ctx)
}
}

pub(super) fn validate_agent_mode_base_model_id_for_scope(
Expand Down Expand Up @@ -222,6 +226,15 @@ pub fn resolve_owner(scope: &ObjectScope, ctx: &AppContext) -> anyhow::Result<Ow
}
}

pub(super) fn environment_is_visible_to_scope(
environment: &CloudAmbientAgentEnvironment,
team_scope: &(impl TeamScope + ?Sized),
) -> bool {
match environment.permissions().owner {
Owner::User { .. } => true,
Owner::Team { team_uid } => team_scope.team_uid() == Some(team_uid),
}
}
pub(super) fn resolve_owner_for_team_scope(
team_scope: &impl TeamScope,
ctx: &AppContext,
Expand All @@ -234,15 +247,6 @@ pub(super) fn resolve_owner_for_team_scope(
}
}

pub(super) fn environment_is_visible_to_scope(
environment: &CloudAmbientAgentEnvironment,
team_scope: &(impl TeamScope + ?Sized),
) -> bool {
match environment.permissions().owner {
Owner::User { .. } => true,
Owner::Team { team_uid } => team_scope.team_uid() == Some(team_uid),
}
}
/// Refresh workspace metadata before executing an operation.
///
/// This ensures that team state is up-to-date before creating cloud objects or performing
Expand Down Expand Up @@ -277,6 +281,22 @@ pub fn refresh_warp_drive(
.map_err(|_| anyhow::anyhow!("Timed out waiting for Warp Drive to sync"))
}

pub fn refresh_warp_drive_for_scope(
team_scope: RequestTeamScope,
ctx: &AppContext,
) -> impl Future<Output = anyhow::Result<InitialLoadResponse>> + Send + 'static + use<> {
let server_api = ServerApiProvider::as_ref(ctx).get();
let objects_to_update = CloudModel::as_ref(ctx).get_versions_for_request_scope(team_scope, ctx);
async move {
server_api
.fetch_changed_objects_for_scope(objects_to_update, false, team_scope)
.await
}
.with_timeout(WARP_DRIVE_SYNC_TIMEOUT)
.map_err(|_| anyhow::anyhow!("Timed out refreshing Warp Drive"))
.and_then(|result| async move { result })
}

/// Fetch the conversation's server metadata and validate that its harness matches the caller's
/// `--harness` choice. Returns the metadata on success so the caller can reuse it (e.g. for the
/// server conversation token).
Expand Down
1 change: 1 addition & 0 deletions app/src/ai/agent_sdk/common_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use crate::workspaces::user_workspaces::{
TeamContextForOperation, TeamScope, TeamlessScopeForTest, UserWorkspaces,
};
use crate::workspaces::workspace::{Workspace, WorkspaceUid};

fn environment_with_owner(
sync_id: SyncId,
name: &str,
Expand Down
2 changes: 1 addition & 1 deletion app/src/ai/agent_sdk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1933,7 +1933,7 @@ fn command_to_telemetry_event(command: &CliCommand) -> CliTelemetryEvent {
},
CliCommand::Schedule(c) => match c.subcommand() {
None | Some(ScheduleSubcommand::Create(_)) => CliTelemetryEvent::ScheduleCreate,
Some(ScheduleSubcommand::List) => CliTelemetryEvent::ScheduleList,
Some(ScheduleSubcommand::List { .. }) => CliTelemetryEvent::ScheduleList,
Some(ScheduleSubcommand::Get(_)) => CliTelemetryEvent::ScheduleGet,
Some(ScheduleSubcommand::Pause(_)) => CliTelemetryEvent::SchedulePause,
Some(ScheduleSubcommand::Unpause(_)) => CliTelemetryEvent::ScheduleUnpause,
Expand Down
Loading