Add operator Mentra memory browser
This commit is contained in:
145
vendor/mentra/tests/skills_api.rs
vendored
Normal file
145
vendor/mentra/tests/skills_api.rs
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
//! Public-API tests for skill registration and enumeration.
|
||||
//!
|
||||
//! These exercise what a host can actually reach: registering roots through
|
||||
//! `Runtime`, listing what loaded, and naming the error type in its own
|
||||
//! signatures.
|
||||
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
use mentra::{BuiltinProvider, Runtime, SkillInfo, SkillLoadError};
|
||||
|
||||
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
fn temp_dir(label: &str) -> PathBuf {
|
||||
let unique = NEXT_ID.fetch_add(1, Ordering::Relaxed);
|
||||
let stamp = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("system time")
|
||||
.as_nanos();
|
||||
let path = std::env::temp_dir().join(format!("mentra-skills-api-{label}-{stamp}-{unique}"));
|
||||
fs::create_dir_all(&path).expect("create temp dir");
|
||||
path
|
||||
}
|
||||
|
||||
fn write_skill(root: &Path, dir: &str, name: &str, description: &str, body: &str) {
|
||||
let skill_dir = root.join(dir);
|
||||
fs::create_dir_all(&skill_dir).expect("create skill dir");
|
||||
fs::write(
|
||||
skill_dir.join("SKILL.md"),
|
||||
format!("---\nname: {name}\ndescription: {description}\n---\n{body}\n"),
|
||||
)
|
||||
.expect("write skill");
|
||||
}
|
||||
|
||||
fn runtime() -> Runtime {
|
||||
Runtime::builder()
|
||||
.with_provider(BuiltinProvider::OpenAI, "test-key")
|
||||
.build()
|
||||
.expect("runtime builds")
|
||||
}
|
||||
|
||||
/// The error type must be nameable by a caller — this signature is the test.
|
||||
fn register(runtime: &Runtime, path: &Path) -> Result<(), SkillLoadError> {
|
||||
runtime.register_skills_dir(path)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_host_can_name_the_error_type() {
|
||||
let runtime = runtime();
|
||||
let missing = temp_dir("nameable").join("does-not-exist");
|
||||
|
||||
let error = register(&runtime, &missing).expect_err("an unreadable root is an error");
|
||||
|
||||
// And match on it, which is the point of it being an enum.
|
||||
assert!(matches!(error, SkillLoadError::ReadDir { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn registering_a_second_root_keeps_the_first() {
|
||||
let workspace = temp_dir("layer-workspace");
|
||||
write_skill(&workspace, "review", "review", "project review", "PROJECT");
|
||||
let global = temp_dir("layer-global");
|
||||
write_skill(&global, "review", "review", "personal review", "PERSONAL");
|
||||
write_skill(&global, "deploy", "deploy", "personal deploy", "DEPLOY");
|
||||
|
||||
let runtime = runtime();
|
||||
runtime
|
||||
.register_skills_dirs([workspace.as_path(), global.as_path()])
|
||||
.expect("both roots register");
|
||||
|
||||
let skills = runtime.skills();
|
||||
let names: Vec<&str> = skills.iter().map(|skill| skill.name.as_str()).collect();
|
||||
assert_eq!(names, vec!["deploy", "review"]);
|
||||
|
||||
let review = skills
|
||||
.iter()
|
||||
.find(|skill| skill.name == "review")
|
||||
.expect("review present");
|
||||
assert_eq!(
|
||||
review.description, "project review",
|
||||
"the earlier root must win the collision"
|
||||
);
|
||||
assert!(review.path.starts_with(&workspace));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn enumeration_reports_name_description_and_source() {
|
||||
let root = temp_dir("enumerate");
|
||||
write_skill(&root, "haiku", "haiku", "writes haiku", "BODY");
|
||||
|
||||
let runtime = runtime();
|
||||
runtime.register_skills_dir(&root).expect("registers");
|
||||
|
||||
let skills = runtime.skills();
|
||||
assert_eq!(skills.len(), 1);
|
||||
let SkillInfo {
|
||||
name,
|
||||
description,
|
||||
path,
|
||||
} = &skills[0];
|
||||
assert_eq!(name, "haiku");
|
||||
assert_eq!(description, "writes haiku");
|
||||
assert_eq!(path, &root.join("haiku").join("SKILL.md"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_runtime_without_skills_lists_none() {
|
||||
assert!(runtime().skills().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_duplicate_name_inside_one_root_is_still_an_error() {
|
||||
let root = temp_dir("duplicate");
|
||||
write_skill(&root, "first", "shared", "one", "A");
|
||||
write_skill(&root, "second", "shared", "two", "B");
|
||||
|
||||
let error = runtime()
|
||||
.register_skills_dir(&root)
|
||||
.expect_err("a repeated name in one root is a mistake");
|
||||
|
||||
assert!(matches!(error, SkillLoadError::DuplicateSkillName { .. }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn roots_before_a_failing_one_stay_registered() {
|
||||
let good = temp_dir("partial-good");
|
||||
write_skill(&good, "keep", "keep", "kept", "BODY");
|
||||
let missing = temp_dir("partial-missing").join("absent");
|
||||
|
||||
let runtime = runtime();
|
||||
let error = runtime
|
||||
.register_skills_dirs([good.as_path(), missing.as_path()])
|
||||
.expect_err("the second root fails");
|
||||
|
||||
assert!(matches!(error, SkillLoadError::ReadDir { .. }));
|
||||
assert_eq!(
|
||||
runtime.skills().len(),
|
||||
1,
|
||||
"the root that loaded before the failure stays registered"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user