fix(memory): harden lucid recall timeout and add cold-start test (#466)
This commit is contained in:
parent
87dcd7a7a0
commit
bc18b8d3c6
1 changed files with 63 additions and 4 deletions
|
|
@ -24,7 +24,9 @@ pub struct LucidMemory {
|
||||||
impl LucidMemory {
|
impl LucidMemory {
|
||||||
const DEFAULT_LUCID_CMD: &'static str = "lucid";
|
const DEFAULT_LUCID_CMD: &'static str = "lucid";
|
||||||
const DEFAULT_TOKEN_BUDGET: usize = 200;
|
const DEFAULT_TOKEN_BUDGET: usize = 200;
|
||||||
const DEFAULT_RECALL_TIMEOUT_MS: u64 = 120;
|
// Lucid CLI cold start can exceed 120ms on slower machines, which causes
|
||||||
|
// avoidable fallback to local-only memory and premature cooldown.
|
||||||
|
const DEFAULT_RECALL_TIMEOUT_MS: u64 = 500;
|
||||||
const DEFAULT_STORE_TIMEOUT_MS: u64 = 800;
|
const DEFAULT_STORE_TIMEOUT_MS: u64 = 800;
|
||||||
const DEFAULT_LOCAL_HIT_THRESHOLD: usize = 3;
|
const DEFAULT_LOCAL_HIT_THRESHOLD: usize = 3;
|
||||||
const DEFAULT_FAILURE_COOLDOWN_MS: u64 = 15_000;
|
const DEFAULT_FAILURE_COOLDOWN_MS: u64 = 15_000;
|
||||||
|
|
@ -415,6 +417,38 @@ EOF
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "unsupported command" >&2
|
||||||
|
exit 1
|
||||||
|
"#;
|
||||||
|
|
||||||
|
fs::write(&script_path, script).unwrap();
|
||||||
|
let mut perms = fs::metadata(&script_path).unwrap().permissions();
|
||||||
|
perms.set_mode(0o755);
|
||||||
|
fs::set_permissions(&script_path, perms).unwrap();
|
||||||
|
script_path.display().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_delayed_lucid_script(dir: &Path) -> String {
|
||||||
|
let script_path = dir.join("delayed-lucid.sh");
|
||||||
|
let script = r#"#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "store" ]]; then
|
||||||
|
echo '{"success":true,"id":"mem_1"}'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "context" ]]; then
|
||||||
|
# Simulate a cold start that is slower than 120ms but below the 500ms timeout.
|
||||||
|
sleep 0.2
|
||||||
|
cat <<'EOF'
|
||||||
|
<lucid-context>
|
||||||
|
- [decision] Delayed token refresh guidance
|
||||||
|
</lucid-context>
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
echo "unsupported command" >&2
|
echo "unsupported command" >&2
|
||||||
exit 1
|
exit 1
|
||||||
"#;
|
"#;
|
||||||
|
|
@ -468,7 +502,7 @@ exit 1
|
||||||
cmd,
|
cmd,
|
||||||
200,
|
200,
|
||||||
3,
|
3,
|
||||||
Duration::from_millis(120),
|
Duration::from_millis(500),
|
||||||
Duration::from_millis(400),
|
Duration::from_millis(400),
|
||||||
Duration::from_secs(2),
|
Duration::from_secs(2),
|
||||||
)
|
)
|
||||||
|
|
@ -520,6 +554,31 @@ exit 1
|
||||||
assert!(entries.iter().any(|e| e.content.contains("token refresh")));
|
assert!(entries.iter().any(|e| e.content.contains("token refresh")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn recall_handles_lucid_cold_start_delay_within_timeout() {
|
||||||
|
let tmp = TempDir::new().unwrap();
|
||||||
|
let delayed_cmd = write_delayed_lucid_script(tmp.path());
|
||||||
|
let memory = test_memory(tmp.path(), delayed_cmd);
|
||||||
|
|
||||||
|
memory
|
||||||
|
.store(
|
||||||
|
"local_note",
|
||||||
|
"Local sqlite auth fallback note",
|
||||||
|
MemoryCategory::Core,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let entries = memory.recall("auth", 5).await.unwrap();
|
||||||
|
|
||||||
|
assert!(entries
|
||||||
|
.iter()
|
||||||
|
.any(|e| e.content.contains("Local sqlite auth fallback note")));
|
||||||
|
assert!(entries
|
||||||
|
.iter()
|
||||||
|
.any(|e| e.content.contains("Delayed token refresh guidance")));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn recall_skips_lucid_when_local_hits_are_enough() {
|
async fn recall_skips_lucid_when_local_hits_are_enough() {
|
||||||
let tmp = TempDir::new().unwrap();
|
let tmp = TempDir::new().unwrap();
|
||||||
|
|
@ -533,7 +592,7 @@ exit 1
|
||||||
probe_cmd,
|
probe_cmd,
|
||||||
200,
|
200,
|
||||||
1,
|
1,
|
||||||
Duration::from_millis(120),
|
Duration::from_millis(500),
|
||||||
Duration::from_millis(400),
|
Duration::from_millis(400),
|
||||||
Duration::from_secs(2),
|
Duration::from_secs(2),
|
||||||
);
|
);
|
||||||
|
|
@ -603,7 +662,7 @@ exit 1
|
||||||
failing_cmd,
|
failing_cmd,
|
||||||
200,
|
200,
|
||||||
99,
|
99,
|
||||||
Duration::from_millis(120),
|
Duration::from_millis(500),
|
||||||
Duration::from_millis(400),
|
Duration::from_millis(400),
|
||||||
Duration::from_secs(5),
|
Duration::from_secs(5),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue