@@ -578,7 +578,16 @@ export function deriveWorkLogEntries(
578578) : WorkLogEntry [ ] {
579579 const isSessionRunning = options ?. isSessionRunning ?? false ;
580580 const provider = options ?. provider ;
581- const ordered = [ ...activities ] . toSorted ( compareActivitiesByOrder ) ;
581+ const cacheKey = `${ latestTurnId ?? "" } \x1f${ isSessionRunning ? "1" : "0" } \x1f${ provider ?? "" } ` ;
582+ const cachedByKey = workLogEntriesCache . get ( activities ) ;
583+ const cached = cachedByKey ?. get ( cacheKey ) ;
584+ if ( cached ) {
585+ return cached ;
586+ }
587+ const relevantActivities = latestTurnId
588+ ? activities . filter ( ( activity ) => activity . turnId === latestTurnId )
589+ : activities ;
590+ const ordered = [ ...relevantActivities ] . toSorted ( compareActivitiesByOrder ) ;
582591
583592 const previousPlanStepsByActivityId = new Map < string , PlanStep [ ] | null > ( ) ;
584593 let runningPreviousPlanSteps : PlanStep [ ] | null = null ;
@@ -599,7 +608,6 @@ export function deriveWorkLogEntries(
599608 const collabToolDataUnkeyed : SubagentCollabToolData [ ] = [ ] ;
600609 const collabToolItemIds = new Set < string > ( ) ;
601610 for ( const activity of ordered ) {
602- if ( latestTurnId && activity . turnId !== latestTurnId ) continue ;
603611 if ( activity . kind === "tool.started" ) {
604612 const payload = asRecord ( activity . payload ) ;
605613 if ( payload ?. itemType === "collab_agent_tool_call" ) {
@@ -628,7 +636,6 @@ export function deriveWorkLogEntries(
628636 const nestedTaskIds = new Set < string > ( ) ;
629637 for ( const activity of ordered ) {
630638 if ( activity . kind !== "task.started" ) continue ;
631- if ( latestTurnId && activity . turnId !== latestTurnId ) continue ;
632639 const payload = asRecord ( activity . payload ) ;
633640 const taskId = asTrimmedString ( payload ?. taskId ) ;
634641 if ( ! taskId ) continue ;
@@ -641,7 +648,6 @@ export function deriveWorkLogEntries(
641648 }
642649
643650 const filtered = ordered
644- . filter ( ( activity ) => ( latestTurnId ? activity . turnId === latestTurnId : true ) )
645651 . filter (
646652 ( activity ) =>
647653 activity . kind !== "tool.started" ||
@@ -756,11 +762,22 @@ export function deriveWorkLogEntries(
756762 entries . push ( toDerivedWorkLogEntry ( activity , previousPlanSteps ) ) ;
757763 }
758764
759- return deduplicateToolLifecycleEntries ( collapseDerivedWorkLogEntries ( entries ) ) . map (
765+ const result = deduplicateToolLifecycleEntries ( collapseDerivedWorkLogEntries ( entries ) ) . map (
760766 ( { activityKind : _activityKind , collapseKey : _collapseKey , ...entry } ) => entry ,
761767 ) ;
768+ const nextCachedByKey = cachedByKey ?? new Map < string , WorkLogEntry [ ] > ( ) ;
769+ nextCachedByKey . set ( cacheKey , result ) ;
770+ if ( ! cachedByKey ) {
771+ workLogEntriesCache . set ( activities , nextCachedByKey ) ;
772+ }
773+ return result ;
762774}
763775
776+ const workLogEntriesCache = new WeakMap <
777+ ReadonlyArray < OrchestrationThreadActivity > ,
778+ Map < string , WorkLogEntry [ ] >
779+ > ( ) ;
780+
764781function isPlanBoundaryToolActivity ( activity : OrchestrationThreadActivity ) : boolean {
765782 if ( activity . kind !== "tool.updated" && activity . kind !== "tool.completed" ) {
766783 return false ;
@@ -1066,6 +1083,12 @@ function toDerivedWorkLogEntry(
10661083 activity : OrchestrationThreadActivity ,
10671084 previousPlanSteps : PlanStep [ ] | null = null ,
10681085) : DerivedWorkLogEntry {
1086+ if ( previousPlanSteps === null ) {
1087+ const cached = derivedWorkLogEntryCache . get ( activity ) ;
1088+ if ( cached ) {
1089+ return cached ;
1090+ }
1091+ }
10691092 const payload =
10701093 activity . payload && typeof activity . payload === "object"
10711094 ? ( activity . payload as Record < string , unknown > )
@@ -1189,9 +1212,14 @@ function toDerivedWorkLogEntry(
11891212 if ( collapseKey ) {
11901213 entry . collapseKey = collapseKey ;
11911214 }
1215+ if ( previousPlanSteps === null ) {
1216+ derivedWorkLogEntryCache . set ( activity , entry ) ;
1217+ }
11921218 return entry ;
11931219}
11941220
1221+ const derivedWorkLogEntryCache = new WeakMap < OrchestrationThreadActivity , DerivedWorkLogEntry > ( ) ;
1222+
11951223function collapseDerivedWorkLogEntries (
11961224 entries : ReadonlyArray < DerivedWorkLogEntry > ,
11971225) : DerivedWorkLogEntry [ ] {
@@ -1963,6 +1991,12 @@ export function deriveTimelineEntries(
19631991 proposedPlans : ProposedPlan [ ] ,
19641992 workEntries : WorkLogEntry [ ] ,
19651993) : TimelineEntry [ ] {
1994+ const cachedByProposedPlans = timelineEntriesCache . get ( messages ) ;
1995+ const cachedByWorkEntries = cachedByProposedPlans ?. get ( proposedPlans ) ;
1996+ const cached = cachedByWorkEntries ?. get ( workEntries ) ;
1997+ if ( cached ) {
1998+ return cached ;
1999+ }
19662000 const messageRows : TimelineEntry [ ] = messages . map ( ( message ) => ( {
19672001 id : message . id ,
19682002 kind : "message" ,
@@ -1981,11 +2015,29 @@ export function deriveTimelineEntries(
19812015 createdAt : entry . createdAt ,
19822016 entry,
19832017 } ) ) ;
1984- return [ ...messageRows , ...proposedPlanRows , ...workRows ] . toSorted ( ( a , b ) =>
2018+ const result = [ ...messageRows , ...proposedPlanRows , ...workRows ] . toSorted ( ( a , b ) =>
19852019 a . createdAt . localeCompare ( b . createdAt ) ,
19862020 ) ;
2021+ const nextCachedByProposedPlans =
2022+ cachedByProposedPlans ??
2023+ new WeakMap < ProposedPlan [ ] , WeakMap < WorkLogEntry [ ] , TimelineEntry [ ] > > ( ) ;
2024+ const nextCachedByWorkEntries =
2025+ cachedByWorkEntries ?? new WeakMap < WorkLogEntry [ ] , TimelineEntry [ ] > ( ) ;
2026+ nextCachedByWorkEntries . set ( workEntries , result ) ;
2027+ if ( ! cachedByWorkEntries ) {
2028+ nextCachedByProposedPlans . set ( proposedPlans , nextCachedByWorkEntries ) ;
2029+ }
2030+ if ( ! cachedByProposedPlans ) {
2031+ timelineEntriesCache . set ( messages , nextCachedByProposedPlans ) ;
2032+ }
2033+ return result ;
19872034}
19882035
2036+ const timelineEntriesCache = new WeakMap <
2037+ ChatMessage [ ] ,
2038+ WeakMap < ProposedPlan [ ] , WeakMap < WorkLogEntry [ ] , TimelineEntry [ ] > >
2039+ > ( ) ;
2040+
19892041export function inferCheckpointTurnCountByTurnId (
19902042 summaries : TurnDiffSummary [ ] ,
19912043) : Record < TurnId , number > {
0 commit comments