@@ -9,6 +9,8 @@ import React, { useState, useEffect, useCallback } from 'react';
99import { Timeline } from './components/Timeline' ;
1010import { ChatInput } from './components/ChatInput' ;
1111import { ModelConfig } from './components/ModelSelector' ;
12+ import { SelectedFile } from './components/FileChip' ;
13+ import { CompletionItem } from './components/CompletionPopup' ;
1214import { useVSCode , ExtensionMessage } from './hooks/useVSCode' ;
1315import type { AgentState , ToolCallInfo , TerminalOutput , ToolCallTimelineItem } from './types/timeline' ;
1416import './App.css' ;
@@ -18,6 +20,12 @@ interface ConfigState {
1820 currentConfigName : string | null ;
1921}
2022
23+ interface CompletionResult {
24+ newText : string ;
25+ newCursorPosition : number ;
26+ shouldTriggerNextCompletion : boolean ;
27+ }
28+
2129const App : React . FC = ( ) => {
2230 // Agent state - mirrors ComposeRenderer's state
2331 const [ agentState , setAgentState ] = useState < AgentState > ( {
@@ -35,6 +43,16 @@ const App: React.FC = () => {
3543 currentConfigName : null
3644 } ) ;
3745
46+ // Token usage state
47+ const [ totalTokens , setTotalTokens ] = useState < number | null > ( null ) ;
48+
49+ // Active file state (for auto-add current file feature)
50+ const [ activeFile , setActiveFile ] = useState < SelectedFile | null > ( null ) ;
51+
52+ // Completion state - from mpp-core
53+ const [ completionItems , setCompletionItems ] = useState < CompletionItem [ ] > ( [ ] ) ;
54+ const [ completionResult , setCompletionResult ] = useState < CompletionResult | null > ( null ) ;
55+
3856 const { postMessage, onMessage, isVSCode } = useVSCode ( ) ;
3957
4058 // Handle messages from extension
@@ -198,6 +216,43 @@ const App: React.FC = () => {
198216 } ) ;
199217 }
200218 break ;
219+
220+ // Token usage update
221+ case 'tokenUpdate' :
222+ if ( msg . data ?. totalTokens != null ) {
223+ setTotalTokens ( msg . data . totalTokens as number ) ;
224+ }
225+ break ;
226+
227+ // Active file changed (for auto-add current file)
228+ case 'activeFileChanged' :
229+ if ( msg . data ) {
230+ setActiveFile ( {
231+ path : msg . data . path as string ,
232+ name : msg . data . name as string ,
233+ relativePath : msg . data . path as string ,
234+ isDirectory : msg . data . isDirectory as boolean || false
235+ } ) ;
236+ }
237+ break ;
238+
239+ // Completion results from mpp-core
240+ case 'completionsResult' :
241+ if ( msg . data ?. items ) {
242+ setCompletionItems ( msg . data . items as CompletionItem [ ] ) ;
243+ }
244+ break ;
245+
246+ // Completion applied result
247+ case 'completionApplied' :
248+ if ( msg . data ) {
249+ setCompletionResult ( {
250+ newText : msg . data . newText as string ,
251+ newCursorPosition : msg . data . newCursorPosition as number ,
252+ shouldTriggerNextCompletion : msg . data . shouldTriggerNextCompletion as boolean
253+ } ) ;
254+ }
255+ break ;
201256 }
202257 } , [ ] ) ;
203258
@@ -206,21 +261,35 @@ const App: React.FC = () => {
206261 return onMessage ( handleExtensionMessage ) ;
207262 } , [ onMessage , handleExtensionMessage ] ) ;
208263
264+ // Request config on mount
265+ useEffect ( ( ) => {
266+ postMessage ( { type : 'requestConfig' } ) ;
267+ } , [ postMessage ] ) ;
268+
209269 // Send message to extension
210- const handleSend = useCallback ( ( content : string ) => {
270+ const handleSend = useCallback ( ( content : string , files ?: SelectedFile [ ] ) => {
271+ // Build message with file context (DevIns format)
272+ let fullContent = content ;
273+ if ( files && files . length > 0 ) {
274+ const fileCommands = files . map ( f =>
275+ f . isDirectory ? `/dir:${ f . relativePath } ` : `/file:${ f . relativePath } `
276+ ) . join ( '\n' ) ;
277+ fullContent = `${ fileCommands } \n\n${ content } ` ;
278+ }
279+
211280 // Immediately show user message in timeline for feedback
212281 setAgentState ( prev => ( {
213282 ...prev ,
214283 isProcessing : true ,
215284 timeline : [ ...prev . timeline , {
216285 type : 'message' ,
217286 timestamp : Date . now ( ) ,
218- message : { role : 'user' , content }
287+ message : { role : 'user' , content : fullContent }
219288 } ]
220289 } ) ) ;
221290
222291 // Send to extension
223- postMessage ( { type : 'sendMessage' , content } ) ;
292+ postMessage ( { type : 'sendMessage' , content : fullContent } ) ;
224293 } , [ postMessage ] ) ;
225294
226295 // Clear history
@@ -248,6 +317,48 @@ const App: React.FC = () => {
248317 postMessage ( { type : 'selectConfig' , data : { configName : config . name } } ) ;
249318 } , [ postMessage ] ) ;
250319
320+ // Handle prompt optimization
321+ const handlePromptOptimize = useCallback ( async ( prompt : string ) : Promise < string > => {
322+ return new Promise ( ( resolve ) => {
323+ // Send optimization request to extension
324+ postMessage ( { type : 'action' , action : 'optimizePrompt' , data : { prompt } } ) ;
325+
326+ // Listen for response
327+ const handler = ( event : MessageEvent ) => {
328+ const msg = event . data ;
329+ if ( msg . type === 'promptOptimized' && msg . data ?. optimizedPrompt ) {
330+ window . removeEventListener ( 'message' , handler ) ;
331+ resolve ( msg . data . optimizedPrompt as string ) ;
332+ } else if ( msg . type === 'promptOptimizeFailed' ) {
333+ window . removeEventListener ( 'message' , handler ) ;
334+ resolve ( prompt ) ; // Return original on failure
335+ }
336+ } ;
337+ window . addEventListener ( 'message' , handler ) ;
338+
339+ // Timeout after 30 seconds
340+ setTimeout ( ( ) => {
341+ window . removeEventListener ( 'message' , handler ) ;
342+ resolve ( prompt ) ;
343+ } , 30000 ) ;
344+ } ) ;
345+ } , [ postMessage ] ) ;
346+
347+ // Handle MCP config click
348+ const handleMcpConfigClick = useCallback ( ( ) => {
349+ postMessage ( { type : 'action' , action : 'openMcpConfig' } ) ;
350+ } , [ postMessage ] ) ;
351+
352+ // Handle get completions from mpp-core
353+ const handleGetCompletions = useCallback ( ( text : string , cursorPosition : number ) => {
354+ postMessage ( { type : 'getCompletions' , data : { text, cursorPosition } } ) ;
355+ } , [ postMessage ] ) ;
356+
357+ // Handle apply completion from mpp-core
358+ const handleApplyCompletion = useCallback ( ( text : string , cursorPosition : number , completionIndex : number ) => {
359+ postMessage ( { type : 'applyCompletion' , data : { text, cursorPosition, completionIndex } } ) ;
360+ } , [ postMessage ] ) ;
361+
251362 // Check if we need to show config prompt
252363 const needsConfig = agentState . timeline . length === 0 &&
253364 agentState . currentStreamingContent . includes ( 'No configuration found' ) ||
@@ -310,11 +421,19 @@ const App: React.FC = () => {
310421 onStop = { handleStop }
311422 onConfigSelect = { handleConfigSelect }
312423 onConfigureClick = { handleOpenConfig }
424+ onMcpConfigClick = { handleMcpConfigClick }
425+ onPromptOptimize = { handlePromptOptimize }
426+ onGetCompletions = { handleGetCompletions }
427+ onApplyCompletion = { handleApplyCompletion }
428+ completionItems = { completionItems }
429+ completionResult = { completionResult }
313430 disabled = { agentState . isProcessing }
314431 isExecuting = { agentState . isProcessing }
315432 placeholder = "Ask AutoDev anything... (use / for commands, @ for agents)"
316433 availableConfigs = { configState . availableConfigs }
317434 currentConfigName = { configState . currentConfigName }
435+ totalTokens = { totalTokens }
436+ activeFile = { activeFile }
318437 />
319438 </ div >
320439 ) ;
0 commit comments