Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/OpenClaw.Chat/ChatModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ public record ChatThread
{
public required string Id { get; init; }
public required string Title { get; init; }
public string? AgentId { get; init; }
public bool IsBackground { get; init; }
public bool IsVisibleInSessionPicker(string? activeThreadId) =>
!IsBackground || string.Equals(Id, activeThreadId, StringComparison.Ordinal);
public ChatThreadStatus Status { get; init; }
public ChatActivity Activity { get; init; }
public string? Cwd { get; init; }
Expand Down Expand Up @@ -230,9 +234,9 @@ public record ChatDataSnapshot(
/// and accepts <see cref="IChatDataProvider.SendMessageAsync"/> calls keyed by
/// <see cref="SessionKey"/>.
/// </param>
public sealed record ChatComposeTarget(string? SessionKey, bool IsReady)
public sealed record ChatComposeTarget(string? SessionKey, bool IsReady, string? AgentId = null)
{
public static ChatComposeTarget NotReady { get; } = new(null, false);
public static ChatComposeTarget NotReady { get; } = new(null, false, null);
}

public sealed class ChatDataChangedEventArgs(ChatDataSnapshot snapshot) : EventArgs
Expand Down
56 changes: 33 additions & 23 deletions src/OpenClaw.Shared/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,27 @@ private static bool TryGetBool(JsonElement parent, string property) =>
}
}

public sealed class SessionPresentationInfo
{
public string Title { get; set; } = "";
public string TitleSource { get; set; } = "generated";
public string? Subtitle { get; set; }
public string Family { get; set; } = "custom";
public string? AgentId { get; set; }
public string? Channel { get; set; }
public string? AccountId { get; set; }
public string? PeerKind { get; set; }
public bool IsMain { get; set; }
public bool IsBackground { get; set; }
}

public sealed class SessionWorktreeInfo
{
public string? Id { get; set; }
public string? Branch { get; set; }
public string? RepoRoot { get; set; }
}

public class SessionInfo
{
/// <summary>Defensive copy so a snapshot handed to a SessionsUpdated subscriber does not
Expand All @@ -259,14 +280,24 @@ public class SessionInfo

public string Key { get; set; } = "";
public bool IsMain { get; set; }
internal bool IsMainResolved { get; set; }
public string? Label { get; set; }
public string Status { get; set; } = "unknown";
public string? Model { get; set; }
public string? Channel { get; set; }
public string? DisplayName { get; set; }
public string? DerivedTitle { get; set; }
public string? Provider { get; set; }
public string? Subject { get; set; }
public string? Room { get; set; }
public string? Space { get; set; }
public string? ChatType { get; set; }
public string? OriginLabel { get; set; }
public SessionWorktreeInfo? Worktree { get; set; }
public string? ExecNode { get; set; }
public string? ParentSessionKey { get; set; }
public int? SpawnDepth { get; set; }
public SessionPresentationInfo? Presentation { get; set; }
public string? SessionId { get; set; }
public string? ThinkingLevel { get; set; }
public string? VerboseLevel { get; set; }
Expand Down Expand Up @@ -304,9 +335,7 @@ public string RichDisplayText
{
get
{
var title = !string.IsNullOrWhiteSpace(DisplayName)
? DisplayName!
: (IsMain ? "Main session" : "Session");
var title = SessionPresentationResolver.Resolve(this).Title;

// Fixed-size array avoids List<string> allocation; at most 9 detail slots.
var details = new string?[9];
Expand Down Expand Up @@ -349,26 +378,7 @@ public string ContextSummaryShort
/// <summary>Gets a shortened, user-friendly version of the session key.</summary>
public string ShortKey
{
get
{
if (string.IsNullOrEmpty(Key)) return "unknown";

// Extract meaningful part from session keys like "agent:main:subagent:uuid"
var parts = Key.Split(':');
if (parts.Length >= 3)
{
// Return something like "subagent" or "cron"
return parts[^2]; // Second to last part
}

// For file paths, just return filename
if (Key.Contains('/') || Key.Contains('\\'))
{
return Path.GetFileName(Key);
}

return Key.Length > 20 ? Key[..17] + "..." : Key;
}
get => SessionPresentationResolver.Resolve(this).Title;
}

}
Expand Down
Loading
Loading