diff --git a/.opencode/plugins/tui-smoke.tsx b/.opencode/plugins/tui-smoke.tsx
index 220989d448..cac60db45c 100644
--- a/.opencode/plugins/tui-smoke.tsx
+++ b/.opencode/plugins/tui-smoke.tsx
@@ -3,14 +3,15 @@ import mytheme from "../themes/mytheme.json" with { type: "json" }
const slot = (label) => ({
id: "workspace-smoke",
slots: {
- home_hint() {
- return [plugin:{label}]
+ home_logo() {
+ return plugin logo:{label}
},
- home_footer() {
- return theme:workspace-plugin-smoke
- },
- session_footer(_ctx, props) {
- return session:{props.session_id.slice(0, 8)}
+ sidebar_top(_ctx, props) {
+ return (
+
+ plugin:{label} session:{props.session_id.slice(0, 8)}
+
+ )
},
},
})
diff --git a/packages/opencode/src/cli/cmd/tui/plugin.ts b/packages/opencode/src/cli/cmd/tui/plugin.ts
index 9b5d24f3a3..14bc179242 100644
--- a/packages/opencode/src/cli/cmd/tui/plugin.ts
+++ b/packages/opencode/src/cli/cmd/tui/plugin.ts
@@ -4,6 +4,7 @@ import {
type TuiSlotContext,
type TuiSlotMap,
type TuiSlots,
+ type SlotMode,
} from "@opencode-ai/plugin/tui"
import { createSlot, createSolidSlotRegistry, type JSX, type SolidPlugin } from "@opentui/solid"
import type { CliRenderer } from "@opentui/core"
@@ -17,10 +18,29 @@ import { Instance } from "@/project/instance"
import { resolvePluginTarget, uniqueModuleEntries } from "@/plugin/shared"
import { registerThemes } from "./context/theme"
-type Slot = (props: { name: K } & TuiSlotMap[K]) => JSX.Element | null
+type SlotInput = {
+ name: K
+ mode?: SlotMode
+ slotMode?: SlotMode
+ children?: JSX.Element
+} & TuiSlotMap[K]
+
+type SlotProps = {
+ name: K
+ mode?: SlotMode
+ children?: JSX.Element
+} & TuiSlotMap[K]
+
+type Slot = (props: SlotInput) => JSX.Element | null
type InitInput = Omit, "slots">
-function empty(_props: { name: K } & TuiSlotMap[K]) {
+function normalize(props: SlotInput): SlotProps {
+ const { slotMode, ...rest } = props
+ if (!slotMode || rest.mode) return rest as SlotProps
+ return { ...rest, mode: slotMode } as SlotProps
+}
+
+function empty(_props: SlotInput) {
return null
}
@@ -79,7 +99,7 @@ export namespace TuiPlugin {
)
const slot = createSlot(reg)
- view = (props) => slot(props)
+ view = (props) => slot(normalize(props))
return {
register(pluginSlot) {
if (!isTuiSlotPlugin(pluginSlot)) return () => {}
diff --git a/packages/opencode/src/cli/cmd/tui/routes/home.tsx b/packages/opencode/src/cli/cmd/tui/routes/home.tsx
index 6650159535..ea3a093c1d 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/home.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/home.tsx
@@ -73,7 +73,6 @@ export function Home() {
- {TuiPlugin.Slot({ name: "home_hint" })}
)
@@ -113,7 +112,9 @@ export function Home() {
-
+
+
+
@@ -152,7 +153,6 @@ export function Home() {
- {TuiPlugin.Slot({ name: "home_footer" })}
{Installation.VERSION}
diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
index 013729de03..f3b2a5c31a 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
@@ -80,7 +80,6 @@ import { DialogExportOptions } from "../../ui/dialog-export-options"
import { formatTranscript } from "../../util/transcript"
import { UI } from "@/cli/ui.ts"
import { useTuiConfig } from "../../context/tui-config"
-import { TuiPlugin } from "../../plugin"
addDefaultParsers(parsers.parsers)
@@ -1178,7 +1177,6 @@ export function Session() {
}}
sessionID={route.sessionID}
/>
- {TuiPlugin.Slot({ name: "session_footer", session_id: route.sessionID })}
diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx
index 42ac5fbe08..ebcc8101bc 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx
@@ -11,6 +11,7 @@ import { useKeybind } from "../../context/keybind"
import { useDirectory } from "../../context/directory"
import { useKV } from "../../context/kv"
import { TodoItem } from "../../component/todo-item"
+import { TuiPlugin } from "../../plugin"
export function Sidebar(props: { sessionID: string; overlay?: boolean }) {
const sync = useSync()
@@ -90,6 +91,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) {
}}
>
+ {TuiPlugin.Slot({ name: "sidebar_top", session_id: props.sessionID })}
{session().title}
diff --git a/packages/plugin/src/tui.ts b/packages/plugin/src/tui.ts
index f8b13c10e5..13716a846b 100644
--- a/packages/plugin/src/tui.ts
+++ b/packages/plugin/src/tui.ts
@@ -23,9 +23,8 @@ export type ThemeJson = {
}
export type TuiSlotMap = {
- home_hint: {}
- home_footer: {}
- session_footer: {
+ home_logo: {}
+ sidebar_top: {
session_id: string
}
}