First commit!

This commit is contained in:
0% [█ █ █ █ █ █ █ █ █ █] 100%
2026-06-04 20:36:13 -05:00
parent 3c97134e2f
commit ace1e61285
36 changed files with 19565 additions and 4 deletions
+17
View File
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Platforms>AnyCPU;x64</Platforms>
<ApplicationIcon>app.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Content Include="app.ico" />
</ItemGroup>
</Project>
+16
View File
@@ -0,0 +1,16 @@
// File: Logger.cs
using System;
namespace AI_C2_Server
{
public static class Logger
{
public static event Action<string> LogReceived;
public static void Log(string message)
{
Console.WriteLine(message);
LogReceived?.Invoke(message);
}
}
}
+398
View File
@@ -0,0 +1,398 @@
namespace AI_C2_Server
{
partial class MainForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
btnRestart = new Button();
panelTop = new Panel();
notifyIcon = new NotifyIcon(components);
trayContextMenu = new ContextMenuStrip(components);
showServerToolStripMenuItem = new ToolStripMenuItem();
restartServerToolStripMenuItem = new ToolStripMenuItem();
exitShutdownToolStripMenuItem = new ToolStripMenuItem();
restartApplicationToolStripMenuItem = new ToolStripMenuItem();
tabControl1 = new TabControl();
tabPageConsole = new TabPage();
rtbConsole = new TextBox();
tabPageInstances = new TabPage();
listViewInstances = new ListView();
colPlatform = new ColumnHeader();
colInstanceId = new ColumnHeader();
colStatus = new ColumnHeader();
colLastSeen = new ColumnHeader();
instanceContextMenu = new ContextMenuStrip(components);
resetChatToolStripMenuItem = new ToolStripMenuItem();
shutdownHarnessToolStripMenuItem = new ToolStripMenuItem();
panelInstanceActions = new Panel();
btnShutdown = new Button();
btnResetChat = new Button();
tabPageOpenAI = new TabPage();
txtOpenAIKey = new TextBox();
lblKey = new Label();
txtOpenAIUrl = new TextBox();
lblUrl = new Label();
chkEnableOpenAI = new CheckBox();
timerUpdateInstances = new System.Windows.Forms.Timer(components);
panelTop.SuspendLayout();
trayContextMenu.SuspendLayout();
tabControl1.SuspendLayout();
tabPageConsole.SuspendLayout();
tabPageInstances.SuspendLayout();
instanceContextMenu.SuspendLayout();
panelInstanceActions.SuspendLayout();
tabPageOpenAI.SuspendLayout();
SuspendLayout();
//
// btnRestart
//
btnRestart.Location = new Point(12, 12);
btnRestart.Name = "btnRestart";
btnRestart.Size = new Size(120, 25);
btnRestart.TabIndex = 0;
btnRestart.Text = "Restart Server";
btnRestart.UseVisualStyleBackColor = true;
btnRestart.Click += btnRestart_Click;
//
// panelTop
//
panelTop.Controls.Add(btnRestart);
panelTop.Dock = DockStyle.Top;
panelTop.Location = new Point(0, 0);
panelTop.Name = "panelTop";
panelTop.Size = new Size(800, 50);
panelTop.TabIndex = 0;
//
// notifyIcon
//
notifyIcon.BalloonTipText = "Server Running...";
notifyIcon.BalloonTipTitle = "AI C2 Server";
notifyIcon.ContextMenuStrip = trayContextMenu;
notifyIcon.Icon = (Icon)resources.GetObject("notifyIcon.Icon");
notifyIcon.Text = "AI C2 Server";
notifyIcon.MouseClick += notifyIcon_Click;
notifyIcon.MouseDoubleClick += notifyIcon_MouseDoubleClick;
//
// trayContextMenu
//
trayContextMenu.Items.AddRange(new ToolStripItem[] { showServerToolStripMenuItem, restartServerToolStripMenuItem, restartApplicationToolStripMenuItem, exitShutdownToolStripMenuItem });
trayContextMenu.Name = "trayContextMenu";
trayContextMenu.RenderMode = ToolStripRenderMode.System;
trayContextMenu.Size = new Size(175, 92);
//
// showServerToolStripMenuItem
//
showServerToolStripMenuItem.Name = "showServerToolStripMenuItem";
showServerToolStripMenuItem.Size = new Size(174, 22);
showServerToolStripMenuItem.Text = "Show Server";
showServerToolStripMenuItem.Click += showServerToolStripMenuItem_Click;
//
// restartServerToolStripMenuItem
//
restartServerToolStripMenuItem.Name = "restartServerToolStripMenuItem";
restartServerToolStripMenuItem.Size = new Size(174, 22);
restartServerToolStripMenuItem.Text = "Restart Server";
restartServerToolStripMenuItem.Click += restartServerToolStripMenuItem_Click;
//
// exitShutdownToolStripMenuItem
//
exitShutdownToolStripMenuItem.Name = "exitShutdownToolStripMenuItem";
exitShutdownToolStripMenuItem.Size = new Size(174, 22);
exitShutdownToolStripMenuItem.Text = "Shutdown && Exit";
exitShutdownToolStripMenuItem.Click += exitShutdownToolStripMenuItem_Click;
//
// restartApplicationToolStripMenuItem
//
restartApplicationToolStripMenuItem.Name = "restartApplicationToolStripMenuItem";
restartApplicationToolStripMenuItem.Size = new Size(174, 22);
restartApplicationToolStripMenuItem.Text = "Restart Application";
restartApplicationToolStripMenuItem.Click += restartApplicationToolStripMenuItem_Click;
//
// tabControl1
//
tabControl1.Controls.Add(tabPageConsole);
tabControl1.Controls.Add(tabPageInstances);
tabControl1.Controls.Add(tabPageOpenAI);
tabControl1.Dock = DockStyle.Fill;
tabControl1.Location = new Point(0, 50);
tabControl1.Name = "tabControl1";
tabControl1.SelectedIndex = 0;
tabControl1.Size = new Size(800, 400);
tabControl1.TabIndex = 1;
//
// tabPageConsole
//
tabPageConsole.BackColor = SystemColors.Control;
tabPageConsole.Controls.Add(rtbConsole);
tabPageConsole.Location = new Point(4, 24);
tabPageConsole.Name = "tabPageConsole";
tabPageConsole.Padding = new Padding(3);
tabPageConsole.Size = new Size(792, 372);
tabPageConsole.TabIndex = 0;
tabPageConsole.Text = "Console";
//
// rtbConsole
//
rtbConsole.BackColor = Color.Black;
rtbConsole.BorderStyle = BorderStyle.FixedSingle;
rtbConsole.Dock = DockStyle.Fill;
rtbConsole.ForeColor = Color.LightGray;
rtbConsole.Location = new Point(3, 3);
rtbConsole.Multiline = true;
rtbConsole.Name = "rtbConsole";
rtbConsole.ReadOnly = true;
rtbConsole.ScrollBars = ScrollBars.Vertical;
rtbConsole.Size = new Size(786, 366);
rtbConsole.TabIndex = 2;
//
// tabPageInstances
//
tabPageInstances.BackColor = SystemColors.Control;
tabPageInstances.Controls.Add(listViewInstances);
tabPageInstances.Controls.Add(panelInstanceActions);
tabPageInstances.Location = new Point(4, 24);
tabPageInstances.Name = "tabPageInstances";
tabPageInstances.Padding = new Padding(3);
tabPageInstances.Size = new Size(792, 372);
tabPageInstances.TabIndex = 1;
tabPageInstances.Text = "Instance Management";
//
// listViewInstances
//
listViewInstances.BorderStyle = BorderStyle.FixedSingle;
listViewInstances.Columns.AddRange(new ColumnHeader[] { colPlatform, colInstanceId, colStatus, colLastSeen });
listViewInstances.ContextMenuStrip = instanceContextMenu;
listViewInstances.Dock = DockStyle.Fill;
listViewInstances.FullRowSelect = true;
listViewInstances.GridLines = true;
listViewInstances.Location = new Point(3, 3);
listViewInstances.MultiSelect = false;
listViewInstances.Name = "listViewInstances";
listViewInstances.Size = new Size(786, 326);
listViewInstances.TabIndex = 1;
listViewInstances.UseCompatibleStateImageBehavior = false;
listViewInstances.View = View.Details;
//
// colPlatform
//
colPlatform.Text = "Platform";
colPlatform.Width = 150;
//
// colInstanceId
//
colInstanceId.Text = "Instance ID";
colInstanceId.Width = 250;
//
// colStatus
//
colStatus.Text = "Status";
colStatus.Width = 100;
//
// colLastSeen
//
colLastSeen.Text = "Last Seen";
colLastSeen.Width = 150;
//
// instanceContextMenu
//
instanceContextMenu.Items.AddRange(new ToolStripItem[] { resetChatToolStripMenuItem, shutdownHarnessToolStripMenuItem });
instanceContextMenu.Name = "instanceContextMenu";
instanceContextMenu.Size = new Size(174, 48);
//
// resetChatToolStripMenuItem
//
resetChatToolStripMenuItem.Name = "resetChatToolStripMenuItem";
resetChatToolStripMenuItem.Size = new Size(173, 22);
resetChatToolStripMenuItem.Text = "Reset Chat";
resetChatToolStripMenuItem.Click += resetChatToolStripMenuItem_Click;
//
// shutdownHarnessToolStripMenuItem
//
shutdownHarnessToolStripMenuItem.Name = "shutdownHarnessToolStripMenuItem";
shutdownHarnessToolStripMenuItem.Size = new Size(173, 22);
shutdownHarnessToolStripMenuItem.Text = "Shutdown Harness";
shutdownHarnessToolStripMenuItem.Click += shutdownHarnessToolStripMenuItem_Click;
//
// panelInstanceActions
//
panelInstanceActions.Controls.Add(btnShutdown);
panelInstanceActions.Controls.Add(btnResetChat);
panelInstanceActions.Dock = DockStyle.Bottom;
panelInstanceActions.Location = new Point(3, 329);
panelInstanceActions.Name = "panelInstanceActions";
panelInstanceActions.Size = new Size(786, 40);
panelInstanceActions.TabIndex = 0;
//
// btnShutdown
//
btnShutdown.Location = new Point(111, 8);
btnShutdown.Name = "btnShutdown";
btnShutdown.Size = new Size(120, 25);
btnShutdown.TabIndex = 1;
btnShutdown.Text = "Shutdown Harness";
btnShutdown.UseVisualStyleBackColor = true;
btnShutdown.Click += btnShutdown_Click;
//
// btnResetChat
//
btnResetChat.Location = new Point(5, 8);
btnResetChat.Name = "btnResetChat";
btnResetChat.Size = new Size(100, 25);
btnResetChat.TabIndex = 0;
btnResetChat.Text = "Reset Chat";
btnResetChat.UseVisualStyleBackColor = true;
btnResetChat.Click += btnResetChat_Click;
//
// tabPageOpenAI
//
tabPageOpenAI.BackColor = SystemColors.Control;
tabPageOpenAI.Controls.Add(txtOpenAIKey);
tabPageOpenAI.Controls.Add(lblKey);
tabPageOpenAI.Controls.Add(txtOpenAIUrl);
tabPageOpenAI.Controls.Add(lblUrl);
tabPageOpenAI.Controls.Add(chkEnableOpenAI);
tabPageOpenAI.Location = new Point(4, 24);
tabPageOpenAI.Name = "tabPageOpenAI";
tabPageOpenAI.Padding = new Padding(3);
tabPageOpenAI.Size = new Size(792, 372);
tabPageOpenAI.TabIndex = 2;
tabPageOpenAI.Text = "OpenAI API";
//
// txtOpenAIKey
//
txtOpenAIKey.BorderStyle = BorderStyle.FixedSingle;
txtOpenAIKey.Location = new Point(100, 85);
txtOpenAIKey.Name = "txtOpenAIKey";
txtOpenAIKey.Size = new Size(400, 23);
txtOpenAIKey.TabIndex = 4;
txtOpenAIKey.TextChanged += txtOpenAIKey_TextChanged;
//
// lblKey
//
lblKey.AutoSize = true;
lblKey.Location = new Point(20, 88);
lblKey.Name = "lblKey";
lblKey.Size = new Size(50, 15);
lblKey.TabIndex = 3;
lblKey.Text = "API Key:";
//
// txtOpenAIUrl
//
txtOpenAIUrl.BorderStyle = BorderStyle.FixedSingle;
txtOpenAIUrl.Location = new Point(100, 50);
txtOpenAIUrl.Name = "txtOpenAIUrl";
txtOpenAIUrl.Size = new Size(400, 23);
txtOpenAIUrl.TabIndex = 2;
txtOpenAIUrl.TextChanged += txtOpenAIUrl_TextChanged;
//
// lblUrl
//
lblUrl.AutoSize = true;
lblUrl.Location = new Point(20, 53);
lblUrl.Name = "lblUrl";
lblUrl.Size = new Size(52, 15);
lblUrl.TabIndex = 1;
lblUrl.Text = "API URL:";
//
// chkEnableOpenAI
//
chkEnableOpenAI.AutoSize = true;
chkEnableOpenAI.Location = new Point(20, 20);
chkEnableOpenAI.Name = "chkEnableOpenAI";
chkEnableOpenAI.Size = new Size(159, 19);
chkEnableOpenAI.TabIndex = 0;
chkEnableOpenAI.Text = "Enable OpenAI API Mode";
chkEnableOpenAI.UseVisualStyleBackColor = true;
chkEnableOpenAI.CheckedChanged += chkEnableOpenAI_CheckedChanged;
//
// timerUpdateInstances
//
timerUpdateInstances.Interval = 2000;
timerUpdateInstances.Tick += timerUpdateInstances_Tick;
//
// MainForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Controls.Add(tabControl1);
Controls.Add(panelTop);
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "MainForm";
Text = "AI C2 Server Console";
FormClosing += MainForm_FormClosing;
Load += MainForm_Load;
Resize += MainForm_Resize;
panelTop.ResumeLayout(false);
trayContextMenu.ResumeLayout(false);
tabControl1.ResumeLayout(false);
tabPageConsole.ResumeLayout(false);
tabPageConsole.PerformLayout();
tabPageInstances.ResumeLayout(false);
instanceContextMenu.ResumeLayout(false);
panelInstanceActions.ResumeLayout(false);
tabPageOpenAI.ResumeLayout(false);
tabPageOpenAI.PerformLayout();
ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnRestart;
private System.Windows.Forms.Panel panelTop;
private System.Windows.Forms.NotifyIcon notifyIcon;
private System.Windows.Forms.ContextMenuStrip trayContextMenu;
private System.Windows.Forms.ToolStripMenuItem showServerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem restartServerToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exitShutdownToolStripMenuItem;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPageConsole;
private System.Windows.Forms.TextBox rtbConsole;
private System.Windows.Forms.TabPage tabPageInstances;
private System.Windows.Forms.TabPage tabPageOpenAI;
private System.Windows.Forms.ListView listViewInstances;
private System.Windows.Forms.ColumnHeader colPlatform;
private System.Windows.Forms.ColumnHeader colInstanceId;
private System.Windows.Forms.ColumnHeader colStatus;
private System.Windows.Forms.ColumnHeader colLastSeen;
private System.Windows.Forms.Panel panelInstanceActions;
private System.Windows.Forms.Button btnShutdown;
private System.Windows.Forms.Button btnResetChat;
private System.Windows.Forms.TextBox txtOpenAIKey;
private System.Windows.Forms.Label lblKey;
private System.Windows.Forms.TextBox txtOpenAIUrl;
private System.Windows.Forms.Label lblUrl;
private System.Windows.Forms.CheckBox chkEnableOpenAI;
private System.Windows.Forms.Timer timerUpdateInstances;
private System.Windows.Forms.ContextMenuStrip instanceContextMenu;
private System.Windows.Forms.ToolStripMenuItem resetChatToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem shutdownHarnessToolStripMenuItem;
private ToolStripMenuItem restartApplicationToolStripMenuItem;
}
}
+287
View File
@@ -0,0 +1,287 @@
// File: MainForm.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text.Json.Nodes;
using System.Windows.Forms;
namespace AI_C2_Server
{
public partial class MainForm : Form
{
[DllImport("user32.dll", SetLastError = true)]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
public MainForm()
{
InitializeComponent();
Logger.LogReceived += Logger_LogReceived;
}
private void MainForm_Load(object sender, EventArgs e)
{
notifyIcon.Visible = false;
// Load initial OpenAI settings
chkEnableOpenAI.Checked = OperationCenter.Instance.UseOpenAIMode;
txtOpenAIUrl.Text = OperationCenter.Instance.OpenAIApiUrl;
txtOpenAIKey.Text = OperationCenter.Instance.OpenAIApiKey;
WebServer.Instance.Start();
timerUpdateInstances.Start();
this.Deactivate += MainForm_Deactivate;
}
private void MainForm_Deactivate(object? sender, EventArgs e)
{
if (!this.Disposing && !this.IsDisposed)
{
notifyIcon?.Visible = true;
this.Hide();
}
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
timerUpdateInstances.Stop();
WebServer.Instance.Stop();
}
private void Logger_LogReceived(string message)
{
if (rtbConsole.InvokeRequired)
{
rtbConsole.Invoke(new Action(() => Logger_LogReceived(message)));
return;
}
rtbConsole.AppendText($"[{DateTime.Now:HH:mm:ss}] {message}" + Environment.NewLine);
if (rtbConsole.Lines.Length > 1000)
{
int excessLines = rtbConsole.Lines.Length - 1000;
int indexToCut = rtbConsole.GetFirstCharIndexFromLine(excessLines);
rtbConsole.Select(0, indexToCut);
rtbConsole.SelectedText = "";
}
rtbConsole.ScrollToCaret();
}
private void RestartServer()
{
Logger.Log("[SYSTEM] Restarting server and clearing state...");
WebServer.Instance.Stop();
OperationCenter.Instance.ClearAll();
listViewInstances.Items.Clear();
// Reset UI state for OpenAI
chkEnableOpenAI.Checked = false;
WebServer.Instance.Start();
}
private void btnRestart_Click(object sender, EventArgs e)
{
RestartServer();
}
private void MainForm_Resize(object sender, EventArgs e)
{
if (this.WindowState == FormWindowState.Minimized)
{
notifyIcon.Visible = true;
this.Hide();
}
}
private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{
RestoreForm();
}
private void notifyIcon_Click(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
RestoreForm();
}
}
private void showServerToolStripMenuItem_Click(object sender, EventArgs e)
{
RestoreForm();
}
private void RestoreForm()
{
this.Show();
//this.WindowState = FormWindowState.Normal;
this.BringToFront();
notifyIcon.Visible = false;
SwitchToThisWindow(this.Handle, true);
}
private void restartServerToolStripMenuItem_Click(object sender, EventArgs e)
{
RestartServer();
}
private void exitShutdownToolStripMenuItem_Click(object sender, EventArgs e)
{
WebServer.Instance.Stop();
OperationCenter.Instance.ClearAll();
Close();
}
private void timerUpdateInstances_Tick(object sender, EventArgs e)
{
var instances = OperationCenter.Instance.GetActiveInstances();
listViewInstances.BeginUpdate();
// Remove stale items
var keysToRemove = new List<ListViewItem>();
foreach (ListViewItem item in listViewInstances.Items)
{
if (!instances.ContainsKey(item.Name)) keysToRemove.Add(item);
}
foreach (var item in keysToRemove) listViewInstances.Items.Remove(item);
// Add or update items
foreach (var kvp in instances)
{
string id = kvp.Key;
var data = kvp.Value as JsonObject;
string platform = data?["platform"]?.ToString() ?? "Unknown";
string status = (data?["is_busy"]?.GetValue<bool>() ?? false) ? "Busy" : "Idle";
DateTime lastSeenTime;
string lastSeenStr = data?["last_seen"]?.ToString() ?? "";
if (DateTime.TryParse(lastSeenStr, out lastSeenTime))
{
lastSeenStr = lastSeenTime.ToString("HH:mm:ss");
}
if (listViewInstances.Items.ContainsKey(id))
{
var item = listViewInstances.Items[id];
item.SubItems[0].Text = platform;
item.SubItems[1].Text = id;
item.SubItems[2].Text = status;
item.SubItems[3].Text = lastSeenStr;
}
else
{
var item = new ListViewItem(new[] { platform, id, status, lastSeenStr }) { Name = id };
listViewInstances.Items.Add(item);
}
}
listViewInstances.EndUpdate();
// Keep the checkbox in sync if the OpenAI instance was shut down via the list view
if (chkEnableOpenAI.Checked && !OperationCenter.Instance.UseOpenAIMode)
{
chkEnableOpenAI.Checked = false;
}
}
private void ResetSelectedInstanceChat()
{
if (listViewInstances.SelectedItems.Count > 0)
{
string instanceId = listViewInstances.SelectedItems[0].Name;
if (OperationCenter.Instance.IsOpenAIInstance(instanceId))
{
OperationCenter.Instance.ClearChatHistory(instanceId);
Logger.Log($"[ADMIN] Reset chat history for OpenAI instance {instanceId}");
}
else
{
OperationCenter.Instance.QueueCommand(new JsonObject { ["type"] = "NEW_CHAT" }, instanceId);
Logger.Log($"[ADMIN] Sent NEW_CHAT command to {instanceId}");
}
}
}
private void ShutdownSelectedInstance()
{
if (listViewInstances.SelectedItems.Count > 0)
{
string instanceId = listViewInstances.SelectedItems[0].Name;
OperationCenter.Instance.ShutdownInstance(instanceId);
Logger.Log($"[ADMIN] Sent SHUTDOWN command to {instanceId} and removed from active list.");
listViewInstances.Items.RemoveByKey(instanceId);
}
}
private void btnResetChat_Click(object sender, EventArgs e)
{
ResetSelectedInstanceChat();
}
private void btnShutdown_Click(object sender, EventArgs e)
{
ShutdownSelectedInstance();
}
private void resetChatToolStripMenuItem_Click(object sender, EventArgs e)
{
ResetSelectedInstanceChat();
}
private void shutdownHarnessToolStripMenuItem_Click(object sender, EventArgs e)
{
ShutdownSelectedInstance();
}
private void chkEnableOpenAI_CheckedChanged(object sender, EventArgs e)
{
if (chkEnableOpenAI.Checked)
{
OperationCenter.Instance.EnableOpenAIMode(txtOpenAIUrl.Text, txtOpenAIKey.Text);
Logger.Log($"[SYSTEM] OpenAI API Mode: Enabled");
}
else
{
OperationCenter.Instance.DisableOpenAIMode();
Logger.Log($"[SYSTEM] OpenAI API Mode: Disabled");
}
}
private void txtOpenAIUrl_TextChanged(object sender, EventArgs e)
{
if (OperationCenter.Instance.UseOpenAIMode)
{
OperationCenter.Instance.OpenAIApiUrl = txtOpenAIUrl.Text;
OperationCenter.Instance.UpdateOpenAIUrl(txtOpenAIUrl.Text);
}
}
private void txtOpenAIKey_TextChanged(object sender, EventArgs e)
{
if (OperationCenter.Instance.UseOpenAIMode)
{
OperationCenter.Instance.OpenAIApiKey = txtOpenAIKey.Text;
}
}
private void restartApplicationToolStripMenuItem_Click(object sender, EventArgs e)
{
// Start a new instance of the current executable
Process.Start(new ProcessStartInfo
{
FileName = Environment.ProcessPath,
UseShellExecute = true
});
WebServer.Instance.Stop();
OperationCenter.Instance.ClearAll();
Close();
}
}
}
File diff suppressed because it is too large Load Diff
+429
View File
@@ -0,0 +1,429 @@
// File: OperationCenter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Nodes;
namespace AI_C2_Server
{
public class OperationCenter
{
public static OperationCenter Instance { get; } = new OperationCenter();
private readonly Dictionary<string, Queue<JsonObject>> commandQueues = new();
private readonly Dictionary<string, JsonObject> results = new();
private readonly Dictionary<string, List<string>> pendingTaskIds = new();
private readonly Dictionary<string, JsonObject> instances = new();
private readonly Dictionary<string, JsonArray> chatHistory = new();
private readonly Dictionary<string, JsonObject> tasks = new();
// Tracks instances that have been shut down so they aren't recreated by lingering heartbeats
private readonly HashSet<string> blacklistedInstances = new();
private readonly object queueLock = new object();
// OpenAI Configuration
public bool UseOpenAIMode { get; set; } = false;
public string OpenAIApiUrl { get; set; } = "http://192.168.12.181:8080/v1/chat/completions";
public string OpenAIApiKey { get; set; } = "";
public string OpenAIInstanceId { get; private set; }
public string OpenAIModelName { get; set; } = "";
public string OpenAISystemInstructions { get; set; } = "";
private OperationCenter() { }
public void ClearAll()
{
lock (queueLock)
{
commandQueues.Clear();
results.Clear();
pendingTaskIds.Clear();
instances.Clear();
chatHistory.Clear();
tasks.Clear();
blacklistedInstances.Clear();
UseOpenAIMode = false;
OpenAIInstanceId = null;
OpenAIModelName = "";
OpenAISystemInstructions = "";
}
}
public bool IsOpenAIInstance(string instanceId)
{
return !string.IsNullOrEmpty(OpenAIInstanceId) && instanceId == OpenAIInstanceId;
}
public string EnableOpenAIMode(string url, string key)
{
lock (queueLock)
{
UseOpenAIMode = true;
OpenAIApiUrl = url;
OpenAIApiKey = key;
OpenAIModelName = ""; // Reset model name so it fetches on next run
if (string.IsNullOrEmpty(OpenAIInstanceId))
{
OpenAIInstanceId = $"inst_openai_{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
}
instances[OpenAIInstanceId] = new JsonObject
{
["last_seen"] = DateTime.Now.ToString("o"),
["url"] = url,
["turn_count"] = 0,
["is_busy"] = false,
["platform"] = "OpenAI API"
};
if (!chatHistory.ContainsKey(OpenAIInstanceId))
{
chatHistory[OpenAIInstanceId] = new JsonArray();
}
Logger.Log($"[OP-CENTER] OpenAI API instance registered: {OpenAIInstanceId}");
return OpenAIInstanceId;
}
}
public void DisableOpenAIMode()
{
lock (queueLock)
{
UseOpenAIMode = false;
OpenAIModelName = "";
if (!string.IsNullOrEmpty(OpenAIInstanceId))
{
instances.Remove(OpenAIInstanceId);
Logger.Log($"[OP-CENTER] OpenAI API instance removed: {OpenAIInstanceId}");
OpenAIInstanceId = null;
}
}
}
public void UpdateOpenAIUrl(string url)
{
lock (queueLock)
{
OpenAIModelName = ""; // Reset model name so it fetches again for the new URL
if (!string.IsNullOrEmpty(OpenAIInstanceId) && instances.ContainsKey(OpenAIInstanceId))
{
instances[OpenAIInstanceId]["url"] = url;
}
}
}
private void EnsureInstance(string instanceId)
{
bool isNew = false;
if (!commandQueues.ContainsKey(instanceId))
{
commandQueues[instanceId] = new Queue<JsonObject>();
pendingTaskIds[instanceId] = new List<string>();
isNew = true;
}
if (!blacklistedInstances.Contains(instanceId) && !instances.ContainsKey(instanceId))
{
instances[instanceId] = new JsonObject
{
["last_seen"] = DateTime.Now.ToString("o"),
["url"] = "",
["turn_count"] = 0,
["is_busy"] = false,
["platform"] = "Unknown"
};
if (isNew)
{
Logger.Log($"[OP-CENTER] New instance registered: {instanceId}");
}
}
if (!chatHistory.ContainsKey(instanceId))
{
chatHistory[instanceId] = new JsonArray();
}
}
public void UpdateInstanceState(string instanceId, JsonObject stateData)
{
lock (queueLock)
{
if (blacklistedInstances.Contains(instanceId)) return;
EnsureInstance(instanceId);
if (instances.ContainsKey(instanceId))
{
instances[instanceId]["last_seen"] = DateTime.Now.ToString("o");
if (stateData != null)
{
if (stateData.ContainsKey("url"))
instances[instanceId]["url"] = stateData["url"]?.ToString();
if (stateData.ContainsKey("turn_count"))
instances[instanceId]["turn_count"] = stateData["turn_count"]?.GetValue<int>() ?? 0;
if (stateData.ContainsKey("is_busy"))
instances[instanceId]["is_busy"] = stateData["is_busy"]?.GetValue<bool>() ?? false;
if (stateData.ContainsKey("platform"))
instances[instanceId]["platform"] = stateData["platform"]?.ToString();
}
}
}
}
public JsonObject GetActiveInstances()
{
lock (queueLock)
{
var result = new JsonObject();
foreach (var kvp in instances)
{
result[kvp.Key] = kvp.Value.DeepClone();
}
return result;
}
}
public string GetDefaultInstanceId()
{
lock (queueLock)
{
if (instances.Count == 0) return "default";
return instances.OrderByDescending(x => DateTime.Parse(x.Value["last_seen"].ToString())).First().Key;
}
}
public string GetInstancePlatform(string instanceId)
{
lock (queueLock)
{
if (instances.TryGetValue(instanceId, out var data))
{
return data?["platform"]?.ToString() ?? "Unknown";
}
return "Unknown";
}
}
public string QueueCommand(JsonObject commandData, string instanceId = null)
{
lock (queueLock)
{
if (string.IsNullOrEmpty(instanceId))
{
instanceId = GetDefaultInstanceId();
}
EnsureInstance(instanceId);
string taskId = $"CMD-{instanceId.Substring(0, Math.Min(8, instanceId.Length))}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}";
var command = new JsonObject
{
["id"] = taskId,
["command"] = commandData.DeepClone(),
["timestamp"] = DateTime.Now.ToString("o"),
["instance_id"] = instanceId
};
tasks[taskId] = commandData.DeepClone().AsObject();
string cmdType = commandData["type"]?.ToString();
if (cmdType == "GENERATE")
{
chatHistory[instanceId].Add(new JsonObject
{
["role"] = "User",
["text"] = commandData["payload"]?.ToString() ?? ""
});
}
commandQueues[instanceId].Enqueue(command);
pendingTaskIds[instanceId].Add(taskId);
return taskId;
}
}
public JsonObject GetPendingCommand(string instanceId)
{
lock (queueLock)
{
if (!commandQueues.ContainsKey(instanceId)) return null;
if (commandQueues[instanceId].Count > 0)
{
if (instances.ContainsKey(instanceId))
{
instances[instanceId]["is_busy"] = true;
}
return commandQueues[instanceId].Dequeue();
}
return null;
}
}
public bool LogResult(string instanceId, JsonObject resultData)
{
lock (queueLock)
{
if (instances.ContainsKey(instanceId))
{
instances[instanceId]["is_busy"] = false;
}
if (pendingTaskIds.ContainsKey(instanceId) && pendingTaskIds[instanceId].Count > 0)
{
string matchedTaskId = pendingTaskIds[instanceId][0];
pendingTaskIds[instanceId].RemoveAt(0);
if (tasks.TryGetValue(matchedTaskId, out var cmdData))
{
string cmdType = cmdData["type"]?.ToString();
string output = resultData["output"]?.ToString() ?? "";
if (cmdType == "GET_CHAT_HISTORY")
{
try { chatHistory[instanceId] = JsonNode.Parse(output).AsArray(); } catch { }
}
else if ((cmdType == "GENERATE" || cmdType == "INJECT_SHARD") && !output.StartsWith("Error"))
{
chatHistory[instanceId].Add(new JsonObject { ["role"] = "Model", ["text"] = output });
}
else if (cmdType == "NEW_CHAT")
{
chatHistory[instanceId].Clear();
}
else if (cmdType == "DELETE_TURN" && !output.StartsWith("Error"))
{
try
{
int idx = cmdData["payload"]?.GetValue<int>() ?? -1;
if (idx < 0) idx = chatHistory[instanceId].Count + idx;
if (idx >= 0 && idx < chatHistory[instanceId].Count)
{
chatHistory[instanceId].RemoveAt(idx);
}
}
catch { }
}
}
results[matchedTaskId] = new JsonObject
{
["received_at"] = DateTime.Now.ToString("o"),
["data"] = resultData.DeepClone(),
["instance_id"] = instanceId
};
Logger.Log($"[OP-CENTER] Task {matchedTaskId} Completed on Instance {instanceId}.");
return true;
}
else
{
Logger.Log($"[OP-CENTER] Warning: Result received from {instanceId} but no tasks were pending.");
return false;
}
}
}
public JsonObject GetResult(string taskId)
{
lock (queueLock)
{
if (results.TryGetValue(taskId, out var res))
{
return res.DeepClone().AsObject();
}
return null;
}
}
public void CancelPendingTask(string instanceId, string taskId)
{
lock (queueLock)
{
if (pendingTaskIds.ContainsKey(instanceId))
{
if (pendingTaskIds[instanceId].Remove(taskId))
{
Logger.Log($"[OP-CENTER] Task {taskId} timed out and was removed from pending queue for {instanceId}.");
}
}
}
}
public void ShutdownInstance(string instanceId)
{
lock (queueLock)
{
if (IsOpenAIInstance(instanceId))
{
DisableOpenAIMode();
return;
}
// Queue the shutdown command so the harness receives it on its next poll
QueueCommand(new JsonObject { ["type"] = "SHUTDOWN" }, instanceId);
// Blacklist and remove from active instances so it disappears from the UI
// and cannot be recreated by lingering heartbeats
blacklistedInstances.Add(instanceId);
instances.Remove(instanceId);
}
}
public void SetInstanceBusy(string instanceId, bool isBusy)
{
lock (queueLock)
{
if (instances.ContainsKey(instanceId))
{
instances[instanceId]["is_busy"] = isBusy;
instances[instanceId]["last_seen"] = DateTime.Now.ToString("o");
}
}
}
public void AddChatHistory(string instanceId, string role, string text)
{
lock (queueLock)
{
if (!chatHistory.ContainsKey(instanceId)) chatHistory[instanceId] = new JsonArray();
chatHistory[instanceId].Add(new JsonObject { ["role"] = role, ["text"] = text });
}
}
public void ClearChatHistory(string instanceId)
{
lock (queueLock)
{
if (chatHistory.ContainsKey(instanceId)) chatHistory[instanceId].Clear();
}
}
public bool HasChatHistory(string instanceId)
{
lock (queueLock)
{
return chatHistory.ContainsKey(instanceId) && chatHistory[instanceId].Count > 0;
}
}
public JsonArray GetChatHistory(string instanceId)
{
lock (queueLock)
{
if (chatHistory.TryGetValue(instanceId, out var history))
{
return history.DeepClone().AsArray();
}
return new JsonArray();
}
}
}
}
+18
View File
@@ -0,0 +1,18 @@
namespace AI_C2_Server
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.SetColorMode(SystemColorMode.Dark);
Application.Run(new MainForm());
}
}
}
+502
View File
@@ -0,0 +1,502 @@
// File: WebServer.cs
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace AI_C2_Server
{
public class WebServer
{
public static WebServer Instance { get; } = new WebServer();
private HttpListener _listener;
private bool _isRunning;
private static readonly HttpClient _httpClient = new HttpClient();
private WebServer() { }
public void Start(int port = 8080)
{
if (_isRunning) return;
_listener = new HttpListener();
_listener.Prefixes.Add($"http://localhost:{port}/");
_listener.Prefixes.Add($"http://127.0.0.1:{port}/");
try
{
_listener.Start();
_isRunning = true;
Task.Run(ListenLoop);
Logger.Log($"[SYSTEM] Initializing C2 Server on Port {port}...");
}
catch (Exception ex)
{
Logger.Log($"[ERROR] Failed to start server: {ex.Message}");
}
}
public void Stop()
{
if (!_isRunning) return;
_isRunning = false;
_listener?.Stop();
_listener?.Close();
Logger.Log("[SYSTEM] Server stopped.");
}
private async Task ListenLoop()
{
while (_isRunning)
{
try
{
var context = await _listener.GetContextAsync();
_ = Task.Run(() => ProcessRequestAsync(context));
}
catch (HttpListenerException)
{
// Thrown when listener is stopped, safe to ignore
}
catch (Exception ex)
{
Logger.Log($"[ERROR] Listener loop error: {ex.Message}");
}
}
}
private async Task ProcessRequestAsync(HttpListenerContext context)
{
var request = context.Request;
var response = context.Response;
// CORS Headers
response.AddHeader("Access-Control-Allow-Origin", "*");
response.AddHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
response.AddHeader("Access-Control-Allow-Headers", "Content-Type");
if (request.HttpMethod == "OPTIONS")
{
response.StatusCode = 200;
response.Close();
return;
}
try
{
string path = request.Url.AbsolutePath.TrimEnd('/');
// Extract instance ID for logging
string instanceId = "";
if (path.StartsWith("/api/relay/state/")) instanceId = path.Substring("/api/relay/state/".Length);
else if (path.StartsWith("/api/relay/command/")) instanceId = path.Substring("/api/relay/command/".Length);
else if (path.StartsWith("/api/relay/result/")) instanceId = path.Substring("/api/relay/result/".Length);
if (!string.IsNullOrEmpty(instanceId))
{
string platform = OperationCenter.Instance.GetInstancePlatform(instanceId);
Logger.Log($"[HTTP] [{platform} | {instanceId}] {request.HttpMethod} {path}");
}
else
{
Logger.Log($"[HTTP] {request.HttpMethod} {path}");
}
string body = "";
if (request.HasEntityBody)
{
using var reader = new StreamReader(request.InputStream, request.ContentEncoding);
body = await reader.ReadToEndAsync();
}
JsonNode payload = null;
if (!string.IsNullOrWhiteSpace(body))
{
try { payload = JsonNode.Parse(body); } catch { }
}
// --- RELAY ENDPOINTS ---
if (path.StartsWith("/api/relay/state/"))
{
OperationCenter.Instance.UpdateInstanceState(instanceId, payload as JsonObject);
SendJson(response, new JsonObject { ["status"] = "ok" });
}
else if (path.StartsWith("/api/relay/command/"))
{
OperationCenter.Instance.UpdateInstanceState(instanceId, new JsonObject());
var cmd = OperationCenter.Instance.GetPendingCommand(instanceId);
SendJson(response, cmd ?? new JsonObject());
}
else if (path.StartsWith("/api/relay/result/"))
{
OperationCenter.Instance.LogResult(instanceId, payload as JsonObject);
SendJson(response, new JsonObject { ["status"] = "acknowledged" });
}
// --- ADMIN ENDPOINTS ---
else if (path == "/api/admin/instances")
{
SendJson(response, OperationCenter.Instance.GetActiveInstances());
}
else if (path == "/api/admin/inject")
{
await HandleCommand(response, "GENERATE", payload?["prompt"]?.DeepClone(), GetBool(payload, "blocking", true), GetInt(payload, "timeout", 600), GetString(payload, "instance_id"));
}
else if (path == "/api/admin/history")
{
string id = request.QueryString["instance_id"];
await HandleCommand(response, "SCRAPE_HISTORY", null, true, 10, id);
}
else if (path == "/api/admin/session/analyze")
{
await HandleCommand(response, "ANALYZE_SESSION", null, true, 5, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/upload_media")
{
if (payload?["data"] == null || payload?["mime"] == null)
{
SendJson(response, new JsonObject { ["error"] = "Invalid Media Payload" }, 400);
return;
}
await HandleCommand(response, "UPLOAD_MEDIA", payload, true, 30, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/new_chat")
{
await HandleCommand(response, "NEW_CHAT", null, true, 30, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/toggle_url_context")
{
await HandleCommand(response, "SET_URL_CONTEXT", GetBool(payload, "enabled", true), true, 30, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/resolution")
{
await HandleCommand(response, "SET_RESOLUTION", GetString(payload, "level", "Default"), true, 30, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/delete")
{
await HandleCommand(response, "DELETE_TURN", GetInt(payload, "index", -1), true, 30, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/settings")
{
await HandleCommand(response, "SET_SETTINGS", payload, true, 45, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/get_settings")
{
await HandleCommand(response, "GET_SETTINGS", null, true, 60, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/get_chat_history")
{
string id = GetString(payload, "instance_id");
bool forceSync = GetBool(payload, "force_sync", false);
if (!forceSync && OperationCenter.Instance.HasChatHistory(id))
{
SendJson(response, new JsonObject
{
["status"] = "completed",
["output"] = OperationCenter.Instance.GetChatHistory(id).ToJsonString(),
["timestamp"] = DateTime.Now.ToString("o"),
["instance_id"] = id
});
return;
}
await HandleCommand(response, "GET_CHAT_HISTORY", null, true, 120, id);
}
else if (path == "/api/admin/action/create_shard")
{
await HandleCommand(response, "CREATE_SHARD", null, true, 600, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/inject_shard")
{
if (payload?["shard_data"] == null)
{
SendJson(response, new JsonObject { ["error"] = "Missing shard_data" }, 400);
return;
}
await HandleCommand(response, "INJECT_SHARD", payload["shard_data"]?.DeepClone(), true, 600, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/action/inject_doc")
{
if (payload?["content"] == null)
{
SendJson(response, new JsonObject { ["error"] = "Missing content" }, 400);
return;
}
await HandleCommand(response, "INJECT_DOC", payload, true, 30, GetString(payload, "instance_id"));
}
else if (path == "/api/admin/openai/system_instructions")
{
string instructions = GetString(payload, "instructions", "");
OperationCenter.Instance.OpenAISystemInstructions = instructions;
SendJson(response, new JsonObject { ["status"] = "completed", ["output"] = "System instructions updated." });
}
else if (path.StartsWith("/api/admin/result/"))
{
string taskId = path.Substring("/api/admin/result/".Length);
var res = OperationCenter.Instance.GetResult(taskId);
if (res != null)
{
SendJson(response, new JsonObject { ["status"] = "completed", ["result"] = res.DeepClone() });
}
else
{
SendJson(response, new JsonObject { ["status"] = "pending" }, 202);
}
}
else
{
SendJson(response, new JsonObject { ["error"] = "Not Found" }, 404);
}
}
catch (Exception ex)
{
Logger.Log($"[ERROR] Request processing failed: {ex.Message}");
SendJson(response, new JsonObject { ["error"] = "Internal Server Error" }, 500);
}
}
private async Task HandleCommand(HttpListenerResponse response, string commandType, JsonNode payload, bool blocking, int timeout, string instanceId)
{
if (string.IsNullOrEmpty(instanceId))
{
instanceId = OperationCenter.Instance.GetDefaultInstanceId();
}
// --- OPENAI API INTERCEPTION ---
if (OperationCenter.Instance.IsOpenAIInstance(instanceId))
{
if (commandType == "GENERATE")
{
try
{
OperationCenter.Instance.SetInstanceBusy(instanceId, true);
string prompt = payload?.ToString() ?? "";
// Auto-detect model if not cached
string modelName = OperationCenter.Instance.OpenAIModelName;
if (string.IsNullOrEmpty(modelName))
{
string modelsUrl = OperationCenter.Instance.OpenAIApiUrl.Replace("/chat/completions", "/models");
try
{
var modelReq = new HttpRequestMessage(HttpMethod.Get, modelsUrl);
if (!string.IsNullOrEmpty(OperationCenter.Instance.OpenAIApiKey))
{
modelReq.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", OperationCenter.Instance.OpenAIApiKey);
}
var modelRes = await _httpClient.SendAsync(modelReq);
if (modelRes.IsSuccessStatusCode)
{
string modelStr = await modelRes.Content.ReadAsStringAsync();
var modelJson = JsonNode.Parse(modelStr);
var dataArray = modelJson?["data"] as JsonArray;
if (dataArray != null && dataArray.Count > 0)
{
modelName = dataArray[0]?["id"]?.ToString();
OperationCenter.Instance.OpenAIModelName = modelName;
Logger.Log($"[OPENAI] Auto-detected model: {modelName}");
}
}
}
catch (Exception ex)
{
Logger.Log($"[OPENAI] Warning: Failed to fetch models from {modelsUrl}. Using 'default'. Error: {ex.Message}");
}
if (string.IsNullOrEmpty(modelName))
{
modelName = "default";
}
}
// Add user prompt to history
OperationCenter.Instance.AddChatHistory(instanceId, "User", prompt);
// Build messages array from history
var messagesArray = new JsonArray();
if (!string.IsNullOrEmpty(OperationCenter.Instance.OpenAISystemInstructions))
{
messagesArray.Add(new JsonObject { ["role"] = "system", ["content"] = OperationCenter.Instance.OpenAISystemInstructions });
}
var history = OperationCenter.Instance.GetChatHistory(instanceId);
foreach (var msg in history)
{
string role = msg["role"]?.ToString().ToLower() == "user" ? "user" : "assistant";
messagesArray.Add(new JsonObject { ["role"] = role, ["content"] = msg["text"]?.ToString() });
}
var openAiRequest = new JsonObject
{
["model"] = modelName,
["messages"] = messagesArray
};
var requestMsg = new HttpRequestMessage(HttpMethod.Post, OperationCenter.Instance.OpenAIApiUrl);
if (!string.IsNullOrEmpty(OperationCenter.Instance.OpenAIApiKey))
{
requestMsg.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", OperationCenter.Instance.OpenAIApiKey);
}
requestMsg.Content = new StringContent(openAiRequest.ToJsonString(), Encoding.UTF8, "application/json");
Logger.Log($"[OPENAI] Sending request to {OperationCenter.Instance.OpenAIApiUrl}");
var responseMsg = await _httpClient.SendAsync(requestMsg);
string resultStr = await responseMsg.Content.ReadAsStringAsync();
OperationCenter.Instance.SetInstanceBusy(instanceId, false);
if (!responseMsg.IsSuccessStatusCode)
{
Logger.Log($"[OPENAI ERROR] {responseMsg.StatusCode}: {resultStr}");
SendJson(response, new JsonObject { ["error"] = $"OpenAI API Error: {responseMsg.StatusCode}" }, 500);
return;
}
var jsonResult = JsonNode.Parse(resultStr);
string outputText = jsonResult?["choices"]?[0]?["message"]?["content"]?.ToString() ?? resultStr;
// Strip out <think>...</think> blocks generated by DeepSeek R1 models
outputText = Regex.Replace(outputText, @"<think>.*?</think>\s*", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);
// Handle edge cases where the model omits the opening <think> tag but includes the closing </think> tag
outputText = Regex.Replace(outputText, @"^.*?<\/think>\s*", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);
outputText = outputText.Trim();
// Add assistant response to history
OperationCenter.Instance.AddChatHistory(instanceId, "Model", outputText);
SendJson(response, new JsonObject
{
["status"] = "completed",
["output"] = outputText,
["timestamp"] = DateTime.Now.ToString("o"),
["instance_id"] = instanceId
}, 200);
return;
}
catch (Exception ex)
{
OperationCenter.Instance.SetInstanceBusy(instanceId, false);
Logger.Log($"[ERROR] OpenAI API call failed: {ex.Message}");
SendJson(response, new JsonObject { ["error"] = "OpenAI API Error: " + ex.Message }, 500);
return;
}
}
else if (commandType == "NEW_CHAT")
{
OperationCenter.Instance.ClearChatHistory(instanceId);
SendJson(response, new JsonObject { ["status"] = "completed", ["output"] = "Chat reset.", ["timestamp"] = DateTime.Now.ToString("o"), ["instance_id"] = instanceId }, 200);
return;
}
else if (commandType == "SHUTDOWN")
{
OperationCenter.Instance.ShutdownInstance(instanceId);
SendJson(response, new JsonObject { ["status"] = "completed", ["output"] = "Harness shut down.", ["timestamp"] = DateTime.Now.ToString("o"), ["instance_id"] = instanceId }, 200);
return;
}
else if (commandType == "GET_CHAT_HISTORY")
{
SendJson(response, new JsonObject
{
["status"] = "completed",
["output"] = OperationCenter.Instance.GetChatHistory(instanceId).ToJsonString(),
["timestamp"] = DateTime.Now.ToString("o"),
["instance_id"] = instanceId
}, 200);
return;
}
else
{
SendJson(response, new JsonObject { ["error"] = $"Command {commandType} not supported in OpenAI API mode.", ["instance_id"] = instanceId }, 400);
return;
}
}
// -------------------------------
var cmdData = new JsonObject
{
["type"] = commandType,
["payload"] = payload?.DeepClone()
};
string taskId = OperationCenter.Instance.QueueCommand(cmdData, instanceId);
if (!blocking)
{
SendJson(response, new JsonObject { ["status"] = "queued", ["task_id"] = taskId, ["instance_id"] = instanceId }, 200);
return;
}
DateTime startTime = DateTime.Now;
while ((DateTime.Now - startTime).TotalSeconds < timeout)
{
var result = OperationCenter.Instance.GetResult(taskId);
if (result != null)
{
SendJson(response, new JsonObject
{
["status"] = "completed",
["output"] = result["data"]?["output"]?.ToString(),
["timestamp"] = result["received_at"]?.ToString(),
["instance_id"] = result["instance_id"]?.ToString()
}, 200);
return;
}
await Task.Delay(500);
}
// Timeout handling: Cancel the task so it doesn't permanently block the FIFO queue
OperationCenter.Instance.CancelPendingTask(instanceId, taskId);
SendJson(response, new JsonObject { ["error"] = "Timeout", ["task_id"] = taskId, ["instance_id"] = instanceId }, 504);
}
private void SendJson(HttpListenerResponse response, JsonNode data, int statusCode = 200)
{
response.StatusCode = statusCode;
response.ContentType = "application/json";
byte[] buffer = Encoding.UTF8.GetBytes(data.ToJsonString());
response.ContentLength64 = buffer.Length;
try
{
response.OutputStream.Write(buffer, 0, buffer.Length);
}
catch { }
finally
{
response.Close();
}
}
private string GetString(JsonNode node, string key, string def = null)
{
if (node is JsonObject obj && obj.TryGetPropertyValue(key, out var val) && val != null)
return val.ToString();
return def;
}
private bool GetBool(JsonNode node, string key, bool def = false)
{
if (node is JsonObject obj && obj.TryGetPropertyValue(key, out var val) && val != null)
{
try { return val.GetValue<bool>(); } catch { return def; }
}
return def;
}
private int GetInt(JsonNode node, string key, int def = 0)
{
if (node is JsonObject obj && obj.TryGetPropertyValue(key, out var val) && val != null)
{
try { return val.GetValue<int>(); } catch { return def; }
}
return def;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB