@@ -4,7 +4,11 @@ import {
44 createSubsystemLogger ,
55 type OpenClawConfig ,
66} from "openclaw/plugin-sdk/memory-core-host-engine-foundation" ;
7- import type { MemorySyncProgressUpdate } from "openclaw/plugin-sdk/memory-core-host-engine-storage" ;
7+ import type {
8+ MemorySessionSyncTarget ,
9+ MemorySyncParams ,
10+ MemorySyncProgressUpdate ,
11+ } from "openclaw/plugin-sdk/memory-core-host-engine-storage" ;
812
913const log = createSubsystemLogger ( "memory" ) ;
1014
@@ -21,6 +25,7 @@ export type MemoryReadonlyRecoveryState = {
2125 runSync : ( params ?: {
2226 reason ?: string ;
2327 force ?: boolean ;
28+ sessions ?: MemorySessionSyncTarget [ ] ;
2429 sessionFiles ?: string [ ] ;
2530 progress ?: ( update : MemorySyncProgressUpdate ) => void ;
2631 } ) => Promise < void > ;
@@ -82,12 +87,7 @@ export function extractMemoryErrorReason(err: unknown): string {
8287
8388export async function runMemorySyncWithReadonlyRecovery (
8489 state : MemoryReadonlyRecoveryState ,
85- params ?: {
86- reason ?: string ;
87- force ?: boolean ;
88- sessionFiles ?: string [ ] ;
89- progress ?: ( update : MemorySyncProgressUpdate ) => void ;
90- } ,
90+ params ?: MemorySyncParams ,
9191) : Promise < void > {
9292 try {
9393 await state . runSync ( params ) ;
@@ -123,37 +123,46 @@ export function enqueueMemoryTargetedSessionSync(
123123 isClosed : ( ) => boolean ;
124124 getSyncing : ( ) => Promise < void > | null ;
125125 getQueuedSessionFiles : ( ) => Set < string > ;
126+ getQueuedSessions : ( ) => Map < string , MemorySessionSyncTarget > ;
126127 getQueuedSessionSync : ( ) => Promise < void > | null ;
127128 setQueuedSessionSync : ( value : Promise < void > | null ) => void ;
128- sync : ( params ?: {
129- reason ?: string ;
130- force ?: boolean ;
131- sessionFiles ?: string [ ] ;
132- progress ?: ( update : MemorySyncProgressUpdate ) => void ;
133- } ) => Promise < void > ;
129+ sync : ( params ?: MemorySyncParams ) => Promise < void > ;
134130 } ,
135- sessionFiles ?: string [ ] ,
131+ targets ?: Pick < MemorySyncParams , "sessions" | "sessionFiles" > ,
136132) : Promise < void > {
137133 const queuedSessionFiles = state . getQueuedSessionFiles ( ) ;
138- for ( const sessionFile of sessionFiles ?? [ ] ) {
134+ for ( const sessionFile of targets ?. sessionFiles ?? [ ] ) {
139135 const trimmed = sessionFile . trim ( ) ;
140136 if ( trimmed ) {
141137 queuedSessionFiles . add ( trimmed ) ;
142138 }
143139 }
144- if ( queuedSessionFiles . size === 0 ) {
140+ const queuedSessions = state . getQueuedSessions ( ) ;
141+ for ( const session of targets ?. sessions ?? [ ] ) {
142+ const normalized = normalizeQueuedMemorySessionSyncTarget ( session ) ;
143+ if ( normalized ) {
144+ queuedSessions . set ( memorySessionSyncTargetKey ( normalized ) , normalized ) ;
145+ }
146+ }
147+ if ( queuedSessionFiles . size === 0 && queuedSessions . size === 0 ) {
145148 return state . getSyncing ( ) ?? Promise . resolve ( ) ;
146149 }
147150 if ( ! state . getQueuedSessionSync ( ) ) {
148151 state . setQueuedSessionSync (
149152 ( async ( ) => {
150153 try {
151154 await state . getSyncing ( ) ?. catch ( ( ) => undefined ) ;
152- while ( ! state . isClosed ( ) && state . getQueuedSessionFiles ( ) . size > 0 ) {
155+ while (
156+ ! state . isClosed ( ) &&
157+ ( state . getQueuedSessionFiles ( ) . size > 0 || state . getQueuedSessions ( ) . size > 0 )
158+ ) {
153159 const pendingSessionFiles = Array . from ( state . getQueuedSessionFiles ( ) ) ;
160+ const pendingSessions = Array . from ( state . getQueuedSessions ( ) . values ( ) ) ;
154161 state . getQueuedSessionFiles ( ) . clear ( ) ;
162+ state . getQueuedSessions ( ) . clear ( ) ;
155163 await state . sync ( {
156- reason : "queued-session-files" ,
164+ reason : "queued-sessions" ,
165+ sessions : pendingSessions ,
157166 sessionFiles : pendingSessionFiles ,
158167 } ) ;
159168 }
@@ -166,6 +175,26 @@ export function enqueueMemoryTargetedSessionSync(
166175 return state . getQueuedSessionSync ( ) ?? Promise . resolve ( ) ;
167176}
168177
178+ function normalizeQueuedMemorySessionSyncTarget (
179+ target : MemorySessionSyncTarget ,
180+ ) : MemorySessionSyncTarget | null {
181+ const sessionId = target . sessionId . trim ( ) ;
182+ if ( ! sessionId ) {
183+ return null ;
184+ }
185+ const agentId = target . agentId ?. trim ( ) ;
186+ const sessionKey = target . sessionKey ?. trim ( ) ;
187+ return {
188+ ...( agentId ? { agentId } : { } ) ,
189+ sessionId,
190+ ...( sessionKey ? { sessionKey } : { } ) ,
191+ } ;
192+ }
193+
194+ function memorySessionSyncTargetKey ( target : MemorySessionSyncTarget ) : string {
195+ return [ target . agentId ?? "" , target . sessionId , target . sessionKey ?? "" ] . join ( "\0" ) ;
196+ }
197+
169198export function createMemorySyncControlConfigForTests (
170199 workspaceDir : string ,
171200 indexPath : string ,
0 commit comments