88 createChecklist ,
99 buildActivationMessage ,
1010} from "../../tools/dp-tools.js" ;
11+ import type { MemoryRef } from "../../tools/deep-search/tool.js" ;
12+ import { FEEDBACK_SIGNALS , type FeedbackStatus } from "../../memory/types.js" ;
1113
1214
1315/**
@@ -156,10 +158,13 @@ function formatHypothesesWidget(text: string, theme: any): string[] {
156158
157159// --- Extension ---
158160
159- export default function deepInvestigationExtension ( api : ExtensionAPI ) : void {
161+ export default function deepInvestigationExtension ( api : ExtensionAPI , memoryRef ?: MemoryRef ) : void {
160162 // --- Mode state ---
161163 let checklist : DpChecklist | null = null ;
162164 let pendingActivation = false ;
165+ let pendingFeedbackId : string | null = null ;
166+ let deepSearchRan = false ;
167+ let feedbackCleanup : ( ( ) => void ) | null = null ;
163168
164169 // --- Progress rendering state ---
165170 let activeUI : ExtensionUIContext | null = null ;
@@ -209,13 +214,53 @@ export default function deepInvestigationExtension(api: ExtensionAPI): void {
209214 pendingActivation = true ;
210215 }
211216
217+ /** Show feedback hint in status bar if deep_search ran. Can be called independently of DP mode exit. */
218+ function showFeedbackIfNeeded ( ctx : ExtensionContext ) : void {
219+ if ( ! deepSearchRan || ! ctx . hasUI ) {
220+ deepSearchRan = false ;
221+ pendingFeedbackId = null ;
222+ return ;
223+ }
224+ deepSearchRan = false ;
225+ const id = pendingFeedbackId ;
226+ pendingFeedbackId = null ;
227+
228+ const cleanup = ( ) => {
229+ ctx . ui . setStatus ( "dp-mode" , undefined ) ;
230+ unsubInput ( ) ;
231+ clearTimeout ( timer ) ;
232+ feedbackCleanup = null ;
233+ } ;
234+
235+ const timer = setTimeout ( cleanup , 60_000 ) ;
236+
237+ const unsubInput = ctx . ui . onTerminalInput ( ( data : string ) => {
238+ if ( ctx . ui . getEditorText ( ) . length > 0 ) return undefined ;
239+ const keyMap : Record < string , FeedbackStatus > = { "1" : "confirmed" , "2" : "corrected" , "3" : "rejected" } ;
240+ const status = keyMap [ data ] ;
241+ if ( ! status ) return undefined ;
242+
243+ if ( id && memoryRef ?. indexer ) {
244+ memoryRef . indexer . updateInvestigationFeedback ( id , FEEDBACK_SIGNALS [ status ] , status ) ;
245+ }
246+ ctx . ui . notify ( `Feedback recorded: ${ status } ` ) ;
247+ cleanup ( ) ;
248+ return { consume : true } ;
249+ } ) ;
250+
251+ feedbackCleanup = cleanup ;
252+ const hint = "Thanks! Rate: 1-\uD83D\uDC4D 2-\uD83D\uDC4E 3-\u274C" ;
253+ ctx . ui . setStatus ( "dp-mode" , isThemeUsable ( ctx ) ? ctx . ui . theme . fg ( "muted" , hint ) : hint ) ;
254+ }
255+
212256 function disableDpMode ( ctx : ExtensionContext ) : void {
213257 if ( ! checklist ) return ;
214258 checklist = null ;
215- updateStatus ( ctx ) ;
216259 persistState ( ) ;
217260 if ( ctx . hasUI ) ctx . ui . notify ( "Deep Investigation OFF" ) ;
218261 pendingActivation = false ;
262+ showFeedbackIfNeeded ( ctx ) ;
263+ if ( ! feedbackCleanup ) updateStatus ( ctx ) ; // only clear status if no feedback hint active
219264 }
220265
221266 function toggleDpMode ( ctx : ExtensionContext ) : void {
@@ -552,6 +597,11 @@ export default function deepInvestigationExtension(api: ExtensionAPI): void {
552597 // --- session_start: restore persisted state ---
553598
554599 api . on ( "session_start" , async ( _event , ctx ) => {
600+ // Clean up stale feedback prompt from previous session
601+ feedbackCleanup ?.( ) ;
602+ deepSearchRan = false ;
603+ pendingFeedbackId = null ;
604+
555605 // Reset state — each session starts clean (prevents bleed from previous session)
556606 checklist = null ;
557607
@@ -609,7 +659,7 @@ export default function deepInvestigationExtension(api: ExtensionAPI): void {
609659
610660 // --- tool_result: progress cleanup (no auto-mark) ---
611661
612- api . on ( "tool_result" , ( event ) => {
662+ api . on ( "tool_result" , ( event , ctx ) => {
613663 if ( event . toolName === "deep_search" ) {
614664 // Progress rendering cleanup
615665 if ( activeUI ) {
@@ -618,9 +668,25 @@ export default function deepInvestigationExtension(api: ExtensionAPI): void {
618668 }
619669 activeUI = null ;
620670 resetProgressState ( ) ;
671+
672+ // Flag that deep_search ran; capture investigationId if available
673+ deepSearchRan = true ;
674+ const details = event . details as Record < string , unknown > | undefined ;
675+ pendingFeedbackId = ( details ?. investigationId as string ) ?? null ;
676+
677+ // Standalone deep_search (no DP mode): show feedback immediately since
678+ // disableDpMode() won't fire. Guard with !checklist to avoid double-prompting.
679+ if ( ! checklist ) {
680+ showFeedbackIfNeeded ( ctx ) ;
681+ }
621682 }
622683 } ) ;
623684
685+ // Clean up feedback hint when agent starts processing next message
686+ api . on ( "agent_start" , ( ) => {
687+ feedbackCleanup ?.( ) ;
688+ } ) ;
689+
624690 // --- context: filter UI-only custom messages ---
625691
626692 // Custom types that are UI-only metadata — must never be sent to the LLM.
0 commit comments