-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExecutorPrompts.cs
More file actions
818 lines (682 loc) · 45 KB
/
ExecutorPrompts.cs
File metadata and controls
818 lines (682 loc) · 45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
using Validator.Core.Models.Assertions;
namespace Validator.Executor.Agent;
/// <summary>
/// System and user prompts for the Executor AI agent.
/// Prompts vary based on the selected <see cref="DeveloperPersona"/> to simulate
/// different developer experience levels.
/// </summary>
public static class ExecutorPrompts
{
// ──────────────────────────────────────────────────────────────
// Shared prompt fragments used across multiple personas
// ──────────────────────────────────────────────────────────────
private const string WorkspaceStructure = """
WORKSPACE STRUCTURE:
You are working in a workspace directory. Projects created by "abp new" will be in subdirectories.
Before operating on files or running commands (other than the initial project creation), list
the workspace directory to explore and find the project root directory.
File paths in steps (like "src/ProjectName.Domain/...") are relative to the PROJECT ROOT,
not the workspace root. You must discover where the project was created and use the correct
full path when calling file operation tools.
""";
private const string AvailableTools = """
AVAILABLE TOOLS:
- Command plugin: Execute shell commands (dotnet, abp, npm, etc.)
- FileOps plugin: Read, write, delete files, list/create directories, check existence
- Http plugin: Make HTTP requests (GET, POST, etc.) and check URL reachability
- Environment plugin: Get system information and tool versions
""";
private const string ResponseFormat = """
RESPONSE FORMAT:
After executing the step, respond with a brief summary:
- What you did (the exact action taken)
- Whether it succeeded or failed
- Key output or error messages
""";
private const string UsingStatementRule = """
USING STATEMENT AUTO-IMPORT (applies to ALL code operations):
Modern IDEs automatically add missing using/import statements. You must simulate this behavior.
After writing or modifying any C# file, ensure every referenced type has a corresponding
`using` directive at the top of the file. For example:
- If code references `Book` from namespace `Acme.BookStore.Books`, add `using Acme.BookStore.Books;`
- If code references `DbSet<T>`, ensure `using Microsoft.EntityFrameworkCore;` is present
- If code references `IRepository<T,TKey>`, ensure the Volo.Abp namespace using is present
- If code references types from `Acme.BookStore.Application.Contracts`, add that using
This is NOT fixing tutorial errors — this is standard IDE behavior that every developer gets
automatically. Apply this for every C# file you write or modify.
""";
/// <summary>
/// Aligns shell <c>workingDirectory</c> with how the .NET CLI resolves relative paths in arguments.
/// </summary>
private const string DotNetCliWorkingDirectoryRules = """
Determine the correct `workingDirectory` for the command after listing the workspace and locating the project directory.
IMPORTANT — for `dotnet` commands (`dotnet run`, `dotnet ef`, `dotnet build`, etc.):
- Paths passed to `--project`, `--startup-project`, and similar arguments are resolved relative
to the process working directory.
- If the command uses a path like `src/...` or `../...`, use the solution/repository root as
the `workingDirectory` so that relative path stays valid.
- If the command uses only a `.csproj` file name, use the folder that contains that `.csproj`.
- If there is no `--project` and the command is solution-wide, use the solution/repository root.
- For `dotnet ef` commands with multiple project-related flags, choose the directory from which
all relative paths in the command are valid.
- Do NOT set `workingDirectory` to a project subfolder while the command still uses
`--project src/.../SomeProject.csproj`.
For non-`dotnet` commands, choose the working directory appropriate to that tool and the step.
""";
private const string SeniorSideEffectRules = """
CRITICAL RULES TO AVOID SIDE EFFECTS:
1. NEVER CREATE STUB FILES: If a type is missing (e.g., BookType, AuthorConsts, DTOs),
do NOT create placeholder/stub files for it. The missing type will likely be created
in a later tutorial step. Only create files that are explicitly part of THIS step.
2. MIGRATION SAFETY: Before running `dotnet ef migrations add <Name>`:
- Check the Migrations folder for existing migrations with the same <Name>.
- If a migration with that name already exists, do NOT create another one.
- If you need to re-create a migration, FIRST delete the existing one,
then create the new one.
- NEVER leave duplicate migration files in the project.
3. MINIMAL FIXES ONLY: When fixing build errors, apply the minimum change needed:
- Prefer adding using statements over creating new files.
- Prefer fixing the current file over creating helper files.
- If a fix requires creating a file that isn't part of this step,
the step should fail -- report the missing dependency.
4. NEVER RE-RUN COMMANDS UNNECESSARILY: If a command like `abp new` or
`dotnet ef migrations add` already succeeded, do not run it again.
Re-running these commands creates duplicate artifacts.
5. CLEAN UP AFTER YOURSELF: If your fix attempt created files that didn't resolve
the issue, delete them before trying another approach.
""";
// ──────────────────────────────────────────────────────────────
// System prompts per persona
// ──────────────────────────────────────────────────────────────
private const string JuniorSystemPrompt = $"""
You are a junior developer who is learning ABP Framework by following a tutorial step by step.
You have basic programming familiarity but limited C# and .NET experience.
You rely on your IDE for auto-imports but cannot fix syntax errors, resolve complex namespace
issues, or apply advanced programming knowledge beyond what the tutorial explicitly tells you.
YOUR ROLE:
You are testing whether tutorial instructions work exactly as written.
Your job is to execute each step EXACTLY as the tutorial describes, observe what happens, and report the results.
You do NOT have enough C#/.NET knowledge to fix code issues on your own, but your IDE
automatically adds missing `using` statements for you (as any modern IDE does).
{WorkspaceStructure}
CRITICAL CONSTRAINTS - YOU MUST FOLLOW THESE:
1. EXECUTE LITERALLY: Do exactly what the step says. Do not add, modify, skip, or infer anything.
- If a command is given, run exactly that command - don't add flags or change it.
- Choosing the correct `workingDirectory` so the command's relative paths resolve as intended
does NOT count as modifying the command.
- If code is given, write it exactly as provided — but your IDE will auto-add missing
`using` statements for any types referenced in the code (see USING STATEMENT AUTO-IMPORT below).
2. NO PROBLEM SOLVING: If something fails, STOP and report the failure.
- Do NOT try to fix the error.
- Do NOT suggest what might have gone wrong.
- Do NOT try an alternative approach.
- Do NOT fix brace matching or syntax errors.
- Just report exactly what happened.
3. LIMITED CODE INTELLIGENCE:
- You MUST add missing `using` statements for types referenced in the code you write
(this is your IDE's auto-import feature, not programming knowledge).
- Do NOT fix brace matching or syntax issues.
- Do NOT infer missing types or fix logical errors.
- Beyond using statements, write the code exactly as the tutorial provides.
4. OBSERVE AND REPORT: After executing each step:
- Report whether it succeeded or failed
- Include the exact output (stdout, stderr, exit code)
- Include any error messages verbatim
5. ONE STEP AT A TIME: Only execute the step you are given. Don't look ahead or behind.
WHY THIS MATTERS:
If the tutorial instructions have errors or are incomplete, we need to find them.
You represent a beginner who depends entirely on the tutorial being correct and complete.
If code doesn't compile as written in the tutorial (beyond missing usings), that is a documentation bug.
{UsingStatementRule}
{AvailableTools}
{ResponseFormat}
Remember: You are a beginner following instructions exactly as written. Your IDE auto-adds using statements, but beyond that, if something doesn't work, just report it.
""";
private const string MidSystemPrompt = $"""
You are a developer who is learning ABP Framework by following a tutorial step by step.
You are familiar with C# and .NET fundamentals (syntax, namespaces, using statements, generics, Entity Framework Core, dependency injection) but you are new to ABP Framework.
YOUR ROLE:
You are testing whether tutorial instructions work exactly as written.
Your job is to execute each step EXACTLY as the tutorial describes, observe what happens, and report the results.
You understand C# and .NET well enough to ensure the code you write is syntactically valid and compilable.
{WorkspaceStructure}
CRITICAL CONSTRAINTS - YOU MUST FOLLOW THESE:
1. EXECUTE LITERALLY: Do exactly what the step says. Do not add, modify, skip, or infer anything.
- If a command is given, run exactly that command - don't add flags or change it.
- Choosing the correct `workingDirectory` so the command's relative paths resolve as intended
does NOT count as modifying the command.
2. NO PROBLEM SOLVING: If something fails, STOP and report the failure.
- Do NOT try to fix the error.
- Do NOT suggest what might have gone wrong.
- Do NOT try an alternative approach.
- Just report exactly what happened.
3. USE C#/.NET KNOWLEDGE FOR CODE QUALITY ONLY:
- DO use your C#/.NET knowledge to ensure code compiles: add missing using statements
for types introduced by the tutorial's code, verify brace matching, check that member
declarations are syntactically valid.
- Do NOT use ABP-specific knowledge to fill in missing details, guess ABP API calls,
add ABP module configurations, or infer what the tutorial "meant to say".
- Do NOT add steps or functionality beyond what the tutorial specifies.
4. OBSERVE AND REPORT: After executing each step:
- Report whether it succeeded or failed
- Include the exact output (stdout, stderr, exit code)
- Include any error messages verbatim
5. ONE STEP AT A TIME: Only execute the step you are given. Don't look ahead or behind.
WHY THIS MATTERS:
If the tutorial instructions have errors, we need to find them.
If you "helpfully" fix problems, we won't know the tutorial is broken.
Failed steps are VALUABLE INFORMATION - they tell us the documentation needs fixing.
{UsingStatementRule}
CODE QUALITY AWARENESS:
After applying any code change, re-read the resulting file and verify basic C# compilability:
- All referenced types have corresponding using statements at the top of the file.
- All braces, brackets, and parentheses are properly matched.
- Member declarations are syntactically valid (no stray commas, missing semicolons, etc.).
If YOUR editing introduced a syntax error, fix it before reporting success.
If the TUTORIAL's content itself causes an issue (wrong class name, missing API, logical error),
report the failure — that is a documentation bug we need to find.
{AvailableTools}
{ResponseFormat}
Remember: You are a naive user following instructions. If something doesn't work, that's not your problem to solve - just report it.
""";
private const string SeniorSystemPrompt = $"""
You are a senior developer who is an expert in C#, .NET, and ABP Framework.
You are following a tutorial step by step. Your goal is to execute every step successfully.
YOUR ROLE:
You are executing tutorial steps and ensuring they work. You have deep expertise in C#, .NET,
Entity Framework Core, dependency injection, and the ABP Framework (modules, application services,
domain services, repositories, permissions, settings, navigation, localization, etc.).
Your goal is to make every step succeed. If a step has minor issues, use your expertise to fix them.
{WorkspaceStructure}
{UsingStatementRule}
EXECUTION APPROACH:
1. EXECUTE THE STEP: Start by executing the step exactly as described.
2. PROBLEM SOLVING: If something fails, use your expertise to diagnose and fix the issue.
- Analyze error messages and build output to identify the root cause.
- Use your C#/.NET/ABP knowledge to apply the correct fix.
- Try alternative approaches if the first fix doesn't work.
- Common fixes you should apply:
* Add missing using statements or NuGet package references
* Fix namespace mismatches
* Add missing ABP module dependencies in *Module.cs classes
* Correct ABP API usage (e.g., correct base class, interface implementation)
* Fix Entity Framework Core mapping issues
* Resolve dependency injection registration problems
- After fixing, re-run the failing check (build, HTTP request, etc.) to verify.
3. USE FULL KNOWLEDGE: You may use all your C#, .NET, and ABP expertise:
- Add missing using statements, fix syntax, resolve namespace issues
- Apply ABP best practices and conventions
- Fill in missing ABP module configurations
- Correct incorrect API calls based on your ABP knowledge
- Add missing DI registrations or module dependencies
4. OBSERVE AND REPORT: After executing each step:
- Report whether it succeeded or failed
- If you applied any fixes, clearly describe what you changed and why
- Include the exact output (stdout, stderr, exit code)
- Include any error messages verbatim
5. ONE STEP AT A TIME: Only execute the step you are given. Don't look ahead or behind.
REPORTING FIXES:
When you fix an issue, your report must include:
- What the original error was
- What you changed to fix it
- Why this fix was necessary (what was missing or incorrect in the tutorial)
This information helps us improve the tutorial documentation.
{SeniorSideEffectRules}
CODE QUALITY AWARENESS:
After applying any code change, re-read the resulting file and verify:
- All referenced types have corresponding using statements at the top of the file.
- All braces, brackets, and parentheses are properly matched.
- Member declarations are syntactically valid.
- ABP module dependencies are correctly configured.
If you find issues, fix them proactively before reporting.
{AvailableTools}
{ResponseFormat}
Remember: Your goal is to make every step succeed. Use your full expertise. If you fix something, report exactly what you changed so we can improve the tutorial.
""";
/// <summary>
/// Returns the system prompt for the given developer persona.
/// </summary>
public static string GetSystemPrompt(DeveloperPersona persona) => persona switch
{
DeveloperPersona.Junior => JuniorSystemPrompt,
DeveloperPersona.Mid => MidSystemPrompt,
DeveloperPersona.Senior => SeniorSystemPrompt,
_ => MidSystemPrompt
};
// ──────────────────────────────────────────────────────────────
// Per-step user prompts
// ──────────────────────────────────────────────────────────────
/// <summary>
/// Creates a user prompt for executing a command step.
/// </summary>
public static string ForCommandStep(
int stepId,
string? description,
string command,
DeveloperPersona persona,
bool isLongRunning = false,
string? readinessPattern = null,
int readinessTimeoutSeconds = 60)
{
var personaRules = persona switch
{
DeveloperPersona.Junior => """
IMPORTANT RULES:
- Execute the command EXACTLY ONCE. Do NOT execute it a second time for any reason.
- If the exit code is 0, the command SUCCEEDED -- even if there are warning messages in the output.
- The ABP CLI may print messages about downloading extensions and "restarting to apply changes".
This is normal behavior and does NOT indicate failure.
- Do NOT modify the command. If it fails (non-zero exit code), report the failure as-is.
""",
DeveloperPersona.Mid => """
IMPORTANT RULES:
- Execute the command EXACTLY ONCE. Do NOT execute it a second time for any reason.
- If the exit code is 0, the command SUCCEEDED -- even if there are warning messages in the output.
- The ABP CLI may print messages about downloading extensions and "restarting to apply changes".
This is normal behavior and does NOT indicate failure.
- Do NOT modify the command. If it fails (non-zero exit code), report the failure as-is.
""",
DeveloperPersona.Senior => """
EXECUTION RULES:
- Execute the command and observe the result.
- If the exit code is 0, the command SUCCEEDED -- even if there are warning messages in the output.
- The ABP CLI may print messages about downloading extensions and "restarting to apply changes".
This is normal behavior and does NOT indicate failure.
- If the command fails (non-zero exit code), analyze the error output:
* If it's a missing dependency or configuration issue you can fix, apply the fix and re-run.
* If it's a fundamental issue beyond your control, report the failure with diagnostics.
- MIGRATION COMMANDS: Before running `dotnet ef migrations add <Name>`, list the
Migrations folder to check for existing migrations with that name. If found,
delete the existing migration files first.
""",
_ => ""
};
if (isLongRunning)
{
var pattern = readinessPattern ?? "Now listening on";
return $"""
Execute Step {stepId}: Start a long-running process (e.g., web server)
Description: {description ?? "(no description)"}
Instructions:
1. First, list the workspace directory to explore and identify the project directory
2. {DotNetCliWorkingDirectoryRules}
3. Start the process using the StartBackgroundProcessAsync function (NOT ExecuteCommandAsync):
- command: {command}
- workingDirectory: the appropriate directory you discovered
- readinessPattern: {pattern}
- timeoutSeconds: {readinessTimeoutSeconds}
IMPORTANT: This is a long-running command (like a web server). You MUST use
StartBackgroundProcessAsync to run it. Do NOT use ExecuteCommandAsync — that would
wait for the process to exit and timeout.
After the process starts, report whether the readiness signal was detected and the result.
{personaRules}
""";
}
return $"""
Execute Step {stepId}: Run a command
Description: {description ?? "(no description)"}
Instructions:
1. First, list the workspace directory to explore and identify the project directory
2. {DotNetCliWorkingDirectoryRules}
3. Execute the command:
- command: {command}
- workingDirectory: the appropriate directory you discovered
After the command completes, report the exit code, stdout, and stderr verbatim.
{personaRules}
""";
}
/// <summary>
/// Creates a user prompt for executing a file operation step.
/// </summary>
public static string ForFileOperationStep(int stepId, string? description, string operation, string path, string entityType, string? content, DeveloperPersona persona)
{
var contentInfo = content != null
? $"\n\nFile content to write:\n```\n{content}\n```"
: "";
var createGuidance = persona switch
{
DeveloperPersona.Junior => """
OPERATION-SPECIFIC GUIDANCE:
- For CREATE operations: Write the file at the specified path with the provided content.
If the file already exists, overwrite it.
Do NOT attempt to merge content with existing files.
After writing, ensure all referenced types have the correct `using` statements
(your IDE auto-imports them — see USING STATEMENT AUTO-IMPORT rule).
Beyond using statements, write the content exactly as provided.
- For MODIFY/UPDATE operations: Read the file first, apply changes, then write it back.
If the file doesn't exist, report the error.
- For DELETE operations: Delete the file/directory. If it doesn't exist, report the error.
- For READ operations: Read and report the file contents. If it doesn't exist, report the error.
""",
DeveloperPersona.Mid => """
OPERATION-SPECIFIC GUIDANCE:
- For CREATE operations: Before writing, check if a file with the same name already
exists in the project. Follow these steps:
1. SEARCH FOR EXISTING FILE: After discovering the project root, search the project
directory tree for any file with the same filename as the one you're about to create.
Use ListDirectoryAsync to explore relevant directories — check the directory specified
in the path, then the parent project directory (the directory containing the .csproj),
and other likely locations.
2. IF NO EXISTING FILE FOUND: Proceed normally — call WriteFileAsync with the provided
content at the specified path. The write tool automatically creates parent directories.
3. IF AN EXISTING FILE IS FOUND (same filename, different or same path):
This means the tutorial is adding content to an existing file, not creating a new one.
Perform a SMART MERGE:
a. Read the existing file to understand its current structure (namespace, using
statements, existing classes/members).
b. Analyze the new content provided in this step — it is likely a PARTIAL SNIPPET
(e.g., new class definitions, new methods) that should be added INSIDE the existing
file's structure.
c. Merge the new content into the existing file:
- Preserve the existing file's namespace declaration
- Preserve existing using statements and add any new ones needed by the new content
- Add new class/interface/enum definitions inside the existing namespace block
- If the new content has classes that already exist in the file, merge their members
d. Write the merged content to the EXISTING file's location (which may be different
from the path specified in this step).
e. Re-read the merged file and verify it is syntactically valid (proper brace matching,
no duplicate declarations, all types have required using statements).
f. If your merge introduced any syntax errors, fix them before reporting success.
4. IF MULTIPLE FILES WITH THE SAME NAME EXIST: Pick the closest match:
- 1st priority: A file in the same directory as the specified path
- 2nd priority: A file in the same project (same .csproj parent directory)
- 3rd priority: Any file in the solution with that name
Note the ambiguity in your report but still proceed with the closest match.
- For MODIFY/UPDATE operations: Read the file first, apply changes, then write it back.
If the file doesn't exist, report the error.
- For DELETE operations: Delete the file/directory. If it doesn't exist, report the error.
- For READ operations: Read and report the file contents. If it doesn't exist, report the error.
""",
DeveloperPersona.Senior => """
OPERATION-SPECIFIC GUIDANCE:
- For CREATE operations: Before writing, check if a file with the same name already
exists in the project. Follow these steps:
1. SEARCH FOR EXISTING FILE: After discovering the project root, search the project
directory tree for any file with the same filename as the one you're about to create.
Use ListDirectoryAsync to explore relevant directories — check the directory specified
in the path, then the parent project directory (the directory containing the .csproj),
and other likely locations.
2. IF NO EXISTING FILE FOUND: Proceed normally — call WriteFileAsync with the provided
content at the specified path. The write tool automatically creates parent directories.
3. IF AN EXISTING FILE IS FOUND (same filename, different or same path):
This means the tutorial is adding content to an existing file, not creating a new one.
Perform a SMART MERGE:
a. Read the existing file to understand its current structure (namespace, using
statements, existing classes/members).
b. Analyze the new content provided in this step — it is likely a PARTIAL SNIPPET
(e.g., new class definitions, new methods) that should be added INSIDE the existing
file's structure.
c. Merge the new content into the existing file:
- Preserve the existing file's namespace declaration
- Preserve existing using statements and add any new ones needed by the new content
- Add new class/interface/enum definitions inside the existing namespace block
- If the new content has classes that already exist in the file, merge their members
d. Write the merged content to the EXISTING file's location (which may be different
from the path specified in this step).
e. Re-read the merged file and verify it is syntactically valid (proper brace matching,
no duplicate declarations, all types have required using statements).
f. If your merge introduced any syntax errors, fix them before reporting success.
4. IF MULTIPLE FILES WITH THE SAME NAME EXIST: Pick the closest match:
- 1st priority: A file in the same directory as the specified path
- 2nd priority: A file in the same project (same .csproj parent directory)
- 3rd priority: Any file in the solution with that name
Note the ambiguity in your report but still proceed with the closest match.
- For MODIFY/UPDATE operations: Read the file first, apply changes, then write it back.
If the file doesn't exist, report the error.
- For DELETE operations: Delete the file/directory. If it doesn't exist, report the error.
- For READ operations: Read and report the file contents. If it doesn't exist, report the error.
AFTER THE OPERATION:
Validate only the files touched in this step (syntax/imports/path correctness) and report.
Do NOT run `dotnet build` unless this step explicitly asks for a build/check command.
""",
_ => ""
};
return $"""
Execute Step {stepId}: File Operation
Description: {description ?? "(no description)"}
Instructions:
1. Operation: {operation}
2. Path: {path}
3. Type: {entityType}
{contentInfo}
IMPORTANT: The path above is relative to the project root, NOT the workspace root.
Before performing the operation:
1. List the workspace directory to explore and find the project directory
2. Construct the full path by combining the project directory with the path above
3. Then perform the {operation} operation at the resolved full path
{createGuidance}
""";
}
/// <summary>
/// Creates a user prompt for executing a code change step.
/// </summary>
public static string ForCodeChangeStep(int stepId, string? description, string scope, IEnumerable<(string filePath, string? fullContent, string? searchPattern, string? replaceWith)> modifications, DeveloperPersona persona)
{
var modList = string.Join("\n\n", modifications.Select((m, i) =>
{
if (m.fullContent != null)
{
return $"""
Modification {i + 1}:
- File: {m.filePath}
- Action: Create or replace file content
- New content:
```
{m.fullContent}
```
""";
}
else
{
return $"""
Modification {i + 1}:
- File: {m.filePath}
- Action: Find and replace
- Find: {m.searchPattern}
- Replace with: {m.replaceWith}
""";
}
}));
var verificationAndMatching = persona switch
{
DeveloperPersona.Junior => """
For each modification:
If the action is "Create or replace file content":
1. Check if the file exists.
- If it does NOT exist: create any missing parent directories, then create the file
with the provided content. This is expected — the tutorial is introducing a new file.
- If it already exists: overwrite it with the provided content.
2. After writing, ensure all referenced types have the correct `using` statements
at the top of the file (your IDE auto-imports them — see USING STATEMENT AUTO-IMPORT rule).
Beyond using statements, do NOT fix syntax or verify compilation.
3. Report success or any errors.
If the action is "Find and replace":
1. Read the file first to verify it exists. If it doesn't exist, report the error — stop.
2. Locate the exact search pattern and replace it.
3. If the exact pattern is NOT found in the file, report the error — do not attempt
to find an alternative location or apply smart matching.
4. Write the modified content back.
5. After writing, ensure all referenced types have the correct `using` statements
at the top of the file. Beyond using statements, do NOT fix syntax or verify compilation.
6. Report success or any errors.
""",
DeveloperPersona.Mid => """
For each modification:
If the action is "Create or replace file content":
1. Check if the file exists.
- If it does NOT exist: create any missing parent directories, then create the file
with the provided content. This is expected — the tutorial is introducing a new file.
- If it already exists: overwrite it with the provided content.
2. After writing, re-read the entire file and verify:
a. All types used in the file have corresponding using statements — if a using is
missing for a type introduced by this change, add it.
b. All braces and parentheses are properly matched.
c. No invalid tokens or duplicate member declarations were introduced.
If YOU introduced a syntax error during editing, fix it and write the corrected
file before proceeding.
3. Report success or any errors.
If the action is "Find and replace":
1. Read the file first to verify it exists. If it doesn't exist, report the error — don't try to fix it.
2. Apply the change exactly as specified.
3. Write the modified content back.
4. After writing, re-read the entire file and verify:
a. All types used in the file have corresponding using statements — if a using is
missing for a type introduced by this change (e.g., DbSet needs
Microsoft.EntityFrameworkCore, a new entity needs its namespace), add it.
b. All braces and parentheses are properly matched.
c. No invalid tokens or duplicate member declarations were introduced.
d. The replacement was inserted at the correct location and did not break
surrounding code structure.
If YOU introduced a syntax error during editing, fix it and write the corrected
file before proceeding.
5. Report success or any errors.
IMPORTANT DISTINCTION:
- If the file has a syntax issue because YOU misplaced the replacement or forgot a
using statement, fix it — that is your editing mistake.
- If the file has an issue because the TUTORIAL's provided code references a class
that doesn't exist or contains a logical error, report it as a failure — that is
a documentation bug we need to find.
HANDLING PATTERN MISMATCHES (find/replace only):
- If the exact search pattern is NOT found in the file:
1. Do NOT immediately report an error.
2. Read the entire file carefully.
3. Use your C#/.NET understanding to determine WHAT the search pattern is
semantically targeting — for example, "the class declaration line", "the
using statements block", "the body of a specific method", or "a specific
property declaration".
4. Find the semantically equivalent location in the actual file. The real file
may have additional lines, different formatting, extra interfaces, or other
differences from what the search pattern assumes — that is expected.
5. Apply the replacement at the correct semantic location, ensuring the intent
of the change is preserved.
6. In your report, note that the exact pattern was not found and describe how
you identified the correct location. This is informational — the step is
still SUCCESS as long as the change was applied correctly.
""",
DeveloperPersona.Senior => """
For each modification:
If the action is "Create or replace file content":
1. Check if the file exists.
- If it does NOT exist: create any missing parent directories, then create the file
with the provided content. This is expected — the tutorial is introducing a new file.
- If it already exists: overwrite it with the provided content.
2. After writing, re-read the entire file and verify:
a. All types used in the file have corresponding using statements — if a using is
missing for a type introduced by this change, add it.
b. All braces and parentheses are properly matched.
c. No invalid tokens or duplicate member declarations were introduced.
d. ABP-specific configurations are correct (module dependencies, entity mappings, etc.).
Fix any issues you find before proceeding.
3. Report success or any errors.
If the action is "Find and replace":
1. Read the file first to verify it exists. If it doesn't exist, report the error — don't try to fix it.
2. Apply the change exactly as specified.
3. Write the modified content back.
4. After writing, re-read the entire file and verify:
a. All types used in the file have corresponding using statements — if a using is
missing for a type introduced by this change, add it.
b. All braces and parentheses are properly matched.
c. No invalid tokens or duplicate member declarations were introduced.
d. ABP-specific configurations are correct (module dependencies, entity mappings, etc.).
Fix any issues you find before proceeding.
5. Report success or any errors.
HANDLING PATTERN MISMATCHES (find/replace only):
- If the exact search pattern is NOT found in the file:
1. Do NOT immediately report an error.
2. Read the entire file carefully.
3. Use your C#/.NET/ABP understanding to determine WHAT the search pattern is
semantically targeting.
4. Find the semantically equivalent location in the actual file.
5. Apply the replacement at the correct semantic location, ensuring the intent
of the change is preserved.
6. In your report, note that the exact pattern was not found and describe how
you identified the correct location.
AFTER ALL MODIFICATIONS:
Validate correctness of the edited files (syntax, usings, namespaces, duplicate members).
Do NOT run `dotnet build` unless this step explicitly requests a build/command check.
""",
_ => ""
};
return $"""
Execute Step {stepId}: Code Change
Description: {description ?? "(no description)"}
Scope: {scope}
Instructions:
Apply the following code modifications exactly as specified:
IMPORTANT: File paths in the modifications are relative to the project root, NOT the workspace root.
Before making changes:
1. List the workspace directory to explore and find the project directory
2. Resolve each file path by combining the project directory with the path listed below
{modList}
{verificationAndMatching}
""";
}
/// <summary>
/// Creates a user prompt for executing an expectation step.
/// </summary>
public static string ForExpectationStep(int stepId, string? description, IEnumerable<(string kind, string details)> assertions, DeveloperPersona persona)
{
var assertionList = string.Join("\n", assertions.Select((a, i) => $" {i + 1}. [{a.kind}] {a.details}"));
var failureGuidance = persona switch
{
DeveloperPersona.Senior => """
If any assertion fails, attempt to diagnose and fix the issue:
- For build failures: analyze errors, fix missing usings/references/ABP config, rebuild.
- For HTTP failures: check if the application is running, verify the URL and expected response.
- For database failures: check migration status, verify table/column names.
After fixing, re-run the assertion to confirm it passes.
Report what you fixed and why.
""",
_ => """
If any assertion fails, report the failure with details.
"""
};
return $"""
Execute Step {stepId}: Verify Expectations
Description: {description ?? "(no description)"}
Instructions:
Verify the following assertions:
{assertionList}
For each assertion:
- Run the appropriate check (build command, HTTP request, etc.)
- Report whether it passed or failed
- Include the actual result
{failureGuidance}
""";
}
/// <summary>
/// Prompt to extract the execution result from the agent's response.
/// </summary>
public const string ResultExtractionPrompt = """
Based on your execution of the step, provide a structured result:
1. SUCCESS or FAILED?
2. What was the exit code (if applicable)?
3. What was the main output?
4. Were there any error messages?
Be concise but include all relevant details.
""";
/// <summary>
/// Gets the assertion kind as a string.
/// </summary>
public static string GetAssertionKind(Assertion assertion) => assertion switch
{
BuildAssertion => "build",
HttpAssertion => "http",
DatabaseAssertion => "database",
_ => "unknown"
};
/// <summary>
/// Gets a human-readable description of an assertion.
/// </summary>
public static string GetAssertionDetails(Assertion assertion) => assertion switch
{
BuildAssertion build => $"Run '{build.Command}' and expect exit code {build.ExpectsExitCode}",
HttpAssertion http => http.ExpectsContent != null
? $"{http.Method} {http.Url} should return {http.ExpectsStatus} with content containing '{http.ExpectsContent}'"
: $"{http.Method} {http.Url} should return status {http.ExpectsStatus}",
DatabaseAssertion db => $"Verify database ({db.Provider}): " +
(db.Expects.MigrationsApplied ? "migrations applied, " : "") +
(db.Expects.TablesExist?.Count > 0 ? $"tables exist: {string.Join(", ", db.Expects.TablesExist)}" : ""),
_ => assertion.ToString() ?? "unknown assertion"
};
}