Synapse-OS-Assistant-And-AI.../AI.Client/AiClient.cs
0% [█ █ █ █ █ █ █ █ █ █] 100% ace1e61285 First commit!
2026-06-04 20:36:13 -05:00

189 lines
7.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace AI.Client
{
public class AiClient
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl;
public AiClient(string baseUrl = "http://localhost:8080/api")
{
_baseUrl = baseUrl.TrimEnd('/');
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromMinutes(15); // Increased to 15 minutes for long generations
}
// --- CORE COMMANDS ---
public async Task<Dictionary<string, InstanceState>> GetInstancesAsync()
{
return await GetJsonAsync<Dictionary<string, InstanceState>>("/admin/instances");
}
public async Task<AiResponse> SendPromptAsync(string text, string instanceId = null)
{
var payload = new { prompt = text, blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/inject", payload);
}
public async Task<AiResponse> NewChatAsync(string instanceId = null)
{
var payload = new { blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/new_chat", payload);
}
public async Task<AiResponse> ToggleUrlContextAsync(bool enabled, string instanceId = null)
{
var payload = new { enabled = enabled, blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/toggle_url_context", payload);
}
public async Task<AiResponse> SetResolutionAsync(string level, string instanceId = null)
{
var payload = new { level = level, blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/resolution", payload);
}
public async Task<AiResponse> DeleteTurnAsync(int index, string instanceId = null)
{
var payload = new { index = index, blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/delete", payload);
}
// --- ADVANCED COMMANDS ---
public async Task<AiResponse> SetSettingsAsync(string instanceId, float? temp, float? topP, string model, string sysInst, string thinkingLevel)
{
// Use a dictionary to avoid sending null values which might confuse the backend
var payload = new Dictionary<string, object>();
if (!string.IsNullOrEmpty(instanceId)) payload["instance_id"] = instanceId;
if (temp.HasValue) payload["temperature"] = temp.Value;
if (topP.HasValue) payload["top_p"] = topP.Value;
if (!string.IsNullOrEmpty(model)) payload["model"] = model;
if (!string.IsNullOrEmpty(sysInst)) payload["system_instructions"] = sysInst;
if (!string.IsNullOrEmpty(thinkingLevel)) payload["thinking_level"] = thinkingLevel;
payload["blocking"] = true;
return await PostJsonAsync<AiResponse>("/admin/action/settings", payload);
}
public async Task<AiResponse> GetSettingsAsync(string instanceId = null)
{
var payload = new { blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/get_settings", payload);
}
public async Task<AiResponse> GetChatHistoryAsync(string instanceId = null, bool forceSync = false)
{
var payload = new { blocking = true, instance_id = instanceId, force_sync = forceSync };
return await PostJsonAsync<AiResponse>("/admin/action/get_chat_history", payload);
}
public async Task<AiResponse> CreateShardAsync(string instanceId = null)
{
var payload = new { blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/create_shard", payload);
}
public async Task<AiResponse> InjectShardAsync(string shardData, string instanceId = null)
{
var payload = new { shard_data = shardData, blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/inject_shard", payload);
}
public async Task<AiResponse> InjectDocAsync(string filename, string content, string instanceId = null)
{
var payload = new { filename = filename, content = content, blocking = true, instance_id = instanceId };
return await PostJsonAsync<AiResponse>("/admin/action/inject_doc", payload);
}
public async Task<AiResponse> SetOpenAISystemInstructionsAsync(string instructions)
{
var payload = new { instructions = instructions };
return await PostJsonAsync<AiResponse>("/admin/openai/system_instructions", payload);
}
// --- INTERNAL HELPERS ---
private async Task<T> GetJsonAsync<T>(string endpoint)
{
try
{
var response = await _httpClient.GetAsync(_baseUrl + endpoint);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
return JsonSerializer.Deserialize<T>(responseString, options);
}
catch (Exception ex)
{
throw new Exception($"API GET Failed: {ex.Message}", ex);
}
}
private async Task<T> PostJsonAsync<T>(string endpoint, object data)
{
try
{
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(_baseUrl + endpoint, content);
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
return JsonSerializer.Deserialize<T>(responseString, options);
}
catch (Exception ex)
{
throw new Exception($"API POST Failed: {ex.Message}", ex);
}
}
}
// --- DATA MODELS ---
public class AiResponse
{
public string Status { get; set; }
public string Task_Id { get; set; }
public string Instance_Id { get; set; }
public string Mode { get; set; }
public string Output { get; set; }
public string Error { get; set; }
}
public class InstanceState
{
public string last_seen { get; set; }
public string url { get; set; }
public int turn_count { get; set; }
public bool is_busy { get; set; }
}
public class AiSettings
{
public float? Temperature { get; set; }
public float? Top_P { get; set; }
public string Model { get; set; }
public string Thinking_Level { get; set; }
public string System_Instructions { get; set; }
public string Resolution { get; set; }
public bool? Url_Context { get; set; }
}
public class AiChatTurn
{
public string Role { get; set; }
public string Text { get; set; }
}
}