blob: a7c75d8502dd93b21cd02886fb785d659c7805b7 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
use super::{Error, SessionBoundary, name};
use maka_agent_facts::execution::BehaviorId;
use maka_agent_facts::execution::CollaborationMode;
use maka_agent_facts::execution::ModelBinding;
use maka_agent_facts::execution::SandboxMode;
use maka_agent_facts::execution::ThinkingLevel;
use maka_agent_facts::execution::WorkspaceIdentity;
use maka_agent_facts::execution::WorkspaceTarget;
use serde::{Deserialize, Serialize};
/// Explicit choices for a new root Session. No mutable Host defaults are
/// resolved behind a retry identity.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Settings {
pub target: super::Target,
pub sandbox_mode: SandboxMode,
pub approval_policy: maka_agent_facts::execution::ApprovalPolicy,
pub collaboration_mode: CollaborationMode,
pub behavior: BehaviorId,
#[serde(default)]
pub bound_tools: Option<std::collections::BTreeSet<String>>,
#[serde(default)]
pub instructions: Option<String>,
}
impl Settings {
pub fn validate(&self) -> Result<(), Error> {
self.target.validate()?;
if let Some(tools) = &self.bound_tools {
for tool in tools {
name(tool)?;
}
}
Ok(())
}
}
/// Fully explicit execution surface approved by Host. Defaults are resolved
/// before persistence; a later restart cannot reinterpret configuration defaults.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RootTemplate {
pub workspace: WorkspaceTarget,
pub cwd: String,
pub workspace_identity: WorkspaceIdentity,
pub model: ModelBinding,
pub thinking_level: Option<ThinkingLevel>,
pub sandbox_mode: SandboxMode,
pub approval_policy: maka_agent_facts::execution::ApprovalPolicy,
pub collaboration_mode: CollaborationMode,
pub orchestration_mode: BehaviorId,
}
impl RootTemplate {
pub fn settings(&self) -> Settings {
Settings {
target: super::Target::Model {
model: self.model.clone(),
thinking_level: self.thinking_level,
},
sandbox_mode: self.sandbox_mode,
approval_policy: self.approval_policy,
collaboration_mode: self.collaboration_mode,
behavior: self.orchestration_mode.clone(),
bound_tools: None,
instructions: None,
}
}
pub fn validate(&self) -> Result<(), Error> {
name(&self.model.connection_id)?;
name(&self.model.connection_slug)?;
name(&self.model.model)?;
if self.cwd.is_empty() || self.cwd.contains('\0') {
return Err(Error::Invalid("invalid root Session workspace".into()));
}
match &self.workspace {
WorkspaceTarget::Project { project_id } => name(project_id)?,
WorkspaceTarget::HostPath { path } if path == &self.cwd => {}
_ => {
return Err(Error::Invalid(
"root Session workspace must be canonical".into(),
));
}
}
Ok(())
}
}
/// Frozen Host approval data. Restoring a capability requires an explicit Host
/// grant; normal execution capabilities cannot create root Sessions.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RootApproval {
pub template: RootTemplate,
/// Agent-created plans retain their originating Session's permission ceiling.
pub source: Option<SessionBoundary>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct CreateRoot {
/// Only the creating package/scope may admit work or change this Session.
/// Canonical execution facts and already accepted work remain Host-owned.
#[serde(default)]
pub managed: bool,
pub operation_id: String,
pub name: String,
pub settings: Settings,
}
impl CreateRoot {
pub fn validate(&self) -> Result<(), Error> {
name(&self.operation_id)?;
self.settings.validate()?;
if self.name.trim().is_empty() || self.name.len() > 1024 || self.name.contains('\0') {
return Err(Error::Invalid("invalid root Session name".into()));
}
Ok(())
}
}