@@ -15,6 +15,7 @@ import {
1515 type SessionsCleanupOptions ,
1616 type SessionsCleanupResult ,
1717} from "../config/sessions.js" ;
18+ import { resolveSqliteTargetFromSessionStorePath } from "../config/sessions/session-sqlite-target.js" ;
1819import type { OpenClawConfig } from "../config/types.openclaw.js" ;
1920import { callGateway , isGatewayTransportError } from "../gateway/call.js" ;
2021import { type RuntimeEnv , writeRuntimeJson } from "../runtime.js" ;
@@ -141,6 +142,15 @@ function renderLabelSummaries(params: {
141142 params . runtime . log ( `Total: ${ totalKept } kept, ${ totalPruned } pruned` ) ;
142143}
143144
145+ function toDisplayedCleanupSummary ( summary : SessionCleanupSummary ) : SessionCleanupSummary {
146+ return {
147+ ...summary ,
148+ storePath : resolveSqliteTargetFromSessionStorePath ( summary . storePath , {
149+ agentId : summary . agentId ,
150+ } ) . path ,
151+ } ;
152+ }
153+
144154function renderStoreDryRunPlan ( params : {
145155 cfg : OpenClawConfig ;
146156 summary : SessionCleanupSummary ;
@@ -149,10 +159,11 @@ function renderStoreDryRunPlan(params: {
149159 showAgentHeader : boolean ;
150160} ) {
151161 const rich = isRich ( ) ;
162+ const displaySummary = toDisplayedCleanupSummary ( params . summary ) ;
152163 if ( params . showAgentHeader ) {
153164 params . runtime . log ( `Agent: ${ params . summary . agentId } ` ) ;
154165 }
155- params . runtime . log ( `Session store: ${ params . summary . storePath } ` ) ;
166+ params . runtime . log ( `Session store: ${ displaySummary . storePath } ` ) ;
156167 params . runtime . log ( `Maintenance mode: ${ params . summary . mode } ` ) ;
157168 params . runtime . log (
158169 `Entries: ${ params . summary . beforeCount } -> ${ params . summary . afterCount } (remove ${ params . summary . beforeCount - params . summary . afterCount } )` ,
@@ -202,6 +213,7 @@ function renderStoreDryRunPlan(params: {
202213function renderAppliedSummaries ( params : {
203214 summaries : SessionCleanupSummary [ ] ;
204215 runtime : RuntimeEnv ;
216+ locallyOwned : boolean ;
205217} ) {
206218 for ( let i = 0 ; i < params . summaries . length ; i += 1 ) {
207219 const summary = params . summaries [ i ] ;
@@ -214,7 +226,10 @@ function renderAppliedSummaries(params: {
214226 if ( params . summaries . length > 1 ) {
215227 params . runtime . log ( `Agent: ${ summary . agentId } ` ) ;
216228 }
217- params . runtime . log ( `Session store: ${ summary . storePath } ` ) ;
229+ const storePath = params . locallyOwned
230+ ? toDisplayedCleanupSummary ( summary ) . storePath
231+ : summary . storePath ;
232+ params . runtime . log ( `Session store: ${ storePath } ` ) ;
218233 params . runtime . log ( `Applied maintenance. Current entries: ${ summary . appliedCount ?? 0 } ` ) ;
219234 if ( summary . unreferencedArtifacts ?. removedFiles ) {
220235 params . runtime . log (
@@ -226,14 +241,14 @@ function renderAppliedSummaries(params: {
226241
227242async function maybeRunGatewayCleanup (
228243 opts : SessionsCleanupOptions ,
229- ) : Promise < SessionsCleanupResult | null > {
244+ ) : Promise < { delegated : true ; result : SessionsCleanupResult } | { delegated : false } > {
230245 if ( opts . store || opts . dryRun ) {
231246 // Explicit store paths and dry-runs must stay local; the gateway only owns
232247 // live in-process cleanup for default stores.
233- return null ;
248+ return { delegated : false } ;
234249 }
235250 try {
236- return await callGateway < SessionsCleanupResult > ( {
251+ const result = await callGateway < SessionsCleanupResult > ( {
237252 method : "sessions.cleanup" ,
238253 params : {
239254 agent : opts . agent ,
@@ -247,27 +262,32 @@ async function maybeRunGatewayCleanup(
247262 clientName : GATEWAY_CLIENT_NAMES . CLI ,
248263 requiredMethods : [ "sessions.cleanup" ] ,
249264 } ) ;
265+ return { delegated : true , result } ;
250266 } catch ( error ) {
251267 if ( isGatewayTransportError ( error ) ) {
252268 // A stopped gateway should not block local maintenance; fall back to the
253269 // on-disk session stores when transport is unavailable.
254- return null ;
270+ return { delegated : false } ;
255271 }
256272 throw error ;
257273 }
258274}
259275
260276/** Runs session cleanup, optionally using the live gateway for active stores. */
261277export async function sessionsCleanupCommand ( opts : SessionsCleanupOptions , runtime : RuntimeEnv ) {
262- const gatewayResult = await maybeRunGatewayCleanup ( opts ) ;
263- if ( gatewayResult ) {
278+ const gatewayCleanup = await maybeRunGatewayCleanup ( opts ) ;
279+ if ( gatewayCleanup . delegated ) {
280+ // The Gateway owns this path. Preserve its syntax because resolving a remote
281+ // Windows path on a POSIX client (or vice versa) would fabricate a local path.
264282 if ( opts . json ) {
265- writeRuntimeJson ( runtime , gatewayResult ) ;
283+ writeRuntimeJson ( runtime , gatewayCleanup . result ) ;
266284 return ;
267285 }
268286 renderAppliedSummaries ( {
269- summaries : "stores" in gatewayResult ? gatewayResult . stores : [ gatewayResult ] ,
287+ summaries :
288+ "stores" in gatewayCleanup . result ? gatewayCleanup . result . stores : [ gatewayCleanup . result ] ,
270289 runtime,
290+ locallyOwned : false ,
271291 } ) ;
272292 return ;
273293 }
@@ -298,7 +318,7 @@ export async function sessionsCleanupCommand(opts: SessionsCleanupOptions, runti
298318 serializeSessionCleanupResult ( {
299319 mode,
300320 dryRun : true ,
301- summaries : previewResults . map ( ( result ) => result . summary ) ,
321+ summaries : previewResults . map ( ( result ) => toDisplayedCleanupSummary ( result . summary ) ) ,
302322 } ) ,
303323 ) ;
304324 return ;
@@ -325,11 +345,11 @@ export async function sessionsCleanupCommand(opts: SessionsCleanupOptions, runti
325345 serializeSessionCleanupResult ( {
326346 mode,
327347 dryRun : false ,
328- summaries : appliedSummaries ,
348+ summaries : appliedSummaries . map ( toDisplayedCleanupSummary ) ,
329349 } ) ,
330350 ) ;
331351 return ;
332352 }
333353
334- renderAppliedSummaries ( { summaries : appliedSummaries , runtime } ) ;
354+ renderAppliedSummaries ( { summaries : appliedSummaries , runtime, locallyOwned : true } ) ;
335355}
0 commit comments