Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com>
132 lines
4.9 KiB
TypeScript
132 lines
4.9 KiB
TypeScript
import { base64Encode } from "@opencode-ai/core/util/encode"
|
|
import { createQuery } from "@tanstack/solid-query"
|
|
import { useNavigate, useSearchParams } from "@solidjs/router"
|
|
import { type Accessor, createMemo } from "solid-js"
|
|
import type { PromptInputControls } from "@/components/prompt-input"
|
|
import type { PromptProjectControls } from "@/components/prompt-project-selector"
|
|
import { useDirectoryPicker } from "@/components/directory-picker"
|
|
import { useGlobal } from "@/context/global"
|
|
import { useLayout } from "@/context/layout"
|
|
import { useLocal, type ModelSelection } from "@/context/local"
|
|
import type { QueryOptionsApi } from "@/context/server-sync"
|
|
import { useServerSDK } from "@/context/server-sdk"
|
|
import { serverName, ServerConnection, useServer } from "@/context/server"
|
|
import { useSDK } from "@/context/sdk"
|
|
import { useSettings } from "@/context/settings"
|
|
import { useSync } from "@/context/sync"
|
|
import { useTabs } from "@/context/tabs"
|
|
import { useProviders } from "@/hooks/use-providers"
|
|
import { pathKey } from "@/utils/path-key"
|
|
|
|
export function createPromptInputController(input: {
|
|
sessionKey: Accessor<string>
|
|
sessionID: Accessor<string | undefined>
|
|
queryOptions: Pick<QueryOptionsApi, "agents" | "providers">
|
|
model?: ModelSelection
|
|
}) {
|
|
const layout = useLayout()
|
|
const local = useLocal()
|
|
const providers = useProviders()
|
|
const settings = useSettings()
|
|
const sync = useSync()
|
|
const sdk = useSDK()
|
|
const view = layout.view(input.sessionKey)
|
|
const agentsQuery = createQuery(() => input.queryOptions.agents(pathKey(sdk().directory)))
|
|
const globalProvidersQuery = createQuery(() => input.queryOptions.providers(null))
|
|
const providersQuery = createQuery(() => input.queryOptions.providers(pathKey(sdk().directory)))
|
|
|
|
return createMemo<PromptInputControls>(() => ({
|
|
agents: {
|
|
available: sync().data.agent,
|
|
options: local.agent.list().map((agent) => agent.name),
|
|
current: local.agent.current()?.name ?? "",
|
|
loading: agentsQuery.isLoading,
|
|
visible: local.agent.visible(),
|
|
select: local.agent.set,
|
|
},
|
|
model: {
|
|
selection: input.model ?? local.model,
|
|
paid: providers.paid().length > 0,
|
|
loading: agentsQuery.isLoading || providersQuery.isLoading || globalProvidersQuery.isLoading,
|
|
},
|
|
session: {
|
|
id: input.sessionID(),
|
|
tabs: layout.tabs(input.sessionKey),
|
|
reviewPanel: view.reviewPanel,
|
|
},
|
|
newLayoutDesigns: settings.general.newLayoutDesigns(),
|
|
}))
|
|
}
|
|
|
|
export function createPromptProjectControls() {
|
|
const navigate = useNavigate()
|
|
const layout = useLayout()
|
|
const server = useServer()
|
|
const serverSDK = useServerSDK()
|
|
const sdk = useSDK()
|
|
const tabs = useTabs()
|
|
const global = useGlobal()
|
|
const pickDirectory = useDirectoryPicker()
|
|
const [search] = useSearchParams<{ draftId?: string }>()
|
|
const projectServer = () => serverSDK().server
|
|
const projectServerCtx = createMemo(() => global.ensureServerCtx(projectServer()))
|
|
const projects = createMemo(() => {
|
|
if (server.list.length <= 1) {
|
|
return search.draftId ? projectServerCtx().projects.list() : layout.projects.list()
|
|
}
|
|
return server.list.flatMap((conn) => {
|
|
const item = { key: ServerConnection.key(conn), name: serverName(conn) }
|
|
return global
|
|
.ensureServerCtx(conn)
|
|
.projects.list()
|
|
.map((project) => ({ ...project, server: item }))
|
|
})
|
|
})
|
|
const selectProject = (worktree: string, serverKey?: string) => {
|
|
const conn = serverKey ? server.list.find((conn) => ServerConnection.key(conn) === serverKey) : projectServer()
|
|
if (search.draftId) {
|
|
if (!conn) return
|
|
const target = global.ensureServerCtx(conn)
|
|
target.projects.open(worktree)
|
|
target.projects.touch(worktree)
|
|
tabs.updateDraft(search.draftId, { server: ServerConnection.key(conn), directory: worktree })
|
|
return
|
|
}
|
|
|
|
if (!serverKey) {
|
|
layout.projects.open(worktree)
|
|
server.projects.touch(worktree)
|
|
navigate(`/${base64Encode(worktree)}/session`)
|
|
return
|
|
}
|
|
|
|
if (!conn) return
|
|
const target = global.ensureServerCtx(conn)
|
|
target.projects.open(worktree)
|
|
target.projects.touch(worktree)
|
|
server.setActive(ServerConnection.key(conn))
|
|
navigate(`/${base64Encode(worktree)}/session`)
|
|
}
|
|
|
|
const addProject = (title: string, serverKey?: string) => {
|
|
const conn = serverKey ? server.list.find((conn) => ServerConnection.key(conn) === serverKey) : projectServer()
|
|
if (!conn) return
|
|
pickDirectory({
|
|
server: conn,
|
|
title,
|
|
onSelect: (result) => {
|
|
const directory = Array.isArray(result) ? result[0] : result
|
|
if (directory) selectProject(directory, serverKey)
|
|
},
|
|
})
|
|
}
|
|
|
|
return createMemo<PromptProjectControls>(() => ({
|
|
available: projects(),
|
|
directory: sdk().directory,
|
|
server: server.list.length > 1 ? ServerConnection.key(projectServer()) : undefined,
|
|
select: selectProject,
|
|
add: addProject,
|
|
}))
|
|
}
|