Skip to content

Commit 52f9019

Browse files
Merge branch 'dev' into enable-disable-models
2 parents 9e62f23 + f607353 commit 52f9019

File tree

9 files changed

+103
-138
lines changed

9 files changed

+103
-138
lines changed

packages/app/src/components/dialog-select-file.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil
4444
"session.previous",
4545
"session.next",
4646
"terminal.toggle",
47-
"fileTree.toggle",
47+
"review.toggle",
4848
]
4949
const limit = 5
5050

@@ -162,6 +162,7 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil
162162
const value = file.tab(path)
163163
tabs().open(value)
164164
file.load(path)
165+
layout.fileTree.open()
165166
layout.fileTree.setTab("all")
166167
props.onOpenFile?.(path)
167168
}

packages/app/src/components/prompt-input.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,13 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
189189

190190
const wantsReview = item.commentOrigin === "review" || (item.commentOrigin !== "file" && commentInReview(item.path))
191191
if (wantsReview) {
192+
layout.fileTree.open()
192193
layout.fileTree.setTab("changes")
193-
if (!layout.fileTree.opened()) tabs().open("review")
194194
requestAnimationFrame(() => comments.setFocus(focus))
195195
return
196196
}
197197

198+
layout.fileTree.open()
198199
layout.fileTree.setTab("all")
199200
const tab = files.tab(item.path)
200201
tabs().open(tab)

packages/app/src/components/session-context-usage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
5757

5858
const openContext = () => {
5959
if (!params.id) return
60+
layout.fileTree.open()
6061
layout.fileTree.setTab("all")
6162
tabs().open("context")
6263
tabs().setActive("context")

packages/app/src/components/session/session-header.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,17 +280,14 @@ export function SessionHeader() {
280280
</TooltipKeybind>
281281
</div>
282282
<div class="hidden md:block shrink-0">
283-
<TooltipKeybind
284-
title={language.t("command.fileTree.toggle")}
285-
keybind={command.keybind("fileTree.toggle")}
286-
>
283+
<TooltipKeybind title={language.t("command.review.toggle")} keybind={command.keybind("review.toggle")}>
287284
<Button
288285
variant="ghost"
289286
class="group/file-tree-toggle size-6 p-0"
290287
onClick={() => layout.fileTree.toggle()}
291-
aria-label={language.t("command.fileTree.toggle")}
288+
aria-label={language.t("command.review.toggle")}
292289
aria-expanded={layout.fileTree.opened()}
293-
aria-controls="file-tree-panel"
290+
aria-controls="review-panel"
294291
>
295292
<div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
296293
<Icon

packages/app/src/context/layout.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,11 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
624624
const tabs = createMemo(() => store.sessionTabs[key()] ?? { all: [] })
625625
return {
626626
tabs,
627-
active: createMemo(() => tabs().active),
627+
active: createMemo(() => (tabs().active === "review" ? undefined : tabs().active)),
628628
all: createMemo(() => tabs().all.filter((tab) => tab !== "review")),
629629
setActive(tab: string | undefined) {
630630
const session = key()
631+
if (tab === "review") return
631632
if (!store.sessionTabs[session]) {
632633
setStore("sessionTabs", session, { all: [], active: tab })
633634
} else {
@@ -644,18 +645,10 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
644645
}
645646
},
646647
async open(tab: string) {
648+
if (tab === "review") return
647649
const session = key()
648650
const current = store.sessionTabs[session] ?? { all: [] }
649651

650-
if (tab === "review") {
651-
if (!store.sessionTabs[session]) {
652-
setStore("sessionTabs", session, { all: current.all, active: tab })
653-
return
654-
}
655-
setStore("sessionTabs", session, "active", tab)
656-
return
657-
}
658-
659652
if (tab === "context") {
660653
const all = [tab, ...current.all.filter((x) => x !== tab)]
661654
if (!store.sessionTabs[session]) {

packages/app/src/pages/session.tsx

Lines changed: 30 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { IconButton } from "@opencode-ai/ui/icon-button"
2323
import { Button } from "@opencode-ai/ui/button"
2424
import { Icon } from "@opencode-ai/ui/icon"
2525
import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
26-
import { DiffChanges } from "@opencode-ai/ui/diff-changes"
2726
import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
2827
import { Tabs } from "@opencode-ai/ui/tabs"
2928
import { useCodeComponent } from "@opencode-ai/ui/context/code"
@@ -325,6 +324,7 @@ export default function Page() {
325324
}
326325

327326
const isDesktop = createMediaQuery("(min-width: 768px)")
327+
const centered = createMemo(() => isDesktop() && !layout.fileTree.opened())
328328

329329
function normalizeTab(tab: string) {
330330
if (!tab.startsWith("file://")) return tab
@@ -730,8 +730,8 @@ export default function Page() {
730730
onSelect: () => view().terminal.toggle(),
731731
},
732732
{
733-
id: "fileTree.toggle",
734-
title: language.t("command.fileTree.toggle"),
733+
id: "review.toggle",
734+
title: language.t("command.review.toggle"),
735735
description: "",
736736
category: language.t("command.category.view"),
737737
keybind: "mod+shift+r",
@@ -1097,12 +1097,11 @@ export default function Page() {
10971097
}, 0)
10981098
}
10991099

1100-
const reviewTab = createMemo(() => isDesktop() && !layout.fileTree.opened())
11011100
const contextOpen = createMemo(() => tabs().active() === "context" || tabs().all().includes("context"))
11021101
const openedTabs = createMemo(() =>
11031102
tabs()
11041103
.all()
1105-
.filter((tab) => tab !== "context" && tab !== "review"),
1104+
.filter((tab) => tab !== "context"),
11061105
)
11071106

11081107
const mobileChanges = createMemo(() => !isDesktop() && store.mobileTab === "changes")
@@ -1271,56 +1270,29 @@ export default function Page() {
12711270
const activeTab = createMemo(() => {
12721271
const active = tabs().active()
12731272
if (active === "context") return "context"
1274-
if (active === "review" && reviewTab()) return "review"
12751273
if (active && file.pathFromTab(active)) return normalizeTab(active)
12761274

12771275
const first = openedTabs()[0]
12781276
if (first) return first
12791277
if (contextOpen()) return "context"
1280-
if (reviewTab() && hasReview()) return "review"
12811278
return "empty"
12821279
})
12831280

12841281
createEffect(() => {
12851282
if (!layout.ready()) return
12861283
if (tabs().active()) return
1287-
if (openedTabs().length === 0 && !contextOpen() && !(reviewTab() && hasReview())) return
1284+
if (openedTabs().length === 0 && !contextOpen()) return
12881285

12891286
const next = activeTab()
12901287
if (next === "empty") return
12911288
tabs().setActive(next)
12921289
})
12931290

1294-
createEffect(
1295-
on(
1296-
() => layout.fileTree.opened(),
1297-
(opened, prev) => {
1298-
if (prev === undefined) return
1299-
if (!isDesktop()) return
1300-
1301-
if (opened) {
1302-
const active = tabs().active()
1303-
const tab = active === "review" || (!active && hasReview()) ? "changes" : "all"
1304-
layout.fileTree.setTab(tab)
1305-
return
1306-
}
1307-
1308-
if (fileTreeTab() !== "changes") return
1309-
tabs().setActive("review")
1310-
},
1311-
{ defer: true },
1312-
),
1313-
)
1314-
13151291
createEffect(() => {
13161292
const id = params.id
13171293
if (!id) return
13181294

1319-
const wants = isDesktop()
1320-
? layout.fileTree.opened()
1321-
? fileTreeTab() === "changes"
1322-
: activeTab() === "review"
1323-
: store.mobileTab === "changes"
1295+
const wants = isDesktop() ? layout.fileTree.opened() && fileTreeTab() === "changes" : store.mobileTab === "changes"
13241296
if (!wants) return
13251297
if (sync.data.session_diff[id] !== undefined) return
13261298
if (sync.status === "loading") return
@@ -1789,10 +1761,11 @@ export default function Page() {
17891761
<div
17901762
classList={{
17911763
"@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger": true,
1792-
"flex-1 md:flex-none pt-6 md:pt-3": true,
1764+
"flex-1 pt-6 md:pt-3": true,
1765+
"md:flex-none": layout.fileTree.opened(),
17931766
}}
17941767
style={{
1795-
width: isDesktop() ? `${layout.session.width()}px` : "100%",
1768+
width: isDesktop() && layout.fileTree.opened() ? `${layout.session.width()}px` : "100%",
17961769
"--prompt-height": store.promptHeight ? `${store.promptHeight}px` : undefined,
17971770
}}
17981771
>
@@ -1967,6 +1940,7 @@ export default function Page() {
19671940
"sticky top-0 z-30 bg-background-stronger": true,
19681941
"w-full": true,
19691942
"px-4 md:px-6": true,
1943+
"md:max-w-200 md:mx-auto": centered(),
19701944
}}
19711945
>
19721946
<div class="h-10 flex items-center gap-1">
@@ -1991,7 +1965,13 @@ export default function Page() {
19911965
<div
19921966
ref={autoScroll.contentRef}
19931967
role="log"
1994-
class="flex flex-col gap-32 items-start justify-start w-full mt-0 pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]"
1968+
class="flex flex-col gap-32 items-start justify-start pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]"
1969+
classList={{
1970+
"w-full": true,
1971+
"md:max-w-200 md:mx-auto": centered(),
1972+
"mt-0.5": centered(),
1973+
"mt-0": !centered(),
1974+
}}
19951975
>
19961976
<Show when={store.turnStart > 0}>
19971977
<div class="w-full flex justify-center">
@@ -2039,7 +2019,10 @@ export default function Page() {
20392019
<div
20402020
id={anchor(message.id)}
20412021
data-message-id={message.id}
2042-
class="min-w-0 w-full max-w-full"
2022+
classList={{
2023+
"min-w-0 w-full max-w-full": true,
2024+
"md:max-w-200": centered(),
2025+
}}
20432026
>
20442027
<SessionTurn
20452028
sessionID={params.id!}
@@ -2092,7 +2075,12 @@ export default function Page() {
20922075
ref={(el) => (promptDock = el)}
20932076
class="absolute inset-x-0 bottom-0 pt-12 pb-4 flex flex-col justify-center items-center z-50 px-4 md:px-0 bg-gradient-to-t from-background-stronger via-background-stronger to-transparent pointer-events-none"
20942077
>
2095-
<div class="w-full px-4 pointer-events-auto">
2078+
<div
2079+
classList={{
2080+
"w-full px-4 pointer-events-auto": true,
2081+
"md:max-w-200 md:mx-auto": centered(),
2082+
}}
2083+
>
20962084
<Show when={request()} keyed>
20972085
{(perm) => (
20982086
<div data-component="tool-part-wrapper" data-permission="true" class="mb-3">
@@ -2163,7 +2151,7 @@ export default function Page() {
21632151
</div>
21642152
</div>
21652153

2166-
<Show when={isDesktop()}>
2154+
<Show when={isDesktop() && layout.fileTree.opened()}>
21672155
<ResizeHandle
21682156
direction="horizontal"
21692157
size={layout.session.width()}
@@ -2175,15 +2163,15 @@ export default function Page() {
21752163
</div>
21762164

21772165
{/* Desktop side panel - hidden on mobile */}
2178-
<Show when={isDesktop()}>
2166+
<Show when={isDesktop() && layout.fileTree.opened()}>
21792167
<aside
21802168
id="review-panel"
21812169
aria-label={language.t("session.panel.reviewAndFiles")}
21822170
class="relative flex-1 min-w-0 h-full border-l border-border-weak-base flex"
21832171
>
21842172
<div class="flex-1 min-w-0 h-full">
21852173
<Show
2186-
when={layout.fileTree.opened() && fileTreeTab() === "changes"}
2174+
when={fileTreeTab() === "changes"}
21872175
fallback={
21882176
<DragDropProvider
21892177
onDragStart={handleDragStart}
@@ -2196,23 +2184,6 @@ export default function Page() {
21962184
<Tabs value={activeTab()} onChange={openTab}>
21972185
<div class="sticky top-0 shrink-0 flex">
21982186
<Tabs.List>
2199-
<Show when={reviewTab()}>
2200-
<Tabs.Trigger value="review" classes={{ button: "!pl-6" }}>
2201-
<div class="flex items-center gap-3">
2202-
<Show when={hasReview() && diffsReady()}>
2203-
<DiffChanges changes={diffs()} variant="bars" />
2204-
</Show>
2205-
<div class="flex items-center gap-1.5">
2206-
<div>{language.t("session.tab.review")}</div>
2207-
<Show when={hasReview()}>
2208-
<div class="text-12-medium text-text-strong h-4 px-2 flex flex-col items-center justify-center rounded-full bg-surface-base">
2209-
{reviewCount()}
2210-
</div>
2211-
</Show>
2212-
</div>
2213-
</div>
2214-
</Tabs.Trigger>
2215-
</Show>
22162187
<Show when={contextOpen()}>
22172188
<Tabs.Trigger
22182189
value="context"
@@ -2261,12 +2232,6 @@ export default function Page() {
22612232
</Tabs.List>
22622233
</div>
22632234

2264-
<Show when={reviewTab()}>
2265-
<Tabs.Content value="review" class="flex flex-col h-full overflow-hidden contain-strict">
2266-
<Show when={activeTab() === "review"}>{reviewPanel()}</Show>
2267-
</Tabs.Content>
2268-
</Show>
2269-
22702235
<Tabs.Content value="empty" class="flex flex-col h-full overflow-hidden contain-strict">
22712236
<Show when={activeTab() === "empty"}>
22722237
<div class="relative pt-2 flex-1 min-h-0 overflow-hidden">

packages/opencode/src/session/message-v2.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ export namespace MessageV2 {
176176
})
177177
.optional(),
178178
command: z.string().optional(),
179+
}).meta({
180+
ref: "SubtaskPart",
179181
})
180182
export type SubtaskPart = z.infer<typeof SubtaskPart>
181183

packages/sdk/js/src/v2/gen/types.gen.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,21 @@ export type TextPart = {
233233
}
234234
}
235235

236+
export type SubtaskPart = {
237+
id: string
238+
sessionID: string
239+
messageID: string
240+
type: "subtask"
241+
prompt: string
242+
description: string
243+
agent: string
244+
model?: {
245+
providerID: string
246+
modelID: string
247+
}
248+
command?: string
249+
}
250+
236251
export type ReasoningPart = {
237252
id: string
238253
sessionID: string
@@ -449,20 +464,7 @@ export type CompactionPart = {
449464

450465
export type Part =
451466
| TextPart
452-
| {
453-
id: string
454-
sessionID: string
455-
messageID: string
456-
type: "subtask"
457-
prompt: string
458-
description: string
459-
agent: string
460-
model?: {
461-
providerID: string
462-
modelID: string
463-
}
464-
command?: string
465-
}
467+
| SubtaskPart
466468
| ReasoningPart
467469
| FilePart
468470
| ToolPart

0 commit comments

Comments
 (0)