use std::{path::Path, sync::Arc};
use agent_client_protocol::schema::v1::SessionModeState;
use rho_sdk::{provider::ModelProvider, ApprovalSession, SessionOptions};
use super::super::{permission, AcpStartup};
use crate::{
added_dirs::AddedDirs,
app::{
automation::ensure_headless_auto_classifier_model,
interactive_runtime::startup::{
approval_channel_for, ApprovalChannel, ApprovalChannelOptions,
},
session_assembly::{
assemble_session, ApprovalInputs, SessionApproval, SessionAssembly,
SessionAssemblyOptions,
},
tools_prompt::McpSamplingSupport,
},
config::Config,
permission::PermissionMode,
};
pub(super) async fn build_session(
startup: &AcpStartup,
config: &Config,
workspace: &Path,
added_dirs: &AddedDirs,
session_options: impl FnOnce(Arc<dyn ModelProvider>) -> anyhow::Result<SessionOptions>,
) -> anyhow::Result<SessionAssembly> {
ensure_headless_auto_classifier_model(config)?;
assemble_session(SessionAssemblyOptions {
config,
config_path: startup.config_path.clone(),
cwd: workspace,
no_system_prompt: startup.no_system_prompt,
no_tools: startup.no_tools,
no_subagents: startup.no_subagents,
questionnaire_enabled: false,
mcp_elicitation: crate::tools::mcp::McpElicitationSupport::Unavailable,
mcp_sampling: McpSamplingSupport::Unavailable,
mcp_attach: crate::app::tools_prompt::McpAttach::Connect,
diagnostics: &startup.diagnostics,
agent: &startup.agent,
max_steps: None,
usage_purpose: "agent",
usage_parent_session_id: None,
hook_host_labels: rho_sdk::hooks::HookHostLabels::new(),
added_dirs,
extend_tools: std::convert::identity,
system_prompt_suffix: None,
approval: |inputs: ApprovalInputs| {
let ApprovalChannel {
handler, receiver, ..
} = approval_channel_for(
inputs.config.permission_mode,
ApprovalChannelOptions {
config: inputs.config,
workspace_path: inputs.workspace_root,
usage_recording: inputs.usage_recording,
session_writes: inputs.session_writes,
},
);
Ok(SessionApproval {
session: handler.map(ApprovalSession::from_shared),
receiver,
})
},
session_options,
})
.await
}
pub(super) fn mode_state(mode: PermissionMode) -> SessionModeState {
SessionModeState::new(permission::mode_id(mode), permission::mode_list())
}
pub(super) fn session_config(
process: &Config,
host_servers: &[agent_client_protocol::schema::v1::McpServer],
) -> Config {
let mut config = process.clone();
super::super::host_mcp::overlay_host_mcp(&mut config.mcp, host_servers);
config
}