feat(opencode): enhance recall/retain config and memory instructions#2340
feat(opencode): enhance recall/retain config and memory instructions#2340sdrobov wants to merge 3 commits into
Conversation
|
This PR improves memory utilization in OpenCode by making memory retrieval and retention happen more proactively. I validated the changes through practical usage and observed that OpenCode uses memory significantly more often and in more relevant situations. The agent is noticeably better at recalling previously learned information and applying it during subsequent interactions. One of the main goals was to improve memory effectiveness without increasing context overhead. In my testing, token consumption remained nearly unchanged while memory usage became substantially more productive. The implementation is heavily inspired by the memory system used in Hermes Agent. In particular, the overall retrieval/retention strategy and the motivational tool instructions were adapted from mechanisms that have already proven effective in practice. The idea is to encourage the model to treat memory as an active problem-solving resource rather than a passive storage system. Given Hindsight's focus on helping agents learn over time rather than simply storing information, I believe these changes align well with the project's goals and improve the real-world usefulness of memory-enabled agents. |
|
I reproduced the failing Running Prettier on the integration rewrites only:
The diff is long-line wrapping, indentation in string concatenation, and adding the final newline. After applying that formatter output, these passed for me: npx --yes prettier --check --config "$PWD/.prettierrc.json" --ignore-path "$PWD/.gitignore" hindsight-integrations/opencode
cd hindsight-integrations/opencode
npm test -- --run src/hooks.test.ts src/config.test.ts src/content.test.ts src/plugin.test.tsResult: |
|
@koriyoshi2041 thank you so much for the explanation. I guess it was a mistake to create this PR at night, because my mind wasn't working as well and I couldn't figure out why the tests were failing. I fixed the formatting, and now everything is fine. |
nicoloboschi
left a comment
There was a problem hiding this comment.
Reviewed the full diff, the source on the branch, and ran the suite. Direction is reasonable and the changed-surface tests pass, but there are three correctness bugs in the new every-turn retain path plus a design issue with the prefetch that I'd resolve before merge.
Must fix
1. Off-by-one turn pairing in retainTurn (correctness) — hooks.ts:526-535
experimental.chat.system.transform fires before the assistant generates its reply to the current user message. At that point messages = […, asst(N-1), userN]. The code pairs lastUserMsg (= userN, current/unanswered) with lastAssistantMsg (= asst(N-1), the previous answer), so every retained "turn" mismatches the current question with the previous answer. This corrupts the conversational structure fact extraction relies on. Retaining from system.transform is structurally wrong — the assistant response doesn't exist yet. This belongs on a post-response event (e.g. session.idle / message-completed), not the system-prompt transform.
2. sessionTurns buffer is never cleared after a retain — hooks.ts:275-306
retainTurn pushes to the buffer and then sends the entire accumulated buffer every time (content = "[" + turns.join(",") + "]") into a new documentId (${sessionId}-turn-${turnNum}). With the new default retainEveryNTurns: 1, turn 2 sends [t2], turn 3 [t2,t3], turn 4 [t2,t3,t4]… so the same early turns get re-extracted into every subsequent document — duplicate facts and redundant async LLM extraction that grows O(n²) over a session. Reset the buffer after a successful flush so each retain sends only the turns since the last one.
3. Three overlapping retain paths run simultaneously
retainTurn (every turn) + handleSessionIdle→retainSession (full window on idle) + pre-compaction retain all persist the same conversation. Combined with #2 this is a lot of duplicate ingestion. Was every-turn retain meant to replace the idle retain? Please make the intended relationship explicit.
Should fix
4. Prefetch serves stale recall and undermines contextual recall — hooks.ts:323-367, 488-521
queueBackgroundPrefetch is called with the current turn's user message but its result is consumed on the next turn (a different message). When the cache hits, the live recall is skipped (if (!cachedContext)), so the injected memories are relevant to the previous question — exactly the staleness contextual recall was meant to fix. After turn 1 nearly every turn takes the stale cached path. Reconsider whether the prefetch earns its complexity, given recall is already awaited inline.
5. Default-value blast radius — config.ts
Recall goes once/session → every turn; recallMaxTokens 1024→4096 (4×), recallContextTurns 1→3, retainEveryNTurns 3→1. Large jump in per-turn injected tokens + recall load + retain volume for everyone on upgrade. Worth a deliberate call on each default and a changelog note.
6. Docs not updated — hindsight-docs/docs-integrations/opencode.md still says retain happens "when the session goes idle" and shows retainEveryNTurns: 3. Behavior and defaults changed; docs should follow.
Nits
- Misleading comment
hooks.ts:492-494("Use only if this entry was created after…") — the code unconditionally deletes and uses the cache; the described guard doesn't exist. - The
<hindsight_memories>…block is now duplicated inrecallForContextandqueueBackgroundPrefetch— extract a helper. - Removed
recallPromptPreambleis fine for OpenCode (not env-backed/not documented there), but the new preamble is a hardcoded English string and ignores any language config. - Tests rely on
setTimeout(100)to await background work — mild CI flakiness risk.
I'd ask for #1–#3 before merge — as written, the every-turn retain path produces mispaired, heavily-duplicated memories.
85e2d54 to
43db6ea
Compare
|
@nicoloboschi Thank you for your feedback. I've simplified the code and fixed the errors and issues. I couldn't figure out why ❯ git tag -l 'integrations/*' | cat | grep eve || echo 'not found'
not found |
|
I checked the
So this should clear by updating the branch from current |
Update default configuration values for the OpenCode integration to improve memory management. Increase `recallMaxTokens` from 1024 to 4096 and `recallContextTurns` from 1 to 3 to allow for richer context retrieval. Add "observation" to recall types and retain every turn instead of every 3 to capture more granular interaction data. Refactor content preparation by removing the `messageCount` return value from `prepareRetentionTranscript`, simplifying the interface. Update the retention context description to be more explicit about the conversation participants. Introduce `buildMemoryInstructions` to generate comprehensive system prompts that guide the LLM on when and how to use memory tools proactively, improving long-term context awareness and user preference retention.
The OpenCode integration documentation has been updated to reflect a shift from session-based memory operations to per-turn operations. - Changed auto-recall to trigger on every turn based on the latest user message, ensuring contextually relevant memories. - Changed auto-retain to trigger after each agent response, capturing even one-shot prompts. - Added new configuration options: `recallMaxTokens`, `recallTypes`, `recallContextTurns`, `retainContext`, and `recallMaxQueryChars`. - Updated environment variable documentation to match new config options. - Added notes regarding API load implications of per-turn operations.
43db6ea to
f653186
Compare
Update default configuration values for the OpenCode integration to improve memory management. Increase
recallMaxTokensfrom 1024 to 4096 andrecallContextTurnsfrom 1 to 3 to allow for richer context retrieval. Add "observation" to recall types and retain every turn instead of every 3 to capture more granular interaction data.Refactor content preparation by removing the
messageCountreturn value fromprepareRetentionTranscript, simplifying the interface. Update the retention context description to be more explicit about the conversation participants.Introduce
buildMemoryInstructionsto generate comprehensive system prompts that guide the LLM on when and how to use memory tools proactively, improving long-term context awareness and user preference retention.