feat(memory): add Insight type hierarchy, DetectedPattern model, and ToolMetricsCollector (#13)#19
Conversation
…ToolMetricsCollector (#13) Foundation for the self-learning pipeline (P3 Phase 4): - Sealed Insight interface with ErrorInsight, SuccessInsight, PatternInsight variants - PatternType enum (REPEATED_TOOL_SEQUENCE, ERROR_CORRECTION, USER_PREFERENCE, WORKFLOW) - DetectedPattern record with validation and toInsight() conversion - ToolMetrics record with derived avgExecutionMs() and successRate() - Thread-safe ToolMetricsCollector using ConcurrentHashMap + atomics - Wire ToolMetricsCollector into AgentLoopConfig and StreamingAgentLoop
|
No actionable comments were generated in the recent review. 🎉 📝 WalkthroughWalkthroughAdds per-tool metrics collection and memory insight types: a thread-safe ToolMetricsCollector and ToolMetrics record; integrates an optional metricsCollector into AgentLoopConfig and records metrics in StreamingAgentLoop; introduces PatternType, DetectedPattern, and a sealed Insight hierarchy with unit tests for metrics and memory types. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
aceclaw-core/src/main/java/dev/aceclaw/core/agent/StreamingAgentLoop.java (2)
456-458: Consider defensive wrapping for metrics recording.If
metricsCollector.record()throws unexpectedly (e.g., due to a bug or resource exhaustion), it would propagate up and fail the tool result return. Since metrics are non-critical, consider wrapping in a try-catch to ensure tool execution isn't affected by metrics failures.Proposed defensive wrapper
if (config.metricsCollector() != null) { - config.metricsCollector().record(tool.name(), !result.isError(), toolDuration); + try { + config.metricsCollector().record(tool.name(), !result.isError(), toolDuration); + } catch (Exception e) { + log.warn("Failed to record tool metrics for {}: {}", tool.name(), e.getMessage()); + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@aceclaw-core/src/main/java/dev/aceclaw/core/agent/StreamingAgentLoop.java` around lines 456 - 458, In StreamingAgentLoop, the call to config.metricsCollector().record(tool.name(), !result.isError(), toolDuration) should be made defensive: wrap that invocation in a try-catch so any thrown exception from metrics collection does not propagate and affect returning the tool result; on catch, log the exception using the class logger (or existing logging mechanism) with context (tool.name(), toolDuration) and continue normal flow so metrics failures remain non-critical.
465-467: Same defensive consideration applies here.The metrics recording in the exception path has the same potential issue. If you apply defensive wrapping to the success path, apply it here as well for consistency.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@aceclaw-core/src/main/java/dev/aceclaw/core/agent/StreamingAgentLoop.java` around lines 465 - 467, In StreamingAgentLoop, the metrics recording in the exception path should mirror the defensive handling used in the success path: check config.metricsCollector() for null and guard the call to config.metricsCollector().record(tool.name(), false, toolDuration) inside the same safe wrapper (or a try/catch) so that exceptions from the metrics collector don't propagate; update the exception-path block that references config.metricsCollector(), record(), tool.name(), and toolDuration to perform the null check and handle any thrown errors consistently with the success-path implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@aceclaw-core/src/main/java/dev/aceclaw/core/agent/StreamingAgentLoop.java`:
- Around line 456-458: In StreamingAgentLoop, the call to
config.metricsCollector().record(tool.name(), !result.isError(), toolDuration)
should be made defensive: wrap that invocation in a try-catch so any thrown
exception from metrics collection does not propagate and affect returning the
tool result; on catch, log the exception using the class logger (or existing
logging mechanism) with context (tool.name(), toolDuration) and continue normal
flow so metrics failures remain non-critical.
- Around line 465-467: In StreamingAgentLoop, the metrics recording in the
exception path should mirror the defensive handling used in the success path:
check config.metricsCollector() for null and guard the call to
config.metricsCollector().record(tool.name(), false, toolDuration) inside the
same safe wrapper (or a try/catch) so that exceptions from the metrics collector
don't propagate; update the exception-path block that references
config.metricsCollector(), record(), tool.name(), and toolDuration to perform
the null check and handle any thrown errors consistently with the success-path
implementation.
Extract recordMetrics() helper with try-catch so exceptions from ToolMetricsCollector never swallow tool results or replace original exceptions. Metrics failures are logged and silently ignored.
Summary
Insightinterface withErrorInsight,SuccessInsight,PatternInsightvariantsPatternTypeenum,DetectedPatternrecord with validation andtoInsight()conversionToolMetricsCollectorwired intoAgentLoopConfigandStreamingAgentLoopTest plan
InsightTest— 13 tests (sealed exhaustiveness, targetCategory, confidence bounds, defensive copies)DetectedPatternTest— 8 tests (validation, immutability, toInsight conversion)ToolMetricsCollectorTest— 10 tests (single/multi tool, concurrent access, derived methods)./gradlew clean build— 64 tasks, BUILD SUCCESSFUL)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests