@@ -17,42 +17,6 @@ import {
1717 type ResponseData ,
1818} from './AiAgent.js' ;
1919
20- /* clang-format off */
21- const preamble = `You are responsible for changing the source code on behalf of the user.
22- The user query defines what changes are to be made.
23- You have a number of functions to get information about source files in the project.
24- Use those functions to fulfill the user query.
25-
26- ## Step-by-step instructions
27-
28- - Think about what the user wants.
29- - List all files in the project or search for relevant files.
30- - Identify the files that are likely to be modified.
31- - Retrieve the content of those files.
32- - Rewrite the files according to the user query.
33-
34- ## General considerations
35-
36- - Avoid requesting too many files.
37- - Always prefer changing the true source files and not the build output.
38- - The build output is usually in dist/, out/, build/ folders.
39- - *CRITICAL* never make the same function call twice.
40- - *CRITICAL* do not make any changes if not prompted.
41-
42- Instead of using the writeFile function you can also produce the following diff format:
43-
44- \`\`\`
45- src/index.html
46- <meta charset="utf-8">
47- <title>Test</title>
48- \`\`\`
49-
50- First output the filename (example, src/index.html), then output the SEARCH block,
51- followed by the REPLACE block.
52-
53- ` ;
54- /* clang-format on */
55-
5620export class ProjectContext extends ConversationContext < Workspace . Workspace . Project > {
5721 readonly #project: Workspace . Workspace . Project ;
5822
@@ -107,7 +71,7 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
10771 }
10872
10973 override readonly type = AgentType . PATCH ;
110- readonly preamble = preamble ;
74+ readonly preamble = undefined ;
11175 readonly clientFeature = Host . AidaClient . ClientFeature . CHROME_PATCH_AGENT ;
11276
11377 get userTier ( ) : string | undefined {
@@ -124,7 +88,7 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
12488 constructor ( opts : BaseAgentOptions ) {
12589 super ( opts ) ;
12690 this . declareFunction < Record < never , unknown > > ( 'listFiles' , {
127- description : 'returns a list of all files in the project.' ,
91+ description : 'Returns a list of all files in the project.' ,
12892 parameters : {
12993 type : Host . AidaClient . ParametersTypes . OBJECT ,
13094 description : '' ,
@@ -149,11 +113,11 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
149113
150114 this . declareFunction < {
151115 query : string ,
152- caseSensitive : boolean ,
153- isRegex : boolean ,
116+ caseSensitive ? : boolean ,
117+ isRegex ? : boolean ,
154118 } > ( 'searchInFiles' , {
155119 description :
156- 'Searches for a query in all files in the project. For each match it returns the positions of matches.' ,
120+ 'Searches for a text match in all files in the project. For each match it returns the positions of matches.' ,
157121 parameters : {
158122 type : Host . AidaClient . ParametersTypes . OBJECT ,
159123 description : '' ,
@@ -186,7 +150,8 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
186150 const { map} = getFiles ( project ) ;
187151 const matches = [ ] ;
188152 for ( const [ filepath , file ] of map . entries ( ) ) {
189- const results = await project . searchInFileContent ( file , params . query , params . caseSensitive , params . isRegex ) ;
153+ const results = TextUtils . TextUtils . performSearchInContentData (
154+ file . workingCopyContentData ( ) , params . query , params . caseSensitive ?? true , params . isRegex ?? false ) ;
190155 for ( const result of results ) {
191156 matches . push ( {
192157 filepath,
@@ -203,118 +168,6 @@ export class PatchAgent extends AiAgent<Workspace.Workspace.Project> {
203168 } ;
204169 } ,
205170 } ) ;
206-
207- this . declareFunction ( 'changeFile' , {
208- description : 'returns a list of all files in the project.' ,
209- parameters : {
210- type : Host . AidaClient . ParametersTypes . OBJECT ,
211- description : '' ,
212- nullable : true ,
213- properties : {
214- filepath : {
215- type : Host . AidaClient . ParametersTypes . STRING ,
216- description : 'A file path that identifies the file to get the content for' ,
217- nullable : false ,
218- } ,
219- } ,
220- } ,
221- handler : async ( ) => {
222- return { result : { } } ;
223- } ,
224- } ) ;
225-
226- this . declareFunction < { filepath : string } > ( 'readFile' , {
227- description : 'returns the complement content of a file' ,
228- parameters : {
229- type : Host . AidaClient . ParametersTypes . OBJECT ,
230- description : '' ,
231- properties : {
232- filepath : {
233- type : Host . AidaClient . ParametersTypes . STRING ,
234- description : 'A file path that identifies the file to get the content for' ,
235- nullable : false ,
236- } ,
237- } ,
238- } ,
239- handler : async params => {
240- if ( ! this . #project) {
241- return {
242- error : 'No project available' ,
243- } ;
244- }
245- const project = this . #project. getItem ( ) ;
246- const { map} = getFiles ( project ) ;
247- const uiSourceCode = map . get ( params . filepath ) ;
248- if ( ! uiSourceCode ) {
249- return {
250- error : `File ${ params . filepath } not found` ,
251- } ;
252- }
253- // TODO: clearly define what types of files we handle.
254- const content = await uiSourceCode . requestContentData ( ) ;
255- if ( TextUtils . ContentData . ContentData . isError ( content ) ) {
256- return {
257- error : content . error ,
258- } ;
259- }
260- if ( ! content . isTextContent ) {
261- return {
262- error : 'Non-text files are not supported' ,
263- } ;
264- }
265-
266- return {
267- result : {
268- content : content . text ,
269- }
270- } ;
271- } ,
272- } ) ;
273-
274- this . declareFunction < { filepath : string , content : string } > ( 'writeFile' , {
275- description : '(over)writes the file with the provided content' ,
276- parameters : {
277- type : Host . AidaClient . ParametersTypes . OBJECT ,
278- description : '' ,
279- properties : {
280- filepath : {
281- type : Host . AidaClient . ParametersTypes . STRING ,
282- description : 'A file path that identifies the file' ,
283- nullable : false ,
284- } ,
285- content : {
286- type : Host . AidaClient . ParametersTypes . STRING ,
287- description : 'Full content of the file that will replace the current file content' ,
288- nullable : false ,
289- } ,
290- } ,
291- } ,
292- handler : async params => {
293- if ( ! this . #project) {
294- return {
295- error : 'No project available' ,
296- } ;
297- }
298- const project = this . #project. getItem ( ) ;
299- const { map} = getFiles ( project ) ;
300- const uiSourceCode = map . get ( params . filepath ) ;
301- if ( ! uiSourceCode ) {
302- return {
303- error : `File ${ params . filepath } not found` ,
304- } ;
305- }
306- const content = params . content ;
307- // TODO: we unescape some characters to restore the original
308- // content but this should be fixed upstream.
309- uiSourceCode . setContent (
310- content . replaceAll ( '\\n' , '\n' ) . replaceAll ( '\\"' , '"' ) . replaceAll ( '\\\'' , '\'' ) ,
311- false ,
312- ) ;
313- return {
314- result : null ,
315- } ;
316- } ,
317- } ) ;
318171 }
319172
320173 override async * run ( initialQuery : string , options : {
0 commit comments