Move the Global module from packages/opencode/src/global to packages/core/src/global to provide a unified location for managing XDG directories and application paths. This eliminates duplicate path definitions across packages and ensures consistent access to data, config, cache, state, log, and bin directories throughout the codebase.
94 lines
2.9 KiB
TypeScript
94 lines
2.9 KiB
TypeScript
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
|
import { createMemo, Show } from "solid-js"
|
|
import { Global } from "@opencode-ai/core/global"
|
|
|
|
const id = "internal:sidebar-footer"
|
|
|
|
function View(props: { api: TuiPluginApi }) {
|
|
const theme = () => props.api.theme.current
|
|
const has = createMemo(() =>
|
|
props.api.state.provider.some(
|
|
(item) => item.id !== "opencode" || Object.values(item.models).some((model) => model.cost?.input !== 0),
|
|
),
|
|
)
|
|
const done = createMemo(() => props.api.kv.get("dismissed_getting_started", false))
|
|
const show = createMemo(() => !has() && !done())
|
|
const path = createMemo(() => {
|
|
const dir = props.api.state.path.directory || process.cwd()
|
|
const out = dir.replace(Global.Path.home, "~")
|
|
const text = props.api.state.vcs?.branch ? out + ":" + props.api.state.vcs.branch : out
|
|
const list = text.split("/")
|
|
return {
|
|
parent: list.slice(0, -1).join("/"),
|
|
name: list.at(-1) ?? "",
|
|
}
|
|
})
|
|
|
|
return (
|
|
<box gap={1}>
|
|
<Show when={show()}>
|
|
<box
|
|
backgroundColor={theme().backgroundElement}
|
|
paddingTop={1}
|
|
paddingBottom={1}
|
|
paddingLeft={2}
|
|
paddingRight={2}
|
|
flexDirection="row"
|
|
gap={1}
|
|
>
|
|
<text flexShrink={0} fg={theme().text}>
|
|
⬖
|
|
</text>
|
|
<box flexGrow={1} gap={1}>
|
|
<box flexDirection="row" justifyContent="space-between">
|
|
<text fg={theme().text}>
|
|
<b>Getting started</b>
|
|
</text>
|
|
<text fg={theme().textMuted} onMouseDown={() => props.api.kv.set("dismissed_getting_started", true)}>
|
|
✕
|
|
</text>
|
|
</box>
|
|
<text fg={theme().textMuted}>OpenCode includes free models so you can start immediately.</text>
|
|
<text fg={theme().textMuted}>
|
|
Connect from 75+ providers to use other models, including Claude, GPT, Gemini etc
|
|
</text>
|
|
<box flexDirection="row" gap={1} justifyContent="space-between">
|
|
<text fg={theme().text}>Connect provider</text>
|
|
<text fg={theme().textMuted}>/connect</text>
|
|
</box>
|
|
</box>
|
|
</box>
|
|
</Show>
|
|
<text>
|
|
<span style={{ fg: theme().textMuted }}>{path().parent}/</span>
|
|
<span style={{ fg: theme().text }}>{path().name}</span>
|
|
</text>
|
|
<text fg={theme().textMuted}>
|
|
<span style={{ fg: theme().success }}>•</span> <b>Open</b>
|
|
<span style={{ fg: theme().text }}>
|
|
<b>Code</b>
|
|
</span>{" "}
|
|
<span>{props.api.app.version}</span>
|
|
</text>
|
|
</box>
|
|
)
|
|
}
|
|
|
|
const tui: TuiPlugin = async (api) => {
|
|
api.slots.register({
|
|
order: 100,
|
|
slots: {
|
|
sidebar_footer() {
|
|
return <View api={api} />
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
const plugin: TuiPluginModule & { id: string } = {
|
|
id,
|
|
tui,
|
|
}
|
|
|
|
export default plugin
|