7
7
import { openGenerateUIPrefilled } from '@nx-console/vscode-generate-ui-webview' ;
8
8
import { EXECUTE_ARBITRARY_COMMAND } from '@nx-console/vscode-nx-commands-view' ;
9
9
import { getGenerators , getNxWorkspace } from '@nx-console/vscode-nx-workspace' ;
10
- import { renderPrompt } from '@vscode/prompt-tsx' ;
10
+ import { sendChatParticipantRequest } from '@vscode/chat-extension-utils' ;
11
+ import { PromptElementAndProps } from '@vscode/chat-extension-utils/dist/toolsPrompt' ;
11
12
import { readFile } from 'fs/promises' ;
12
13
import type { TargetConfiguration } from 'nx/src/devkit-exports.js' ;
13
14
import {
@@ -19,8 +20,7 @@ import {
19
20
ChatResponseStream ,
20
21
commands ,
21
22
ExtensionContext ,
22
- LanguageModelChatMessage ,
23
- lm ,
23
+ LanguageModelToolResult ,
24
24
MarkdownString ,
25
25
Uri ,
26
26
} from 'vscode' ;
@@ -51,20 +51,12 @@ const handler: ChatRequestHandler = async (
51
51
token : CancellationToken
52
52
) => {
53
53
const enableNxCopilotFeaturesSetting = GlobalConfigurationStore . instance . get (
54
- 'enableNxCopilotFeatures ' ,
54
+ 'debugMode ' ,
55
55
false
56
56
) ;
57
57
58
58
if ( ! enableNxCopilotFeaturesSetting ) {
59
- stream . markdown (
60
- 'The @nx copilot chat participant is experimental. To use it, please enable it in the settings.'
61
- ) ;
62
-
63
- stream . button ( {
64
- title : 'Enable Nx Copilot' ,
65
- command : 'workbench.action.openSettings' ,
66
- arguments : [ 'nxConsole.enableNxCopilotFeatures' ] ,
67
- } ) ;
59
+ stream . markdown ( '@nx is coming soon. Stay tuned!' ) ;
68
60
return ;
69
61
}
70
62
const workspacePath = getNxWorkspacePath ( ) ;
@@ -75,7 +67,6 @@ const handler: ChatRequestHandler = async (
75
67
76
68
const pmExec = ( await getPackageManagerCommand ( workspacePath ) ) . exec ;
77
69
78
- let messages : LanguageModelChatMessage [ ] ;
79
70
const baseProps : NxCopilotPromptProps = {
80
71
userQuery : request . prompt ,
81
72
projectGraph : projectGraph ,
@@ -84,91 +75,97 @@ const handler: ChatRequestHandler = async (
84
75
packageManagerExecCommand : pmExec ,
85
76
} ;
86
77
78
+ let promptElementAndProps : PromptElementAndProps <
79
+ NxCopilotPrompt | GeneratePrompt
80
+ > ;
81
+
87
82
if ( request . command === 'generate' ) {
88
83
stream . progress ( 'Retrieving generator schemas...' ) ;
89
84
90
- const prompt = await renderPrompt (
91
- GeneratePrompt ,
92
- {
85
+ promptElementAndProps = {
86
+ promptElement : GeneratePrompt ,
87
+ props : {
93
88
...baseProps ,
94
89
generatorSchemas : await getGeneratorSchemas ( ) ,
95
90
} ,
96
- { modelMaxPromptTokens : request . model . maxInputTokens } ,
97
- request . model
98
- ) ;
99
- messages = prompt . messages ;
91
+ } ;
100
92
} else {
101
- try {
102
- const prompt = await renderPrompt (
103
- NxCopilotPrompt ,
104
- baseProps ,
105
- { modelMaxPromptTokens : request . model . maxInputTokens } ,
106
- request . model
107
- ) ;
108
- messages = prompt . messages ;
109
- } catch ( error ) {
110
- console . error ( 'Error rendering prompt:' , error ) ;
111
- stream . markdown (
112
- 'An error occurred while rendering the prompt. Please try again later.'
113
- ) ;
114
- return ;
115
- }
93
+ promptElementAndProps = {
94
+ promptElement : NxCopilotPrompt ,
95
+ props : baseProps ,
96
+ } ;
116
97
}
117
98
118
- const chatResponse = await request . model . sendRequest ( messages , { } , token ) ;
99
+ const chatParticipantRequest = sendChatParticipantRequest (
100
+ request ,
101
+ context ,
102
+ {
103
+ prompt : promptElementAndProps ,
104
+ responseStreamOptions : {
105
+ stream,
106
+ } ,
107
+ tools : [ ] ,
108
+ } ,
109
+ token
110
+ ) ;
119
111
120
112
const startMarker = new RegExp ( `"""\\s*${ pmExec } \\s+nx\\s*` ) ;
121
113
const endMarker = `"""` ;
122
114
123
115
let pendingText = '' ;
124
116
let codeBuffer : string | null = null ;
125
117
126
- for await ( const fragment of chatResponse . text ) {
127
- if ( codeBuffer !== null ) {
128
- codeBuffer += fragment ;
118
+ for await ( const fragment of chatParticipantRequest . stream ) {
119
+ if ( fragment instanceof LanguageModelToolResult ) {
120
+ stream . markdown ( JSON . stringify ( fragment ) ) ;
121
+ continue ;
129
122
} else {
130
- pendingText += fragment ;
131
- }
132
-
133
- // Process when we're not in a code block: look for a start marker.
134
- while ( codeBuffer === null ) {
135
- const match = pendingText . match ( startMarker ) ;
136
- const startIndex = match ? match . index : - 1 ;
137
- if ( startIndex === - 1 ) {
138
- break ;
139
- }
140
- if ( startIndex > 0 ) {
141
- stream . markdown ( pendingText . slice ( 0 , startIndex ) ) ;
123
+ if ( codeBuffer !== null ) {
124
+ codeBuffer += fragment . value ;
125
+ } else {
126
+ pendingText += fragment . value ;
142
127
}
143
- // Switch to code mode.
144
- codeBuffer = '' ;
145
- pendingText = pendingText . slice ( startIndex + match [ 0 ] . length ) ;
146
- codeBuffer += pendingText ;
147
- pendingText = '' ;
148
- }
149
128
150
- // If we are in a code block, look for the end marker.
151
- while ( codeBuffer !== null ) {
152
- const endIndex = codeBuffer . indexOf ( endMarker ) ;
153
- if ( endIndex === - 1 ) {
154
- break ;
129
+ // Process when we're not in a code block: look for a start marker.
130
+ while ( codeBuffer === null ) {
131
+ const match = pendingText . match ( startMarker ) ;
132
+ const startIndex = match ? match . index : - 1 ;
133
+ if ( startIndex === - 1 ) {
134
+ break ;
135
+ }
136
+ if ( startIndex > 0 ) {
137
+ stream . markdown ( pendingText . slice ( 0 , startIndex ) ) ;
138
+ }
139
+ // Switch to code mode.
140
+ codeBuffer = '' ;
141
+ pendingText = pendingText . slice ( startIndex + match [ 0 ] . length ) ;
142
+ codeBuffer += pendingText ;
143
+ pendingText = '' ;
155
144
}
156
- const codeSnippet = codeBuffer . slice ( 0 , endIndex ) ;
157
145
158
- renderCommandSnippet ( codeSnippet , stream , pmExec ) ;
159
- codeBuffer = codeBuffer . slice ( endIndex + endMarker . length ) ;
146
+ // If we are in a code block, look for the end marker.
147
+ while ( codeBuffer !== null ) {
148
+ const endIndex = codeBuffer . indexOf ( endMarker ) ;
149
+ if ( endIndex === - 1 ) {
150
+ break ;
151
+ }
152
+ const codeSnippet = codeBuffer . slice ( 0 , endIndex ) ;
153
+
154
+ renderCommandSnippet ( codeSnippet , stream , pmExec ) ;
155
+ codeBuffer = codeBuffer . slice ( endIndex + endMarker . length ) ;
160
156
161
- // switch back to normal mode.
162
- pendingText += codeBuffer ;
163
- codeBuffer = null ;
157
+ // switch back to normal mode.
158
+ pendingText += codeBuffer ;
159
+ codeBuffer = null ;
160
+ }
164
161
}
165
162
}
166
163
167
164
if ( codeBuffer === null && pendingText ) {
168
165
stream . markdown ( pendingText ) ;
169
166
}
170
167
171
- return ;
168
+ return await chatParticipantRequest . result ;
172
169
} ;
173
170
174
171
async function renderCommandSnippet (
0 commit comments