新增 JSON tool_calls 解析/序列化并替换核心执行与提示词为 JSON-only:JsonToolCallParser.cs、AIIntelligenceCore.cs 工具基类移除 XML 解析,统一 JSON 参数读取与类型转换辅助:AITool.cs 工具实现统一 JSON args/UsageSchema(含重写/修复):Tool_ModifyGoodwill.cs、Tool_SendReinforcement.cs、Tool_GetMapPawns.cs、Tool_GetMapResources.cs、Tool_GetAvailablePrefabs.cs、Tool_CallPrefabAirdrop.cs、Tool_CallBombardment.cs、Tool_GetAvailableBombardments.cs、Tool_GetPawnStatus.cs、Tool_GetRecentNotifications.cs、Tool_SearchThingDef.cs、Tool_SearchPawnKind.cs、Tool_ChangeExpression.cs、Tool_SetOverwatchMode.cs、Tool_RememberFact.cs、Tool_RecallMemories.cs、Tool_SpawnResources.cs、Tool_AnalyzeScreen.cs 轰炸相关解析统一到 JSON 字典并增强数值解析:BombardmentUtility.cs UI 对话展示改为剥离 JSON tool_calls:Overlay_WulaLink.cs、Dialog_AIConversation.cs
153 lines
5.1 KiB
C#
153 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using Verse;
|
|
using WulaFallenEmpire.EventSystem.AI.Utils;
|
|
|
|
namespace WulaFallenEmpire.EventSystem.AI.Tools
|
|
{
|
|
public abstract class AITool
|
|
{
|
|
public abstract string Name { get; }
|
|
public abstract string Description { get; }
|
|
public abstract string UsageSchema { get; } // JSON schema description
|
|
|
|
public virtual string Execute(string args) => "Error: Synchronous execution not supported for this tool.";
|
|
public virtual Task<string> ExecuteAsync(string args) => Task.FromResult(Execute(args));
|
|
|
|
/// <summary>
|
|
/// Helper method to parse JSON arguments into a dictionary.
|
|
/// </summary>
|
|
protected Dictionary<string, object> ParseJsonArgs(string json)
|
|
{
|
|
var argsDict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
|
if (string.IsNullOrWhiteSpace(json)) return argsDict;
|
|
if (JsonToolCallParser.TryParseObject(json, out Dictionary<string, object> parsed))
|
|
{
|
|
return parsed;
|
|
}
|
|
return argsDict;
|
|
}
|
|
|
|
protected static bool TryGetString(Dictionary<string, object> args, string key, out string value)
|
|
{
|
|
value = null;
|
|
if (args == null || string.IsNullOrWhiteSpace(key)) return false;
|
|
if (args.TryGetValue(key, out object raw) && raw != null)
|
|
{
|
|
value = Convert.ToString(raw, CultureInfo.InvariantCulture);
|
|
return !string.IsNullOrWhiteSpace(value);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected static bool TryGetInt(Dictionary<string, object> args, string key, out int value)
|
|
{
|
|
value = 0;
|
|
if (!TryGetNumber(args, key, out double number)) return false;
|
|
value = (int)Math.Round(number);
|
|
return true;
|
|
}
|
|
|
|
protected static bool TryGetFloat(Dictionary<string, object> args, string key, out float value)
|
|
{
|
|
value = 0f;
|
|
if (!TryGetNumber(args, key, out double number)) return false;
|
|
value = (float)number;
|
|
return true;
|
|
}
|
|
|
|
protected static bool TryGetBool(Dictionary<string, object> args, string key, out bool value)
|
|
{
|
|
value = false;
|
|
if (args == null || string.IsNullOrWhiteSpace(key)) return false;
|
|
if (!args.TryGetValue(key, out object raw) || raw == null) return false;
|
|
if (raw is bool b)
|
|
{
|
|
value = b;
|
|
return true;
|
|
}
|
|
if (raw is string s && bool.TryParse(s, out bool parsed))
|
|
{
|
|
value = parsed;
|
|
return true;
|
|
}
|
|
if (raw is long l)
|
|
{
|
|
value = l != 0;
|
|
return true;
|
|
}
|
|
if (raw is double d)
|
|
{
|
|
value = Math.Abs(d) > 0.0001;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected static bool TryGetObject(Dictionary<string, object> args, string key, out Dictionary<string, object> value)
|
|
{
|
|
value = null;
|
|
if (args == null || string.IsNullOrWhiteSpace(key)) return false;
|
|
if (args.TryGetValue(key, out object raw) && raw is Dictionary<string, object> dict)
|
|
{
|
|
value = dict;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected static bool TryGetList(Dictionary<string, object> args, string key, out List<object> value)
|
|
{
|
|
value = null;
|
|
if (args == null || string.IsNullOrWhiteSpace(key)) return false;
|
|
if (args.TryGetValue(key, out object raw) && raw is List<object> list)
|
|
{
|
|
value = list;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected static bool LooksLikeJson(string input)
|
|
{
|
|
return JsonToolCallParser.LooksLikeJson(input);
|
|
}
|
|
|
|
private static bool TryGetNumber(Dictionary<string, object> args, string key, out double value)
|
|
{
|
|
value = 0;
|
|
if (args == null || string.IsNullOrWhiteSpace(key)) return false;
|
|
if (!args.TryGetValue(key, out object raw) || raw == null) return false;
|
|
if (raw is double d)
|
|
{
|
|
value = d;
|
|
return true;
|
|
}
|
|
if (raw is float f)
|
|
{
|
|
value = f;
|
|
return true;
|
|
}
|
|
if (raw is int i)
|
|
{
|
|
value = i;
|
|
return true;
|
|
}
|
|
if (raw is long l)
|
|
{
|
|
value = l;
|
|
return true;
|
|
}
|
|
if (raw is string s && double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out double parsed))
|
|
{
|
|
value = parsed;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|