Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
// Acceptance tests for the memory system end-to-end.
|
||||
//
|
||||
// These tests verify that the memory system's file I/O, index management,
|
||||
// and prompt building work together correctly. No LLM API calls are needed.
|
||||
|
||||
use nomi_agent::context::{SystemPromptCache, build_system_prompt};
|
||||
use nomi_memory::index::{append_index_entry, remove_index_entry};
|
||||
use nomi_memory::paths::ENTRYPOINT_NAME;
|
||||
use nomi_memory::store::{delete_memory, write_memory};
|
||||
use nomi_memory::types::{MemoryEntry, MemoryType};
|
||||
|
||||
/// TC-A1-01: Memory injection into system prompt.
|
||||
///
|
||||
/// Verifies that when a memory directory exists with an index file and a
|
||||
/// memory entry, `build_system_prompt()` produces output containing both
|
||||
/// the compact behavioral instructions and the MEMORY.md index content.
|
||||
#[test]
|
||||
fn memory_injection_into_system_prompt() {
|
||||
let tmp = tempfile::TempDir::new().unwrap();
|
||||
let mem_dir = tmp.path().join("memory");
|
||||
std::fs::create_dir_all(&mem_dir).unwrap();
|
||||
|
||||
// Write MEMORY.md index with one entry
|
||||
let index_path = mem_dir.join(ENTRYPOINT_NAME);
|
||||
std::fs::write(
|
||||
&index_path,
|
||||
"# Memory Index\n\n- [User role](user_role.md) \u{2014} senior Rust engineer\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Write a corresponding memory entry file
|
||||
std::fs::write(
|
||||
mem_dir.join("user_role.md"),
|
||||
"---\nname: user_role\ndescription: senior Rust engineer\ntype: user\n---\n\nThe user is a senior Rust engineer.\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let prompt = build_system_prompt(
|
||||
&mut SystemPromptCache::new(),
|
||||
None,
|
||||
"/tmp",
|
||||
"test-model",
|
||||
&[],
|
||||
None,
|
||||
Some(&mem_dir),
|
||||
false,
|
||||
false,
|
||||
false, // browser_enabled
|
||||
);
|
||||
|
||||
// Behavioral instructions must be present
|
||||
assert!(
|
||||
prompt.contains("auto memory"),
|
||||
"system prompt should contain the memory display name"
|
||||
);
|
||||
assert!(
|
||||
prompt.contains("Memory types:"),
|
||||
"system prompt should contain the compact memory type summary"
|
||||
);
|
||||
|
||||
// MEMORY.md content must be injected
|
||||
assert!(
|
||||
prompt.contains("user_role.md"),
|
||||
"system prompt should contain the MEMORY.md index filename reference"
|
||||
);
|
||||
assert!(
|
||||
prompt.contains("senior Rust engineer"),
|
||||
"system prompt should contain the MEMORY.md index summary"
|
||||
);
|
||||
}
|
||||
|
||||
/// TC-A1-02: Memory full lifecycle (create, index, verify, delete, verify gone).
|
||||
///
|
||||
/// Exercises the complete lifecycle of a memory entry through the public API:
|
||||
/// 1. write_memory() -> create the file
|
||||
/// 2. append_index_entry() -> add to MEMORY.md
|
||||
/// 3. build_system_prompt() -> verify the content appears
|
||||
/// 4. delete_memory() -> remove the file
|
||||
/// 5. remove_index_entry() -> clean the index
|
||||
/// 6. build_system_prompt() -> verify the content is gone
|
||||
#[test]
|
||||
fn memory_full_lifecycle() {
|
||||
let tmp = tempfile::TempDir::new().unwrap();
|
||||
let mem_dir = tmp.path().join("memory");
|
||||
std::fs::create_dir_all(&mem_dir).unwrap();
|
||||
|
||||
let index_path = mem_dir.join(ENTRYPOINT_NAME);
|
||||
|
||||
// -- Phase 1: Create memory entry via the store API -----------------------
|
||||
|
||||
let entry = MemoryEntry::build(
|
||||
"project status",
|
||||
"current sprint goals",
|
||||
MemoryType::Project,
|
||||
"We are migrating the auth service to the new provider.",
|
||||
);
|
||||
|
||||
let entry_path = write_memory(&mem_dir, &entry).unwrap();
|
||||
assert!(entry_path.exists(), "memory file should be created on disk");
|
||||
|
||||
let entry_filename = entry_path.file_name().unwrap().to_str().unwrap().to_owned();
|
||||
|
||||
// -- Phase 2: Add the entry to the MEMORY.md index ------------------------
|
||||
|
||||
append_index_entry(
|
||||
&index_path,
|
||||
"Project status",
|
||||
&entry_filename,
|
||||
"current sprint goals",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let index_content = std::fs::read_to_string(&index_path).unwrap();
|
||||
assert!(
|
||||
index_content.contains(&entry_filename),
|
||||
"MEMORY.md should reference the new entry file"
|
||||
);
|
||||
|
||||
// -- Phase 3: Verify system prompt includes the memory content ------------
|
||||
|
||||
let prompt_with_memory = build_system_prompt(
|
||||
&mut SystemPromptCache::new(),
|
||||
None,
|
||||
"/tmp",
|
||||
"test-model",
|
||||
&[],
|
||||
None,
|
||||
Some(&mem_dir),
|
||||
false,
|
||||
false,
|
||||
false, // browser_enabled
|
||||
);
|
||||
|
||||
assert!(
|
||||
prompt_with_memory.contains("auto memory"),
|
||||
"prompt should contain behavioral instructions"
|
||||
);
|
||||
assert!(
|
||||
prompt_with_memory.contains("Memory types:"),
|
||||
"prompt should contain compact memory type summary"
|
||||
);
|
||||
assert!(
|
||||
prompt_with_memory.contains(&entry_filename),
|
||||
"prompt should contain the memory entry filename from the index"
|
||||
);
|
||||
assert!(
|
||||
prompt_with_memory.contains("current sprint goals"),
|
||||
"prompt should contain the index summary"
|
||||
);
|
||||
|
||||
// -- Phase 4: Delete the memory file --------------------------------------
|
||||
|
||||
delete_memory(&entry_path).unwrap();
|
||||
assert!(
|
||||
!entry_path.exists(),
|
||||
"memory file should be removed from disk"
|
||||
);
|
||||
|
||||
// -- Phase 5: Remove the entry from the MEMORY.md index -------------------
|
||||
|
||||
remove_index_entry(&index_path, &entry_filename).unwrap();
|
||||
|
||||
let index_after = std::fs::read_to_string(&index_path).unwrap();
|
||||
assert!(
|
||||
!index_after.contains(&entry_filename),
|
||||
"MEMORY.md should no longer reference the deleted entry"
|
||||
);
|
||||
|
||||
// -- Phase 6: Verify the content is gone from the system prompt -----------
|
||||
|
||||
let prompt_after_delete = build_system_prompt(
|
||||
&mut SystemPromptCache::new(),
|
||||
None,
|
||||
"/tmp",
|
||||
"test-model",
|
||||
&[],
|
||||
None,
|
||||
Some(&mem_dir),
|
||||
false,
|
||||
false,
|
||||
false, // browser_enabled
|
||||
);
|
||||
|
||||
assert!(
|
||||
!prompt_after_delete.contains(&entry_filename),
|
||||
"prompt should no longer contain the deleted entry filename"
|
||||
);
|
||||
assert!(
|
||||
!prompt_after_delete.contains("current sprint goals"),
|
||||
"prompt should no longer contain the deleted entry summary"
|
||||
);
|
||||
// With everything removed, the index is empty — the prompt should show the empty state
|
||||
assert!(
|
||||
prompt_after_delete.contains("currently empty"),
|
||||
"prompt should show empty memory state after all entries are removed"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user