fix(tui): restore legacy sync consumers (#31908)
This commit is contained in:
@@ -1,17 +1,17 @@
|
|||||||
import { createMemo, createSignal } from "solid-js"
|
import { createMemo, createSignal } from "solid-js"
|
||||||
import { useLocal } from "../context/local"
|
import { useLocal } from "../context/local"
|
||||||
import { map, pipe, filter, sortBy, take } from "remeda"
|
import { map, pipe, flatMap, entries, filter, sortBy, take } from "remeda"
|
||||||
import { DialogSelect } from "../ui/dialog-select"
|
import { DialogSelect } from "../ui/dialog-select"
|
||||||
import { useDialog } from "../ui/dialog"
|
import { useDialog } from "../ui/dialog"
|
||||||
import { createDialogProviderOptions, DialogProvider } from "./dialog-provider"
|
import { createDialogProviderOptions, DialogProvider } from "./dialog-provider"
|
||||||
import { DialogVariant } from "./dialog-variant"
|
import { DialogVariant } from "./dialog-variant"
|
||||||
import * as fuzzysort from "fuzzysort"
|
import * as fuzzysort from "fuzzysort"
|
||||||
import { useConnected } from "./use-connected"
|
import { useConnected } from "./use-connected"
|
||||||
import { useData } from "../context/data"
|
import { useSync } from "../context/sync"
|
||||||
|
|
||||||
export function DialogModel(props: { providerID?: string }) {
|
export function DialogModel(props: { providerID?: string }) {
|
||||||
const local = useLocal()
|
const local = useLocal()
|
||||||
const data = useData()
|
const sync = useSync()
|
||||||
const dialog = useDialog()
|
const dialog = useDialog()
|
||||||
const [query, setQuery] = createSignal("")
|
const [query, setQuery] = createSignal("")
|
||||||
|
|
||||||
@@ -29,21 +29,19 @@ export function DialogModel(props: { providerID?: string }) {
|
|||||||
function toOptions(items: typeof favorites, category: string) {
|
function toOptions(items: typeof favorites, category: string) {
|
||||||
if (!showSections) return []
|
if (!showSections) return []
|
||||||
return items.flatMap((item) => {
|
return items.flatMap((item) => {
|
||||||
const provider = data.location.provider.list()?.find((provider) => provider.id === item.providerID)
|
const provider = sync.data.provider.find((provider) => provider.id === item.providerID)
|
||||||
if (!provider) return []
|
if (!provider) return []
|
||||||
const model = data.location.model
|
const model = provider.models[item.modelID]
|
||||||
.list()
|
|
||||||
?.find((model) => model.providerID === item.providerID && model.id === item.modelID)
|
|
||||||
if (!model) return []
|
if (!model) return []
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: item,
|
key: item,
|
||||||
value: { providerID: provider.id, modelID: model.id },
|
value: { providerID: provider.id, modelID: model.id },
|
||||||
title: model.name,
|
title: model.name ?? item.modelID,
|
||||||
description: provider.name,
|
description: provider.name,
|
||||||
category,
|
category,
|
||||||
disabled: provider.id === "opencode" && model.id.includes("-nano"),
|
disabled: provider.id === "opencode" && model.id.includes("-nano"),
|
||||||
footer: model.cost[0]?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
|
footer: model.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
onSelect(provider.id, model.id)
|
onSelect(provider.id, model.id)
|
||||||
},
|
},
|
||||||
@@ -61,43 +59,50 @@ export function DialogModel(props: { providerID?: string }) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const providerOptions = pipe(
|
const providerOptions = pipe(
|
||||||
data.location.model.list() ?? [],
|
sync.data.provider,
|
||||||
filter((model) => model.status !== "deprecated"),
|
|
||||||
filter((model) => (props.providerID ? model.providerID === props.providerID : true)),
|
|
||||||
sortBy(
|
sortBy(
|
||||||
(model) => model.providerID !== "opencode",
|
(provider) => provider.id !== "opencode",
|
||||||
(model) => data.location.provider.list()?.find((provider) => provider.id === model.providerID)?.name ?? "",
|
(provider) => provider.name,
|
||||||
[(model) => model.time.released, "desc"],
|
),
|
||||||
|
flatMap((provider) =>
|
||||||
|
pipe(
|
||||||
|
provider.models,
|
||||||
|
entries(),
|
||||||
|
filter(([_, info]) => info.status !== "deprecated"),
|
||||||
|
filter(([_, info]) => (props.providerID ? info.providerID === props.providerID : true)),
|
||||||
|
map(([model, info]) => ({
|
||||||
|
value: { providerID: provider.id, modelID: model },
|
||||||
|
title: info.name ?? model,
|
||||||
|
releaseDate: info.release_date,
|
||||||
|
description: favorites.some((item) => item.providerID === provider.id && item.modelID === model)
|
||||||
|
? "(Favorite)"
|
||||||
|
: undefined,
|
||||||
|
category: connected() ? provider.name : undefined,
|
||||||
|
disabled: provider.id === "opencode" && model.includes("-nano"),
|
||||||
|
footer: info.cost?.input === 0 && provider.id === "opencode" ? "Free" : undefined,
|
||||||
|
onSelect() {
|
||||||
|
onSelect(provider.id, model)
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
filter((option) => {
|
||||||
|
if (!showSections) return true
|
||||||
|
if (
|
||||||
|
favorites.some(
|
||||||
|
(item) => item.providerID === option.value.providerID && item.modelID === option.value.modelID,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
if (
|
||||||
|
recents.some(
|
||||||
|
(item) => item.providerID === option.value.providerID && item.modelID === option.value.modelID,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
return true
|
||||||
|
}),
|
||||||
|
(options) => sortModelOptions(options, props.providerID !== undefined),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
map((model) => ({
|
|
||||||
value: { providerID: model.providerID, modelID: model.id },
|
|
||||||
title: model.name,
|
|
||||||
releaseDate: model.time.released,
|
|
||||||
description: favorites.some((item) => item.providerID === model.providerID && item.modelID === model.id)
|
|
||||||
? "(Favorite)"
|
|
||||||
: undefined,
|
|
||||||
category: connected()
|
|
||||||
? data.location.provider.list()?.find((provider) => provider.id === model.providerID)?.name
|
|
||||||
: undefined,
|
|
||||||
disabled: !model.enabled || (model.providerID === "opencode" && model.id.includes("-nano")),
|
|
||||||
footer: model.cost[0]?.input === 0 && model.providerID === "opencode" ? "Free" : undefined,
|
|
||||||
onSelect() {
|
|
||||||
onSelect(model.providerID, model.id)
|
|
||||||
},
|
|
||||||
})),
|
|
||||||
filter((option) => {
|
|
||||||
if (!showSections) return true
|
|
||||||
if (
|
|
||||||
favorites.some((item) => item.providerID === option.value.providerID && item.modelID === option.value.modelID)
|
|
||||||
)
|
|
||||||
return false
|
|
||||||
if (
|
|
||||||
recents.some((item) => item.providerID === option.value.providerID && item.modelID === option.value.modelID)
|
|
||||||
)
|
|
||||||
return false
|
|
||||||
return true
|
|
||||||
}),
|
|
||||||
(options) => sortModelOptions(options, props.providerID !== undefined),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const popularProviders = !connected()
|
const popularProviders = !connected()
|
||||||
@@ -122,7 +127,7 @@ export function DialogModel(props: { providerID?: string }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const provider = createMemo(() =>
|
const provider = createMemo(() =>
|
||||||
props.providerID ? data.location.provider.list()?.find((item) => item.id === props.providerID) : null,
|
props.providerID ? sync.data.provider.find((item) => item.id === props.providerID) : null,
|
||||||
)
|
)
|
||||||
|
|
||||||
const title = createMemo(() => {
|
const title = createMemo(() => {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export async function warpWorkspaceSession(input: {
|
|||||||
|
|
||||||
input.project.workspace.set(input.workspaceID)
|
input.project.workspace.set(input.workspaceID)
|
||||||
|
|
||||||
await input.sync.bootstrap()
|
await input.sync.bootstrap({ fatal: false }).catch(() => undefined)
|
||||||
|
|
||||||
const dir = input.project.instance.directory() || input.sync.path.directory
|
const dir = input.project.instance.directory() || input.sync.path.directory
|
||||||
if (dir) {
|
if (dir) {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export function DialogWorkspaceList() {
|
|||||||
route.navigate({ type: "home" })
|
route.navigate({ type: "home" })
|
||||||
}
|
}
|
||||||
await project.workspace.sync()
|
await project.workspace.sync()
|
||||||
await sync.bootstrap()
|
await sync.bootstrap({ fatal: false }).catch(() => undefined)
|
||||||
setRemoving(undefined)
|
setRemoving(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -317,9 +317,10 @@ export function Autocomplete(props: {
|
|||||||
const { lineRange, baseQuery } = extractLineRange(query ?? "")
|
const { lineRange, baseQuery } = extractLineRange(query ?? "")
|
||||||
|
|
||||||
// Get files from SDK
|
// Get files from SDK
|
||||||
const result = await sdk.client.find.files({
|
const result = await sdk.client.v2.fs.find({
|
||||||
query: baseQuery,
|
query: baseQuery,
|
||||||
workspace: project.workspace.current(),
|
limit: "20",
|
||||||
|
location: { workspace: project.workspace.current() },
|
||||||
})
|
})
|
||||||
|
|
||||||
const options: AutocompleteOption[] = []
|
const options: AutocompleteOption[] = []
|
||||||
@@ -329,15 +330,13 @@ export function Autocomplete(props: {
|
|||||||
if (!result.error && result.data) {
|
if (!result.error && result.data) {
|
||||||
const width = props.anchor().width - 4
|
const width = props.anchor().width - 4
|
||||||
options.push(
|
options.push(
|
||||||
...result.data.map((item): AutocompleteOption => {
|
...result.data.data.map((item): AutocompleteOption => {
|
||||||
const { filename, url, part } = createFilePart(item, lineRange)
|
const { filename, url, part } = createFilePart(item.path, lineRange)
|
||||||
|
|
||||||
const isDir = item.endsWith("/")
|
|
||||||
return {
|
return {
|
||||||
display: Locale.truncateMiddle(filename, width),
|
display: Locale.truncateMiddle(filename, width),
|
||||||
value: filename,
|
value: filename,
|
||||||
isDirectory: isDir,
|
isDirectory: item.type === "directory",
|
||||||
path: item,
|
path: item.path,
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
insertPart(filename, part)
|
insertPart(filename, part)
|
||||||
},
|
},
|
||||||
@@ -390,15 +389,15 @@ export function Autocomplete(props: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const agents = createMemo(() => {
|
const agents = createMemo(() => {
|
||||||
return (data.location.agent.list() ?? [])
|
return sync.data.agent
|
||||||
.filter((agent) => !agent.hidden && agent.mode !== "primary")
|
.filter((agent) => !agent.hidden && agent.mode !== "primary")
|
||||||
.map(
|
.map(
|
||||||
(agent): AutocompleteOption => ({
|
(agent): AutocompleteOption => ({
|
||||||
display: "@" + agent.id,
|
display: "@" + agent.name,
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
insertPart(agent.id, {
|
insertPart(agent.name, {
|
||||||
type: "agent",
|
type: "agent",
|
||||||
name: agent.id,
|
name: agent.name,
|
||||||
source: {
|
source: {
|
||||||
start: 0,
|
start: 0,
|
||||||
end: 0,
|
end: 0,
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { createMemo } from "solid-js"
|
import { createMemo } from "solid-js"
|
||||||
import { useData } from "../context/data"
|
import { useSync } from "../context/sync"
|
||||||
|
|
||||||
export function useConnected() {
|
export function useConnected() {
|
||||||
const data = useData()
|
const sync = useSync()
|
||||||
return createMemo(() => (data.location.provider.list() ?? []).some((provider) => provider.enabled !== false))
|
return createMemo(() =>
|
||||||
|
sync.data.provider.some((provider) =>
|
||||||
|
provider.id !== "opencode" || Object.values(provider.models).some((model) => model.cost?.input !== 0),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { readJson, writeJsonAtomic } from "../util/persistence"
|
|||||||
import { useTheme } from "./theme"
|
import { useTheme } from "./theme"
|
||||||
import { useToast } from "../ui/toast"
|
import { useToast } from "../ui/toast"
|
||||||
import { useRoute } from "./route"
|
import { useRoute } from "./route"
|
||||||
import { useData } from "./data"
|
|
||||||
|
|
||||||
export type LocalTheme = {
|
export type LocalTheme = {
|
||||||
secondary: RGBA
|
secondary: RGBA
|
||||||
@@ -52,17 +51,15 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
name: "Local",
|
name: "Local",
|
||||||
init: () => {
|
init: () => {
|
||||||
const sync = useSync()
|
const sync = useSync()
|
||||||
const data = useData()
|
|
||||||
const sdk = useSDK()
|
const sdk = useSDK()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
const theme = useTheme().theme
|
const theme = useTheme().theme
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const paths = useTuiPaths()
|
const paths = useTuiPaths()
|
||||||
const providers = createMemo(() => data.location.provider.list() ?? [])
|
|
||||||
const models = createMemo(() => data.location.model.list() ?? [])
|
|
||||||
|
|
||||||
function isModelValid(model: { providerID: string; modelID: string }) {
|
function isModelValid(model: { providerID: string; modelID: string }) {
|
||||||
return models().some((item) => item.providerID === model.providerID && item.id === model.modelID && item.enabled)
|
const provider = sync.data.provider.find((item) => item.id === model.providerID)
|
||||||
|
return !!provider?.models[model.modelID]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFirstValidModel(...modelFns: (() => { providerID: string; modelID: string } | undefined)[]) {
|
function getFirstValidModel(...modelFns: (() => { providerID: string; modelID: string } | undefined)[]) {
|
||||||
@@ -74,18 +71,8 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createAgent() {
|
function createAgent() {
|
||||||
const all = createMemo(() =>
|
const agents = createMemo(() => sync.data.agent.filter((agent) => agent.mode !== "subagent" && !agent.hidden))
|
||||||
(data.location.agent.list() ?? []).map((agent) => ({
|
const visibleAgents = createMemo(() => sync.data.agent.filter((agent) => !agent.hidden))
|
||||||
...agent,
|
|
||||||
name: agent.id,
|
|
||||||
native: false,
|
|
||||||
model: agent.model
|
|
||||||
? { providerID: agent.model.providerID, modelID: agent.model.id, variant: agent.model.variant }
|
|
||||||
: undefined,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
const agents = createMemo(() => all().filter((agent) => agent.mode !== "subagent" && !agent.hidden))
|
|
||||||
const visibleAgents = createMemo(() => all().filter((agent) => !agent.hidden))
|
|
||||||
const [agentStore, setAgentStore] = createStore({
|
const [agentStore, setAgentStore] = createStore({
|
||||||
current: undefined as string | undefined,
|
current: undefined as string | undefined,
|
||||||
})
|
})
|
||||||
@@ -231,13 +218,15 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const model = models().find(
|
const provider = sync.data.provider[0]
|
||||||
(item) => item.enabled && providers().some((provider) => provider.id === item.providerID),
|
if (!provider) return undefined
|
||||||
)
|
const defaultModel = sync.data.provider_default[provider.id]
|
||||||
|
const firstModel = Object.values(provider.models)[0]
|
||||||
|
const model = defaultModel ?? firstModel?.id
|
||||||
if (!model) return undefined
|
if (!model) return undefined
|
||||||
return {
|
return {
|
||||||
providerID: model.providerID,
|
providerID: provider.id,
|
||||||
modelID: model.id,
|
modelID: model,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -272,12 +261,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
reasoning: false,
|
reasoning: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const provider = providers().find((item) => item.id === value.providerID)
|
const provider = sync.data.provider.find((item) => item.id === value.providerID)
|
||||||
const info = models().find((item) => item.providerID === value.providerID && item.id === value.modelID)
|
const info = provider?.models[value.modelID]
|
||||||
return {
|
return {
|
||||||
provider: provider?.name ?? value.providerID,
|
provider: provider?.name ?? value.providerID,
|
||||||
model: info?.name ?? value.modelID,
|
model: info?.name ?? value.modelID,
|
||||||
reasoning: false,
|
reasoning: info?.capabilities?.reasoning ?? false,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
cycle(direction: 1 | -1) {
|
cycle(direction: 1 | -1) {
|
||||||
@@ -383,8 +372,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
list() {
|
list() {
|
||||||
const m = currentModel()
|
const m = currentModel()
|
||||||
if (!m) return []
|
if (!m) return []
|
||||||
const info = models().find((item) => item.providerID === m.providerID && item.id === m.modelID)
|
const provider = sync.data.provider.find((item) => item.id === m.providerID)
|
||||||
return info?.variants.map((variant) => variant.id) ?? []
|
const info = provider?.models[m.modelID]
|
||||||
|
if (!info?.variants) return []
|
||||||
|
return Object.keys(info.variants)
|
||||||
},
|
},
|
||||||
set(value: string | undefined) {
|
set(value: string | undefined) {
|
||||||
const m = currentModel()
|
const m = currentModel()
|
||||||
|
|||||||
@@ -4,20 +4,19 @@ import { createMemo, Match, Show, Switch } from "solid-js"
|
|||||||
import { abbreviateHome } from "../../runtime"
|
import { abbreviateHome } from "../../runtime"
|
||||||
import { useTuiPaths } from "../../context/runtime"
|
import { useTuiPaths } from "../../context/runtime"
|
||||||
import { useHomeSessionDestination } from "../../routes/home/session-destination"
|
import { useHomeSessionDestination } from "../../routes/home/session-destination"
|
||||||
import { useData } from "../../context/data"
|
|
||||||
|
|
||||||
const id = "internal:home-footer"
|
const id = "internal:home-footer"
|
||||||
|
|
||||||
function Directory(props: { api: TuiPluginApi }) {
|
function Directory(props: { api: TuiPluginApi }) {
|
||||||
const theme = () => props.api.theme.current
|
const theme = () => props.api.theme.current
|
||||||
const destination = useHomeSessionDestination()
|
const destination = useHomeSessionDestination()
|
||||||
const data = useData()
|
|
||||||
const paths = useTuiPaths()
|
const paths = useTuiPaths()
|
||||||
const dir = createMemo(() => {
|
const dir = createMemo(() => {
|
||||||
const selected = destination?.destination()
|
const selected = destination?.destination()
|
||||||
const directory = !selected || selected.type === "new" ? data.location.default().directory : selected.directory
|
if (!selected || selected.type === "new") return
|
||||||
const out = abbreviateHome(directory, paths.home)
|
const out = abbreviateHome(selected.directory, paths.home)
|
||||||
const branch = directory === (props.api.state.path.directory || paths.cwd) ? props.api.state.vcs?.branch : undefined
|
const branch =
|
||||||
|
selected.directory === (props.api.state.path.directory || paths.cwd) ? props.api.state.vcs?.branch : undefined
|
||||||
if (branch) return out + ":" + branch
|
if (branch) return out + ":" + branch
|
||||||
return out
|
return out
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import {
|
|||||||
type ParentProps,
|
type ParentProps,
|
||||||
type Setter,
|
type Setter,
|
||||||
} from "solid-js"
|
} from "solid-js"
|
||||||
import { useData } from "../../context/data"
|
import { useSync } from "../../context/sync"
|
||||||
|
import { useTuiPaths } from "../../context/runtime"
|
||||||
|
|
||||||
export type HomeSessionDestination = { type: "directory"; directory: string; subdirectory: boolean } | { type: "new" }
|
export type HomeSessionDestination = { type: "directory"; directory: string; subdirectory: boolean } | { type: "new" }
|
||||||
|
|
||||||
@@ -20,10 +21,11 @@ type Context = {
|
|||||||
const HomeSessionDestinationContext = createContext<Context>()
|
const HomeSessionDestinationContext = createContext<Context>()
|
||||||
|
|
||||||
export function HomeSessionDestinationProvider(props: ParentProps) {
|
export function HomeSessionDestinationProvider(props: ParentProps) {
|
||||||
const data = useData()
|
const sync = useSync()
|
||||||
|
const paths = useTuiPaths()
|
||||||
const [selected, setDestination] = createSignal<HomeSessionDestination>()
|
const [selected, setDestination] = createSignal<HomeSessionDestination>()
|
||||||
const destination = createMemo<HomeSessionDestination>(
|
const destination = createMemo<HomeSessionDestination>(
|
||||||
() => selected() ?? { type: "directory", directory: data.location.default().directory, subdirectory: false },
|
() => selected() ?? { type: "directory", directory: sync.path.directory || paths.cwd, subdirectory: false },
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<HomeSessionDestinationContext.Provider
|
<HomeSessionDestinationContext.Provider
|
||||||
|
|||||||
Reference in New Issue
Block a user