1515// *****************************************************************************
1616import { ChangeSet , ChatAgent , ChatChangeEvent , ChatModel , ChatRequestModel } from '@theia/ai-chat' ;
1717import { Disposable , DisposableCollection , InMemoryResources , URI , nls } from '@theia/core' ;
18- import { ContextMenuRenderer , LabelProvider , Message , ReactWidget } from '@theia/core/lib/browser' ;
18+ import { ContextMenuRenderer , LabelProvider , Message , OpenerService , ReactWidget } from '@theia/core/lib/browser' ;
1919import { Deferred } from '@theia/core/lib/common/promise-util' ;
2020import { inject , injectable , optional , postConstruct } from '@theia/core/shared/inversify' ;
2121import * as React from '@theia/core/shared/react' ;
@@ -27,12 +27,14 @@ import { AIVariableResolutionRequest } from '@theia/ai-core';
2727import { FrontendVariableService } from '@theia/ai-core/lib/browser' ;
2828import { ContextVariablePicker } from './context-variable-picker' ;
2929import { ChangeSetActionRenderer , ChangeSetActionService } from './change-set-actions/change-set-action-service' ;
30+ import { ChatInputAgentSuggestions } from './chat-input-agent-suggestions' ;
3031
3132type Query = ( query : string ) => Promise < void > ;
3233type Unpin = ( ) => void ;
3334type Cancel = ( requestModel : ChatRequestModel ) => void ;
3435type DeleteChangeSet = ( requestModel : ChatRequestModel ) => void ;
3536type DeleteChangeSetElement = ( requestModel : ChatRequestModel , index : number ) => void ;
37+ type OpenContextElement = ( request : AIVariableResolutionRequest ) => unknown ;
3638
3739export const AIChatInputConfiguration = Symbol ( 'AIChatInputConfiguration' ) ;
3840export interface AIChatInputConfiguration {
@@ -69,6 +71,9 @@ export class AIChatInputWidget extends ReactWidget {
6971 @inject ( ChangeSetActionService )
7072 protected readonly changeSetActionService : ChangeSetActionService ;
7173
74+ @inject ( OpenerService )
75+ protected readonly openerService : OpenerService ;
76+
7277 protected editorRef : MonacoEditor | undefined = undefined ;
7378 private editorReady = new Deferred < void > ( ) ;
7479
@@ -94,6 +99,10 @@ export class AIChatInputWidget extends ReactWidget {
9499 set onDeleteChangeSetElement ( deleteChangeSetElement : DeleteChangeSetElement ) {
95100 this . _onDeleteChangeSetElement = deleteChangeSetElement ;
96101 }
102+ private _onOpenContextELement : OpenContextElement ;
103+ set onOpenContextElement ( opener : OpenContextElement ) {
104+ this . _onOpenContextELement = opener ;
105+ }
97106
98107 protected onDisposeForChatModel = new DisposableCollection ( ) ;
99108 private _chatModel : ChatModel ;
@@ -142,6 +151,7 @@ export class AIChatInputWidget extends ReactWidget {
142151 onDeleteChangeSetElement = { this . _onDeleteChangeSetElement . bind ( this ) }
143152 onAddContextElement = { this . addContextElement . bind ( this ) }
144153 onDeleteContextElement = { this . deleteContextElement . bind ( this ) }
154+ onOpenContextElement = { this . _onOpenContextELement . bind ( this ) }
145155 context = { this . _chatModel . context . getVariables ( ) }
146156 chatModel = { this . _chatModel }
147157 pinnedAgent = { this . _pinnedAgent }
@@ -157,6 +167,7 @@ export class AIChatInputWidget extends ReactWidget {
157167 showPinnedAgent = { this . configuration ?. showPinnedAgent }
158168 labelProvider = { this . labelProvider }
159169 actionService = { this . changeSetActionService }
170+ openerService = { this . openerService }
160171 />
161172 ) ;
162173 }
@@ -237,6 +248,7 @@ interface ChatInputProperties {
237248 onDeleteChangeSetElement : ( sessionId : string , index : number ) => void ;
238249 onAddContextElement : ( ) => void ;
239250 onDeleteContextElement : ( index : number ) => void ;
251+ onOpenContextElement : OpenContextElement ;
240252 context ?: readonly AIVariableResolutionRequest [ ] ;
241253 isEnabled ?: boolean ;
242254 chatModel : ChatModel ;
@@ -249,6 +261,7 @@ interface ChatInputProperties {
249261 showPinnedAgent ?: boolean ;
250262 labelProvider : LabelProvider ;
251263 actionService : ChangeSetActionService ;
264+ openerService : OpenerService ;
252265}
253266
254267const ChatInput : React . FunctionComponent < ChatInputProperties > = ( props : ChatInputProperties ) => {
@@ -515,9 +528,10 @@ const ChatInput: React.FunctionComponent<ChatInputProperties> = (props: ChatInpu
515528 disabled : isInputEmpty || ! props . isEnabled
516529 } ] ;
517530
518- const contextUI = buildContextUI ( props . context , props . labelProvider , props . onDeleteContextElement ) ;
531+ const contextUI = buildContextUI ( props . context , props . labelProvider , props . onDeleteContextElement , props . onOpenContextElement ) ;
519532
520- return < div className = 'theia-ChatInput' onDragOver = { props . onDragOver } onDrop = { props . onDrop } >
533+ return < div className = 'theia-ChatInput' onDragOver = { props . onDragOver } onDrop = { props . onDrop } >
534+ { ! ! props . pinnedAgent ?. suggestions ?. length && < ChatInputAgentSuggestions suggestions = { props . pinnedAgent ?. suggestions } opener = { props . openerService } /> }
521535 { changeSetUI ?. elements &&
522536 < ChangeSetBox changeSet = { changeSetUI } />
523537 }
@@ -685,7 +699,12 @@ function getLatestRequest(chatModel: ChatModel): ChatRequestModel | undefined {
685699 return requests . length > 0 ? requests [ requests . length - 1 ] : undefined ;
686700}
687701
688- function buildContextUI ( context : readonly AIVariableResolutionRequest [ ] | undefined , labelProvider : LabelProvider , onDeleteContextElement : ( index : number ) => void ) : ChatContextUI {
702+ function buildContextUI (
703+ context : readonly AIVariableResolutionRequest [ ] | undefined ,
704+ labelProvider : LabelProvider ,
705+ onDeleteContextElement : ( index : number ) => void ,
706+ onOpen : OpenContextElement
707+ ) : ChatContextUI {
689708 if ( ! context ) {
690709 return { context : [ ] } ;
691710 }
@@ -697,6 +716,7 @@ function buildContextUI(context: readonly AIVariableResolutionRequest[] | undefi
697716 additionalInfo : labelProvider . getDetails ( element ) ,
698717 details : labelProvider . getLongName ( element ) ,
699718 delete : ( ) => onDeleteContextElement ( index ) ,
719+ open : ( ) => onOpen ( element )
700720 } ) )
701721 } ;
702722}
@@ -725,7 +745,7 @@ const ChatContext: React.FunctionComponent<ChatContextUI> = ({ context }) => (
725745 < span className = 'theia-ChatInput-ChatContext-additionalInfo' >
726746 { element . additionalInfo }
727747 </ span >
728- < span className = "codicon codicon-close action" title = { nls . localizeByDefault ( 'Delete' ) } onClick = { ( ) => element . delete ( ) } />
748+ < span className = "codicon codicon-close action" title = { nls . localizeByDefault ( 'Delete' ) } onClick = { e => { e . stopPropagation ( ) ; element . delete ( ) ; } } />
729749 </ li >
730750 ) ) }
731751 </ ul >
0 commit comments