fix(openclaw): migrate example plugin memory search to the v1 POST + Filters DSL API#245
Open
Fearvox wants to merge 1 commit into
Open
Conversation
…Filters DSL API
The example plugin's memory recall never worked against the v1 backend.
searchMemories spoke the v0 dialect on both sides:
- Request: GET /api/v1/memories/search with a flat top-level user_id and a
retrieve_method field. The v1 route is POST-only (GET -> 405); even as POST,
SearchMemoriesRequest requires a Filters DSL object (user_id/group_id must sit
inside `filters`), so a flat top-level user_id -> 422 "Field required: filters";
and the method field is `method`, not `retrieve_method`.
- Response: it read r.result.memories / r.result.pending_messages, but the v1
response is { data: { episodes, profiles, raw_messages, ... } }, so even a
successful call surfaced zero memories.
Migrate searchMemories to the v1 contract end-to-end while preserving its return
shape (parseSearchResponse and the assembler are untouched): build the v1 POST
envelope with filters:{user_id,group_id?} + method, and map data.episodes ->
memories (tagging memory_type so the episodic filter matches) and
data.raw_messages -> pending_messages (flattening content_items to text).
Verified live against EverCore on :1995: old GET -> 405; flat top-level user_id
(POST) -> 422 "Field required: filters"; fixed body (POST + filters + method) ->
200 with "filters_applied":{"user_id":...}; the real searchMemories() driven
end-to-end (method=keyword) returns status:"ok" and maps the response with no
error. Adds offline test/search-memories.test.js (node --test) asserting the v1
request envelope and that the v1 response maps into the caller contract and is
consumable by the existing parseSearchResponse (2 passed).
The v1 demo migration (EverMind-AI#191, PR EverMind-AI#196) covered methods/evermemos/demo/* and docs
but not this example plugin; this finishes that migration for the plugin's search
path. Scope: src/api.js (searchMemories only) + its regression test. saveMemories
is migrated separately as the EverMind-AI#237 fix.
Co-authored-by: CZH-THU <CZH-THU@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The OpenClaw example plugin's memory recall never worked against the v1
backend.
searchMemories(examples/openclaw-plugin/src/api.js) still spoke thev0 dialect on both the request and the response side:
Request — it sent
GET /api/v1/memories/searchwith a flat top-leveluser_idand aretrieve_methodfield. Against the v1 API that fails twice:SearchMemoriesRequestrequires a Filters DSL object(
filtersmust carryuser_id/group_idat the first level), so a flattop-level
user_idreturns 422 "Field required: filters";method, notretrieve_method.Response — it read
r.result.memories/r.result.pending_messages, but thev1 response is
{ data: { episodes, profiles, raw_messages, ... } }. So even asuccessful call surfaced zero memories.
This PR migrates
searchMemoriesto the v1 contract end-to-end while preservingthe function's return shape (so
parseSearchResponseand the assembler areuntouched):
POST+filters: { user_id, group_id? }+method(mapped fromretrieve_method) +query/top_k/memory_types.data.episodes → memories(taggingmemory_type: "episodic_memory"so the downstream episodic filter matches; carryingsummary/episode/subject/score/timestamp), anddata.raw_messages → pending_messages(flatteningcontent_itemsto text).Verification
Live against a running EverCore (
:1995):GET …/search→ 405; flat top-leveluser_id(POST) → 422"Field required: filters".
POST+filters:{user_id}+method) → HTTP 200, withthe response echoing
"filters_applied": {"user_id": "…"}.searchMemories()driven end-to-end against:1995(
method=keyword) returnsstatus: "ok"and maps the response with no error.Offline regression — adds
test/search-memories.test.js(node --test, nolive stack):
POSTwhose body carriesfilters: { user_id }(notop-level
user_id) andmethod(noretrieve_method), with onlybackend-searchable
memory_types;{ data: { episodes, raw_messages } }response and assertsit maps into
{ memories, pending_messages }and that the existingparseSearchResponseconsumes the mapped shape into the expected episodic /pending text.
cd methods/EverCore/examples/openclaw-plugin node --test test/search-memories.test.jsResult: 2 passed.
Scope
Surgical:
src/api.js(searchMemoriesonly) + its new regression test. The v1demo migration (#191, PR #196) covered
methods/evermemos/demo/*and docs butnot this example plugin, so the plugin's search path was left on v0. This PR
finishes that migration for the plugin. Does not touch
saveMemories(shippedseparately as the #237 fix).
Credit
Builds on prior art:
endpoints (the POST
/searchroute this aligns the client to).Co-authored-by: CZH-THU CZH-THU@users.noreply.github.com
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
🤖 Generated with Claude Code