@@ -36,10 +36,11 @@ import {
3636 mergeChannelsStatus ,
3737} from "./channelsSettings.ts" ;
3838import {
39+ getTaskResponseUiState ,
3940 prepareTaskResponse ,
4041 selectTickAfterRefresh ,
4142 startHeartbeatTickPolling ,
42- taskNeedsResponse ,
43+ type TaskResponseRefreshResult ,
4344} from "./operatorUi.ts" ;
4445import { buildExecutionSteps } from "./traceSteps.ts" ;
4546
@@ -3071,6 +3072,7 @@ function DetailPanel({ task, onClose, onRespond, onResume }: any) {
30713072 const [ answerText , setAnswerText ] = useState ( "" ) ;
30723073 const [ responseLoading , setResponseLoading ] = useState ( false ) ;
30733074 const [ responseError , setResponseError ] = useState ( "" ) ;
3075+ const [ responseResult , setResponseResult ] = useState < TaskResponseRefreshResult | null > ( null ) ;
30743076 const [ messages , setMessages ] = useState < any [ ] > ( [ ] ) ;
30753077 const [ events , setEvents ] = useState < any [ ] > ( [ ] ) ;
30763078 const [ showMessages , setShowMessages ] = useState ( false ) ;
@@ -3152,6 +3154,7 @@ function DetailPanel({ task, onClose, onRespond, onResume }: any) {
31523154 setAnswerText ( "" ) ;
31533155 setResponseError ( "" ) ;
31543156 setResponseLoading ( false ) ;
3157+ setResponseResult ( null ) ;
31553158 } , [ task . id , task . question , task . answer ] ) ;
31563159
31573160 const handleResponse = async ( ) => {
@@ -3164,14 +3167,16 @@ function DetailPanel({ task, onClose, onRespond, onResume }: any) {
31643167 setResponseError ( "" ) ;
31653168 setResponseLoading ( true ) ;
31663169 try {
3167- await onRespond ( task . id , prepared . answer ) ;
3170+ const result = await onRespond ( task . id , prepared . answer ) ;
31683171 setAnswerText ( "" ) ;
3172+ setResponseResult ( { refreshed : result ?. refreshed !== false } ) ;
31693173 } catch ( error ) {
31703174 setResponseError ( error instanceof Error ? error . message : "Failed to submit response." ) ;
31713175 } finally {
31723176 setResponseLoading ( false ) ;
31733177 }
31743178 } ;
3179+ const responseUiState = getTaskResponseUiState ( task . question , task . answer , responseResult ) ;
31753180
31763181 const handleResume = async ( ) => {
31773182 if ( ! resumeText . trim ( ) ) return ;
@@ -3296,7 +3301,7 @@ function DetailPanel({ task, onClose, onRespond, onResume }: any) {
32963301 ) }
32973302 </ Section >
32983303
3299- { taskNeedsResponse ( task . question , task . answer ) && (
3304+ { responseUiState !== "hidden" && (
33003305 < Section title = "Agent Question" >
33013306 < div
33023307 style = { {
@@ -3314,46 +3319,68 @@ function DetailPanel({ task, onClose, onRespond, onResume }: any) {
33143319 >
33153320 { task . question }
33163321 </ div >
3317- < textarea
3318- value = { answerText }
3319- onChange = { ( event ) => {
3320- setAnswerText ( event . target . value ) ;
3321- if ( responseError ) setResponseError ( "" ) ;
3322- } }
3323- placeholder = "Enter your answer..."
3324- disabled = { responseLoading }
3325- rows = { 4 }
3326- style = { {
3327- width : "100%" ,
3328- boxSizing : "border-box" ,
3329- background : theme . field ,
3330- color : theme . text ,
3331- border : `1px solid ${ responseError ? theme . red : theme . border } ` ,
3332- borderRadius : 8 ,
3333- padding : 12 ,
3334- fontSize : 12 ,
3335- fontFamily : "'JetBrains Mono', monospace" ,
3336- lineHeight : 1.6 ,
3337- resize : "vertical" ,
3338- outline : "none" ,
3339- } }
3340- />
3341- { responseError && (
3342- < div style = { { color : theme . red , fontSize : 11 , marginTop : 8 } } > { responseError } </ div >
3343- ) }
3344- < div style = { { display : "flex" , justifyContent : "flex-end" , marginTop : 10 } } >
3345- < button
3346- onClick = { handleResponse }
3347- disabled = { responseLoading }
3322+ { responseUiState === "form" ? (
3323+ < >
3324+ < textarea
3325+ value = { answerText }
3326+ onChange = { ( event ) => {
3327+ setAnswerText ( event . target . value ) ;
3328+ if ( responseError ) setResponseError ( "" ) ;
3329+ } }
3330+ placeholder = "Enter your answer..."
3331+ disabled = { responseLoading }
3332+ rows = { 4 }
3333+ style = { {
3334+ width : "100%" ,
3335+ boxSizing : "border-box" ,
3336+ background : theme . field ,
3337+ color : theme . text ,
3338+ border : `1px solid ${ responseError ? theme . red : theme . border } ` ,
3339+ borderRadius : 8 ,
3340+ padding : 12 ,
3341+ fontSize : 12 ,
3342+ fontFamily : "'JetBrains Mono', monospace" ,
3343+ lineHeight : 1.6 ,
3344+ resize : "vertical" ,
3345+ outline : "none" ,
3346+ } }
3347+ />
3348+ { responseError && (
3349+ < div style = { { color : theme . red , fontSize : 11 , marginTop : 8 } } > { responseError } </ div >
3350+ ) }
3351+ < div style = { { display : "flex" , justifyContent : "flex-end" , marginTop : 10 } } >
3352+ < button
3353+ onClick = { handleResponse }
3354+ disabled = { responseLoading }
3355+ style = { {
3356+ ...primaryButton ( ) ,
3357+ cursor : responseLoading ? "wait" : "pointer" ,
3358+ opacity : responseLoading ? 0.65 : 1 ,
3359+ } }
3360+ >
3361+ { responseLoading ? "Submitting..." : "Submit Answer" }
3362+ </ button >
3363+ </ div >
3364+ </ >
3365+ ) : (
3366+ < div
33483367 style = { {
3349- ...primaryButton ( ) ,
3350- cursor : responseLoading ? "wait" : "pointer" ,
3351- opacity : responseLoading ? 0.65 : 1 ,
3368+ background : responseUiState === "submitted-stale" ? theme . orangeBg : theme . greenBg ,
3369+ border : `1px solid ${
3370+ responseUiState === "submitted-stale" ? theme . orange : theme . green
3371+ } `,
3372+ borderRadius : 8 ,
3373+ padding : 12 ,
3374+ color : theme . text ,
3375+ fontSize : 12 ,
3376+ lineHeight : 1.6 ,
33523377 } }
33533378 >
3354- { responseLoading ? "Submitting..." : "Submit Answer" }
3355- </ button >
3356- </ div >
3379+ { responseUiState === "submitted-stale"
3380+ ? "Answer submitted, but the task refresh failed. This view may be stale; automatic refresh will retry."
3381+ : "Answer submitted. Refreshing task status..." }
3382+ </ div >
3383+ ) }
33573384 </ Section >
33583385 ) }
33593386
@@ -5987,9 +6014,11 @@ export default function App() {
59876014 setSkills ( skillsRes . skills || [ ] ) ;
59886015 setConnected ( true ) ;
59896016 setApiError ( null ) ;
6017+ return true ;
59906018 } catch ( err ) {
59916019 setConnected ( false ) ;
59926020 setApiError ( `Failed to fetch tasks: ${ err . message } ` ) ;
6021+ return false ;
59936022 }
59946023 } , [ ] ) ;
59956024
@@ -6162,11 +6191,12 @@ export default function App() {
61626191 const handleRespond = async ( id , answer ) => {
61636192 try {
61646193 await respondToTask ( id , answer ) ;
6165- await poll ( ) ;
61666194 } catch ( e ) {
61676195 setApiError ( `Respond failed: ${ e . message } ` ) ;
61686196 throw e ;
61696197 }
6198+ const refreshed = await poll ( ) ;
6199+ return { refreshed } ;
61706200 } ;
61716201
61726202 const handleResume = ( ) => {
0 commit comments