-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
139 lines (118 loc) · 5.07 KB
/
Copy pathProgram.cs
File metadata and controls
139 lines (118 loc) · 5.07 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
using DotNetEnv;
using DotNuxt;
using Microsoft.Agents.AI.Workflows;
ApplyWorkingDirectory(args);
LoadEnvironment();
var modelId = Env.GetString("MODEL_ID", "qwen3.6:35b-a3b");
var workspaceDir = Directory.GetCurrentDirectory();
var skillsDir = Path.Combine(AppContext.BaseDirectory, "skills");
Console.WriteLine("dotnuxt - .NET Coding Agent (Microsoft Agent Framework)");
Console.WriteLine($"Model: {modelId}");
Console.WriteLine($"Workspace: {workspaceDir}");
Console.WriteLine($"Skills directory: {skillsDir}");
Console.WriteLine();
Console.WriteLine("Usage: /build <prompt> — Write code, create files, build projects");
Console.WriteLine(" /ask <prompt> — Answer questions, explain concepts, provide guidance");
Console.WriteLine(" /skills — List available skills");
Console.WriteLine(" /plugins — List available plugins");
Console.WriteLine(" /exit — Quit\n");
// --- Single main prompt loop ---
var builderAgent = BuilderAgentFactory.Create(skillsDir);
var session = await builderAgent.CreateSessionAsync();
var questionAgent = BuilderAgentFactory.CreateQuestionAgent();
while (true)
{
Console.Write("> ");
var input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input)) continue;
var trimmed = input.Trim();
if (IsCommand(trimmed, "exit")) break;
if (IsCommand(trimmed, "skills")) { ListSkills(skillsDir); continue; }
if (IsCommand(trimmed, "plugins")) { ListPlugins(skillsDir); continue; }
// Parse command prefix
var parts = trimmed.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries);
var command = parts[0].ToLowerInvariant();
var prompt = parts.Length > 1 ? parts[1] : string.Empty;
switch (command)
{
case "/build":
if (string.IsNullOrWhiteSpace(prompt))
{
Console.WriteLine("Error: /build requires a prompt. Example: /build Create a new ASP.NET Core controller");
continue;
}
await foreach (var update in builderAgent.RunStreamingAsync(prompt, session))
{
Console.Write(update);
}
Console.WriteLine("\n");
break;
case "/ask":
if (string.IsNullOrWhiteSpace(prompt))
{
Console.WriteLine("Error: /ask requires a prompt. Example: /ask What is the tech stack of this project?");
continue;
}
Console.WriteLine("\n---");
await foreach (var update in questionAgent.RunStreamingAsync(prompt))
{
Console.Write(update);
}
Console.WriteLine("\n---\n");
break;
default:
Console.WriteLine("Error: Unknown or missing command prefix. Use /build, /ask, /skills, /plugins, or /exit.");
Console.WriteLine("Usage: /build <prompt> — Write code, create files, build projects");
Console.WriteLine(" /ask <prompt> — Answer questions, explain concepts, provide guidance");
break;
}
}
static void ListSkills(string skillsDir)
{
if (!Directory.Exists(skillsDir)) { Console.WriteLine("No skills directory.\n"); return; }
Console.WriteLine();
foreach (var f in Directory.GetFiles(skillsDir, "SKILL.md", SearchOption.AllDirectories))
Console.WriteLine($" {Path.GetRelativePath(skillsDir, Path.GetDirectoryName(f)!)}");
Console.WriteLine();
}
static bool IsCommand(string input, string command)
{
return input.Equals(command, StringComparison.OrdinalIgnoreCase)
|| input.Equals($"/{command}", StringComparison.OrdinalIgnoreCase);
}
static void ListPlugins(string skillsDir)
{
if (!Directory.Exists(skillsDir)) { Console.WriteLine("No skills directory.\n"); return; }
Console.WriteLine();
foreach (var pluginDir in Directory.GetDirectories(skillsDir))
{
var name = Path.GetFileName(pluginDir);
var count = Directory.GetFiles(pluginDir, "SKILL.md", SearchOption.AllDirectories).Length;
Console.WriteLine($" {name} ({count} skills)");
}
Console.WriteLine();
}
static void ApplyWorkingDirectory(string[] args)
{
var cwdIndex = Array.FindIndex(args, arg => arg.Equals("--cwd", StringComparison.OrdinalIgnoreCase));
if (cwdIndex < 0)
return;
if (cwdIndex + 1 >= args.Length || string.IsNullOrWhiteSpace(args[cwdIndex + 1]))
throw new ArgumentException("--cwd requires a directory path.");
var requestedPath = Path.GetFullPath(args[cwdIndex + 1]);
if (!Directory.Exists(requestedPath))
throw new DirectoryNotFoundException($"Workspace directory not found: {requestedPath}");
Directory.SetCurrentDirectory(requestedPath);
}
static void LoadEnvironment()
{
var homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
if (!string.IsNullOrWhiteSpace(homeDir))
LoadEnvFileIfPresent(Path.Combine(homeDir, ".dotnuxt", ".env"));
LoadEnvFileIfPresent(Path.Combine(Directory.GetCurrentDirectory(), ".env"));
}
static void LoadEnvFileIfPresent(string path)
{
if (File.Exists(path))
Env.Load(path);
}