fix(tui): show content filter finishes
This commit is contained in:
parent
02f012f5d1
commit
cbe1b7d67e
3 changed files with 39 additions and 20 deletions
|
|
@ -297,6 +297,7 @@ export function SessionTurn(
|
|||
const error = createMemo(
|
||||
() => assistantMessages().find((m) => m.error && m.error.name !== "MessageAbortedError")?.error,
|
||||
)
|
||||
const contentFiltered = createMemo(() => assistantMessages().some((m) => m.finish === "content-filter"))
|
||||
const showAssistantCopyPartID = createMemo(() => {
|
||||
const messages = assistantMessages()
|
||||
|
||||
|
|
@ -315,6 +316,7 @@ export function SessionTurn(
|
|||
return undefined
|
||||
})
|
||||
const errorText = createMemo(() => {
|
||||
if (contentFiltered()) return "The response was blocked by the provider's content filter"
|
||||
const msg = error()?.data?.message
|
||||
if (typeof msg === "string") return unwrap(msg)
|
||||
if (msg === undefined || msg === null) return ""
|
||||
|
|
@ -525,7 +527,7 @@ export function SessionTurn(
|
|||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={error()}>
|
||||
<Show when={error() || contentFiltered()}>
|
||||
<Card variant="error" class="error-card">
|
||||
{errorText()}
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -1197,9 +1197,13 @@ function AssistantFooter(props: { message: SessionMessageAssistant }) {
|
|||
const duration = createMemo(() =>
|
||||
props.message.time.completed ? props.message.time.completed - props.message.time.created : 0,
|
||||
)
|
||||
const contentFiltered = createMemo(() => props.message.finish === "content-filter")
|
||||
const errorText = createMemo(() =>
|
||||
contentFiltered() ? "The response was blocked by the provider's content filter" : errorMessage(props.message.error),
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<Show when={props.message.error}>
|
||||
<Show when={props.message.error || contentFiltered()}>
|
||||
<box
|
||||
border={["left"]}
|
||||
paddingTop={1}
|
||||
|
|
@ -1209,12 +1213,16 @@ function AssistantFooter(props: { message: SessionMessageAssistant }) {
|
|||
customBorderChars={SplitBorder.customBorderChars}
|
||||
borderColor={theme.error}
|
||||
>
|
||||
<text fg={theme.textMuted}>{errorMessage(props.message.error)}</text>
|
||||
<text fg={theme.textMuted}>{errorText()}</text>
|
||||
</box>
|
||||
</Show>
|
||||
<box paddingLeft={3} marginTop={props.message.error ? 1 : 0}>
|
||||
<box paddingLeft={3} marginTop={props.message.error || contentFiltered() ? 1 : 0}>
|
||||
<text>
|
||||
<span style={{ fg: props.message.error ? theme.textMuted : local.agent.color(props.message.agent) }}>
|
||||
<span
|
||||
style={{
|
||||
fg: props.message.error || contentFiltered() ? theme.textMuted : local.agent.color(props.message.agent),
|
||||
}}
|
||||
>
|
||||
{Locale.titlecase(props.message.agent)}
|
||||
</span>
|
||||
<span style={{ fg: theme.textMuted }}> · {model()}</span>
|
||||
|
|
@ -1386,13 +1394,7 @@ function UserMessage(props: { message: SessionMessageUser }) {
|
|||
>
|
||||
<text fg={theme.text}>{props.message.text}</text>
|
||||
<Show when={files().length}>
|
||||
<box
|
||||
flexDirection="row"
|
||||
paddingBottom={metadataVisible() ? 1 : 0}
|
||||
paddingTop={1}
|
||||
gap={1}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
<box flexDirection="row" paddingBottom={metadataVisible() ? 1 : 0} paddingTop={1} gap={1} flexWrap="wrap">
|
||||
<For each={files()}>
|
||||
{(file) => {
|
||||
const directory = file.mime === "application/x-directory"
|
||||
|
|
@ -1452,6 +1454,10 @@ function AssistantMessage(props: { message: SessionMessageAssistant; last: boole
|
|||
if (!props.message.time.completed) return 0
|
||||
return props.message.time.completed - props.message.time.created
|
||||
})
|
||||
const contentFiltered = createMemo(() => props.message.finish === "content-filter")
|
||||
const errorText = createMemo(() =>
|
||||
contentFiltered() ? "The response was blocked by the provider's content filter" : errorMessage(props.message.error),
|
||||
)
|
||||
|
||||
const exploration = createMemo(() => {
|
||||
const grouped = new Map<string, { first: boolean; parts: SessionMessageAssistantTool[]; active: boolean }>()
|
||||
|
|
@ -1514,7 +1520,7 @@ function AssistantMessage(props: { message: SessionMessageAssistant; last: boole
|
|||
</Switch>
|
||||
)}
|
||||
</For>
|
||||
<Show when={props.message.error}>
|
||||
<Show when={props.message.error || contentFiltered()}>
|
||||
<box
|
||||
border={["left"]}
|
||||
paddingTop={1}
|
||||
|
|
@ -1524,14 +1530,19 @@ function AssistantMessage(props: { message: SessionMessageAssistant; last: boole
|
|||
customBorderChars={SplitBorder.customBorderChars}
|
||||
borderColor={theme.error}
|
||||
>
|
||||
<text fg={theme.textMuted}>{errorMessage(props.message.error)}</text>
|
||||
<text fg={theme.textMuted}>{errorText()}</text>
|
||||
</box>
|
||||
</Show>
|
||||
<Switch>
|
||||
<Match when={props.last || final() || props.message.error}>
|
||||
<Match when={props.last || final() || props.message.error || contentFiltered()}>
|
||||
<box paddingLeft={3}>
|
||||
<text>
|
||||
<span style={{ fg: props.message.error ? theme.textMuted : local.agent.color(props.message.agent) }}>
|
||||
<span
|
||||
style={{
|
||||
fg:
|
||||
props.message.error || contentFiltered() ? theme.textMuted : local.agent.color(props.message.agent),
|
||||
}}
|
||||
>
|
||||
{Locale.titlecase(props.message.agent)}
|
||||
</span>
|
||||
<span style={{ fg: theme.textMuted }}> · {model()}</span>
|
||||
|
|
@ -1722,7 +1733,8 @@ function ToolPart(props: { part: SessionMessageAssistantTool }) {
|
|||
return Boolean(shellID && data.shell.get(shellID))
|
||||
}
|
||||
if (display() === "subagent") {
|
||||
const sessionID = stringValue(props.part.state.structured.sessionID) ?? stringValue(props.part.state.structured.sessionId)
|
||||
const sessionID =
|
||||
stringValue(props.part.state.structured.sessionID) ?? stringValue(props.part.state.structured.sessionId)
|
||||
return Boolean(sessionID && data.session.status(sessionID) === "running")
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -95,9 +95,7 @@ test("completes exploration groups when another row follows", () => {
|
|||
])
|
||||
finished.finish = "stop"
|
||||
const messages: SessionMessage[] = [
|
||||
assistant("assistant-1", [
|
||||
{ type: "tool", id: "read-1", name: "read", state: pending(), time: { created: 1 } },
|
||||
]),
|
||||
assistant("assistant-1", [{ type: "tool", id: "read-1", name: "read", state: pending(), time: { created: 1 } }]),
|
||||
{ type: "user", id: "user-1", text: "Continue", time: { created: 2 } },
|
||||
finished,
|
||||
]
|
||||
|
|
@ -122,6 +120,13 @@ test("completes exploration groups when another row follows", () => {
|
|||
])
|
||||
})
|
||||
|
||||
test("adds a footer for content-filter assistant finishes without parts", () => {
|
||||
const filtered = assistant("assistant-filtered", [])
|
||||
filtered.finish = "content-filter"
|
||||
|
||||
expect(reduceSessionRows([filtered])).toEqual([{ type: "assistant-footer", messageID: "assistant-filtered" }])
|
||||
})
|
||||
|
||||
test("hides synthetic messages without descriptions", () => {
|
||||
const messages: SessionMessage[] = [
|
||||
assistant("assistant-1", [{ type: "tool", id: "read-1", name: "read", state: pending(), time: { created: 1 } }]),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue