hermes-agent/tests/plugins
Nicolò Boschi 3082fa0829 feat(hindsight): probe API for update_mode='append' support, dedupe across processes
Mirrors the pattern already shipping in hindsight-integrations/openclaw:
probe `<api_url>/version` once per process, gate on Hindsight ≥ 0.5.0.
When supported, retains use a stable session-scoped `document_id`
(`session_id`) plus `update_mode='append'` so cross-process retains for
the same session merge into one document instead of producing
N-different-process-stamped duplicates. When unsupported (or probe
fails), fall back to the existing per-process unique
`f"{session_id}-{start_ts}"` document_id with no `update_mode` — the
resume-overwrite fix (#6654) keeps working unchanged on legacy servers.

Closes the dedup half of #20115. The proposed `document_id_strategy`
config knob isn't needed: auto-detection via the same /version probe
the OpenClaw plugin already uses gives the same outcome with no extra
config burden, and the choice is purely a function of what the server
can do.

Plumbing
--------
- Module-level helpers (`_meets_minimum_version`, `_fetch_hindsight_api_version`,
  `_check_api_supports_update_mode_append`) cache the result per api_url
  so every provider in the process gets one /version round-trip.
- One-time WARN logged when the API is older than 0.5.0, telling the
  user to upgrade for cross-session deduplication.
- New instance helper `_resolve_retain_target(fallback_doc_id)` returns
  `(document_id, update_mode)` based on cached capability. Wired into
  `sync_turn` and the `on_session_switch` flush path.
- For local_embedded mode, the probe URL is taken from the running
  client (`client.url`) so we hit the actual daemon port rather than
  the configured default.
- `update_mode` is set on the per-item dict; `aretain_batch` already
  threads `item['update_mode']` into the API call.

Tests
-----
- `TestUpdateModeAppendCapability` (5 cases): legacy fallback, modern
  stable+append, per-url cache, one-time warn, flush-on-switch resolves
  against the OLD session.
- Existing `_make_hindsight_provider` factory in the manager-side test
  file extended to seed `_mode`/`_api_url`/`_api_key`/`_client` and stub
  `_resolve_retain_target` so the bypass-init pattern keeps working.

E2E verified against installed `~/.hermes/hermes-agent`:
- Legacy probe (unreachable host) → `legacy-session-<ts>` doc_id,
  no `update_mode`.
- Modern probe (live local_embedded 0.5.6 daemon) → stable
  `modern-session` doc_id + `update_mode='append'`.
- `test_hermes_embedded_smoke.py` passes (90s).
2026-05-05 15:09:59 -07:00
..
image_gen fix(image-gen): preserve xAI API error status 2026-05-04 04:43:07 -07:00
memory feat(hindsight): probe API for update_mode='append' support, dedupe across processes 2026-05-05 15:09:59 -07:00
__init__.py fix: mem0 API v2 compat, prefetch context fencing, secret redaction (#5423) 2026-04-05 22:43:33 -07:00
test_achievements_plugin.py fix: stabilize CI — TS widen, sys.modules restore, WS subscriber race (#17836) 2026-04-30 01:34:08 -07:00
test_disk_cleanup_plugin.py feat(plugins): make all plugins opt-in by default 2026-04-20 04:46:45 -07:00
test_google_meet_audio.py feat(plugins): google_meet \u2014 join, transcribe, speak, follow up (#16364) 2026-04-27 06:22:25 -07:00
test_google_meet_node.py feat(plugins): google_meet \u2014 join, transcribe, speak, follow up (#16364) 2026-04-27 06:22:25 -07:00
test_google_meet_plugin.py feat(plugins): google_meet \u2014 join, transcribe, speak, follow up (#16364) 2026-04-27 06:22:25 -07:00
test_google_meet_realtime.py feat(plugins): google_meet \u2014 join, transcribe, speak, follow up (#16364) 2026-04-27 06:22:25 -07:00
test_kanban_dashboard_plugin.py fix(kanban): unify failure counter across spawn/timeout/crash outcomes (#20410) 2026-05-05 13:55:37 -07:00
test_langfuse_plugin.py feat(plugins): add bundled observability/langfuse plugin 2026-04-28 01:40:59 -07:00
test_retaindb_plugin.py test: speed up slow tests (backoff + subprocess + IMDS network) (#11797) 2026-04-17 14:21:22 -07:00