feat(chat): prompt navigator list preview, prompt filtering, shell status fix (#2211)
* feat(chat): prompt navigator list preview with prompt filtering The hover preview is now an interactive scrolling mini-list of prompts: rows render as bordered two-line cards, the highlighted row stays inside a center dead zone and the list glides only near the window edges, wheel steps the highlight, and the panel stays open when the pointer moves into it so a click can be corrected inside the list. Rail entries are filtered to real prompts: previews are built from normalized user display parts (synthetic context stripped), fully synthetic user messages are excluded, and shell-mode messages show their extracted command via the shared shell bridge helpers. * fix(chat): render shell command status transitions The injected /shell text part carries live state in shellAction, which the render-relevant part comparator ignored — a running→completed update reached the store but never re-rendered the message row until the next send. Compare shellAction command/output/status for text parts. * fix(sync): stream shell bridge part updates while running Streaming suspension keeps part updates out of the static message records while an assistant message streams, relying on the live streaming-tail path to render it. Shell-mode bridge messages are hidden from the timeline and rendered inside the user row, so they have no live path — suspension froze their output chunks and left the card without a Show output action until the run finished. Exempt shell bridges (single bash tool part parented to a synthetic shell-marker user message) from suspension; their updates arrive at command-output pace, not delta pace. * feat(chat): syntax-highlight shell command card Render the shell-mode command and its output through the shared WorkerHighlightedCode (Shiki) with bash grammar, matching the bash tool part presentation, instead of plain pre blocks.
This commit is contained in:
committed by
GitHub
parent
68f1c1efe3
commit
a1badccddd
@@ -2512,11 +2512,37 @@ export function dropCachedSessionMessageRecordsSnapshots(
|
||||
}
|
||||
}
|
||||
|
||||
// Shell-mode bridge messages (single bash tool part parented to a synthetic
|
||||
// shell-marker user message) are hidden from the timeline and rendered inside
|
||||
// the user row, so they never go through the live streaming-tail path. Their
|
||||
// part updates (output chunks, running→completed) must not be suspended, or
|
||||
// the shell card freezes until the next full snapshot rebuild.
|
||||
const USER_SHELL_MARKER = "The following tool was executed by the user"
|
||||
|
||||
const isSuspendExemptShellBridge = (state: State, info: Message, parts: Part[] | undefined): boolean => {
|
||||
if (!parts || parts.length !== 1) return false
|
||||
const part = parts[0] as { type?: unknown; tool?: unknown }
|
||||
if (part?.type !== "tool" || typeof part.tool !== "string" || part.tool.toLowerCase() !== "bash") return false
|
||||
const parentID = (info as { parentID?: unknown }).parentID
|
||||
if (typeof parentID !== "string" || parentID.length === 0) return false
|
||||
const parentParts = state.part[parentID]
|
||||
if (!parentParts) return false
|
||||
return parentParts.some((parentPart) => {
|
||||
if (parentPart?.type !== "text") return false
|
||||
if ((parentPart as { synthetic?: boolean }).synthetic !== true) return false
|
||||
const text = (parentPart as { text?: unknown }).text
|
||||
return typeof text === "string" && text.trim().startsWith(USER_SHELL_MARKER)
|
||||
})
|
||||
}
|
||||
|
||||
const snapshotPartsMatchState = (snapshot: SessionMessageRecordsSnapshot, state: State): boolean => {
|
||||
for (const record of snapshot.list) {
|
||||
if (snapshot.suspendPartUpdates) {
|
||||
const suspendedID = snapshot.suspendedPartUpdatesMessageID
|
||||
if (!suspendedID || record.info.id === suspendedID) {
|
||||
if (
|
||||
(!suspendedID || record.info.id === suspendedID)
|
||||
&& !isSuspendExemptShellBridge(state, record.info, state.part[record.info.id])
|
||||
) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -2594,6 +2620,7 @@ export function buildSessionMessageRecordsSnapshot(
|
||||
const shouldSuspendParts = suspendPartUpdates
|
||||
&& previousRecord
|
||||
&& (!suspendedPartUpdatesMessageID || message.id === suspendedPartUpdatesMessageID)
|
||||
&& !isSuspendExemptShellBridge(state, message, state.part[message.id])
|
||||
const parts = shouldSuspendParts
|
||||
? previousRecord.parts
|
||||
: (state.part[message.id] ?? EMPTY_PARTS)
|
||||
|
||||
Reference in New Issue
Block a user