feat(dashboard): AgentModal live working feed & thinking stream
This commit is contained in:
@@ -343,6 +343,23 @@ public class DashboardController(
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the most recent activity entries (assistant messages) for a specific agent.
|
||||
/// </summary>
|
||||
[HttpGet("agents/{id}/activity")]
|
||||
public async Task<List<AgentActivityEntry>> GetAgentActivity(string id, [FromQuery] int limit = 5)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await gateway.GetAgentActivityAsync(id, Math.Clamp(limit, 1, 20));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogWarning(ex, "GetAgentActivity failed for {AgentId}", id);
|
||||
return new List<AgentActivityEntry>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of available models that can be assigned to agents.
|
||||
/// Reads from OpenClaw config dynamically, falls back to hardcoded list.
|
||||
|
||||
@@ -104,3 +104,8 @@ public sealed record UpdateDashboardTaskRequest(
|
||||
public sealed record UpdateDashboardTaskStatusRequest(
|
||||
string Status
|
||||
);
|
||||
|
||||
public sealed record AgentActivityEntry(
|
||||
string Time,
|
||||
string Text
|
||||
);
|
||||
|
||||
@@ -953,6 +953,44 @@ public sealed class OpenClawGatewayClient(HttpClient httpClient, IConfiguration
|
||||
return Math.Clamp(totalQueuePressure + agentPressure, 0, 100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the most recent assistant activity (last N messages) for a specific agent.
|
||||
/// Returns entries with timestamp and truncated content text.
|
||||
/// Falls back to an empty list if the session is unreachable.
|
||||
/// </summary>
|
||||
public async Task<List<AgentActivityEntry>> GetAgentActivityAsync(string agentId, int limit = 5)
|
||||
{
|
||||
var entries = new List<AgentActivityEntry>();
|
||||
try
|
||||
{
|
||||
var sessionKey = $"agent:{agentId}:main";
|
||||
var messages = await GetSessionHistoryAsync(sessionKey, Math.Clamp(limit * 2, 1, 100));
|
||||
foreach (var msg in messages)
|
||||
{
|
||||
if (!string.Equals(msg.Role, "assistant", StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
if (string.IsNullOrWhiteSpace(msg.Content))
|
||||
continue;
|
||||
if (msg.Content == "REPLY_SKIP" || msg.Content == "ANNOUNCE_SKIP")
|
||||
continue;
|
||||
|
||||
// Truncate content to first 200 chars for compact display
|
||||
var text = msg.Content.Length > 200
|
||||
? msg.Content[..200] + "…"
|
||||
: msg.Content;
|
||||
var ts = ParseTimestamp(msg.Timestamp);
|
||||
var timeAgo = FormatTimeAgo(ts);
|
||||
|
||||
entries.Add(new AgentActivityEntry(timeAgo, text));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Return empty list if gateway is unreachable
|
||||
}
|
||||
return entries.Take(Math.Clamp(limit, 1, 20)).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the list of available models by reading from the OpenClaw config,
|
||||
/// with fallback to hardcoded list.
|
||||
|
||||
Reference in New Issue
Block a user