Files
WulaFallenEmpireRW/Source/WulaFallenEmpire/EventSystem/AI/RimTalkBridge.cs
2025-12-12 16:20:52 +08:00

122 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Verse;
namespace WulaFallenEmpire.EventSystem.AI
{
public static class RimTalkBridge
{
private static bool? _isRimTalkActive;
private static Type _aiClientFactoryType;
private static Type _aiClientInterfaceType;
private static Type _roleEnum;
private static MethodInfo _getAIClientAsyncMethod;
private static MethodInfo _getChatCompletionAsyncMethod;
public static bool IsRimTalkActive
{
get
{
if (!_isRimTalkActive.HasValue)
{
_isRimTalkActive = ModsConfig.IsActive("RimTalk.Mod"); // Replace with actual PackageId if different
if (_isRimTalkActive.Value)
{
InitializeReflection();
}
}
return _isRimTalkActive.Value;
}
}
private static void InitializeReflection()
{
try
{
// Assuming RimTalk assembly is loaded
Assembly rimTalkAssembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().Name == "RimTalk");
if (rimTalkAssembly == null)
{
Log.Error("[WulaFallenEmpire] RimTalk assembly not found despite mod being active.");
_isRimTalkActive = false;
return;
}
_aiClientFactoryType = rimTalkAssembly.GetType("RimTalk.Client.AIClientFactory");
_aiClientInterfaceType = rimTalkAssembly.GetType("RimTalk.Client.IAIClient");
_roleEnum = rimTalkAssembly.GetType("RimTalk.Data.Role");
if (_aiClientFactoryType != null)
{
_getAIClientAsyncMethod = _aiClientFactoryType.GetMethod("GetAIClientAsync", BindingFlags.Public | BindingFlags.Static);
}
if (_aiClientInterfaceType != null)
{
_getChatCompletionAsyncMethod = _aiClientInterfaceType.GetMethod("GetChatCompletionAsync");
}
}
catch (Exception ex)
{
Log.Error($"[WulaFallenEmpire] Failed to initialize RimTalk reflection: {ex}");
_isRimTalkActive = false;
}
}
public static async Task<string> GetChatCompletion(string instruction, List<(string role, string message)> messages)
{
if (!IsRimTalkActive || _getAIClientAsyncMethod == null || _getChatCompletionAsyncMethod == null)
{
return null;
}
try
{
// Get AI Client
var clientTask = (Task)_getAIClientAsyncMethod.Invoke(null, null);
await clientTask.ConfigureAwait(false);
// The Task returns an IAIClient object
object client = ((dynamic)clientTask).Result;
if (client == null) return null;
// Prepare messages list
// List<(Role role, string message)>
var tupleType = typeof(ValueTuple<,>).MakeGenericType(_roleEnum, typeof(string));
var listType = typeof(List<>).MakeGenericType(tupleType);
var messageList = Activator.CreateInstance(listType);
var addMethod = listType.GetMethod("Add");
foreach (var msg in messages)
{
object roleValue = Enum.Parse(_roleEnum, msg.role, true);
object tuple = Activator.CreateInstance(tupleType, roleValue, msg.message);
addMethod.Invoke(messageList, new object[] { tuple });
}
// Call GetChatCompletionAsync
var completionTask = (Task)_getChatCompletionAsyncMethod.Invoke(client, new object[] { instruction, messageList });
await completionTask.ConfigureAwait(false);
// The Task returns a Payload object
object payload = ((dynamic)completionTask).Result;
// Payload has a 'Response' property (or similar, based on previous analysis it was 'Content' or 'Response')
// Checking previous analysis: Payload has 'Content' property for the text response.
PropertyInfo contentProp = payload.GetType().GetProperty("Content");
return contentProp?.GetValue(payload) as string;
}
catch (Exception ex)
{
Log.Error($"[WulaFallenEmpire] Error calling RimTalk AI: {ex}");
return null;
}
}
}
}