Compare commits

...

4 Commits

Author SHA1 Message Date
devops 702692cf0c chore: bump version to v0.2.39 [skip ci] 2026-06-09 23:14:57 +00:00
developer 51d1917a7b fix: GetSessionHistory parst content[] blocks korrekt
CI - Build & Test / Backend (.NET) (push) Successful in 24s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 15s
CI - Build & Test / Security Check (push) Successful in 3s
- Messages aus result.details.messages extrahieren
- Content = Array von {type, text} blocks → nur text extrahieren
- Thinking-Blocks + REPLY_SKIP + ANNOUNCE_SKIP herausfiltern
2026-06-10 01:14:08 +02:00
devops 85f3400076 chore: bump version to v0.2.38 [skip ci] 2026-06-09 23:12:40 +00:00
developer a5cbe98f25 fix: Chat-Messages Merge + Session-Key agent:iris:main
CI - Build & Test / Backend (.NET) (push) Successful in 23s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 16s
CI - Build & Test / Security Check (push) Successful in 3s
- fetchChatMessages merged statt replace (verhindert Poll-wipe)
- Chat/Send bereits korrekt via agentId=iris
- Chat/Messages nutzt jetzt agent:iris:main als Session-Key
- Cron-Job deaktiviert (verhinderte Selbst-Konversation)
2026-06-10 01:11:52 +02:00
4 changed files with 49 additions and 17 deletions
+1 -1
View File
@@ -1 +1 @@
0.2.37 0.2.39
+1 -1
View File
@@ -119,7 +119,7 @@ public class DashboardController(OpenClawGatewayClient gateway, ILogger<Dashboar
{ {
try try
{ {
var key = string.IsNullOrWhiteSpace(sessionKey) ? "iris" : sessionKey.Trim(); var key = string.IsNullOrWhiteSpace(sessionKey) ? "agent:iris:main" : sessionKey.Trim();
var messages = await gateway.GetSessionHistoryAsync(key, Math.Clamp(limit, 1, 200), Math.Max(0, offset)); var messages = await gateway.GetSessionHistoryAsync(key, Math.Clamp(limit, 1, 200), Math.Max(0, offset));
// Filter: only user and assistant messages (exclude tool/system) // Filter: only user and assistant messages (exclude tool/system)
+34 -9
View File
@@ -145,24 +145,49 @@ public sealed class OpenClawGatewayClient(HttpClient httpClient, IConfiguration
{ {
try try
{ {
var result = await InvokeToolAsync("sessions_history", new { sessionKey, limit, offset }); var result = await InvokeToolAsync("sessions_history", new {
sessionKey, limit, offset,
includeTools = false
});
if (result is null) return new List<MessageEntry>(); if (result is null) return new List<MessageEntry>();
var messages = new List<MessageEntry>(); // sessions_history returns { details: { messages: [...] } }
var array = result as JsonArray ?? result.AsArray(); var messageArray = result["details"]?["messages"] as JsonArray;
if (array is null) return messages; if (messageArray is null) return new List<MessageEntry>();
foreach (var msg in array) var messages = new List<MessageEntry>();
foreach (var msg in messageArray.Cast<JsonNode?>())
{ {
if (msg is null) continue; if (msg is null) continue;
var role = msg["role"]?.GetValue<string>() ?? ""; var role = msg["role"]?.GetValue<string>() ?? "";
var content = msg["content"]?.GetValue<string>() ?? ""; // Skip non-user/assistant roles
if (role is not ("user" or "assistant")) continue;
// Content is an array of blocks: [{type: "text"/"thinking", text: "..."}]
// Extract only pure text blocks, skip thinking-only messages
var contentBlocks = msg["content"] as JsonArray;
if (contentBlocks is null) continue;
var visibleTexts = new List<string>();
foreach (var block in contentBlocks.Cast<JsonNode?>())
{
if (block is null) continue;
var type = block["type"]?.GetValue<string>() ?? "";
var text = block["text"]?.GetValue<string>() ?? "";
if (type == "text" && !string.IsNullOrWhiteSpace(text))
visibleTexts.Add(text);
}
var visibleContent = string.Join(" ", visibleTexts).Trim();
if (string.IsNullOrWhiteSpace(visibleContent)) continue;
// Skip system-only replies
if (visibleContent is "REPLY_SKIP" or "ANNOUNCE_SKIP") continue;
var timestamp = msg["timestamp"]?.GetValue<string>() var timestamp = msg["timestamp"]?.GetValue<string>()
?? msg["ts"]?.GetValue<string>()
?? msg["createdAt"]?.GetValue<string>()
?? DateTimeOffset.UtcNow.ToString("o"); ?? DateTimeOffset.UtcNow.ToString("o");
messages.Add(new MessageEntry(role, content, timestamp)); messages.Add(new MessageEntry(role, visibleContent, timestamp));
} }
return messages; return messages;
+13 -6
View File
@@ -280,12 +280,19 @@ async function fetchChatMessages(): Promise<void> {
const res = await apiFetch('/api/dashboard/chat/messages?limit=50') const res = await apiFetch('/api/dashboard/chat/messages?limit=50')
if (!res.ok) return if (!res.ok) return
const data: DashboardChatMessage[] = await res.json() const data: DashboardChatMessage[] = await res.json()
chatMessages.value = data.map((msg, idx) => ({ // Merge instead of replace — only add messages not already present
id: `msg-${idx}`, const existingTexts = new Set(chatMessages.value.map(m => m.text))
sender: msg.role === 'assistant' ? 'iris' : 'user', const existingTimestamps = new Set(chatMessages.value.map(m => m.timestamp))
text: msg.content, for (const msg of data) {
timestamp: new Date(msg.timestamp).getTime(), const msgTime = new Date(msg.timestamp).getTime()
})) if (existingTexts.has(msg.content) && existingTimestamps.has(msgTime)) continue
chatMessages.value.push({
id: `msg-${msgTime}-${msg.role}`,
sender: msg.role === 'assistant' ? 'iris' : 'user',
text: msg.content,
timestamp: msgTime,
})
}
} catch { } catch {
// API unreachable keep current values // API unreachable keep current values
} }