11import type { Plugin } from "@opencode-ai/plugin"
22import { tool } from "@opencode-ai/plugin"
3+ import { parse , resolve } from "path"
34import { buildMemorySystemPrompt } from "./prompt.js"
45import { formatRecalledMemories , recallSelectedMemories , type RecalledMemory } from "./recall.js"
56import { assertSupportedRecallSelectorClient , selectRelevantMemoryFilenames , type SessionClient } from "./recallSelector.js"
@@ -154,6 +155,16 @@ function getRecallModel(): { providerID: string; modelID: string } | undefined {
154155 }
155156}
156157
158+ function isRootPath ( path : string ) : boolean {
159+ const resolved = resolve ( path )
160+ return resolved === parse ( resolved ) . root
161+ }
162+
163+ function resolveMemoryRoot ( worktree : string , directory : string ) : string {
164+ if ( isRootPath ( worktree ) && ! isRootPath ( directory ) ) return directory
165+ return worktree
166+ }
167+
157168function isUsefulRecallQuery ( query : string | undefined ) : query is string {
158169 const trimmed = query ?. trim ( )
159170 if ( ! trimmed ) return false
@@ -283,7 +294,8 @@ function getCallID(ctx: unknown): string | undefined {
283294
284295export const MemoryPlugin : Plugin = async ( { worktree, directory, client } ) => {
285296 directory ??= worktree
286- getMemoryDir ( worktree )
297+ const memoryRoot = resolveMemoryRoot ( worktree , directory )
298+ getMemoryDir ( memoryRoot )
287299
288300 return {
289301 config : async ( config ) => {
@@ -348,7 +360,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
348360 : startRecallPrefetch ( {
349361 client : client as unknown as SessionClient ,
350362 directory,
351- worktree,
363+ worktree : memoryRoot ,
352364 parentSessionID : sessionID ,
353365 turnID,
354366 query,
@@ -389,7 +401,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
389401 const recalled = ignoreMemoryContext ? [ ] : consumeRecallPrefetch ( ctx )
390402
391403 const recalledSection = formatRecalledMemories ( recalled )
392- const memoryPrompt = buildMemorySystemPrompt ( worktree , recalledSection , {
404+ const memoryPrompt = buildMemorySystemPrompt ( memoryRoot , recalledSection , {
393405 includeIndex : ! ignoreMemoryContext ,
394406 } )
395407 output . system . push ( memoryPrompt )
@@ -426,7 +438,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
426438 ) ,
427439 } ,
428440 async execute ( args , _ctx ) {
429- const filePath = saveMemory ( worktree , args . file_name , args . name , args . description , args . type , args . content )
441+ const filePath = saveMemory ( memoryRoot , args . file_name , args . name , args . description , args . type , args . content )
430442 return `Memory saved to ${ filePath } `
431443 } ,
432444 } ) ,
@@ -437,7 +449,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
437449 file_name : tool . schema . string ( ) . describe ( "File name of the memory to delete (with or without .md extension)" ) ,
438450 } ,
439451 async execute ( args , _ctx ) {
440- const deleted = deleteMemory ( worktree , args . file_name )
452+ const deleted = deleteMemory ( memoryRoot , args . file_name )
441453 return deleted ? `Memory "${ args . file_name } " deleted.` : `Memory "${ args . file_name } " not found.`
442454 } ,
443455 } ) ,
@@ -449,7 +461,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
449461 "or when you need to recall what's been stored." ,
450462 args : { } ,
451463 async execute ( _args , ctx ) {
452- const entries = listMemories ( worktree )
464+ const entries = listMemories ( memoryRoot )
453465 const callID = getCallID ( ctx )
454466 if ( callID ) memoryListCountByCallID . set ( callID , entries . length )
455467 if ( entries . length === 0 ) {
@@ -470,7 +482,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
470482 query : tool . schema . string ( ) . describe ( "Search query — searches across name, description, and content" ) ,
471483 } ,
472484 async execute ( args , ctx ) {
473- const results = searchMemories ( worktree , args . query )
485+ const results = searchMemories ( memoryRoot , args . query )
474486 const callID = getCallID ( ctx )
475487 if ( callID ) memorySearchCountByCallID . set ( callID , results . length )
476488 if ( results . length === 0 ) {
@@ -489,7 +501,7 @@ export const MemoryPlugin: Plugin = async ({ worktree, directory, client }) => {
489501 file_name : tool . schema . string ( ) . describe ( "File name of the memory to read (with or without .md extension)" ) ,
490502 } ,
491503 async execute ( args , _ctx ) {
492- const entry = readMemory ( worktree , args . file_name )
504+ const entry = readMemory ( memoryRoot , args . file_name )
493505 if ( ! entry ) {
494506 return `Memory "${ args . file_name } " not found.`
495507 }
0 commit comments