@@ -8,25 +8,34 @@ import { CancellationToken } from '../../../../base/common/cancellation.js';
8
8
import { Disposable , IDisposable } from '../../../../base/common/lifecycle.js' ;
9
9
import { URI } from '../../../../base/common/uri.js' ;
10
10
import { generateUuid } from '../../../../base/common/uuid.js' ;
11
+ import * as nls from '../../../../nls.js' ;
11
12
import { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js' ;
12
- import { InstantiationType , registerSingleton } from '../../../../platform/instantiation/common/extensions.js' ;
13
13
import { createDecorator } from '../../../../platform/instantiation/common/instantiation.js' ;
14
14
import { ILogService } from '../../../../platform/log/common/log.js' ;
15
- import { IWebview , IWebviewService } from '../../../contrib/webview/browser/webview.js' ;
15
+ import { IWebview , IWebviewService , WebviewContentPurpose } from '../../../contrib/webview/browser/webview.js' ;
16
+ import { IExtensionService } from '../../../services/extensions/common/extensions.js' ;
17
+ import { ExtensionsRegistry } from '../../../services/extensions/common/extensionsRegistry.js' ;
16
18
17
19
export interface IChatOutputItemRenderer {
18
- renderOutputPart ( mime : string , data : Uint8Array , webivew : IWebview , token : CancellationToken ) : Promise < void > ;
20
+ renderOutputPart ( mime : string , data : Uint8Array , webview : IWebview , token : CancellationToken ) : Promise < void > ;
19
21
}
20
22
21
- export const IChatOutputItemRendererService = createDecorator < IChatOutputItemRendererService > ( 'chatOutputItemRendererService' ) ;
23
+ export const IChatOutputRendererService = createDecorator < IChatOutputRendererService > ( 'chatOutputRendererService' ) ;
24
+
25
+ interface RegisterOptions {
26
+ readonly extension ?: {
27
+ readonly id : ExtensionIdentifier ;
28
+ readonly location : URI ;
29
+ } ;
30
+ }
22
31
23
32
/**
24
33
* Service for rendering chat output items with special MIME types using registered renderers from extensions.
25
34
*/
26
- export interface IChatOutputItemRendererService {
35
+ export interface IChatOutputRendererService {
27
36
readonly _serviceBrand : undefined ;
28
37
29
- registerRenderer ( mime : string , renderer : IChatOutputItemRenderer ) : IDisposable ;
38
+ registerRenderer ( mime : string , renderer : IChatOutputItemRenderer , options : RegisterOptions ) : IDisposable ;
30
39
31
40
renderOutputPart ( mime : string , data : Uint8Array , parent : HTMLElement , token : CancellationToken ) : Promise < IDisposable > ;
32
41
}
@@ -36,21 +45,25 @@ export interface IChatOutputItemRendererService {
36
45
* This service connects with the MainThreadChatResponseOutputRenderer to render output parts
37
46
* in chat responses using extension-provided renderers.
38
47
*/
39
- export class ChatOutputItemRendererService extends Disposable implements IChatOutputItemRendererService {
48
+ export class ChatOutputRendererService extends Disposable implements IChatOutputRendererService {
40
49
_serviceBrand : undefined ;
41
50
42
- private readonly _renderers = new Map < string , IChatOutputItemRenderer > ( ) ;
51
+ private readonly _renderers = new Map < string , {
52
+ readonly renderer : IChatOutputItemRenderer ;
53
+ readonly options : RegisterOptions ;
54
+ } > ( ) ;
43
55
44
56
constructor (
45
57
@ILogService private readonly _logService : ILogService ,
46
58
@IWebviewService private readonly _webviewService : IWebviewService ,
59
+ @IExtensionService private readonly _extensionService : IExtensionService ,
47
60
) {
48
61
super ( ) ;
49
62
this . _logService . debug ( 'ChatOutputItemRendererService: Created' ) ;
50
63
}
51
64
52
- registerRenderer ( mime : string , renderer : IChatOutputItemRenderer ) : IDisposable {
53
- this . _renderers . set ( mime , renderer ) ;
65
+ registerRenderer ( mime : string , renderer : IChatOutputItemRenderer , options : RegisterOptions ) : IDisposable {
66
+ this . _renderers . set ( mime , { renderer, options } ) ;
54
67
this . _logService . debug ( `ChatOutputItemRendererService: Registered renderer for MIME type ${ mime } ` ) ;
55
68
return {
56
69
dispose : ( ) => {
@@ -60,35 +73,62 @@ export class ChatOutputItemRendererService extends Disposable implements IChatOu
60
73
}
61
74
62
75
async renderOutputPart ( mime : string , data : Uint8Array , parent : HTMLElement , token : CancellationToken ) : Promise < IDisposable > {
63
- const renderer = this . _renderers . get ( mime ) ;
64
- if ( ! renderer ) {
76
+ // Activate extensions that contribute to chatOutputRenderer for this mime type
77
+ await this . _extensionService . activateByEvent ( `onChatOutputRenderer:${ mime } ` ) ;
78
+
79
+ const rendererData = this . _renderers . get ( mime ) ;
80
+ if ( ! rendererData ) {
65
81
throw new Error ( `No renderer registered for mime type: ${ mime } ` ) ;
66
82
}
67
83
68
84
const webview = this . _webviewService . createWebviewElement ( {
69
- title : 'My fancy chat renderer ' ,
85
+ title : '' ,
70
86
origin : generateUuid ( ) ,
71
87
options : {
72
-
88
+ enableFindWidget : false ,
89
+ purpose : WebviewContentPurpose . ChatOutputItem ,
90
+ tryRestoreScrollPosition : false ,
73
91
} ,
74
- contentOptions : {
75
- localResourceRoots : [ ] ,
76
- allowScripts : true ,
77
- } ,
78
- extension : { id : new ExtensionIdentifier ( 'xxx.yyy' ) , location : URI . file ( '/' ) }
92
+ contentOptions : { } ,
93
+ extension : rendererData . options . extension ? rendererData . options . extension : undefined ,
79
94
} ) ;
80
95
81
- parent . style = 'max-height: 80vh; width: 100%;' ;
82
96
webview . mountTo ( parent , getWindow ( parent ) ) ;
83
97
84
- await renderer . renderOutputPart ( mime , data , webview , token ) ;
98
+ await rendererData . renderer . renderOutputPart ( mime , data , webview , token ) ;
85
99
86
100
return {
87
- dispose : ( ) => { }
101
+ dispose : ( ) => {
102
+ webview . dispose ( ) ;
103
+ }
88
104
} ;
89
105
}
90
106
}
91
107
92
- // Register the service
93
- registerSingleton ( IChatOutputItemRendererService , ChatOutputItemRendererService , InstantiationType . Delayed ) ;
108
+ interface IChatOutputRendererContribution {
109
+ readonly mimeTypes : readonly string [ ] ;
110
+ }
111
+
112
+ ExtensionsRegistry . registerExtensionPoint < IChatOutputRendererContribution [ ] > ( {
113
+ extensionPoint : 'chatOutputRenderer' ,
114
+ jsonSchema : {
115
+ description : nls . localize ( 'vscode.extension.contributes.chatOutputRenderer' , 'Contributes a renderer for specific MIME types in chat outputs' ) ,
116
+ type : 'array' ,
117
+ items : {
118
+ type : 'object' ,
119
+ additionalProperties : false ,
120
+ required : [ 'mimeTypes' ] ,
121
+ properties : {
122
+ mimeTypes : {
123
+ description : nls . localize ( 'chatOutputRenderer.mimeTypes' , 'MIME types that this renderer can handle' ) ,
124
+ type : 'array' ,
125
+ items : {
126
+ type : 'string'
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ } ) ;
133
+
94
134
0 commit comments