feat(memory): retrieve-inject long-term memory at turn start (closes #154) - #156
Open
dahai80 wants to merge 1 commit into
Open
feat(memory): retrieve-inject long-term memory at turn start (closes #154)#156dahai80 wants to merge 1 commit into
dahai80 wants to merge 1 commit into
Conversation
Closes #154. Completes the retrieve half deferred by #151 (which landed turn-end commit only). fusion-cowork #68 and fusion-agent-studio #247 already have both commit+retrieve; this brings fusion-code to parity. ## What At main-agent turn start (processUserInput), recall relevant cross-session memory from fusion-memory (fm-server) and inject it as an attachment message on the same path as UserPromptSubmit hook additionalContext. The agent now starts each turn with relevant prior context, not stateless. ## How - src/services/memory/retrieveContext.ts (new) — retrieveMemorySection(): calls the existing retrieveContext RPC + formatContextToPrompt (both added by #151 but unwired), returns a <fusion_memory_context> section string or . Main-agent guard (!agentId), fail-empty (logForDebugging, never throws). Env override: FUSION_MEMORY_RETRIEVE_TOP_K / FUSION_MEMORY_RETRIEVE_BUDGET. - src/utils/processUserInput/processUserInput.ts (edit) — after UserPromptSubmit hooks, on the happy path with real input and !context.agentId, fire-and-forget retrieveMemorySection and push the section as a hook_additional_context attachment message. Mirrors the existing hook additionalContext push. Skips silently if fm-server down or FUSION_MEMORY_API_KEY unset. ## Degradation fm-server down / FUSION_MEMORY_API_KEY unset / no memory matched -> section is empty, nothing injected, debug log only. Never blocks the main loop. 100% offline — HTTP only to 127.0.0.1. ## Tests 10 tests in retrieveContext.test.ts (subagent skip, empty input, success format, RPC error, HTTP non-2xx, fetch throw, missing API key, no-match, top_k env override, invalid env fallback). Full memory suite 25 pass, bun run build green.
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.
Closes #154. Completes the retrieve half deferred by #151 (which landed turn-end commit only). fusion-cowork #68 and fusion-agent-studio #247 already have both commit+retrieve; this brings fusion-code to parity.
What
At main-agent turn start (
processUserInput), recall relevant cross-session memory from fusion-memory (fm-server) and inject it as an attachment message on the same path asUserPromptSubmithookadditionalContext. The agent starts each turn with relevant prior context, not stateless.Why now
#151 deliberately wired only the commit half — its body noted the subagent spawn path (
AgentTool.tsx) was the wrong injection seam for retrieve and deferred the correct main-agent seam to a follow-up issue (#154). The correct seam is the user-input processing path (processUserInput), which runs per-turn for the main conversational agent and already collectsadditionalContextfromUserPromptSubmithooks. This PR injects memory there.How
src/services/memory/retrieveContext.ts(new) —retrieveMemorySection(): calls the existingretrieveContextRPC +formatContextToPrompt(both added by feat(memory): integrate fusion-memory long-term memory commit #151 but unwired), returns a<fusion_memory_context>section string or"". Main-agent guard (!agentId), fail-empty (logForDebugging, never throws). Env override:FUSION_MEMORY_RETRIEVE_TOP_K(default 10) /FUSION_MEMORY_RETRIEVE_BUDGET(default 4096).src/utils/processUserInput/processUserInput.ts(edit) — afterUserPromptSubmithooks, on the happy path (result.shouldQuery) with real input and!context.agentId, fire-and-forgetretrieveMemorySectionand push the section as ahook_additional_contextattachment message. Mirrors the existing hookadditionalContextpush. Lazy-requirethe module (same pattern as feat(memory): integrate fusion-memory long-term memory commit #151's stopHooks) to avoid circular deps.Wire contract (already implemented in fm-server)
JSON-RPC 2.0:
retrieve->{blocks: ContextBlock[], total_tokens: number}. HTTPPOST /v1/memory/retrieve(Bearer auth). Full contract:fusion-memory/clients/README.md.Degradation
fm-server down /
FUSION_MEMORY_API_KEYunset / no memory matched -> section is empty, nothing injected, debug log only. Never blocks the main loop. 100% offline — HTTP only to127.0.0.1.Config (operator env, same as #151)
FUSION_MEMORY_BASE_URLhttp://127.0.0.1:11440FUSION_MEMORY_API_KEYFUSION_MEMORY_RETRIEVE_TOP_K10FUSION_MEMORY_RETRIEVE_BUDGET4096Tests
10 tests in
retrieveContext.test.ts(subagent skip, empty input, success format, RPC error, HTTP non-2xx, fetch throw, missing API key, no-match, top_k env override, invalid env fallback). Full memory suite 25 pass,bun run buildgreen (verified against current main incl. #155).Scope
src/services/memory/{retrieveContext,retrieveContext.test}.tssrc/utils/processUserInput/processUserInput.ts(import + inject block, lazy-require module)