f7a720204a
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
177 lines
4.9 KiB
Rust
177 lines
4.9 KiB
Rust
use std::sync::Arc;
|
|
|
|
use nomi_agent::bootstrap::AgentBootstrap;
|
|
use nomi_agent::output::null_sink::NullSink;
|
|
use nomi_config::compat::ProviderCompat;
|
|
use nomi_config::config::{Config, ProviderType};
|
|
|
|
fn minimal_config() -> Config {
|
|
Config {
|
|
provider_label: "openai".into(),
|
|
provider: ProviderType::OpenAI,
|
|
api_key: "sk-test".into(),
|
|
base_url: "http://localhost:0".into(),
|
|
model: "gpt-test-model".into(),
|
|
max_tokens: 1024,
|
|
max_turns: Some(5),
|
|
system_prompt: None,
|
|
thinking: None,
|
|
prompt_caching: false,
|
|
compat: ProviderCompat::openai_defaults(),
|
|
tools: Default::default(),
|
|
session: Default::default(),
|
|
compact: Default::default(),
|
|
plan: Default::default(),
|
|
file_cache: Default::default(),
|
|
hooks: Default::default(),
|
|
bedrock: None,
|
|
vertex: None,
|
|
mcp: Default::default(),
|
|
logging: Default::default(),
|
|
}
|
|
}
|
|
|
|
fn null_output() -> Arc<dyn nomi_agent::output::OutputSink> {
|
|
Arc::new(NullSink)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_builds_engine_with_model_in_prompt() {
|
|
let config = minimal_config();
|
|
let result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.build()
|
|
.await
|
|
.expect("bootstrap should succeed");
|
|
|
|
assert!(!result.engine.tool_names().is_empty());
|
|
assert!(!result.has_mcp);
|
|
assert!(result.mcp_managers.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_registers_all_expected_tools() {
|
|
let config = minimal_config();
|
|
let result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
|
|
let names = result.engine.tool_names();
|
|
|
|
for expected in &["Read", "Write", "Edit", "Bash", "Grep", "Glob"] {
|
|
assert!(
|
|
names.iter().any(|n| n == expected),
|
|
"missing built-in tool: {expected}"
|
|
);
|
|
}
|
|
|
|
assert!(
|
|
names.iter().any(|n| n == "Skill"),
|
|
"SkillTool should be registered"
|
|
);
|
|
assert!(
|
|
names.iter().any(|n| n == "Spawn"),
|
|
"SpawnTool should be registered"
|
|
);
|
|
assert!(
|
|
names.iter().any(|n| n == "ToolSearch"),
|
|
"ToolSearchTool should be registered"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_plan_tools_when_enabled() {
|
|
let mut config = minimal_config();
|
|
config.plan.enabled = true;
|
|
|
|
let result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
|
|
let names = result.engine.tool_names();
|
|
assert!(
|
|
names.iter().any(|n| n == "EnterPlanMode"),
|
|
"EnterPlanMode should be registered when plan.enabled"
|
|
);
|
|
assert!(
|
|
names.iter().any(|n| n == "ExitPlanMode"),
|
|
"ExitPlanMode should be registered when plan.enabled"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_no_plan_tools_when_disabled() {
|
|
let mut config = minimal_config();
|
|
config.plan.enabled = false;
|
|
|
|
let result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
|
|
let names = result.engine.tool_names();
|
|
assert!(
|
|
!names.iter().any(|n| n == "EnterPlanMode"),
|
|
"EnterPlanMode should NOT be registered when plan.disabled"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_no_mcp_when_no_servers() {
|
|
let config = minimal_config();
|
|
let result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
|
|
assert!(!result.has_mcp);
|
|
assert!(result.mcp_managers.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_with_custom_system_prompt() {
|
|
let mut config = minimal_config();
|
|
config.system_prompt = Some("You are a pirate assistant.".into());
|
|
|
|
let _result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_with_agents_md_in_workspace() {
|
|
let tmp = tempfile::TempDir::new().unwrap();
|
|
let workspace = tmp.path();
|
|
std::fs::write(workspace.join("AGENTS.md"), "PROJECT_RULES_MARKER").unwrap();
|
|
|
|
let config = minimal_config();
|
|
let _result = AgentBootstrap::new(config, workspace.to_string_lossy().as_ref(), null_output())
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_config_accessor_returns_config() {
|
|
let config = minimal_config();
|
|
let bootstrap = AgentBootstrap::new(config, "/tmp/ws", null_output());
|
|
assert_eq!(bootstrap.config().model, "gpt-test-model");
|
|
assert_eq!(bootstrap.config().max_tokens, 1024);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn bootstrap_with_external_provider() {
|
|
let config = minimal_config();
|
|
let provider = nomi_providers::create_provider(&config);
|
|
|
|
let result = AgentBootstrap::new(config, "/tmp/test-workspace", null_output())
|
|
.provider(provider)
|
|
.build()
|
|
.await
|
|
.unwrap();
|
|
|
|
assert!(!result.engine.tool_names().is_empty());
|
|
}
|