-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathInteractiveShell.cs
More file actions
123 lines (104 loc) · 4.07 KB
/
Copy pathInteractiveShell.cs
File metadata and controls
123 lines (104 loc) · 4.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
using NeuroCTF.Cli.Commands;
namespace NeuroCTF.Cli.Shell;
public sealed class InteractiveShell(CliRouter router)
{
public async Task RunAsync(CancellationToken cancellationToken)
{
string? loadedFile = null;
string? inlineInput = null;
NeuroCTF.Core.Models.AnalysisReport? lastReport = null;
var history = new List<string>();
Console.WriteLine("NeuroCTF interactive shell. Commands: load <path>, set-input <text>, analyze, decode <module>, pipeline, graph, state, history, run <command>, exit");
while (!cancellationToken.IsCancellationRequested)
{
Console.Write("neuroctf> ");
var line = Console.ReadLine();
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
history.Add(line);
var parts = Split(line);
var verb = parts[0].ToLowerInvariant();
if (verb is "exit" or "quit")
{
break;
}
if (verb == "load" && parts.Length > 1)
{
loadedFile = parts[1];
inlineInput = null;
Console.WriteLine($"Loaded {loadedFile}");
continue;
}
if (verb == "set-input" && parts.Length > 1)
{
inlineInput = string.Join(' ', parts[1..]);
loadedFile = null;
Console.WriteLine("Inline input updated");
continue;
}
if (verb == "analyze")
{
lastReport = await router.AnalyzeReportAsync(inlineInput, loadedFile, cancellationToken).ConfigureAwait(false);
Console.WriteLine(router.RenderPipelineGraph(lastReport));
continue;
}
if (verb == "pipeline")
{
lastReport ??= await router.AnalyzeReportAsync(inlineInput, loadedFile, cancellationToken).ConfigureAwait(false);
Console.WriteLine(router.RenderPipelineGraph(lastReport));
continue;
}
if (verb == "graph")
{
if (lastReport is null)
{
lastReport = await router.AnalyzeReportAsync(inlineInput, loadedFile, cancellationToken).ConfigureAwait(false);
}
Console.WriteLine(router.RenderPipelineGraph(lastReport));
continue;
}
if (verb == "state")
{
Console.WriteLine($"loaded-file: {loadedFile ?? "<none>"}");
Console.WriteLine($"inline-input: {(inlineInput is null ? "<none>" : "<set>")}");
Console.WriteLine($"last-report: {(lastReport is null ? "<none>" : lastReport.Source)}");
continue;
}
if (verb == "history")
{
for (var index = 0; index < history.Count; index++)
{
Console.WriteLine($"{index + 1}: {history[index]}");
}
continue;
}
if (verb == "decode" && parts.Length > 1)
{
await router.RouteAsync(BuildCommand(parts[1], loadedFile, inlineInput), cancellationToken).ConfigureAwait(false);
continue;
}
if (verb == "run" && parts.Length > 1)
{
await router.RouteAsync(parts[1..], cancellationToken).ConfigureAwait(false);
continue;
}
await router.RouteAsync(parts, cancellationToken).ConfigureAwait(false);
}
}
private static string[] BuildCommand(string command, string? file, string? input)
{
if (!string.IsNullOrWhiteSpace(file))
{
return [command, "--file", file];
}
if (!string.IsNullOrWhiteSpace(input))
{
return [command, "--input", input];
}
return [command];
}
private static string[] Split(string value) =>
value.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
}