mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-17 09:41:58 +00:00
feat(display): document and test memory_notifications setting
Follow-up to salvaged PR #4684: - Add display.memory_notifications to DEFAULT_CONFIG (off|on|verbose, default on) - Document the setting in docs/user-guide/features/memory.md - Add resolver tests for off/on/verbose memory + skill paths
This commit is contained in:
parent
4cf9d80fba
commit
98ae28657f
3 changed files with 141 additions and 0 deletions
|
|
@ -1428,6 +1428,12 @@ DEFAULT_CONFIG = {
|
|||
"tui_agents_nudge": True,
|
||||
"bell_on_complete": False,
|
||||
"show_reasoning": False,
|
||||
# Background self-improvement review notifications surfaced in chat.
|
||||
# "off" — no chat notification (the review still runs and writes)
|
||||
# "on" — generic "💾 Memory updated" line (default)
|
||||
# "verbose" — include a compact content preview of what changed
|
||||
# Per-platform overrides via display.platforms.<platform>.memory_notifications.
|
||||
"memory_notifications": "on",
|
||||
"streaming": False,
|
||||
"timestamps": False, # Show [HH:MM] on user and assistant labels
|
||||
"final_response_markdown": "strip", # render | strip | raw
|
||||
|
|
|
|||
|
|
@ -315,3 +315,117 @@ def test_background_review_fork_skips_external_memory_plugins(monkeypatch):
|
|||
"the fork leaks harness prompts into the user's real memory "
|
||||
"namespace via on_turn_start / prefetch_all / sync_all."
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# memory_notifications mode: off | on | verbose
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
import json as _json
|
||||
|
||||
from agent.background_review import summarize_background_review_actions
|
||||
|
||||
|
||||
def _memory_add_review():
|
||||
"""A minimal review transcript: one memory add (assistant call + tool result)."""
|
||||
return [
|
||||
{
|
||||
"role": "assistant",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_mem1",
|
||||
"function": {
|
||||
"name": "memory",
|
||||
"arguments": _json.dumps(
|
||||
{
|
||||
"action": "add",
|
||||
"target": "memory",
|
||||
"content": "User prefers terse replies",
|
||||
}
|
||||
),
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": "call_mem1",
|
||||
"content": _json.dumps(
|
||||
{"success": True, "message": "Entry added.", "target": "memory"}
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def _skill_patch_review():
|
||||
return [
|
||||
{
|
||||
"role": "assistant",
|
||||
"tool_calls": [
|
||||
{
|
||||
"id": "call_skill1",
|
||||
"function": {
|
||||
"name": "skill_manage",
|
||||
"arguments": _json.dumps(
|
||||
{"action": "patch", "name": "demo", "old_string": "a", "new_string": "b"}
|
||||
),
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
"role": "tool",
|
||||
"tool_call_id": "call_skill1",
|
||||
"content": _json.dumps(
|
||||
{
|
||||
"success": True,
|
||||
"message": "Patched SKILL.md in skill 'demo' (1 replacement).",
|
||||
"_change": {"old": "a", "new": "b"},
|
||||
}
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def test_memory_notifications_off_returns_nothing():
|
||||
actions = summarize_background_review_actions(
|
||||
_memory_add_review(), [], notification_mode="off"
|
||||
)
|
||||
assert actions == []
|
||||
|
||||
|
||||
def test_memory_notifications_on_returns_generic_line():
|
||||
actions = summarize_background_review_actions(
|
||||
_memory_add_review(), [], notification_mode="on"
|
||||
)
|
||||
assert actions == ["Memory updated"]
|
||||
|
||||
|
||||
def test_memory_notifications_verbose_includes_content_preview():
|
||||
actions = summarize_background_review_actions(
|
||||
_memory_add_review(), [], notification_mode="verbose"
|
||||
)
|
||||
assert len(actions) == 1
|
||||
# Verbose surfaces the actual content that was saved.
|
||||
assert "User prefers terse replies" in actions[0]
|
||||
assert actions[0] != "Memory updated"
|
||||
|
||||
|
||||
def test_memory_notifications_default_is_on():
|
||||
"""No mode passed → behaves like 'on' (generic line, not empty/verbose)."""
|
||||
actions = summarize_background_review_actions(_memory_add_review(), [])
|
||||
assert actions == ["Memory updated"]
|
||||
|
||||
|
||||
def test_skill_patch_off_silent_verbose_shows_diff():
|
||||
assert (
|
||||
summarize_background_review_actions(
|
||||
_skill_patch_review(), [], notification_mode="off"
|
||||
)
|
||||
== []
|
||||
)
|
||||
verbose = summarize_background_review_actions(
|
||||
_skill_patch_review(), [], notification_mode="verbose"
|
||||
)
|
||||
assert len(verbose) == 1
|
||||
assert "demo" in verbose[0] and "→" in verbose[0]
|
||||
|
|
|
|||
|
|
@ -245,6 +245,27 @@ This is the answer to "the agent saved a wrong assumption about me": set
|
|||
`write_approval: true`, and every save — especially the unprompted background
|
||||
ones — waits for your yes/no before it ever enters your profile.
|
||||
|
||||
## Background review notifications (`display.memory_notifications`)
|
||||
|
||||
After a turn, the background self-improvement review may quietly save a memory
|
||||
or update a skill. By default it surfaces a short `💾 Memory updated` line in
|
||||
chat so you know it happened. Control how chatty that is:
|
||||
|
||||
```yaml
|
||||
display:
|
||||
memory_notifications: on # off | on (default) | verbose
|
||||
```
|
||||
|
||||
| Value | Behaviour |
|
||||
|-------|-----------|
|
||||
| `off` | No chat notification. The review still runs and still writes — you just don't see a line for it. |
|
||||
| `on` (default) | Generic line, e.g. `💾 Memory updated`, `💾 Skill 'foo' patched`. |
|
||||
| `verbose` | Includes a compact preview of what changed, e.g. `💾 Memory ➕ User prefers terse replies` or a `"old" → "new"` skill diff snippet. |
|
||||
|
||||
> This only governs the **gateway** chat notification. The review itself, and
|
||||
> writes to your memory/skill stores, are unaffected by this setting. Set it
|
||||
> per-platform via `display.platforms.<platform>.memory_notifications`.
|
||||
|
||||
## Controlling skill writes (`skills.write_approval`)
|
||||
|
||||
Skills use the same on/off gate, but the review UX differs because a
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue