mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-30 19:32:39 +08:00
Merge pull request #6660 from Kilo-Org/fix/6623-question-prompt-formatting
This commit is contained in:
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:550464711e0d3aab99fa514d6de9501be19e49b65d5643b7762fb7b5ca47464c
|
||||
size 19715
|
||||
oid sha256:b8b1ba56d6632bfcbd0e4c5b0c1514cd80832339dde0c86568572ada656ca33d
|
||||
size 24134
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2cdb43fe23e17f32dd96b36eb3b2f97b4b84c29983996f26406db6ead2f41785
|
||||
size 25707
|
||||
oid sha256:278855516fe11d95b9de942d9690531c114b0a0b9ac0239c2ef31f82b420bd7e
|
||||
size 32467
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:18bd63c206b2afc5d8d05e06a8a1113c7dfa1019e85eebe570be40419dbe35fd
|
||||
size 28187
|
||||
oid sha256:f6193ba79b4d5dda29bf39d1127dacd7e332755d1f6f42dd67ff667088975659
|
||||
size 35678
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:607707e2201d1e50369a5897266136387b2444570b61ac2062c658335a0cdcc7
|
||||
size 5055
|
||||
@@ -1,12 +1,13 @@
|
||||
/**
|
||||
* QuestionDock component
|
||||
* Displays question requests from the AI assistant inline above the prompt input.
|
||||
* Uses kilo-ui's data-component/data-slot CSS pattern for styling.
|
||||
* Uses kilo-ui's DockPrompt component for proper surface styling.
|
||||
*/
|
||||
|
||||
import { Component, For, Show, createMemo, createEffect } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { Button } from "@kilocode/kilo-ui/button"
|
||||
import { DockPrompt } from "@kilocode/kilo-ui/dock-prompt"
|
||||
import { Icon } from "@kilocode/kilo-ui/icon"
|
||||
import { useSession } from "../../context/session"
|
||||
import { useLanguage } from "../../context/language"
|
||||
@@ -148,10 +149,11 @@ export const QuestionDock: Component<{ request: QuestionRequest }> = (props) =>
|
||||
}
|
||||
|
||||
return (
|
||||
<div data-component="tool-part-wrapper" data-question="true" onClick={(e: MouseEvent) => e.stopPropagation()}>
|
||||
<div data-component="question-prompt">
|
||||
<div data-slot="question-body">
|
||||
<div data-slot="question-header">
|
||||
<div onClick={(e: MouseEvent) => e.stopPropagation()}>
|
||||
<DockPrompt
|
||||
kind="question"
|
||||
header={
|
||||
<>
|
||||
<div data-slot="question-header-title">{summary()}</div>
|
||||
<Show when={!single()}>
|
||||
<div data-slot="question-progress">
|
||||
@@ -177,62 +179,65 @@ export const QuestionDock: Component<{ request: QuestionRequest }> = (props) =>
|
||||
</button>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<Show when={!confirm()}>
|
||||
<div data-slot="question-content">
|
||||
<div data-slot="question-text">{question()?.question}</div>
|
||||
<Show
|
||||
when={multi()}
|
||||
fallback={<div data-slot="question-hint">{language.t("ui.question.singleHint")}</div>}
|
||||
>
|
||||
<div data-slot="question-hint">{language.t("ui.question.multiHint")}</div>
|
||||
</>
|
||||
}
|
||||
footer={
|
||||
<>
|
||||
<Button variant="ghost" size="small" onClick={reject} disabled={store.sending}>
|
||||
{language.t("ui.common.dismiss")}
|
||||
</Button>
|
||||
<div data-slot="question-footer-actions">
|
||||
<Show when={store.tab > 0}>
|
||||
<Button variant="secondary" size="small" onClick={back} disabled={store.sending}>
|
||||
{language.t("ui.common.back")}
|
||||
</Button>
|
||||
</Show>
|
||||
<div data-slot="question-options">
|
||||
<For each={options()}>
|
||||
{(opt, i) => {
|
||||
const picked = () => store.answers[store.tab]?.includes(opt.label) ?? false
|
||||
return (
|
||||
<button
|
||||
data-slot="question-option"
|
||||
data-picked={picked()}
|
||||
disabled={store.sending}
|
||||
onClick={() => selectOption(i())}
|
||||
>
|
||||
<span data-slot="question-option-check" aria-hidden="true">
|
||||
<span
|
||||
data-slot="question-option-box"
|
||||
data-type={multi() ? "checkbox" : "radio"}
|
||||
data-picked={picked()}
|
||||
>
|
||||
<Show when={multi()} fallback={<span data-slot="question-option-radio-dot" />}>
|
||||
<Icon name="check-small" size="small" />
|
||||
</Show>
|
||||
</span>
|
||||
</span>
|
||||
<span data-slot="question-option-main">
|
||||
<span data-slot="option-label">{opt.label}</span>
|
||||
<Show when={opt.description}>
|
||||
<span data-slot="option-description">{opt.description}</span>
|
||||
</Show>
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
<Show when={question()?.custom !== false}>
|
||||
<Show
|
||||
when={confirm()}
|
||||
fallback={
|
||||
<Button
|
||||
variant={last() && single() ? "primary" : "secondary"}
|
||||
size="small"
|
||||
onClick={last() && single() ? submit : () => selectTab(store.tab + 1)}
|
||||
disabled={store.sending || (!confirm() && (store.answers[store.tab]?.length ?? 0) === 0)}
|
||||
>
|
||||
{last() && single()
|
||||
? language.t("ui.common.submit")
|
||||
: last()
|
||||
? language.t("common.review")
|
||||
: language.t("ui.common.next")}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Button variant="primary" size="small" onClick={submit} disabled={store.sending}>
|
||||
{language.t("ui.common.submit")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Show when={!confirm()}>
|
||||
<div data-slot="question-text">{question()?.question}</div>
|
||||
<Show when={multi()} fallback={<div data-slot="question-hint">{language.t("ui.question.singleHint")}</div>}>
|
||||
<div data-slot="question-hint">{language.t("ui.question.multiHint")}</div>
|
||||
</Show>
|
||||
<div data-slot="question-options">
|
||||
<For each={options()}>
|
||||
{(opt, i) => {
|
||||
const picked = () => store.answers[store.tab]?.includes(opt.label) ?? false
|
||||
return (
|
||||
<button
|
||||
data-slot="question-option"
|
||||
data-custom="true"
|
||||
data-picked={customPicked()}
|
||||
data-picked={picked()}
|
||||
disabled={store.sending}
|
||||
onClick={() => selectOption(options().length)}
|
||||
onClick={() => selectOption(i())}
|
||||
>
|
||||
<span data-slot="question-option-check" aria-hidden="true">
|
||||
<span
|
||||
data-slot="question-option-box"
|
||||
data-type={multi() ? "checkbox" : "radio"}
|
||||
data-picked={customPicked()}
|
||||
data-picked={picked()}
|
||||
>
|
||||
<Show when={multi()} fallback={<span data-slot="question-option-radio-dot" />}>
|
||||
<Icon name="check-small" size="small" />
|
||||
@@ -240,101 +245,94 @@ export const QuestionDock: Component<{ request: QuestionRequest }> = (props) =>
|
||||
</span>
|
||||
</span>
|
||||
<span data-slot="question-option-main">
|
||||
<span data-slot="option-label">{language.t("ui.messagePart.option.typeOwnAnswer")}</span>
|
||||
<span data-slot="option-description" data-placeholder={!input()}>
|
||||
{input() || language.t("ui.question.custom.placeholder")}
|
||||
</span>
|
||||
<span data-slot="option-label">{opt.label}</span>
|
||||
<Show when={opt.description}>
|
||||
<span data-slot="option-description">{opt.description}</span>
|
||||
</Show>
|
||||
</span>
|
||||
</button>
|
||||
<Show when={store.editing}>
|
||||
<form data-slot="custom-input-form" onSubmit={handleCustomSubmit}>
|
||||
<input
|
||||
ref={(el) => setTimeout(() => el.focus(), 0)}
|
||||
type="text"
|
||||
data-slot="custom-input"
|
||||
placeholder={language.t("ui.question.custom.placeholder")}
|
||||
value={input()}
|
||||
disabled={store.sending}
|
||||
onInput={(e) => {
|
||||
const inputs = [...store.custom]
|
||||
inputs[store.tab] = e.currentTarget.value
|
||||
setStore("custom", inputs)
|
||||
}}
|
||||
/>
|
||||
<Button type="submit" variant="primary" size="small" disabled={store.sending}>
|
||||
{multi() ? language.t("ui.common.add") : language.t("ui.common.submit")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="small"
|
||||
disabled={store.sending}
|
||||
onClick={() => setStore("editing", false)}
|
||||
>
|
||||
{language.t("ui.common.cancel")}
|
||||
</Button>
|
||||
</form>
|
||||
</Show>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={confirm()}>
|
||||
<div data-slot="question-review">
|
||||
<div data-slot="review-title">{language.t("ui.messagePart.review.title")}</div>
|
||||
<For each={questions()}>
|
||||
{(q, index) => {
|
||||
const value = () => store.answers[index()]?.join(", ") ?? ""
|
||||
const answered = () => Boolean(value())
|
||||
return (
|
||||
<div data-slot="review-item">
|
||||
<span data-slot="review-label">{q.question}</span>
|
||||
<span data-slot="review-value" data-answered={answered()}>
|
||||
{answered() ? value() : language.t("ui.question.review.notAnswered")}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
<div data-slot="question-footer">
|
||||
<Button variant="ghost" size="small" onClick={reject} disabled={store.sending}>
|
||||
{language.t("ui.common.dismiss")}
|
||||
</Button>
|
||||
<div data-slot="question-footer-actions">
|
||||
<Show when={store.tab > 0}>
|
||||
<Button variant="secondary" size="small" onClick={back} disabled={store.sending}>
|
||||
{language.t("ui.common.back")}
|
||||
</Button>
|
||||
</Show>
|
||||
<Show
|
||||
when={confirm()}
|
||||
fallback={
|
||||
<Button
|
||||
variant={last() && single() ? "primary" : "secondary"}
|
||||
size="small"
|
||||
onClick={last() && single() ? submit : () => selectTab(store.tab + 1)}
|
||||
disabled={store.sending || (!confirm() && (store.answers[store.tab]?.length ?? 0) === 0)}
|
||||
>
|
||||
{last() && single()
|
||||
? language.t("ui.common.submit")
|
||||
: last()
|
||||
? language.t("common.review")
|
||||
: language.t("ui.common.next")}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<Button variant="primary" size="small" onClick={submit} disabled={store.sending}>
|
||||
{language.t("ui.common.submit")}
|
||||
</Button>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
<Show when={question()?.custom !== false}>
|
||||
<button
|
||||
data-slot="question-option"
|
||||
data-custom="true"
|
||||
data-picked={customPicked()}
|
||||
disabled={store.sending}
|
||||
onClick={() => selectOption(options().length)}
|
||||
>
|
||||
<span data-slot="question-option-check" aria-hidden="true">
|
||||
<span
|
||||
data-slot="question-option-box"
|
||||
data-type={multi() ? "checkbox" : "radio"}
|
||||
data-picked={customPicked()}
|
||||
>
|
||||
<Show when={multi()} fallback={<span data-slot="question-option-radio-dot" />}>
|
||||
<Icon name="check-small" size="small" />
|
||||
</Show>
|
||||
</span>
|
||||
</span>
|
||||
<span data-slot="question-option-main">
|
||||
<span data-slot="option-label">{language.t("ui.messagePart.option.typeOwnAnswer")}</span>
|
||||
<span data-slot="option-description" data-placeholder={!input()}>
|
||||
{input() || language.t("ui.question.custom.placeholder")}
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
<Show when={store.editing}>
|
||||
<form data-slot="custom-input-form" onSubmit={handleCustomSubmit}>
|
||||
<input
|
||||
ref={(el) => setTimeout(() => el.focus(), 0)}
|
||||
type="text"
|
||||
data-slot="custom-input"
|
||||
placeholder={language.t("ui.question.custom.placeholder")}
|
||||
value={input()}
|
||||
disabled={store.sending}
|
||||
onInput={(e) => {
|
||||
const inputs = [...store.custom]
|
||||
inputs[store.tab] = e.currentTarget.value
|
||||
setStore("custom", inputs)
|
||||
}}
|
||||
/>
|
||||
<Button type="submit" variant="primary" size="small" disabled={store.sending}>
|
||||
{multi() ? language.t("ui.common.add") : language.t("ui.common.submit")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="small"
|
||||
disabled={store.sending}
|
||||
onClick={() => setStore("editing", false)}
|
||||
>
|
||||
{language.t("ui.common.cancel")}
|
||||
</Button>
|
||||
</form>
|
||||
</Show>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={confirm()}>
|
||||
<div data-slot="question-review">
|
||||
<div data-slot="review-title">{language.t("ui.messagePart.review.title")}</div>
|
||||
<For each={questions()}>
|
||||
{(q, index) => {
|
||||
const value = () => store.answers[index()]?.join(", ") ?? ""
|
||||
const answered = () => Boolean(value())
|
||||
return (
|
||||
<div data-slot="review-item">
|
||||
<span data-slot="review-label">{q.question}</span>
|
||||
<span data-slot="review-value" data-answered={answered()}>
|
||||
{answered() ? value() : language.t("ui.question.review.notAnswered")}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
</DockPrompt>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -231,6 +231,23 @@ const questionToolPart: ToolPart = {
|
||||
},
|
||||
}
|
||||
|
||||
const questionDismissedPart: ToolPart = {
|
||||
id: "part-question-dismissed-001",
|
||||
sessionID: SESSION_ID,
|
||||
messageID: ASST_MSG_ID,
|
||||
type: "tool",
|
||||
callID: "call-question-dismissed-001",
|
||||
tool: "question",
|
||||
state: {
|
||||
status: "error",
|
||||
input: { question: "Which testing framework?", options: [] },
|
||||
error: "Error: User dismissed this question",
|
||||
title: "Question dismissed",
|
||||
metadata: {},
|
||||
time: { start: now - 2000, end: now - 1500 },
|
||||
},
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Data helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -457,3 +474,19 @@ export const InlineQuestion: Story = {
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 9. Dismissed question (right-aligned "Questions dismissed" text)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const QuestionDismissed: Story = {
|
||||
name: "Question Dismissed",
|
||||
render: () => {
|
||||
const data = dataWith([textPart, questionDismissedPart])
|
||||
return (
|
||||
<StoryProviders data={data} sessionID={SESSION_ID}>
|
||||
<AssistantMessage message={baseAssistantMessage} />
|
||||
</StoryProviders>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -912,6 +912,10 @@
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.vscode-session-turn + .vscode-session-turn {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.vscode-session-turn-user {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -937,14 +941,10 @@
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
Question Prompt
|
||||
Question Prompt (VS Code overrides)
|
||||
============================================ */
|
||||
|
||||
[data-component="question-prompt"] {
|
||||
[data-slot="question-header"] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[data-component="dock-prompt"][data-kind="question"] {
|
||||
[data-slot="question-progress-nav"] {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
@@ -972,12 +972,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="question-footer"] {
|
||||
padding: 8px;
|
||||
padding-top: 8px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
[data-slot="question-footer"] > [data-component="button"][data-variant="ghost"] {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
@@ -997,155 +991,11 @@
|
||||
color: var(--text-weaker);
|
||||
}
|
||||
|
||||
[data-slot="question-text"] {
|
||||
font-size: var(--font-size-base);
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
[data-slot="question-hint"] {
|
||||
font-size: var(--font-size-small);
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
[data-slot="question-options"] {
|
||||
margin-top: 8px;
|
||||
gap: 4px;
|
||||
padding: 1px 1px 4px;
|
||||
}
|
||||
|
||||
[data-slot="question-option"] {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding: 6px 8px;
|
||||
background-color: var(--surface-raised-stronger-non-alpha);
|
||||
border: 1px solid var(--border-weak-base);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: none;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
border-color 0.15s ease,
|
||||
box-shadow 0.15s ease;
|
||||
|
||||
&:hover:not([data-picked="true"]) {
|
||||
background-color: var(--background-base);
|
||||
}
|
||||
|
||||
&[data-picked="true"] {
|
||||
background-color: var(--surface-interactive-weak);
|
||||
border-color: transparent;
|
||||
box-shadow: var(--shadow-xs-border-hover);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="question-option-check"] {
|
||||
display: inline-flex;
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
[data-slot="question-option-box"] {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 2px;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--border-weak-base);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
background-color: transparent;
|
||||
transition:
|
||||
background-color 0.15s ease,
|
||||
border-color 0.15s ease;
|
||||
|
||||
[data-component="icon"] {
|
||||
opacity: 0;
|
||||
color: var(--icon-base);
|
||||
}
|
||||
|
||||
&[data-type="radio"] {
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
[data-slot="question-option-radio-dot"] {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 999px;
|
||||
background-color: var(--background-stronger);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&[data-picked="true"] {
|
||||
border-color: var(--icon-interactive-base);
|
||||
|
||||
[data-component="icon"] {
|
||||
opacity: 1;
|
||||
color: var(--icon-invert-base);
|
||||
}
|
||||
|
||||
&[data-type="checkbox"] {
|
||||
background-color: var(--icon-interactive-base);
|
||||
}
|
||||
|
||||
&[data-type="radio"] {
|
||||
background-color: var(--icon-interactive-base);
|
||||
[data-slot="question-option-radio-dot"] {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="question-option-main"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
[data-slot="option-label"] {
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-base);
|
||||
font-weight: var(--font-weight-medium);
|
||||
line-height: var(--line-height-large);
|
||||
color: var(--text-strong);
|
||||
}
|
||||
|
||||
[data-slot="option-description"] {
|
||||
font-family: var(--font-family-sans);
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-regular);
|
||||
line-height: var(--line-height-large);
|
||||
color: var(--text-base);
|
||||
min-width: 0;
|
||||
white-space: normal;
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
}
|
||||
|
||||
[data-slot="question-option"][data-custom="true"] {
|
||||
[data-slot="option-description"] {
|
||||
overflow: visible;
|
||||
text-overflow: clip;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="question-review"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 4px 2px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
[data-slot="review-title"] {
|
||||
|
||||
@@ -964,22 +964,29 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
|
||||
|
||||
const render = ToolRegistry.render(part.tool) ?? GenericTool
|
||||
|
||||
const dismissed = createMemo(
|
||||
() =>
|
||||
part.tool === "question" &&
|
||||
part.state.status === "error" &&
|
||||
typeof part.state.error === "string" &&
|
||||
part.state.error.includes("dismissed this question"),
|
||||
)
|
||||
|
||||
return (
|
||||
<Show when={!hideQuestion()}>
|
||||
<Show when={dismissed()}>
|
||||
<div style="width: 100%; display: flex; justify-content: flex-end; padding: 4px 8px 4px 0;">
|
||||
<span class="text-13-regular text-text-weak cursor-default">
|
||||
{i18n.t("ui.tool.questions")} dismissed
|
||||
</span>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={!dismissed()}>
|
||||
<div data-component="tool-part-wrapper">
|
||||
<Switch>
|
||||
<Match when={part.state.status === "error" && part.state.error}>
|
||||
{(error) => {
|
||||
const cleaned = error().replace("Error: ", "")
|
||||
if (part.tool === "question" && cleaned.includes("dismissed this question")) {
|
||||
return (
|
||||
<div style="width: 100%; display: flex; justify-content: flex-end;">
|
||||
<span class="text-13-regular text-text-weak cursor-default">
|
||||
{i18n.t("ui.tool.questions")} dismissed
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const [title, ...rest] = cleaned.split(": ")
|
||||
return (
|
||||
<Card variant="error">
|
||||
@@ -1016,6 +1023,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
|
||||
</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
</Show>
|
||||
</Show>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user