// Tests for prompt_builder.mbt — Task 5.10 + 5.11
extern "js" fn _mkdtemp_pb() -> String =
#| () => {
#| const fs = require("node:fs");
#| const os = require("node:os");
#| const path = require("node:path");
#| return fs.mkdtempSync(path.join(os.tmpdir(), "mnemo-pb-"));
#| }
extern "js" fn _rmrf_pb(dir : String) -> Unit =
#| (dir) => { require("node:fs").rmSync(dir, { recursive: true, force: true }); }
extern "js" fn _write_file_pb(path : String, content : String) -> Unit =
#| (p, c) => { require("node:fs").writeFileSync(p, c, "utf8"); }
extern "js" fn _mkdir_p_pb(path : String) -> Unit =
#| (p) => { require("node:fs").mkdirSync(p, { recursive: true }); }
// ---------------------------------------------------------------------------
// Task 5.10: truncation + context file loader tests
// ---------------------------------------------------------------------------
test "pb_truncate: short content unchanged" {
let short = "hello world"
assert_eq(pb_truncate_content(short), short)
}
test "pb_truncate: long content head+tail+marker" {
let long = String::make(25000, 'A')
let out = pb_truncate_content(long)
assert_eq(out.has_prefix("AAAA"), true)
assert_eq(out.has_suffix("AAAA"), true)
assert_eq(out.contains("chars truncated"), true)
}
test "pb_find_context_file: absent returns empty" {
let dir = _mkdtemp_pb()
let result = pb_find_context_file(dir)
assert_eq(result, "")
_rmrf_pb(dir)
}
test "pb_find_context_file: CLAUDE.md in cwd" {
let dir = _mkdtemp_pb()
_write_file_pb(dir + "/CLAUDE.md", "# rules")
let result = pb_find_context_file(dir)
assert_eq(result.contains("rules"), true)
_rmrf_pb(dir)
}
// ---------------------------------------------------------------------------
// Task 5.11: SOUL loader + build_system_prompt tests
// ---------------------------------------------------------------------------
test "pb_load_soul_md: absent returns empty" {
let dir = _mkdtemp_pb()
let result = pb_load_soul_md(dir)
assert_eq(result, "")
_rmrf_pb(dir)
}
test "pb_load_soul_md: present returns content" {
let dir = _mkdtemp_pb()
_write_file_pb(dir + "/SOUL.md", "Be thorough.")
let result = pb_load_soul_md(dir)
assert_eq(result.contains("Be thorough"), true)
_rmrf_pb(dir)
}
test "build_system_prompt: empty config has identity" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "",
available_tools: [],
disabled_skills: [],
})
assert_eq(prompt.contains("Ermes Agent"), true)
assert_eq(prompt.contains("persistent memory"), true)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}
test "build_system_prompt: SOUL.md included when present" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
_write_file_pb(hh + "/SOUL.md", "Be very precise.")
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "",
available_tools: [],
disabled_skills: [],
})
assert_eq(prompt.contains("SOUL.md"), true)
assert_eq(prompt.contains("Be very precise"), true)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}
test "build_system_prompt: context file included" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
_write_file_pb(cwd + "/CLAUDE.md", "# rules\nUse ESM.")
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "",
available_tools: [],
disabled_skills: [],
})
assert_eq(prompt.contains("Project Context"), true)
assert_eq(prompt.contains("Use ESM"), true)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}
test "build_system_prompt: assembly order identity before context" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
_write_file_pb(cwd + "/CLAUDE.md", "# project rules")
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "",
available_tools: [],
disabled_skills: [],
})
// Identity must appear before Project Context in the output
let idx_id = pb_index_of(prompt, "Ermes Agent")
let idx_ctx = pb_index_of(prompt, "Project Context")
assert_eq(idx_id < idx_ctx, true)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}
// ---------------------------------------------------------------------------
// Model-specific guidance tests
// ---------------------------------------------------------------------------
test "build_system_prompt: OpenAI guidance for gpt-4o" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "gpt-4o",
available_tools: [],
disabled_skills: [],
})
assert_eq(prompt.contains("Execution discipline"), true)
assert_eq(prompt.contains("tool_persistence"), true)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}
test "build_system_prompt: Google guidance for gemini model" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "gemini-2.0-flash",
available_tools: [],
disabled_skills: [],
})
assert_eq(prompt.contains("Google model operational directives"), true)
assert_eq(prompt.contains("Absolute paths"), true)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}
test "build_system_prompt: no model-specific guidance for claude" {
let hh = _mkdtemp_pb()
let cwd = _mkdtemp_pb()
let prompt = build_system_prompt({
hermes_home: hh,
cwd,
platform: "",
model: "claude-3-5-sonnet",
available_tools: [],
disabled_skills: [],
})
assert_eq(prompt.contains("Execution discipline"), false)
assert_eq(prompt.contains("Google model operational directives"), false)
_rmrf_pb(hh)
_rmrf_pb(cwd)
}