use std::{path::PathBuf, sync::Arc};
use basis::{PreparedRun, RunConfig, RunError, approval::ApprovalGate, run::prepare_with_session};
use basis_acp::SessionSource;
use mentra::{
RuntimePolicy,
test::{MockRuntime, MockToolCall},
};
pub(crate) const MOCK_RUNTIME: &str = "basis-acp-tests";
pub(crate) struct MockSource {
mock: Arc<MockRuntime>,
workspace: PathBuf,
}
impl MockSource {
pub(crate) fn new(mock: &Arc<MockRuntime>, workspace: &tempfile::TempDir) -> Self {
Self {
mock: Arc::clone(mock),
workspace: workspace.path().to_path_buf(),
}
}
fn config(&self) -> RunConfig {
RunConfig::new(&self.workspace, "").with_context(basis::ContextConfig {
file_name: "AGENTS.md".to_string(),
global_dir: None,
walk_parents: false,
})
}
}
#[async_trait::async_trait]
impl SessionSource for MockSource {
async fn create(
&self,
_cwd: PathBuf,
_mcp: Vec<basis::McpServer>,
) -> Result<PreparedRun, RunError> {
let session = self
.mock
.runtime()
.create_session_with_config(
"test",
self.mock.model(),
mentra::agent::AgentConfig {
workspace: mentra::agent::WorkspaceConfig {
base_dir: self.workspace.clone(),
..Default::default()
},
..Default::default()
},
)
.expect("session");
prepare_with_session(session, &self.config(), "openai", "mock-model")
}
async fn resume(
&self,
agent_id: &str,
_cwd: PathBuf,
_mcp: Vec<basis::McpServer>,
) -> Result<PreparedRun, RunError> {
let session = self.mock.runtime().resume_session(agent_id)?;
prepare_with_session(session, &self.config(), "openai", "mock-model")
}
fn lists_sessions(&self) -> bool {
true
}
async fn list_sessions(&self, _cwd: PathBuf) -> Result<Vec<basis::PersistedSession>, RunError> {
Ok(self
.mock
.runtime()
.list_persisted_agents(MOCK_RUNTIME)?
.into_iter()
.filter(|agent| !agent.is_teammate)
.map(|agent| basis::PersistedSession {
agent_id: agent.id,
name: agent.name,
messages: agent.history_len,
})
.collect())
}
}
pub(crate) fn workspace() -> tempfile::TempDir {
tempfile::tempdir().expect("tempdir")
}
pub(crate) fn text_mock(chunks: &[&str]) -> MockRuntime {
MockRuntime::builder()
.model("mock-model", "openai")
.runtime_identifier(MOCK_RUNTIME)
.with_policy(RuntimePolicy::permissive())
.stream_text(chunks.to_vec())
.build()
.expect("mock runtime builds")
}
pub(crate) fn writing_mock(workspace: &tempfile::TempDir) -> MockRuntime {
MockRuntime::builder()
.model("mock-model", "openai")
.runtime_identifier(MOCK_RUNTIME)
.with_policy(RuntimePolicy::workspace_bounded(workspace.path()))
.with_tool_authorizer(ApprovalGate::new())
.tool_calls(vec![MockToolCall::new(
"files",
serde_json::json!({
"operations": [{ "op": "create", "path": "made.txt", "content": "hi" }]
}),
)])
.text("done")
.build()
.expect("mock runtime builds")
}