extend and use api
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
import type { AssistantMessage } from "@opencode-ai/sdk/v2"
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { createMemo } from "solid-js"
|
||||
import { useSync } from "../../context/sync"
|
||||
import { useTheme } from "../../context/theme"
|
||||
|
||||
const money = new Intl.NumberFormat("en-US", {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
})
|
||||
|
||||
function View(props: { session_id: string }) {
|
||||
const sync = useSync()
|
||||
const { theme } = useTheme()
|
||||
const msg = createMemo(() => sync.data.message[props.session_id] ?? [])
|
||||
function View(props: { api: TuiPluginApi; session_id: string }) {
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
const msg = createMemo(() => props.api.state.session.messages(props.session_id))
|
||||
const cost = createMemo(() => msg().reduce((sum, item) => sum + (item.role === "assistant" ? item.cost : 0), 0))
|
||||
|
||||
const state = createMemo(() => {
|
||||
@@ -26,7 +24,7 @@ function View(props: { session_id: string }) {
|
||||
|
||||
const tokens =
|
||||
last.tokens.input + last.tokens.output + last.tokens.reasoning + last.tokens.cache.read + last.tokens.cache.write
|
||||
const model = sync.data.provider.find((item) => item.id === last.providerID)?.models[last.modelID]
|
||||
const model = props.api.state.provider.find((item) => item.id === last.providerID)?.models[last.modelID]
|
||||
return {
|
||||
tokens,
|
||||
percent: model?.limit.context ? Math.round((tokens / model.limit.context) * 100) : null,
|
||||
@@ -35,12 +33,12 @@ function View(props: { session_id: string }) {
|
||||
|
||||
return (
|
||||
<box>
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>Context</b>
|
||||
</text>
|
||||
<text fg={theme.textMuted}>{state().tokens.toLocaleString()} tokens</text>
|
||||
<text fg={theme.textMuted}>{state().percent ?? 0}% used</text>
|
||||
<text fg={theme.textMuted}>{money.format(cost())} spent</text>
|
||||
<text fg={theme().textMuted}>{state().tokens.toLocaleString()} tokens</text>
|
||||
<text fg={theme().textMuted}>{state().percent ?? 0}% used</text>
|
||||
<text fg={theme().textMuted}>{money.format(cost())} spent</text>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
@@ -50,7 +48,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 100,
|
||||
slots: {
|
||||
sidebar_content(_ctx, props) {
|
||||
return <View session_id={props.session_id} />
|
||||
return <View api={api} session_id={props.session_id} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { createMemo, For, Show, createSignal } from "solid-js"
|
||||
import { useSync } from "../../context/sync"
|
||||
import { useTheme } from "../../context/theme"
|
||||
|
||||
function View(props: { session_id: string }) {
|
||||
const sync = useSync()
|
||||
const { theme } = useTheme()
|
||||
function View(props: { api: TuiPluginApi; session_id: string }) {
|
||||
const [open, setOpen] = createSignal(true)
|
||||
const list = createMemo(() => sync.data.session_diff[props.session_id] ?? [])
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
const list = createMemo(() => props.api.state.session.diff(props.session_id))
|
||||
|
||||
return (
|
||||
<Show when={list().length > 0}>
|
||||
<box>
|
||||
<box flexDirection="row" gap={1} onMouseDown={() => list().length > 2 && setOpen((x) => !x)}>
|
||||
<Show when={list().length > 2}>
|
||||
<text fg={theme.text}>{open() ? "▼" : "▶"}</text>
|
||||
<text fg={theme().text}>{open() ? "▼" : "▶"}</text>
|
||||
</Show>
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>Modified Files</b>
|
||||
</text>
|
||||
</box>
|
||||
@@ -24,15 +22,15 @@ function View(props: { session_id: string }) {
|
||||
<For each={list()}>
|
||||
{(item) => (
|
||||
<box flexDirection="row" gap={1} justifyContent="space-between">
|
||||
<text fg={theme.textMuted} wrapMode="none">
|
||||
<text fg={theme().textMuted} wrapMode="none">
|
||||
{item.file}
|
||||
</text>
|
||||
<box flexDirection="row" gap={1} flexShrink={0}>
|
||||
<Show when={item.additions}>
|
||||
<text fg={theme.diffAdded}>+{item.additions}</text>
|
||||
<text fg={theme().diffAdded}>+{item.additions}</text>
|
||||
</Show>
|
||||
<Show when={item.deletions}>
|
||||
<text fg={theme.diffRemoved}>-{item.deletions}</text>
|
||||
<text fg={theme().diffRemoved}>-{item.deletions}</text>
|
||||
</Show>
|
||||
</box>
|
||||
</box>
|
||||
@@ -49,7 +47,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 500,
|
||||
slots: {
|
||||
sidebar_content(_ctx, props) {
|
||||
return <View session_id={props.session_id} />
|
||||
return <View api={api} session_id={props.session_id} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { createMemo, Show } from "solid-js"
|
||||
import { Installation } from "@/installation"
|
||||
import { useDirectory } from "../../context/directory"
|
||||
import { useKV } from "../../context/kv"
|
||||
import { useSync } from "../../context/sync"
|
||||
import { useTheme } from "../../context/theme"
|
||||
|
||||
function View() {
|
||||
const sync = useSync()
|
||||
const kv = useKV()
|
||||
const dir = useDirectory()
|
||||
const { theme } = useTheme()
|
||||
|
||||
function View(props: { api: TuiPluginApi }) {
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
const has = createMemo(() =>
|
||||
sync.data.provider.some(
|
||||
props.api.state.provider.some(
|
||||
(item) => item.id !== "opencode" || Object.values(item.models).some((model) => model.cost?.input !== 0),
|
||||
),
|
||||
)
|
||||
const done = createMemo(() => kv.get("dismissed_getting_started", false))
|
||||
const done = createMemo(() => props.api.kv.get("dismissed_getting_started", false))
|
||||
const show = createMemo(() => !has() && !done())
|
||||
const path = createMemo(() => {
|
||||
const value = dir()
|
||||
const list = value.split("/")
|
||||
const dir = props.api.app.directory
|
||||
const list = dir.split("/")
|
||||
return {
|
||||
parent: list.slice(0, -1).join("/"),
|
||||
name: list.at(-1) ?? "",
|
||||
@@ -32,7 +24,7 @@ function View() {
|
||||
<box gap={1}>
|
||||
<Show when={show()}>
|
||||
<box
|
||||
backgroundColor={theme.backgroundElement}
|
||||
backgroundColor={theme().backgroundElement}
|
||||
paddingTop={1}
|
||||
paddingBottom={1}
|
||||
paddingLeft={2}
|
||||
@@ -40,39 +32,39 @@ function View() {
|
||||
flexDirection="row"
|
||||
gap={1}
|
||||
>
|
||||
<text flexShrink={0} fg={theme.text}>
|
||||
<text flexShrink={0} fg={theme().text}>
|
||||
⬖
|
||||
</text>
|
||||
<box flexGrow={1} gap={1}>
|
||||
<box flexDirection="row" justifyContent="space-between">
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>Getting started</b>
|
||||
</text>
|
||||
<text fg={theme.textMuted} onMouseDown={() => kv.set("dismissed_getting_started", true)}>
|
||||
<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}>
|
||||
<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>
|
||||
<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>
|
||||
<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 }}>
|
||||
<text fg={theme().textMuted}>
|
||||
<span style={{ fg: theme().success }}>•</span> <b>Open</b>
|
||||
<span style={{ fg: theme().text }}>
|
||||
<b>Code</b>
|
||||
</span>{" "}
|
||||
<span>{Installation.VERSION}</span>
|
||||
<span>{props.api.app.version}</span>
|
||||
</text>
|
||||
</box>
|
||||
)
|
||||
@@ -83,7 +75,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 100,
|
||||
slots: {
|
||||
sidebar_footer() {
|
||||
return <View />
|
||||
return <View api={api} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { createMemo, For, Show, createSignal } from "solid-js"
|
||||
import { useSync } from "../../context/sync"
|
||||
import { useTheme } from "../../context/theme"
|
||||
|
||||
function View() {
|
||||
const sync = useSync()
|
||||
const { theme } = useTheme()
|
||||
function View(props: { api: TuiPluginApi }) {
|
||||
const [open, setOpen] = createSignal(true)
|
||||
const list = createMemo(() => sync.data.lsp.map((item) => ({ id: item.id, root: item.root, status: item.status })))
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
const list = createMemo(() => props.api.state.lsp())
|
||||
const off = createMemo(() => props.api.state.config.lsp === false)
|
||||
|
||||
return (
|
||||
<box>
|
||||
<box flexDirection="row" gap={1} onMouseDown={() => list().length > 2 && setOpen((x) => !x)}>
|
||||
<Show when={list().length > 2}>
|
||||
<text fg={theme.text}>{open() ? "▼" : "▶"}</text>
|
||||
<text fg={theme().text}>{open() ? "▼" : "▶"}</text>
|
||||
</Show>
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>LSP</b>
|
||||
</text>
|
||||
</box>
|
||||
<Show when={list().length <= 2 || open()}>
|
||||
<Show when={list().length === 0}>
|
||||
<text fg={theme.textMuted}>
|
||||
{sync.data.config.lsp === false
|
||||
? "LSPs have been disabled in settings"
|
||||
: "LSPs will activate as files are read"}
|
||||
<text fg={theme().textMuted}>
|
||||
{off() ? "LSPs have been disabled in settings" : "LSPs will activate as files are read"}
|
||||
</text>
|
||||
</Show>
|
||||
<For each={list()}>
|
||||
@@ -33,15 +30,12 @@ function View() {
|
||||
<text
|
||||
flexShrink={0}
|
||||
style={{
|
||||
fg: {
|
||||
connected: theme.success,
|
||||
error: theme.error,
|
||||
}[item.status],
|
||||
fg: item.status === "connected" ? theme().success : theme().error,
|
||||
}}
|
||||
>
|
||||
•
|
||||
</text>
|
||||
<text fg={theme.textMuted}>
|
||||
<text fg={theme().textMuted}>
|
||||
{item.id} {item.root}
|
||||
</text>
|
||||
</box>
|
||||
@@ -57,7 +51,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 300,
|
||||
slots: {
|
||||
sidebar_content() {
|
||||
return <View />
|
||||
return <View api={api} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { createMemo, For, Match, Show, Switch, createSignal } from "solid-js"
|
||||
import { useSync } from "../../context/sync"
|
||||
import { useTheme } from "../../context/theme"
|
||||
|
||||
function View() {
|
||||
const sync = useSync()
|
||||
const { theme } = useTheme()
|
||||
function View(props: { api: TuiPluginApi }) {
|
||||
const [open, setOpen] = createSignal(true)
|
||||
|
||||
const list = createMemo(() =>
|
||||
Object.entries(sync.data.mcp)
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.map(([name, item]) => ({
|
||||
name,
|
||||
status: item.status,
|
||||
error: item.status === "failed" ? item.error : undefined,
|
||||
})),
|
||||
)
|
||||
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
const list = createMemo(() => props.api.state.mcp())
|
||||
const on = createMemo(() => list().filter((item) => item.status === "connected").length)
|
||||
const bad = createMemo(
|
||||
() =>
|
||||
@@ -27,12 +15,15 @@ function View() {
|
||||
).length,
|
||||
)
|
||||
|
||||
const dot: Record<string, typeof theme.success> = {
|
||||
connected: theme.success,
|
||||
failed: theme.error,
|
||||
disabled: theme.textMuted,
|
||||
needs_auth: theme.warning,
|
||||
needs_client_registration: theme.error,
|
||||
const dot = (status: string) => {
|
||||
const map: Record<string, string | RGBA> = {
|
||||
connected: theme().success,
|
||||
failed: theme().error,
|
||||
disabled: theme().textMuted,
|
||||
needs_auth: theme().warning,
|
||||
needs_client_registration: theme().error,
|
||||
}
|
||||
return map[status] ?? theme().textMuted
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -40,12 +31,12 @@ function View() {
|
||||
<box>
|
||||
<box flexDirection="row" gap={1} onMouseDown={() => list().length > 2 && setOpen((x) => !x)}>
|
||||
<Show when={list().length > 2}>
|
||||
<text fg={theme.text}>{open() ? "▼" : "▶"}</text>
|
||||
<text fg={theme().text}>{open() ? "▼" : "▶"}</text>
|
||||
</Show>
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>MCP</b>
|
||||
<Show when={!open()}>
|
||||
<span style={{ fg: theme.textMuted }}>
|
||||
<span style={{ fg: theme().textMuted }}>
|
||||
{" "}
|
||||
({on()} active{bad() > 0 ? `, ${bad()} error${bad() > 1 ? "s" : ""}` : ""})
|
||||
</span>
|
||||
@@ -59,14 +50,14 @@ function View() {
|
||||
<text
|
||||
flexShrink={0}
|
||||
style={{
|
||||
fg: dot[item.status],
|
||||
fg: dot(item.status),
|
||||
}}
|
||||
>
|
||||
•
|
||||
</text>
|
||||
<text fg={theme.text} wrapMode="word">
|
||||
<text fg={theme().text} wrapMode="word">
|
||||
{item.name}{" "}
|
||||
<span style={{ fg: theme.textMuted }}>
|
||||
<span style={{ fg: theme().textMuted }}>
|
||||
<Switch fallback={item.status}>
|
||||
<Match when={item.status === "connected"}>Connected</Match>
|
||||
<Match when={item.status === "failed"}>
|
||||
@@ -92,7 +83,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 200,
|
||||
slots: {
|
||||
sidebar_content() {
|
||||
return <View />
|
||||
return <View api={api} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { Show } from "solid-js"
|
||||
import { useTheme } from "../../context/theme"
|
||||
|
||||
function View(props: { title: string; share_url?: string }) {
|
||||
const { theme } = useTheme()
|
||||
function View(props: { api: TuiPluginApi; title: string; share_url?: string }) {
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
|
||||
return (
|
||||
<box paddingRight={1}>
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>{props.title}</b>
|
||||
</text>
|
||||
<Show when={props.share_url}>
|
||||
<text fg={theme.textMuted}>{props.share_url}</text>
|
||||
<text fg={theme().textMuted}>{props.share_url}</text>
|
||||
</Show>
|
||||
</box>
|
||||
)
|
||||
@@ -22,7 +22,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 100,
|
||||
slots: {
|
||||
sidebar_title(_ctx, props) {
|
||||
return <View title={props.title} share_url={props.share_url} />
|
||||
return <View api={api} title={props.title} share_url={props.share_url} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import type { TuiPlugin } from "@opencode-ai/plugin/tui"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import { createMemo, For, Show, createSignal } from "solid-js"
|
||||
import { useSync } from "../../context/sync"
|
||||
import { useTheme } from "../../context/theme"
|
||||
import { TodoItem } from "../../component/todo-item"
|
||||
|
||||
function View(props: { session_id: string }) {
|
||||
const sync = useSync()
|
||||
const { theme } = useTheme()
|
||||
function View(props: { api: TuiPluginApi; session_id: string }) {
|
||||
const [open, setOpen] = createSignal(true)
|
||||
const list = createMemo(() => sync.data.todo[props.session_id] ?? [])
|
||||
const theme = () => props.api.theme.current as Record<string, string | RGBA>
|
||||
const list = createMemo(() => props.api.state.session.todo(props.session_id))
|
||||
const show = createMemo(() => list().length > 0 && list().some((item) => item.status !== "completed"))
|
||||
|
||||
return (
|
||||
@@ -16,9 +14,9 @@ function View(props: { session_id: string }) {
|
||||
<box>
|
||||
<box flexDirection="row" gap={1} onMouseDown={() => list().length > 2 && setOpen((x) => !x)}>
|
||||
<Show when={list().length > 2}>
|
||||
<text fg={theme.text}>{open() ? "▼" : "▶"}</text>
|
||||
<text fg={theme().text}>{open() ? "▼" : "▶"}</text>
|
||||
</Show>
|
||||
<text fg={theme.text}>
|
||||
<text fg={theme().text}>
|
||||
<b>Todo</b>
|
||||
</text>
|
||||
</box>
|
||||
@@ -35,7 +33,7 @@ const tui: TuiPlugin = async (api) => {
|
||||
order: 400,
|
||||
slots: {
|
||||
sidebar_content(_ctx, props) {
|
||||
return <View session_id={props.session_id} />
|
||||
return <View api={api} session_id={props.session_id} />
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -14,6 +14,8 @@ import { DialogConfirm } from "../ui/dialog-confirm"
|
||||
import { DialogPrompt } from "../ui/dialog-prompt"
|
||||
import { DialogSelect, type DialogSelectOption as SelectOption } from "../ui/dialog-select"
|
||||
import type { useToast } from "../ui/toast"
|
||||
import { Global } from "@/global"
|
||||
import { Installation } from "@/installation"
|
||||
|
||||
type RouteEntry = {
|
||||
key: symbol
|
||||
@@ -119,6 +121,15 @@ function mapOptionCb<Value>(cb?: (item: TuiDialogSelectOption<Value>) => void) {
|
||||
|
||||
function stateApi(sync: ReturnType<typeof useSync>): TuiApi["state"] {
|
||||
return {
|
||||
get ready() {
|
||||
return sync.ready
|
||||
},
|
||||
get config() {
|
||||
return sync.data.config
|
||||
},
|
||||
get provider() {
|
||||
return sync.data.provider
|
||||
},
|
||||
session: {
|
||||
diff(sessionID) {
|
||||
return sync.data.session_diff[sessionID] ?? []
|
||||
@@ -126,6 +137,9 @@ function stateApi(sync: ReturnType<typeof useSync>): TuiApi["state"] {
|
||||
todo(sessionID) {
|
||||
return sync.data.todo[sessionID] ?? []
|
||||
},
|
||||
messages(sessionID) {
|
||||
return sync.data.message[sessionID] ?? []
|
||||
},
|
||||
},
|
||||
lsp() {
|
||||
return sync.data.lsp.map((item) => ({ id: item.id, root: item.root, status: item.status }))
|
||||
@@ -142,8 +156,23 @@ function stateApi(sync: ReturnType<typeof useSync>): TuiApi["state"] {
|
||||
}
|
||||
}
|
||||
|
||||
function appApi(sync: ReturnType<typeof useSync>): TuiApi["app"] {
|
||||
return {
|
||||
get version() {
|
||||
return Installation.VERSION
|
||||
},
|
||||
get directory() {
|
||||
const dir = sync.data.path.directory || process.cwd()
|
||||
const out = dir.replace(Global.Path.home, "~")
|
||||
if (sync.data.vcs?.branch) return out + ":" + sync.data.vcs.branch
|
||||
return out
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export function createTuiApi(input: Input): TuiApi {
|
||||
return {
|
||||
app: appApi(input.sync),
|
||||
command: {
|
||||
register(cb) {
|
||||
return input.command.register(() => cb())
|
||||
|
||||
@@ -18,7 +18,11 @@ type Opts = {
|
||||
count?: Count
|
||||
keybind?: Partial<HostPluginApi["keybind"]>
|
||||
tuiConfig?: HostPluginApi["tuiConfig"]
|
||||
app?: Partial<HostPluginApi["app"]>
|
||||
state?: {
|
||||
ready?: HostPluginApi["state"]["ready"]
|
||||
config?: HostPluginApi["state"]["config"]
|
||||
provider?: HostPluginApi["state"]["provider"]
|
||||
session?: Partial<HostPluginApi["state"]["session"]>
|
||||
lsp?: HostPluginApi["state"]["lsp"]
|
||||
mcp?: HostPluginApi["state"]["mcp"]
|
||||
@@ -68,6 +72,14 @@ export function createTuiPluginApi(opts: Opts = {}): HostPluginApi {
|
||||
}
|
||||
|
||||
return {
|
||||
app: {
|
||||
get version() {
|
||||
return opts.app?.version ?? "0.0.0-test"
|
||||
},
|
||||
get directory() {
|
||||
return opts.app?.directory ?? "~"
|
||||
},
|
||||
},
|
||||
client:
|
||||
opts.client ??
|
||||
createOpencodeClient({
|
||||
@@ -154,9 +166,19 @@ export function createTuiPluginApi(opts: Opts = {}): HostPluginApi {
|
||||
},
|
||||
},
|
||||
state: {
|
||||
get ready() {
|
||||
return opts.state?.ready ?? true
|
||||
},
|
||||
get config() {
|
||||
return opts.state?.config ?? {}
|
||||
},
|
||||
get provider() {
|
||||
return opts.state?.provider ?? []
|
||||
},
|
||||
session: {
|
||||
diff: opts.state?.session?.diff ?? (() => []),
|
||||
todo: opts.state?.session?.todo ?? (() => []),
|
||||
messages: opts.state?.session?.messages ?? (() => []),
|
||||
},
|
||||
lsp: opts.state?.lsp ?? (() => []),
|
||||
mcp: opts.state?.mcp ?? (() => []),
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import type { OpencodeClient, Event, LspStatus, McpStatus, Todo } from "@opencode-ai/sdk/v2"
|
||||
import type {
|
||||
OpencodeClient,
|
||||
Event,
|
||||
LspStatus,
|
||||
McpStatus,
|
||||
Todo,
|
||||
Message,
|
||||
Provider,
|
||||
Config as SdkConfig,
|
||||
} from "@opencode-ai/sdk/v2"
|
||||
import type { CliRenderer, ParsedKey } from "@opentui/core"
|
||||
import type { JSX, SolidPlugin } from "@opentui/solid"
|
||||
import type { Config, Plugin, PluginOptions } from "./index.js"
|
||||
import type { Config as PluginConfig, Plugin, PluginOptions } from "./index.js"
|
||||
|
||||
export type { CliRenderer, SlotMode } from "@opentui/core"
|
||||
|
||||
@@ -143,15 +152,24 @@ export type TuiKV = {
|
||||
}
|
||||
|
||||
export type TuiState = {
|
||||
readonly ready: boolean
|
||||
readonly config: SdkConfig
|
||||
readonly provider: ReadonlyArray<Provider>
|
||||
session: {
|
||||
diff: (sessionID: string) => ReadonlyArray<TuiSidebarFileItem>
|
||||
todo: (sessionID: string) => ReadonlyArray<TuiSidebarTodoItem>
|
||||
messages: (sessionID: string) => ReadonlyArray<Message>
|
||||
}
|
||||
lsp: () => ReadonlyArray<TuiSidebarLspItem>
|
||||
mcp: () => ReadonlyArray<TuiSidebarMcpItem>
|
||||
}
|
||||
|
||||
type TuiConfigView = Pick<Config, "$schema" | "theme" | "keybinds" | "plugin"> & NonNullable<Config["tui"]>
|
||||
type TuiConfigView = Pick<PluginConfig, "$schema" | "theme" | "keybinds" | "plugin"> & NonNullable<PluginConfig["tui"]>
|
||||
|
||||
export type TuiApp = {
|
||||
readonly version: string
|
||||
readonly directory: string
|
||||
}
|
||||
|
||||
type Frozen<Value> = Value extends (...args: never[]) => unknown
|
||||
? Value
|
||||
@@ -162,6 +180,7 @@ type Frozen<Value> = Value extends (...args: never[]) => unknown
|
||||
: Value
|
||||
|
||||
export type TuiApi = {
|
||||
app: TuiApp
|
||||
command: {
|
||||
register: (cb: () => TuiCommand[]) => () => void
|
||||
trigger: (value: string) => void
|
||||
|
||||
Reference in New Issue
Block a user