@@ -8,8 +8,11 @@ import { useLanguage } from "@/context/language"
88import { usePermission } from "@/context/permission"
99import { useSDK } from "@/context/sdk"
1010import { useSync } from "@/context/sync"
11+ import { todoState } from "./session-composer-helpers"
1112import { sessionPermissionRequest , sessionQuestionRequest } from "./session-request-tree"
1213
14+ const idle = { type : "idle" as const }
15+
1316export function createSessionComposerBlocked ( ) {
1417 const params = useParams ( )
1518 const permission = usePermission ( )
@@ -59,9 +62,22 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
5962 return globalSync . data . session_todo [ id ] ?? [ ]
6063 } )
6164
65+ const done = createMemo (
66+ ( ) => todos ( ) . length > 0 && todos ( ) . every ( ( todo ) => todo . status === "completed" || todo . status === "cancelled" ) ,
67+ )
68+
69+ const status = createMemo ( ( ) => {
70+ const id = params . id
71+ if ( ! id ) return idle
72+ return sync . data . session_status [ id ] ?? idle
73+ } )
74+
75+ const busy = createMemo ( ( ) => status ( ) . type !== "idle" )
76+ const live = createMemo ( ( ) => busy ( ) || blocked ( ) )
77+
6278 const [ store , setStore ] = createStore ( {
6379 responding : undefined as string | undefined ,
64- dock : todos ( ) . length > 0 ,
80+ dock : todos ( ) . length > 0 && live ( ) ,
6581 closing : false ,
6682 opening : false ,
6783 } )
@@ -89,10 +105,6 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
89105 } )
90106 }
91107
92- const done = createMemo (
93- ( ) => todos ( ) . length > 0 && todos ( ) . every ( ( todo ) => todo . status === "completed" || todo . status === "cancelled" ) ,
94- )
95-
96108 let timer : number | undefined
97109 let raf : number | undefined
98110
@@ -111,21 +123,42 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
111123 } , closeMs ( ) )
112124 }
113125
126+ // Keep stale turn todos from reopening if the model never clears them.
127+ const clear = ( ) => {
128+ const id = params . id
129+ if ( ! id ) return
130+ globalSync . todo . set ( id , [ ] )
131+ sync . set ( "todo" , id , [ ] )
132+ }
133+
114134 createEffect (
115135 on (
116- ( ) => [ todos ( ) . length , done ( ) ] as const ,
117- ( [ count , complete ] , prev ) => {
136+ ( ) => [ todos ( ) . length , done ( ) , live ( ) ] as const ,
137+ ( [ count , complete , active ] ) => {
118138 if ( raf ) cancelAnimationFrame ( raf )
119139 raf = undefined
120140
121- if ( count === 0 ) {
141+ const next = todoState ( {
142+ count,
143+ done : complete ,
144+ live : active ,
145+ } )
146+
147+ if ( next === "hide" ) {
122148 if ( timer ) window . clearTimeout ( timer )
123149 timer = undefined
124150 setStore ( { dock : false , closing : false , opening : false } )
125151 return
126152 }
127153
128- if ( ! complete ) {
154+ if ( next === "clear" ) {
155+ if ( timer ) window . clearTimeout ( timer )
156+ timer = undefined
157+ clear ( )
158+ return
159+ }
160+
161+ if ( next === "open" ) {
129162 if ( timer ) window . clearTimeout ( timer )
130163 timer = undefined
131164 const hidden = ! store . dock || store . closing
@@ -142,13 +175,8 @@ export function createSessionComposerState(options?: { closeMs?: number | (() =>
142175 return
143176 }
144177
145- if ( prev && prev [ 1 ] ) {
146- if ( store . closing && ! timer ) scheduleClose ( )
147- return
148- }
149-
150178 setStore ( { dock : true , opening : false , closing : true } )
151- scheduleClose ( )
179+ if ( ! timer ) scheduleClose ( )
152180 } ,
153181 ) ,
154182 )
0 commit comments