Skip to content
Merged
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
1 change: 0 additions & 1 deletion packages/app/src/pages/session.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,6 @@ export default function Page() {
anchor={anchor}
onRegisterMessage={scrollSpy.register}
onUnregisterMessage={scrollSpy.unregister}
lastUserMessageID={lastUserMessage()?.id}
/>
</Show>
</Match>
Expand Down
2 changes: 0 additions & 2 deletions packages/app/src/pages/session/message-timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ export function MessageTimeline(props: {
anchor: (id: string) => string
onRegisterMessage: (el: HTMLDivElement, id: string) => void
onUnregisterMessage: (id: string) => void
lastUserMessageID?: string
}) {
let touchGesture: number | undefined

Expand Down Expand Up @@ -601,7 +600,6 @@ export function MessageTimeline(props: {
<SessionTurn
sessionID={sessionID() ?? ""}
messageID={message.id}
lastUserMessageID={props.lastUserMessageID}
showReasoningSummaries={settings.general.showReasoningSummaries()}
shellToolDefaultOpen={settings.general.shellToolPartsExpanded()}
editToolDefaultOpen={settings.general.editToolPartsExpanded()}
Expand Down
27 changes: 27 additions & 0 deletions packages/ui/src/components/message-part.css
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,33 @@
}
}

[data-component="compaction-part"] {
width: 100%;
display: flex;
flex-direction: column;
align-items: stretch;

[data-slot="compaction-part-divider"] {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 0;
width: 100%;
}

[data-slot="compaction-part-line"] {
flex: 1 1 auto;
height: 1px;
background: var(--border-weak-base);
}

[data-slot="compaction-part-label"] {
flex: 0 0 auto;
white-space: nowrap;
text-align: center;
}
}

[data-component="reasoning-part"] {
width: 100%;
color: var(--text-base);
Expand Down
15 changes: 15 additions & 0 deletions packages/ui/src/components/message-part.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,21 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
)
}

PART_MAPPING["compaction"] = function CompactionPartDisplay() {
const i18n = useI18n()
return (
<div data-component="compaction-part">
<div data-slot="compaction-part-divider">
<span data-slot="compaction-part-line" />
<span data-slot="compaction-part-label" class="text-12-regular text-text-weak">
{i18n.t("ui.messagePart.compaction")}
</span>
<span data-slot="compaction-part-line" />
</div>
</div>
)
}

PART_MAPPING["text"] = function TextPartDisplay(props) {
const data = useData()
const i18n = useI18n()
Expand Down
6 changes: 6 additions & 0 deletions packages/ui/src/components/session-turn.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
max-width: 100%;
}

[data-slot="session-turn-compaction"] {
width: 100%;
min-width: 0;
align-self: stretch;
}

[data-slot="session-turn-thinking"] {
display: flex;
align-items: center;
Expand Down
36 changes: 22 additions & 14 deletions packages/ui/src/components/session-turn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Binary } from "@opencode-ai/util/binary"
import { getDirectory, getFilename } from "@opencode-ai/util/path"
import { createEffect, createMemo, createSignal, For, on, ParentProps, Show } from "solid-js"
import { Dynamic } from "solid-js/web"
import { AssistantParts, Message, PART_MAPPING } from "./message-part"
import { AssistantParts, Message, Part, PART_MAPPING } from "./message-part"
import { Card } from "./card"
import { Accordion } from "./accordion"
import { StickyAccordionHeader } from "./sticky-accordion-header"
Expand Down Expand Up @@ -139,7 +139,6 @@ export function SessionTurn(
props: ParentProps<{
sessionID: string
messageID: string
lastUserMessageID?: string
showReasoningSummaries?: boolean
shellToolDefaultOpen?: boolean
editToolDefaultOpen?: boolean
Expand Down Expand Up @@ -187,25 +186,27 @@ export function SessionTurn(
return msg
})

const lastUserMessageID = createMemo(() => {
if (props.lastUserMessageID) return props.lastUserMessageID

const pending = createMemo(() => {
const messages = allMessages() ?? emptyMessages
for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i]
if (msg?.role === "user") return msg.id
}
return undefined
return messages.findLast(
(item): item is AssistantMessage => item.role === "assistant" && typeof item.time.completed !== "number",
)
})
const active = createMemo(() => {
const msg = message()
const item = pending()
if (!msg || !item) return false
return item.parentID === msg.id
})

const isLastUserMessage = createMemo(() => props.messageID === lastUserMessageID())

const parts = createMemo(() => {
const msg = message()
if (!msg) return emptyParts
return list(data.store.part?.[msg.id], emptyParts)
})

const compaction = createMemo(() => parts().find((part) => part.type === "compaction"))

const diffs = createMemo(() => {
const files = message()?.summary?.diffs
if (!files?.length) return emptyDiffs
Expand Down Expand Up @@ -285,7 +286,7 @@ export function SessionTurn(
})

const status = createMemo(() => data.store.session_status[props.sessionID] ?? idle)
const working = createMemo(() => status().type !== "idle" && isLastUserMessage())
const working = createMemo(() => status().type !== "idle" && active())
const showReasoningSummaries = createMemo(() => props.showReasoningSummaries ?? true)

const assistantCopyPartID = createMemo(() => {
Expand Down Expand Up @@ -365,6 +366,13 @@ export function SessionTurn(
<div data-slot="session-turn-message-content" aria-live="off">
<Message message={msg()} parts={parts()} interrupted={interrupted()} />
</div>
<Show when={compaction()}>
{(part) => (
<div data-slot="session-turn-compaction">
<Part part={part()} message={msg()} hideDetails />
</div>
)}
</Show>
<Show when={assistantMessages().length > 0}>
<div data-slot="session-turn-assistant-content" aria-hidden={working()}>
<AssistantParts
Expand All @@ -386,7 +394,7 @@ export function SessionTurn(
</Show>
</div>
</Show>
<SessionRetry status={status()} show={isLastUserMessage()} />
<SessionRetry status={status()} show={active()} />
<Show when={edited() > 0 && !working()}>
<div data-slot="session-turn-diffs">
<Collapsible open={open()} onOpenChange={setOpen} variant="ghost">
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "النظر في الخطوات التالية",

"ui.messagePart.questions.dismissed": "تم رفض الأسئلة",
"ui.messagePart.compaction": "تم ضغط السجل",
"ui.messagePart.context.read.one": "{{count}} قراءة",
"ui.messagePart.context.read.other": "{{count}} قراءات",
"ui.messagePart.context.search.one": "{{count}} بحث",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Considerando próximos passos",

"ui.messagePart.questions.dismissed": "Perguntas descartadas",
"ui.messagePart.compaction": "Histórico compactado",
"ui.messagePart.context.read.one": "{{count}} leitura",
"ui.messagePart.context.read.other": "{{count}} leituras",
"ui.messagePart.context.search.one": "{{count}} pesquisa",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/bs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Razmatranje sljedećih koraka",

"ui.messagePart.questions.dismissed": "Pitanja odbačena",
"ui.messagePart.compaction": "Historija sažeta",
"ui.messagePart.context.read.one": "{{count}} čitanje",
"ui.messagePart.context.read.other": "{{count}} čitanja",
"ui.messagePart.context.search.one": "{{count}} pretraga",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Overvejer næste skridt",

"ui.messagePart.questions.dismissed": "Spørgsmål afvist",
"ui.messagePart.compaction": "Historik komprimeret",
"ui.messagePart.context.read.one": "{{count}} læsning",
"ui.messagePart.context.read.other": "{{count}} læsninger",
"ui.messagePart.context.search.one": "{{count}} søgning",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Nächste Schritte erwägen",

"ui.messagePart.questions.dismissed": "Fragen verworfen",
"ui.messagePart.compaction": "Verlauf komprimiert",
"ui.messagePart.context.read.one": "{{count}} Lesevorgang",
"ui.messagePart.context.read.other": "{{count}} Lesevorgänge",
"ui.messagePart.context.search.one": "{{count}} Suche",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export const dict: Record<string, string> = {
"ui.messagePart.option.typeOwnAnswer": "Type your own answer",
"ui.messagePart.review.title": "Review your answers",
"ui.messagePart.questions.dismissed": "Questions dismissed",
"ui.messagePart.compaction": "History compacted",
"ui.messagePart.context.read.one": "{{count}} read",
"ui.messagePart.context.read.other": "{{count}} reads",
"ui.messagePart.context.search.one": "{{count}} search",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Considerando siguientes pasos",

"ui.messagePart.questions.dismissed": "Preguntas descartadas",
"ui.messagePart.compaction": "Historial compactado",
"ui.messagePart.context.read.one": "{{count}} lectura",
"ui.messagePart.context.read.other": "{{count}} lecturas",
"ui.messagePart.context.search.one": "{{count}} búsqueda",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Examen des prochaines étapes",

"ui.messagePart.questions.dismissed": "Questions ignorées",
"ui.messagePart.compaction": "Historique compacté",
"ui.messagePart.context.read.one": "{{count}} lecture",
"ui.messagePart.context.read.other": "{{count}} lectures",
"ui.messagePart.context.search.one": "{{count}} recherche",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "次のステップを検討中",

"ui.messagePart.questions.dismissed": "質問をスキップしました",
"ui.messagePart.compaction": "履歴を圧縮しました",
"ui.messagePart.context.read.one": "{{count}} 件の読み取り",
"ui.messagePart.context.read.other": "{{count}} 件の読み取り",
"ui.messagePart.context.search.one": "{{count}} 件の検索",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "다음 단계 고려 중",

"ui.messagePart.questions.dismissed": "질문 무시됨",
"ui.messagePart.compaction": "기록이 압축됨",
"ui.messagePart.context.read.one": "{{count}}개 읽음",
"ui.messagePart.context.read.other": "{{count}}개 읽음",
"ui.messagePart.context.search.one": "{{count}}개 검색",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const dict: Record<Keys, string> = {
"ui.sessionTurn.status.consideringNextSteps": "Vurderer neste trinn",

"ui.messagePart.questions.dismissed": "Spørsmål avvist",
"ui.messagePart.compaction": "Historikk komprimert",
"ui.messagePart.context.read.one": "{{count}} lest",
"ui.messagePart.context.read.other": "{{count}} lest",
"ui.messagePart.context.search.one": "{{count}} søk",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Rozważanie kolejnych kroków",

"ui.messagePart.questions.dismissed": "Pytania odrzucone",
"ui.messagePart.compaction": "Historia skompaktowana",
"ui.messagePart.context.read.one": "{{count}} odczyt",
"ui.messagePart.context.read.other": "{{count}} odczyty",
"ui.messagePart.context.search.one": "{{count}} wyszukiwanie",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Рассмотрение следующих шагов",

"ui.messagePart.questions.dismissed": "Вопросы отклонены",
"ui.messagePart.compaction": "История сжата",
"ui.messagePart.context.read.one": "{{count}} чтение",
"ui.messagePart.context.read.other": "{{count}} чтений",
"ui.messagePart.context.search.one": "{{count}} поиск",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/th.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "พิจารณาขั้นตอนถัดไป",

"ui.messagePart.questions.dismissed": "ละทิ้งคำถามแล้ว",
"ui.messagePart.compaction": "ประวัติถูกบีบอัด",
"ui.messagePart.context.read.one": "อ่าน {{count}} รายการ",
"ui.messagePart.context.read.other": "อ่าน {{count}} รายการ",
"ui.messagePart.context.search.one": "ค้นหา {{count}} รายการ",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "Sonraki adımlar değerlendiriliyor",

"ui.messagePart.questions.dismissed": "Sorular reddedildi",
"ui.messagePart.compaction": "Geçmiş sıkıştırıldı",
"ui.messagePart.context.read.one": "{{count}} okuma",
"ui.messagePart.context.read.other": "{{count}} okuma",
"ui.messagePart.context.search.one": "{{count}} arama",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "正在考虑下一步",

"ui.messagePart.questions.dismissed": "问题已忽略",
"ui.messagePart.compaction": "历史已压缩",
"ui.messagePart.context.read.one": "{{count}} 次读取",
"ui.messagePart.context.read.other": "{{count}} 次读取",
"ui.messagePart.context.search.one": "{{count}} 次搜索",
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/i18n/zht.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const dict = {
"ui.sessionTurn.status.consideringNextSteps": "正在考慮下一步",

"ui.messagePart.questions.dismissed": "問題已略過",
"ui.messagePart.compaction": "歷史已壓縮",
"ui.messagePart.context.read.one": "{{count}} 次讀取",
"ui.messagePart.context.read.other": "{{count}} 次讀取",
"ui.messagePart.context.search.one": "{{count}} 次搜尋",
Expand Down
Loading