zc
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -90,6 +90,7 @@ namespace WulaFallenEmpire.EventSystem.AI
|
|||||||
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||||
request.downloadHandler = new DownloadHandlerBuffer();
|
request.downloadHandler = new DownloadHandlerBuffer();
|
||||||
request.SetRequestHeader("Content-Type", "application/json");
|
request.SetRequestHeader("Content-Type", "application/json");
|
||||||
|
request.timeout = 120; // 120 seconds timeout
|
||||||
if (!string.IsNullOrEmpty(_apiKey))
|
if (!string.IsNullOrEmpty(_apiKey))
|
||||||
{
|
{
|
||||||
request.SetRequestHeader("Authorization", $"Bearer {_apiKey}");
|
request.SetRequestHeader("Authorization", $"Bearer {_apiKey}");
|
||||||
|
|||||||
@@ -22,6 +22,20 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
|
|||||||
private bool _isThinking = false;
|
private bool _isThinking = false;
|
||||||
private Vector2 _scrollPosition = Vector2.zero;
|
private Vector2 _scrollPosition = Vector2.zero;
|
||||||
private bool _scrollToBottom = false;
|
private bool _scrollToBottom = false;
|
||||||
|
private int _lastHistoryCount = -1;
|
||||||
|
private float _lastUsedWidth = -1f;
|
||||||
|
private List<CachedMessage> _cachedMessages = new List<CachedMessage>();
|
||||||
|
private float _cachedTotalHeight = 0f;
|
||||||
|
|
||||||
|
private class CachedMessage
|
||||||
|
{
|
||||||
|
public string role;
|
||||||
|
public string message;
|
||||||
|
public string displayText;
|
||||||
|
public float height;
|
||||||
|
public float yOffset;
|
||||||
|
public GameFont font;
|
||||||
|
}
|
||||||
private List<AITool> _tools = new List<AITool>();
|
private List<AITool> _tools = new List<AITool>();
|
||||||
private AIIntelligenceCore _core;
|
private AIIntelligenceCore _core;
|
||||||
private Dictionary<int, Texture2D> _portraits = new Dictionary<int, Texture2D>();
|
private Dictionary<int, Texture2D> _portraits = new Dictionary<int, Texture2D>();
|
||||||
@@ -1400,6 +1414,57 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
_inputText = "";
|
_inputText = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void UpdateCacheIfNeeded(float width)
|
||||||
|
{
|
||||||
|
if (_core == null) return;
|
||||||
|
var history = _core.GetHistorySnapshot();
|
||||||
|
if (history == null) return;
|
||||||
|
|
||||||
|
if (Math.Abs(_lastUsedWidth - width) < 0.1f && history.Count == _lastHistoryCount)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastUsedWidth = width;
|
||||||
|
_lastHistoryCount = history.Count;
|
||||||
|
_cachedMessages.Clear();
|
||||||
|
_cachedTotalHeight = 0f;
|
||||||
|
float curY = 0f;
|
||||||
|
float innerPadding = 5f;
|
||||||
|
float contentWidth = width - innerPadding * 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < history.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = history[i];
|
||||||
|
string messageText = entry.role == "assistant" ? ParseResponseForDisplay(entry.message) : entry.message;
|
||||||
|
|
||||||
|
// Always skip tool/toolcall/system messages (original behavior)
|
||||||
|
if (entry.role == "tool" || entry.role == "system" || entry.role == "toolcall") continue;
|
||||||
|
if (string.IsNullOrEmpty(messageText) || (entry.role == "user" && messageText.StartsWith("[Tool Results]"))) continue;
|
||||||
|
|
||||||
|
bool isLastMessage = i == history.Count - 1;
|
||||||
|
GameFont font = (isLastMessage && entry.role == "assistant") ? GameFont.Small : GameFont.Tiny;
|
||||||
|
float padding = (isLastMessage && entry.role == "assistant") ? 30f : 15f;
|
||||||
|
|
||||||
|
Text.Font = font;
|
||||||
|
float height = Text.CalcHeight(messageText, contentWidth) + padding;
|
||||||
|
|
||||||
|
_cachedMessages.Add(new CachedMessage
|
||||||
|
{
|
||||||
|
role = entry.role,
|
||||||
|
message = entry.message,
|
||||||
|
displayText = messageText,
|
||||||
|
height = height,
|
||||||
|
yOffset = curY,
|
||||||
|
font = font
|
||||||
|
});
|
||||||
|
|
||||||
|
curY += height + 10f;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedTotalHeight = curY;
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawChatHistory(Rect rect)
|
private void DrawChatHistory(Rect rect)
|
||||||
{
|
{
|
||||||
var originalFont = Text.Font;
|
var originalFont = Text.Font;
|
||||||
@@ -1407,98 +1472,72 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
float viewHeight = 0f;
|
|
||||||
var filteredHistory = _history.Where(e => e.role != "tool" && e.role != "system" && e.role != "toolcall").ToList();
|
|
||||||
|
|
||||||
// 添加内边距
|
|
||||||
float innerPadding = 5f;
|
float innerPadding = 5f;
|
||||||
float contentWidth = rect.width - 16f - innerPadding * 2;
|
float contentWidth = rect.width - 16f - innerPadding * 2;
|
||||||
|
|
||||||
// 预计计算高度 - 使用小字体
|
UpdateCacheIfNeeded(rect.width - 16f);
|
||||||
for (int i = 0; i < filteredHistory.Count; i++)
|
|
||||||
{
|
|
||||||
var entry = filteredHistory[i];
|
|
||||||
string text = entry.role == "assistant" ? ParseResponseForDisplay(entry.message) : entry.message;
|
|
||||||
if (string.IsNullOrWhiteSpace(text) || (entry.role == "user" && text.StartsWith("[Tool Results]"))) continue;
|
|
||||||
bool isLastMessage = i == filteredHistory.Count - 1;
|
|
||||||
|
|
||||||
// 设置更小的字体
|
float totalHeight = _cachedTotalHeight;
|
||||||
if (isLastMessage && entry.role == "assistant")
|
|
||||||
{
|
|
||||||
Text.Font = GameFont.Small; // 原来是 Medium,改为 Small
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Text.Font = GameFont.Tiny; // 原来是 Small,改为 Tiny
|
|
||||||
}
|
|
||||||
// 增加padding
|
|
||||||
float padding = (isLastMessage && entry.role == "assistant") ? 30f : 15f;
|
|
||||||
viewHeight += Text.CalcHeight(text, contentWidth) + padding + 10f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为思考指示器预留高度
|
|
||||||
if (_isThinking)
|
if (_isThinking)
|
||||||
{
|
{
|
||||||
viewHeight += 40f;
|
totalHeight += 40f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect viewRect = new Rect(0f, 0f, rect.width - 16f, viewHeight);
|
Rect viewRect = new Rect(0f, 0f, rect.width - 16f, totalHeight);
|
||||||
if (_scrollToBottom)
|
if (_scrollToBottom)
|
||||||
{
|
{
|
||||||
_scrollPosition.y = float.MaxValue;
|
_scrollPosition.y = totalHeight - rect.height;
|
||||||
_scrollToBottom = false;
|
_scrollToBottom = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widgets.BeginScrollView(rect, ref _scrollPosition, viewRect);
|
Widgets.BeginScrollView(rect, ref _scrollPosition, viewRect);
|
||||||
|
|
||||||
float curY = 0f;
|
float viewTop = _scrollPosition.y;
|
||||||
for (int i = 0; i < filteredHistory.Count; i++)
|
float viewBottom = _scrollPosition.y + rect.height;
|
||||||
|
|
||||||
|
foreach (var entry in _cachedMessages)
|
||||||
{
|
{
|
||||||
var entry = filteredHistory[i];
|
if (entry.yOffset + entry.height < viewTop - 100f) continue;
|
||||||
string text = entry.role == "assistant" ? ParseResponseForDisplay(entry.message) : entry.message;
|
if (entry.yOffset > viewBottom + 100f) break;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(text) || (entry.role == "user" && text.StartsWith("[Tool Results]"))) continue;
|
Text.Font = entry.font;
|
||||||
bool isLastMessage = i == filteredHistory.Count - 1;
|
Rect labelRect = new Rect(innerPadding, entry.yOffset, contentWidth, entry.height);
|
||||||
|
|
||||||
// 设置更小的字体
|
|
||||||
if (isLastMessage && entry.role == "assistant")
|
|
||||||
{
|
|
||||||
Text.Font = GameFont.Small; // 原来是 Medium,改为 Small
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Text.Font = GameFont.Tiny; // 原来是 Small,改为 Tiny
|
|
||||||
}
|
|
||||||
|
|
||||||
float padding = (isLastMessage && entry.role == "assistant") ? 30f : 15f;
|
|
||||||
float height = Text.CalcHeight(text, contentWidth) + padding;
|
|
||||||
|
|
||||||
// 娣诲姞鍐呰竟璺?
|
|
||||||
Rect labelRect = new Rect(innerPadding, curY, contentWidth, height);
|
|
||||||
|
|
||||||
if (entry.role == "user")
|
if (entry.role == "user")
|
||||||
{
|
{
|
||||||
Text.Anchor = TextAnchor.MiddleRight;
|
Text.Anchor = TextAnchor.MiddleRight;
|
||||||
Widgets.Label(labelRect, $"<color=#add8e6>{text}</color>");
|
Widgets.Label(labelRect, $"<color=#add8e6>{entry.displayText}</color>");
|
||||||
|
}
|
||||||
|
else if (entry.role == "assistant")
|
||||||
|
{
|
||||||
|
Text.Anchor = TextAnchor.MiddleLeft;
|
||||||
|
Widgets.Label(labelRect, $"P.I.A: {entry.displayText}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Text.Anchor = TextAnchor.MiddleLeft;
|
Text.Anchor = TextAnchor.MiddleLeft;
|
||||||
Widgets.Label(labelRect, $"P.I.A: {text}");
|
GUI.color = Color.gray;
|
||||||
|
Widgets.Label(labelRect, $"[{entry.role}] {entry.displayText}");
|
||||||
|
GUI.color = Color.white;
|
||||||
}
|
}
|
||||||
curY += height + 10f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isThinking)
|
if (_isThinking)
|
||||||
{
|
{
|
||||||
DrawThinkingIndicator(new Rect(innerPadding, curY, contentWidth, 35f));
|
float thinkingY = _cachedTotalHeight > 0 ? _cachedTotalHeight : 0f;
|
||||||
|
if (thinkingY + 40f >= viewTop && thinkingY <= viewBottom)
|
||||||
|
{
|
||||||
|
DrawThinkingIndicator(new Rect(innerPadding, thinkingY, contentWidth, 35f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widgets.EndScrollView();
|
Widgets.EndScrollView();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Text.Font = originalFont;
|
Text.Font = originalFont;
|
||||||
Text.Anchor = originalAnchor;
|
Text.Anchor = originalAnchor;
|
||||||
|
GUI.color = Color.white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,19 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
|
|||||||
private Vector2 _scrollPosition = Vector2.zero;
|
private Vector2 _scrollPosition = Vector2.zero;
|
||||||
private string _inputText = "";
|
private string _inputText = "";
|
||||||
private bool _scrollToBottom = true;
|
private bool _scrollToBottom = true;
|
||||||
|
private int _lastHistoryCount = -1;
|
||||||
|
private float _lastUsedWidth = -1f;
|
||||||
|
private List<CachedMessage> _cachedMessages = new List<CachedMessage>();
|
||||||
|
private float _cachedTotalHeight = 0f;
|
||||||
|
|
||||||
|
private class CachedMessage
|
||||||
|
{
|
||||||
|
public string role;
|
||||||
|
public string message;
|
||||||
|
public string displayText;
|
||||||
|
public float height;
|
||||||
|
public float yOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// HUD / Minimized State
|
// HUD / Minimized State
|
||||||
@@ -323,67 +336,87 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
|
|||||||
return Widgets.ButtonInvisible(rect);
|
return Widgets.ButtonInvisible(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawMessageList(Rect rect)
|
private void UpdateCacheIfNeeded(float width)
|
||||||
{
|
{
|
||||||
var history = _core?.GetHistorySnapshot();
|
var history = _core?.GetHistorySnapshot();
|
||||||
if (history == null) return;
|
if (history == null) return;
|
||||||
|
|
||||||
// Filter out tool messages, empty messages, and XML-only messages
|
// 如果宽度没变且条数没变,就不重算
|
||||||
var displayHistory = new List<(string role, string message, string displayText)>();
|
if (Math.Abs(_lastUsedWidth - width) < 0.1f && history.Count == _lastHistoryCount)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastUsedWidth = width;
|
||||||
|
_lastHistoryCount = history.Count;
|
||||||
|
_cachedMessages.Clear();
|
||||||
|
_cachedTotalHeight = 0f;
|
||||||
|
float reducedSpacing = 8f;
|
||||||
|
float curY = 10f;
|
||||||
|
|
||||||
foreach (var msg in history)
|
foreach (var msg in history)
|
||||||
{
|
{
|
||||||
// Skip tool/toolcall messages to avoid empty spacing
|
// Filter logic
|
||||||
if (msg.role == "tool" || msg.role == "toolcall") continue;
|
if (msg.role == "tool" || msg.role == "toolcall") continue;
|
||||||
if (msg.role == "system" && !Prefs.DevMode) continue;
|
if (msg.role == "system" && !Prefs.DevMode) continue;
|
||||||
|
|
||||||
// For assistant messages, strip XML and check if empty
|
|
||||||
string displayText = msg.message;
|
string displayText = msg.message;
|
||||||
if (msg.role == "assistant")
|
if (msg.role == "assistant")
|
||||||
{
|
{
|
||||||
displayText = StripXmlTags(msg.message)?.Trim() ?? "";
|
displayText = StripXmlTags(msg.message)?.Trim() ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip empty or whitespace-only messages
|
|
||||||
if (string.IsNullOrWhiteSpace(displayText)) continue;
|
if (string.IsNullOrWhiteSpace(displayText)) continue;
|
||||||
|
|
||||||
|
float h = CalcMessageHeight(msg.role == "assistant" ? displayText : msg.message, width);
|
||||||
|
|
||||||
displayHistory.Add((msg.role, msg.message, displayText));
|
_cachedMessages.Add(new CachedMessage
|
||||||
|
{
|
||||||
|
role = msg.role,
|
||||||
|
message = msg.message,
|
||||||
|
displayText = displayText,
|
||||||
|
height = h,
|
||||||
|
yOffset = curY
|
||||||
|
});
|
||||||
|
|
||||||
|
curY += h + reducedSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup ScrollView
|
_cachedTotalHeight = curY;
|
||||||
float contentHeight = 0f;
|
}
|
||||||
|
|
||||||
|
private void DrawMessageList(Rect rect)
|
||||||
|
{
|
||||||
float width = rect.width - 26f; // Scrollbar space
|
float width = rect.width - 26f; // Scrollbar space
|
||||||
float reducedSpacing = 8f;
|
UpdateCacheIfNeeded(width);
|
||||||
|
|
||||||
List<float> heights = new List<float>();
|
float totalContentHeight = _cachedTotalHeight;
|
||||||
foreach (var msg in displayHistory)
|
if (_core != null && _core.IsThinking)
|
||||||
{
|
{
|
||||||
string textToMeasure = msg.role == "assistant" ? msg.displayText : msg.message;
|
totalContentHeight += 40f;
|
||||||
float h = CalcMessageHeight(textToMeasure, width);
|
|
||||||
heights.Add(h);
|
|
||||||
contentHeight += h + reducedSpacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_core.IsThinking)
|
|
||||||
{
|
|
||||||
contentHeight += 40f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect viewRect = new Rect(0, 0, width, contentHeight);
|
Rect viewRect = new Rect(0, 0, width, totalContentHeight);
|
||||||
|
|
||||||
if (_scrollToBottom)
|
if (_scrollToBottom)
|
||||||
{
|
{
|
||||||
_scrollPosition.y = contentHeight - rect.height;
|
_scrollPosition.y = totalContentHeight - rect.height;
|
||||||
_scrollToBottom = false;
|
_scrollToBottom = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widgets.BeginScrollView(rect, ref _scrollPosition, viewRect);
|
Widgets.BeginScrollView(rect, ref _scrollPosition, viewRect);
|
||||||
|
|
||||||
float curY = 10f;
|
// 虚拟化渲染:只绘制在窗口内的消息
|
||||||
for (int i = 0; i < displayHistory.Count; i++)
|
float viewTop = _scrollPosition.y;
|
||||||
|
float viewBottom = _scrollPosition.y + rect.height;
|
||||||
|
|
||||||
|
foreach (var entry in _cachedMessages)
|
||||||
{
|
{
|
||||||
var entry = displayHistory[i];
|
// 检查是否在可见范围内 (略微预留 Buffer)
|
||||||
float h = heights[i];
|
if (entry.yOffset + entry.height < viewTop - 100f) continue;
|
||||||
Rect msgRect = new Rect(0, curY, width, h);
|
if (entry.yOffset > viewBottom + 100f) break;
|
||||||
|
|
||||||
|
Rect msgRect = new Rect(0, entry.yOffset, width, entry.height);
|
||||||
|
|
||||||
if (entry.role == "user")
|
if (entry.role == "user")
|
||||||
{
|
{
|
||||||
@@ -401,14 +434,16 @@ namespace WulaFallenEmpire.EventSystem.AI.UI
|
|||||||
{
|
{
|
||||||
DrawSystemMessage(msgRect, entry.message);
|
DrawSystemMessage(msgRect, entry.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
curY += h + reducedSpacing;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_core.IsThinking)
|
if (_core != null && _core.IsThinking)
|
||||||
{
|
{
|
||||||
Rect thinkingRect = new Rect(0, curY, width, 30f);
|
float thinkingY = _cachedTotalHeight > 0 ? _cachedTotalHeight : 10f;
|
||||||
DrawThinkingIndicator(thinkingRect);
|
Rect thinkingRect = new Rect(0, thinkingY, width, 30f);
|
||||||
|
if (thinkingY + 30f >= viewTop && thinkingY <= viewBottom)
|
||||||
|
{
|
||||||
|
DrawThinkingIndicator(thinkingRect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widgets.EndScrollView();
|
Widgets.EndScrollView();
|
||||||
|
|||||||
Reference in New Issue
Block a user