feat: add tool execution idempotency cache

When the LLM re-requests the same idempotent tool with identical args
(common during self-repair recovery, stuck job retries, or chat-mode
retry loops), the cache returns the previous result instantly without
re-executing.

Design improvements over the closed PR #204:
- Single global LRU cache (lru crate) instead of per-job HashMap with
  O(N) manual eviction
- Global cap of 2000 entries prevents memory leaks from chat-path
  ephemeral job IDs that never get invalidated
- TTL expiry (30min) checked on read; LRU eviction handles the rest
- Job invalidation still runs on worker completion for prompt cleanup

Idempotent tools: echo, time, json, memory_read/search/tree,
read_file, list_dir, list_jobs, job_status.

Closes #204

Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
2026-03-10 02:01:58 -07:00
co-authored by Claude Opus 4.6
parent 3a2989d009
commit 5fcb4d3c03
17 changed files with 453 additions and 15 deletions
+3
View File
@@ -624,6 +624,9 @@ impl TestRigBuilder {
},
transcription: None,
document_extraction: None,
idempotency_cache: ironclaw::tools::idempotency::ToolIdempotencyCache::new(
ironclaw::tools::idempotency::IdempotencyCacheConfig::default(),
),
};
// 7. Create TestChannel and ChannelManager.