Skip to content

feat(hindsight): probe API for update_mode='append' to dedupe across processes - #20222

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
nicoloboschi:feat/hindsight-update-mode-append
May 5, 2026
Merged

feat(hindsight): probe API for update_mode='append' to dedupe across processes#20222
teknium1 merged 1 commit into
NousResearch:mainfrom
nicoloboschi:feat/hindsight-update-mode-append

Conversation

@nicoloboschi

Copy link
Copy Markdown
Contributor

Mirrors the pattern already shipping in hindsight-integrations/openclaw: probe <api_url>/version once per process and gate on Hindsight ≥ 0.5.0. When the API supports update_mode='append', retains use a stable session-scoped document_id (just session_id) so cross-process retains for the same session merge into one document. When unsupported or the probe fails, fall back to the existing per-process unique f"{session_id}-{start_ts}" doc_id and don't pass 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

  • New 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 pays one /version round-trip total.
  • One-time WARN when the API is older than 0.5.0, nudging the user to upgrade for cross-session dedup.
  • New instance helper _resolve_retain_target(fallback_doc_id) -> (document_id, update_mode) wired into sync_turn and the on_session_switch flush path.
  • For local_embedded the probe URL is taken from the live client (client.url) so we hit the actual daemon port, not the configured default.
  • update_mode is set on the per-item dict; Hindsight.aretain_batch already threads item['update_mode'] through.

Test plan

  • uv run pytest tests/plugins/memory/test_hindsight_provider.py tests/agent/test_memory_session_switch.py108/108 passed.
  • New TestUpdateModeAppendCapability (5 cases): legacy fallback, modern stable+append, per-URL cache, one-time WARN, flush-on-switch resolves against the OLD session.

End-to-end against installed ~/.hermes/hermes-agent

unreachable API (legacy fallback) live hindsight-embed 0.5.6
document_id legacy-session-20260505_144153_663958 modern-session
item.update_mode None (not set) "append"

test_hermes_embedded_smoke.py passes in 90s.

…cross 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 (NousResearch#6654) keeps working unchanged on legacy servers.

Closes the dedup half of NousResearch#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).
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins tool/memory Memory tool and memory providers labels May 5, 2026
@teknium1
teknium1 merged commit 3082fa0 into NousResearch:main May 5, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have tool/memory Memory tool and memory providers type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants