@@ -83,7 +83,7 @@ import {
8383 buildSubagentSystemPrompt ,
8484 callGateway ,
8585 emitSessionLifecycleEvent ,
86- forkSessionFromParent ,
86+ forkSessionEntryFromParent ,
8787 getGlobalHookRunner ,
8888 getSessionBindingService ,
8989 getRuntimeConfig ,
@@ -128,7 +128,7 @@ function resolveConfiguredAgentIds(cfg: OpenClawConfig): string[] {
128128
129129type SubagentSpawnDeps = {
130130 callGateway : typeof callGateway ;
131- forkSessionFromParent : typeof forkSessionFromParent ;
131+ forkSessionEntryFromParent : typeof forkSessionEntryFromParent ;
132132 getGlobalHookRunner : ( ) => SubagentLifecycleHookRunner | null ;
133133 getRuntimeConfig : typeof getRuntimeConfig ;
134134 ensureContextEnginesInitialized : typeof ensureContextEnginesInitialized ;
@@ -139,7 +139,7 @@ type SubagentSpawnDeps = {
139139
140140const defaultSubagentSpawnDeps : SubagentSpawnDeps = {
141141 callGateway,
142- forkSessionFromParent ,
142+ forkSessionEntryFromParent ,
143143 getGlobalHookRunner,
144144 getRuntimeConfig,
145145 ensureContextEnginesInitialized,
@@ -474,52 +474,47 @@ async function prepareSubagentSessionContext(params: {
474474 const sessionsDir = path . dirname ( parentTarget . storePath ) ;
475475
476476 try {
477- const forked = ( await updateSubagentSessionStore ( childTarget . storePath , async ( store ) => {
478- parentEntry = resolveStoreEntryByKeys ( store , parentTarget . storeKeys ) ;
479- childEntry = resolveStoreEntryByKeys ( store , childTarget . storeKeys ) ;
480-
481- if ( params . targetAgentId !== params . requesterAgentId ) {
482- throw new Error (
483- 'context="fork" currently requires the same target agent as the requester; use context="isolated" for cross-agent spawns.' ,
484- ) ;
485- }
486- if ( ! parentEntry ?. sessionId ) {
487- throw new Error (
488- 'context="fork" requested but the requester session transcript is not available.' ,
489- ) ;
490- }
491- const forkDecision = await subagentSpawnDeps . resolveParentForkDecision ( {
492- parentEntry,
493- storePath : parentTarget . storePath ,
494- } ) ;
495- if ( forkDecision . status === "skip" ) {
496- forkFallbackNote = forkDecision . message ;
497- return null ;
498- }
477+ if ( params . targetAgentId !== params . requesterAgentId ) {
478+ throw new Error (
479+ 'context="fork" currently requires the same target agent as the requester; use context="isolated" for cross-agent spawns.' ,
480+ ) ;
481+ }
499482
500- const fork = await subagentSpawnDeps . forkSessionFromParent ( {
501- parentEntry,
502- agentId : params . requesterAgentId ,
503- sessionsDir,
504- } ) ;
505- if ( ! fork ) {
506- throw new Error (
507- 'context="fork" requested but OpenClaw could not fork the requester transcript.' ,
508- ) ;
509- }
510- pruneLegacyStoreKeys ( {
511- store,
512- canonicalKey : childTarget . canonicalKey ,
513- candidates : childTarget . storeKeys ,
514- } ) ;
515- store [ childTarget . canonicalKey ] = mergeSessionEntry ( store [ childTarget . canonicalKey ] , {
516- sessionId : fork . sessionId ,
517- sessionFile : fork . sessionFile ,
518- forkedFromParent : true ,
519- } ) ;
520- childEntry = store [ childTarget . canonicalKey ] ;
521- return fork ;
522- } ) ) as { sessionId : string ; sessionFile : string } | null ;
483+ const forkedResult = await subagentSpawnDeps . forkSessionEntryFromParent ( {
484+ storePath : childTarget . storePath ,
485+ parentSessionKey : parentTarget . canonicalKey ,
486+ parentStoreKeys : parentTarget . storeKeys ,
487+ sessionKey : childTarget . canonicalKey ,
488+ sessionStoreKeys : childTarget . storeKeys ,
489+ fallbackEntry : { sessionId : "" , updatedAt : Date . now ( ) } ,
490+ agentId : params . requesterAgentId ,
491+ sessionsDir,
492+ } ) ;
493+ if ( forkedResult . status === "missing-parent" ) {
494+ throw new Error (
495+ 'context="fork" requested but the requester session transcript is not available.' ,
496+ ) ;
497+ }
498+ if ( forkedResult . status === "failed" || forkedResult . status === "missing-entry" ) {
499+ throw new Error (
500+ 'context="fork" requested but OpenClaw could not fork the requester transcript.' ,
501+ ) ;
502+ }
503+ parentEntry = forkedResult . parentEntry ;
504+ childEntry = forkedResult . sessionEntry ;
505+ if ( forkedResult . status === "skipped" ) {
506+ forkFallbackNote = forkedResult . decision ?. status === "skip" ? forkedResult . decision . message : undefined ;
507+ }
508+ if ( forkedResult . status === "forked" ) {
509+ childEntry = forkedResult . sessionEntry ;
510+ }
511+ const forked =
512+ forkedResult . status === "forked"
513+ ? {
514+ sessionId : forkedResult . fork . sessionId ,
515+ sessionFile : forkedResult . fork . sessionFile ,
516+ }
517+ : null ;
523518
524519 if ( params . contextMode === "fork" ) {
525520 if ( ! parentEntry || ! forked ) {
0 commit comments