Improve session refresh and UI polish

This commit is contained in:
Shantur Rathore
2025-11-13 23:36:36 +00:00
parent e12f39abc2
commit 6918232913
6 changed files with 66 additions and 18 deletions

View File

@@ -63,6 +63,7 @@ import {
agents, agents,
getSessionInfo, getSessionInfo,
isSessionMessagesLoading, isSessionMessagesLoading,
fetchSessions,
} from "./stores/sessions" } from "./stores/sessions"
import { isSessionBusy } from "./stores/session-status" import { isSessionBusy } from "./stores/session-status"
import { setupTabKeyboardShortcuts } from "./lib/keyboard" import { setupTabKeyboardShortcuts } from "./lib/keyboard"
@@ -461,13 +462,24 @@ const App: Component = () => {
const sessions = getSessions(instanceId) const sessions = getSessions(instanceId)
const session = sessions.find((s) => s.id === sessionId) const session = sessions.find((s) => s.id === sessionId)
const isParent = session?.parentId === null if (!session) {
return
}
if (!isParent) { const parentSessionId = session.parentId ?? session.id
const parentSession = sessions.find((s) => s.id === parentSessionId)
if (!parentSession || parentSession.parentId !== null) {
return return
} }
clearActiveParentSession(instanceId) clearActiveParentSession(instanceId)
try {
await fetchSessions(instanceId)
} catch (error) {
console.error("Failed to refresh sessions after closing:", error)
}
} }
function setupCommands() { function setupCommands() {

View File

@@ -545,15 +545,14 @@ export default function MessageStream(props: MessageStreamProps) {
return ( return (
<div class="message-stream-container"> <div class="message-stream-container">
<div class="connection-status"> <div class="connection-status">
<div class="connection-status-text flex items-center gap-2 text-sm font-medium"> <div class="connection-status-text connection-status-info flex items-center gap-2 text-sm font-medium">
<span>{formattedSessionInfo()}</span> <span>{formattedSessionInfo()}</span>
</div> </div>
<div class="flex-1" /> <div class="connection-status-text connection-status-shortcut flex items-center gap-2 text-sm font-medium">
<div class="connection-status-text flex items-center gap-2 text-sm font-medium">
<span>Command Palette</span> <span>Command Palette</span>
<Kbd shortcut="cmd+shift+p" /> <Kbd shortcut="cmd+shift+p" />
</div> </div>
<div class="flex-1 flex items-center justify-end gap-3"> <div class="connection-status-meta flex items-center justify-end gap-3">
<Show when={connectionStatus() === "connected"}> <Show when={connectionStatus() === "connected"}>
<span class="status-indicator connected"> <span class="status-indicator connected">
<span class="status-dot" /> <span class="status-dot" />

View File

@@ -225,7 +225,7 @@ const SessionList: Component<SessionListProps> = (props) => {
</div> </div>
<Show when={rowProps.canClose}> <Show when={rowProps.canClose}>
<span <span
class="session-item-close opacity-0 group-hover:opacity-100 hover:bg-status-error hover:text-white rounded p-0.5 transition-all" class="session-item-close opacity-80 hover:opacity-100 hover:bg-status-error hover:text-white rounded p-0.5 transition-all"
onClick={(event) => { onClick={(event) => {
event.stopPropagation() event.stopPropagation()
props.onClose(rowProps.sessionId) props.onClose(rowProps.sessionId)
@@ -333,11 +333,13 @@ const SessionList: Component<SessionListProps> = (props) => {
role="button" role="button"
aria-selected={props.activeSessionId === "info"} aria-selected={props.activeSessionId === "info"}
> >
<div class="flex items-center gap-2 flex-1"> <div class="session-item-row session-item-header">
<Info class="w-4 h-4 flex-shrink-0" /> <div class="session-item-title-row">
<span class="session-item-title truncate">Instance Info</span> <Info class="w-4 h-4 flex-shrink-0" />
<span class="session-item-title truncate">Instance Info</span>
</div>
{infoShortcut && <Kbd shortcut={formatShortcut(infoShortcut)} class="ml-2 not-italic" />}
</div> </div>
{infoShortcut && <Kbd shortcut={formatShortcut(infoShortcut)} class="ml-2 not-italic" />}
</button> </button>
</div> </div>
</div> </div>

View File

@@ -699,7 +699,7 @@ export default function ToolCall(props: ToolCallProps) {
} }
} }
const shouldShowTag = (status: string) => status === "in_progress" || status === "cancelled" const shouldShowTag = (status: string) => status === "cancelled"
return ( return (
<div class="tool-call-todos" role="list"> <div class="tool-call-todos" role="list">

View File

@@ -409,15 +409,19 @@ async function fetchSessions(instanceId: string): Promise<void> {
return return
} }
const existingSessions = sessions().get(instanceId)
for (const apiSession of response.data) { for (const apiSession of response.data) {
const existingSession = existingSessions?.get(apiSession.id)
sessionMap.set(apiSession.id, { sessionMap.set(apiSession.id, {
id: apiSession.id, id: apiSession.id,
instanceId, instanceId,
title: apiSession.title || "Untitled", title: apiSession.title || "Untitled",
parentId: apiSession.parentID || null, parentId: apiSession.parentID || null,
agent: "", agent: existingSession?.agent ?? "",
model: { providerId: "", modelId: "" }, model: existingSession?.model ?? { providerId: "", modelId: "" },
version: apiSession.version, // Include version from SDK version: apiSession.version, // Include version from SDK
time: { time: {
...apiSession.time, ...apiSession.time,
}, },
@@ -429,17 +433,34 @@ async function fetchSessions(instanceId: string): Promise<void> {
diff: apiSession.revert.diff, diff: apiSession.revert.diff,
} }
: undefined, : undefined,
messages: [], messages: existingSession?.messages ?? [],
messagesInfo: new Map(), messagesInfo: existingSession?.messagesInfo ?? new Map(),
}) })
} }
const validSessionIds = new Set(sessionMap.keys())
setSessions((prev) => { setSessions((prev) => {
const next = new Map(prev) const next = new Map(prev)
next.set(instanceId, sessionMap) next.set(instanceId, sessionMap)
return next return next
}) })
setMessagesLoaded((prev) => {
const next = new Map(prev)
const loadedSet = next.get(instanceId)
if (loadedSet) {
const filtered = new Set<string>()
for (const id of loadedSet) {
if (validSessionIds.has(id)) {
filtered.add(id)
}
}
next.set(instanceId, filtered)
}
return next
})
for (const session of sessionMap.values()) { for (const session of sessionMap.values()) {
const flag = (session.time as (Session["time"] & { compacting?: number | boolean }) | undefined)?.compacting const flag = (session.time as (Session["time"] & { compacting?: number | boolean }) | undefined)?.compacting
const active = typeof flag === "number" ? flag > 0 : Boolean(flag) const active = typeof flag === "number" ? flag > 0 : Boolean(flag)

View File

@@ -545,11 +545,25 @@ button.button-primary:disabled {
} }
.connection-status { .connection-status {
@apply flex justify-center items-center px-4 py-2 gap-4; @apply grid items-center px-4 py-2 gap-4;
grid-template-columns: 1fr auto 1fr;
background-color: var(--surface-secondary); background-color: var(--surface-secondary);
border-bottom: 1px solid var(--border-base); border-bottom: 1px solid var(--border-base);
} }
.connection-status-info {
justify-self: start;
}
.connection-status-shortcut {
justify-self: center;
text-align: center;
}
.connection-status-meta {
justify-self: end;
}
.connection-status-text { .connection-status-text {
color: var(--text-muted); color: var(--text-muted);
} }