app: wrap provider data in Map to avoid store (#28765)
This commit is contained in:
@@ -41,9 +41,7 @@ export function DialogConnectProvider(props: { provider: string }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const provider = createMemo(
|
const provider = createMemo(
|
||||||
() =>
|
() => providers.all().get(props.provider) ?? globalSync.data.provider.all.get(props.provider)!,
|
||||||
providers.all().find((x) => x.id === props.provider) ??
|
|
||||||
globalSync.data.provider.all.find((x) => x.id === props.provider)!,
|
|
||||||
)
|
)
|
||||||
const fallback = createMemo<ProviderAuthMethod[]>(() => [
|
const fallback = createMemo<ProviderAuthMethod[]>(() => [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export function DialogCustomProvider(props: Props) {
|
|||||||
form,
|
form,
|
||||||
t: language.t,
|
t: language.t,
|
||||||
disabledProviders: globalSync.data.config.disabled_providers ?? [],
|
disabledProviders: globalSync.data.config.disabled_providers ?? [],
|
||||||
existingProviderIDs: new Set(globalSync.data.provider.all.map((p) => p.id)),
|
existingProviderIDs: new Set(globalSync.data.provider.all.keys()),
|
||||||
})
|
})
|
||||||
batch(() => {
|
batch(() => {
|
||||||
setForm("err", output.err)
|
setForm("err", output.err)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export const DialogSelectModelUnpaid: Component<{ model?: ModelState }> = (props
|
|||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<List
|
<List
|
||||||
class="w-full px-0"
|
class="w-full px-0"
|
||||||
key={(x) => x?.id}
|
key={(p) => p.id}
|
||||||
items={providers.popular}
|
items={providers.popular}
|
||||||
activeIcon="plus-small"
|
activeIcon="plus-small"
|
||||||
sortBy={(a, b) => {
|
sortBy={(a, b) => {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const DialogSelectProvider: Component = () => {
|
|||||||
key={(x) => x?.id}
|
key={(x) => x?.id}
|
||||||
items={() => {
|
items={() => {
|
||||||
language.locale()
|
language.locale()
|
||||||
return [{ id: CUSTOM_ID, name: customLabel() }, ...providers.all()]
|
return [{ id: CUSTOM_ID, name: customLabel() }, ...providers.all().values()]
|
||||||
}}
|
}}
|
||||||
filterKeys={["id", "name"]}
|
filterKeys={["id", "name"]}
|
||||||
groupBy={(x) => (popularProviders.includes(x.id) ? popularGroup() : otherGroup())}
|
groupBy={(x) => (popularProviders.includes(x.id) ? popularGroup() : otherGroup())}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const metrics = createMemo(() => getSessionContextMetrics(messages(), providers.all()))
|
const metrics = createMemo(() => getSessionContextMetrics(messages(), [...providers.all().values()]))
|
||||||
const context = createMemo(() => metrics().context)
|
const context = createMemo(() => metrics().context)
|
||||||
const cost = createMemo(() => {
|
const cost = createMemo(() => {
|
||||||
return usd().format(metrics().totalCost)
|
return usd().format(metrics().totalCost)
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export function SessionContextTab() {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const metrics = createMemo(() => getSessionContextMetrics(messages(), providers.all()))
|
const metrics = createMemo(() => getSessionContextMetrics(messages(), [...providers.all().values()]))
|
||||||
const ctx = createMemo(() => metrics().context)
|
const ctx = createMemo(() => metrics().context)
|
||||||
const formatter = createMemo(() => createSessionContextFormatter(language.intl()))
|
const formatter = createMemo(() => createSessionContextFormatter(language.intl()))
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
import type {
|
import type { Config, OpencodeClient, Path, Project, ProviderAuthResponse, Todo } from "@opencode-ai/sdk/v2/client"
|
||||||
Config,
|
|
||||||
OpencodeClient,
|
|
||||||
Path,
|
|
||||||
Project,
|
|
||||||
ProviderAuthResponse,
|
|
||||||
ProviderListResponse,
|
|
||||||
Todo,
|
|
||||||
} from "@opencode-ai/sdk/v2/client"
|
|
||||||
import { showToast } from "@opencode-ai/ui/toast"
|
import { showToast } from "@opencode-ai/ui/toast"
|
||||||
import { getFilename } from "@opencode-ai/core/util/path"
|
import { getFilename } from "@opencode-ai/core/util/path"
|
||||||
import { batch, createContext, getOwner, onCleanup, onMount, type ParentProps, untrack, useContext } from "solid-js"
|
import { batch, createContext, getOwner, onCleanup, onMount, type ParentProps, untrack, useContext } from "solid-js"
|
||||||
@@ -37,6 +29,7 @@ import { createRefreshQueue } from "./global-sync/queue"
|
|||||||
import { directoryKey } from "./global-sync/utils"
|
import { directoryKey } from "./global-sync/utils"
|
||||||
import { PathKey } from "@/utils/path-key"
|
import { PathKey } from "@/utils/path-key"
|
||||||
import { createDirSyncContext } from "./directory-sync"
|
import { createDirSyncContext } from "./directory-sync"
|
||||||
|
import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
|
||||||
|
|
||||||
type GlobalStore = {
|
type GlobalStore = {
|
||||||
ready: boolean
|
ready: boolean
|
||||||
@@ -46,7 +39,7 @@ type GlobalStore = {
|
|||||||
session_todo: {
|
session_todo: {
|
||||||
[sessionID: string]: Todo[]
|
[sessionID: string]: Todo[]
|
||||||
}
|
}
|
||||||
provider: ProviderListResponse
|
provider: NormalizedProviderListResponse
|
||||||
provider_auth: ProviderAuthResponse
|
provider_auth: ProviderAuthResponse
|
||||||
config: Config
|
config: Config
|
||||||
reload: undefined | "pending" | "complete"
|
reload: undefined | "pending" | "complete"
|
||||||
@@ -121,7 +114,7 @@ function createGlobalSync() {
|
|||||||
return pathQuery.data ?? EMPTY
|
return pathQuery.data ?? EMPTY
|
||||||
},
|
},
|
||||||
get provider() {
|
get provider() {
|
||||||
const EMPTY = { all: [], connected: [], default: {} }
|
const EMPTY = { all: new Map(), connected: [], default: {} }
|
||||||
if (providerQuery.isLoading) return EMPTY
|
if (providerQuery.isLoading) return EMPTY
|
||||||
return providerQuery.data ?? EMPTY
|
return providerQuery.data ?? EMPTY
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import type {
|
|||||||
PermissionRequest,
|
PermissionRequest,
|
||||||
Project,
|
Project,
|
||||||
ProviderAuthResponse,
|
ProviderAuthResponse,
|
||||||
ProviderListResponse,
|
|
||||||
QuestionRequest,
|
QuestionRequest,
|
||||||
Session,
|
Session,
|
||||||
Todo,
|
Todo,
|
||||||
@@ -20,6 +19,7 @@ import { cmp, normalizeAgentList, normalizeProviderList } from "./utils"
|
|||||||
import { formatServerError } from "@/utils/server-errors"
|
import { formatServerError } from "@/utils/server-errors"
|
||||||
import { QueryClient, queryOptions } from "@tanstack/solid-query"
|
import { QueryClient, queryOptions } from "@tanstack/solid-query"
|
||||||
import { loadMcpQuery } from "../global-sync"
|
import { loadMcpQuery } from "../global-sync"
|
||||||
|
import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
|
||||||
|
|
||||||
type GlobalStore = {
|
type GlobalStore = {
|
||||||
ready: boolean
|
ready: boolean
|
||||||
@@ -28,7 +28,7 @@ type GlobalStore = {
|
|||||||
session_todo: {
|
session_todo: {
|
||||||
[sessionID: string]: Todo[]
|
[sessionID: string]: Todo[]
|
||||||
}
|
}
|
||||||
provider: ProviderListResponse
|
provider: NormalizedProviderListResponse
|
||||||
provider_auth: ProviderAuthResponse
|
provider_auth: ProviderAuthResponse
|
||||||
config: Config
|
config: Config
|
||||||
reload: undefined | "pending" | "complete"
|
reload: undefined | "pending" | "complete"
|
||||||
@@ -208,7 +208,7 @@ export async function bootstrapDirectory(input: {
|
|||||||
config: Config
|
config: Config
|
||||||
path: Path
|
path: Path
|
||||||
project: Project[]
|
project: Project[]
|
||||||
provider: ProviderListResponse
|
provider: NormalizedProviderListResponse
|
||||||
}
|
}
|
||||||
queryClient: QueryClient
|
queryClient: QueryClient
|
||||||
}) {
|
}) {
|
||||||
@@ -220,7 +220,6 @@ export async function bootstrapDirectory(input: {
|
|||||||
if (Object.keys(input.store.config).length === 0 && Object.keys(input.global.config).length > 0) {
|
if (Object.keys(input.store.config).length === 0 && Object.keys(input.global.config).length > 0) {
|
||||||
input.setStore("config", reconcile(input.global.config, { merge: false }))
|
input.setStore("config", reconcile(input.global.config, { merge: false }))
|
||||||
}
|
}
|
||||||
if (loading) input.setStore("status", "partial")
|
|
||||||
|
|
||||||
const rev = (providerRev.get(input.directory) ?? 0) + 1
|
const rev = (providerRev.get(input.directory) ?? 0) + 1
|
||||||
providerRev.set(input.directory, rev)
|
providerRev.set(input.directory, rev)
|
||||||
@@ -327,7 +326,5 @@ export async function bootstrapDirectory(input: {
|
|||||||
description: formatServerError(slowErrs[0], input.translate),
|
description: formatServerError(slowErrs[0], input.translate),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading && slowErrs.length === 0) input.setStore("status", "complete")
|
|
||||||
})()
|
})()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createRoot, getOwner, onCleanup, runWithOwner, type Owner } from "solid-js"
|
import { createRoot, getOwner, onCleanup, runWithOwner, type Owner } from "solid-js"
|
||||||
import { createStore, type SetStoreFunction, type Store } from "solid-js/store"
|
import { createStore, type SetStoreFunction, type Store } from "solid-js/store"
|
||||||
import { Persist, persisted } from "@/utils/persist"
|
import { Persist, persisted } from "@/utils/persist"
|
||||||
import type { ProviderListResponse, VcsInfo } from "@opencode-ai/sdk/v2/client"
|
import type { VcsInfo } from "@opencode-ai/sdk/v2/client"
|
||||||
import {
|
import {
|
||||||
DIR_IDLE_TTL_MS,
|
DIR_IDLE_TTL_MS,
|
||||||
MAX_DIR_STORES,
|
MAX_DIR_STORES,
|
||||||
@@ -17,6 +17,7 @@ import { canDisposeDirectory, pickDirectoriesToEvict } from "./eviction"
|
|||||||
import { useQueries } from "@tanstack/solid-query"
|
import { useQueries } from "@tanstack/solid-query"
|
||||||
import { QueryOptionsApi } from "../global-sync"
|
import { QueryOptionsApi } from "../global-sync"
|
||||||
import { directoryKey, type DirectoryKey } from "./utils"
|
import { directoryKey, type DirectoryKey } from "./utils"
|
||||||
|
import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
|
||||||
|
|
||||||
export function createChildStoreManager(input: {
|
export function createChildStoreManager(input: {
|
||||||
owner: Owner
|
owner: Owner
|
||||||
@@ -27,7 +28,7 @@ export function createChildStoreManager(input: {
|
|||||||
translate: (key: string, vars?: Record<string, string | number>) => string
|
translate: (key: string, vars?: Record<string, string | number>) => string
|
||||||
queryOptions: QueryOptionsApi
|
queryOptions: QueryOptionsApi
|
||||||
global: {
|
global: {
|
||||||
provider: ProviderListResponse
|
provider: NormalizedProviderListResponse
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
const children: Record<string, [Store<State>, SetStoreFunction<State>]> = {}
|
const children: Record<string, [Store<State>, SetStoreFunction<State>]> = {}
|
||||||
@@ -190,10 +191,9 @@ export function createChildStoreManager(input: {
|
|||||||
return !providerQuery.isLoading
|
return !providerQuery.isLoading
|
||||||
},
|
},
|
||||||
get provider() {
|
get provider() {
|
||||||
const EMPTY = { all: [], connected: [], default: {} }
|
const EMPTY = { all: new Map(), connected: [], default: {} }
|
||||||
if (providerQuery.isLoading) return EMPTY
|
if (providerQuery.isLoading) return EMPTY
|
||||||
if (providerQuery.data?.all.length === 0 && input.global.provider.all.length > 0)
|
if (providerQuery.data?.all.size === 0 && input.global.provider.all.size > 0) return input.global.provider
|
||||||
return input.global.provider
|
|
||||||
return providerQuery.data ?? EMPTY
|
return providerQuery.data ?? EMPTY
|
||||||
},
|
},
|
||||||
config: {},
|
config: {},
|
||||||
@@ -202,7 +202,7 @@ export function createChildStoreManager(input: {
|
|||||||
return { state: "", config: "", worktree: "", directory: "", home: "" }
|
return { state: "", config: "", worktree: "", directory: "", home: "" }
|
||||||
return pathQuery.data
|
return pathQuery.data
|
||||||
},
|
},
|
||||||
status: "loading" as const,
|
status: "complete" as const,
|
||||||
agent: [],
|
agent: [],
|
||||||
command: [],
|
command: [],
|
||||||
session: [],
|
session: [],
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import type {
|
|||||||
Part,
|
Part,
|
||||||
Path,
|
Path,
|
||||||
PermissionRequest,
|
PermissionRequest,
|
||||||
ProviderListResponse,
|
|
||||||
QuestionRequest,
|
QuestionRequest,
|
||||||
Session,
|
Session,
|
||||||
SessionStatus,
|
SessionStatus,
|
||||||
@@ -16,6 +15,7 @@ import type {
|
|||||||
Todo,
|
Todo,
|
||||||
VcsInfo,
|
VcsInfo,
|
||||||
} from "@opencode-ai/sdk/v2/client"
|
} from "@opencode-ai/sdk/v2/client"
|
||||||
|
import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
|
||||||
import type { Accessor } from "solid-js"
|
import type { Accessor } from "solid-js"
|
||||||
import type { SetStoreFunction, Store } from "solid-js/store"
|
import type { SetStoreFunction, Store } from "solid-js/store"
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ export type State = {
|
|||||||
projectMeta: ProjectMeta | undefined
|
projectMeta: ProjectMeta | undefined
|
||||||
icon: string | undefined
|
icon: string | undefined
|
||||||
provider_ready: boolean
|
provider_ready: boolean
|
||||||
provider: ProviderListResponse
|
provider: NormalizedProviderListResponse
|
||||||
config: Config
|
config: Config
|
||||||
path: Path
|
path: Path
|
||||||
session: Session[]
|
session: Session[]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Agent, Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
|
import type { Agent, Project, ProviderListResponse } from "@opencode-ai/sdk/v2/client"
|
||||||
|
import { NormalizedProviderListResponse } from "@opencode-ai/ui/context"
|
||||||
export { pathKey as directoryKey, type PathKey as DirectoryKey } from "@/utils/path-key"
|
export { pathKey as directoryKey, type PathKey as DirectoryKey } from "@/utils/path-key"
|
||||||
|
|
||||||
export const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0)
|
export const cmp = (a: string, b: string) => (a < b ? -1 : a > b ? 1 : 0)
|
||||||
@@ -17,13 +18,23 @@ export function normalizeAgentList(input: unknown): Agent[] {
|
|||||||
return Object.values(input).filter(isAgent)
|
return Object.values(input).filter(isAgent)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeProviderList(input: ProviderListResponse): ProviderListResponse {
|
export function normalizeProviderList(input: ProviderListResponse): NormalizedProviderListResponse {
|
||||||
return {
|
return {
|
||||||
...input,
|
...input,
|
||||||
all: input.all.map((provider) => ({
|
all: new Map(
|
||||||
...provider,
|
input.all.map(
|
||||||
models: Object.fromEntries(Object.entries(provider.models).filter(([, info]) => info.status !== "deprecated")),
|
(provider) =>
|
||||||
})),
|
[
|
||||||
|
provider.id,
|
||||||
|
{
|
||||||
|
...provider,
|
||||||
|
models: Object.fromEntries(
|
||||||
|
Object.entries(provider.models).filter(([, info]) => info.status !== "deprecated"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] as const,
|
||||||
|
),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const validModel = (model: ModelKey) => {
|
const validModel = (model: ModelKey) => {
|
||||||
const provider = providers.all().find((item) => item.id === model.providerID)
|
const provider = providers.all().get(model.providerID)
|
||||||
return !!provider?.models[model.modelID] && connected().has(model.providerID)
|
return !!provider?.models[model.modelID] && connected().has(model.providerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useGlobalSync } from "@/context/global-sync"
|
import { useGlobalSync } from "@/context/global-sync"
|
||||||
import { decode64 } from "@/utils/base64"
|
import { decode64 } from "@/utils/base64"
|
||||||
import { useParams } from "@solidjs/router"
|
import { useParams } from "@solidjs/router"
|
||||||
|
import { Iterable, pipe } from "effect"
|
||||||
import { createMemo } from "solid-js"
|
import { createMemo } from "solid-js"
|
||||||
|
|
||||||
export const popularProviders = [
|
export const popularProviders = [
|
||||||
@@ -29,16 +30,32 @@ export function useProviders() {
|
|||||||
return {
|
return {
|
||||||
all: () => providers().all,
|
all: () => providers().all,
|
||||||
default: () => providers().default,
|
default: () => providers().default,
|
||||||
popular: () => providers().all.filter((p) => popularProviderSet.has(p.id)),
|
popular: () =>
|
||||||
|
pipe(
|
||||||
|
providers().all,
|
||||||
|
Iterable.map(([, p]) => p),
|
||||||
|
Iterable.filter((p) => popularProviderSet.has(p.id)),
|
||||||
|
(v) => Array.from(v),
|
||||||
|
),
|
||||||
connected: () => {
|
connected: () => {
|
||||||
const connected = new Set(providers().connected)
|
const connected = new Set(providers().connected)
|
||||||
return providers().all.filter((p) => connected.has(p.id))
|
return pipe(
|
||||||
|
providers().all,
|
||||||
|
Iterable.map(([, p]) => p),
|
||||||
|
Iterable.filter((p) => connected.has(p.id)),
|
||||||
|
(v) => Array.from(v),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
paid: () => {
|
paid: () => {
|
||||||
const connected = new Set(providers().connected)
|
const connected = new Set(providers().connected)
|
||||||
return providers().all.filter(
|
return [
|
||||||
(p) => connected.has(p.id) && (p.id !== "opencode" || Object.values(p.models).some((m) => m.cost?.input)),
|
...Iterable.filter(
|
||||||
)
|
providers().all,
|
||||||
|
([id]) =>
|
||||||
|
connected.has(id) &&
|
||||||
|
(id !== "opencode" || Object.values(providers().all.get(id)?.models ?? {}).some((m) => m.cost?.input)),
|
||||||
|
),
|
||||||
|
]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2303,7 +2303,7 @@ export default function Layout(props: ParentProps) {
|
|||||||
<div
|
<div
|
||||||
class="shrink-0 px-3 py-3"
|
class="shrink-0 px-3 py-3"
|
||||||
classList={{
|
classList={{
|
||||||
hidden: store.gettingStartedDismissed || !(providers.all().length > 0 && providers.paid().length === 0),
|
hidden: store.gettingStartedDismissed || !(providers.all().size > 0 && providers.paid().length === 0),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="rounded-xl bg-background-base shadow-xs-border-base" data-component="getting-started">
|
<div class="rounded-xl bg-background-base shadow-xs-border-base" data-component="getting-started">
|
||||||
|
|||||||
@@ -262,8 +262,9 @@ export default function Page() {
|
|||||||
|
|
||||||
const isDesktop = createMediaQuery("(min-width: 768px)")
|
const isDesktop = createMediaQuery("(min-width: 768px)")
|
||||||
const size = createSizing()
|
const size = createSizing()
|
||||||
const desktopReviewOpen = createMemo(() => isDesktop() && view().reviewPanel.opened())
|
const isV2NewSessionPage = () => import.meta.env.VITE_OPENCODE_CHANNEL === "prod" || !params.id
|
||||||
const desktopFileTreeOpen = createMemo(() => isDesktop() && layout.fileTree.opened())
|
const desktopReviewOpen = createMemo(() => isDesktop() && view().reviewPanel.opened() && !isV2NewSessionPage())
|
||||||
|
const desktopFileTreeOpen = createMemo(() => isDesktop() && layout.fileTree.opened() && !isV2NewSessionPage())
|
||||||
const desktopSidePanelOpen = createMemo(() => desktopReviewOpen() || desktopFileTreeOpen())
|
const desktopSidePanelOpen = createMemo(() => desktopReviewOpen() || desktopFileTreeOpen())
|
||||||
const sessionPanelWidth = createMemo(() => {
|
const sessionPanelWidth = createMemo(() => {
|
||||||
if (!desktopSidePanelOpen()) return "100%"
|
if (!desktopSidePanelOpen()) return "100%"
|
||||||
@@ -1733,12 +1734,12 @@ export default function Page() {
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
{/* Session panel */}
|
|
||||||
<div
|
<div
|
||||||
classList={{
|
classList={{
|
||||||
"@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger flex-1 md:flex-none": true,
|
"@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger flex-1 md:flex-none": true,
|
||||||
"transition-[width] duration-[240ms] ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[width] motion-reduce:transition-none":
|
"duration-[240ms] ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[width] motion-reduce:transition-none":
|
||||||
!size.active() && !ui.reviewSnap,
|
!size.active() && !ui.reviewSnap,
|
||||||
|
"transition-[width]": !isV2NewSessionPage(),
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
width: sessionPanelWidth(),
|
width: sessionPanelWidth(),
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function SessionSidePanel(props: {
|
|||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
const command = useCommand()
|
const command = useCommand()
|
||||||
const dialog = useDialog()
|
const dialog = useDialog()
|
||||||
const { sessionKey, tabs, view } = useSessionLayout()
|
const { sessionKey, tabs, view, params } = useSessionLayout()
|
||||||
|
|
||||||
const isDesktop = createMediaQuery("(min-width: 768px)")
|
const isDesktop = createMediaQuery("(min-width: 768px)")
|
||||||
const shown = createMemo(
|
const shown = createMemo(
|
||||||
@@ -207,7 +207,7 @@ export function SessionSidePanel(props: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Show when={isDesktop()}>
|
<Show when={isDesktop() && !(import.meta.env.VITE_OPENCODE_CHANNEL !== "prod" && !params.id)}>
|
||||||
<aside
|
<aside
|
||||||
id="review-panel"
|
id="review-panel"
|
||||||
aria-label={language.t("session.panel.reviewAndFiles")}
|
aria-label={language.t("session.panel.reviewAndFiles")}
|
||||||
|
|||||||
@@ -1063,7 +1063,7 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp
|
|||||||
const providerID = props.message.model?.providerID
|
const providerID = props.message.model?.providerID
|
||||||
const modelID = props.message.model?.modelID
|
const modelID = props.message.model?.modelID
|
||||||
if (!providerID || !modelID) return ""
|
if (!providerID || !modelID) return ""
|
||||||
const match = data.store.provider?.all?.find((p) => p.id === providerID)
|
const match = data.store.provider?.all?.get(providerID)
|
||||||
return match?.models?.[modelID]?.name ?? modelID
|
return match?.models?.[modelID]?.name ?? modelID
|
||||||
})
|
})
|
||||||
const timefmt = createMemo(() => new Intl.DateTimeFormat(i18n.locale(), { timeStyle: "short" }))
|
const timefmt = createMemo(() => new Intl.DateTimeFormat(i18n.locale(), { timeStyle: "short" }))
|
||||||
@@ -1458,7 +1458,7 @@ PART_MAPPING["text"] = function TextPartDisplay(props) {
|
|||||||
const model = createMemo(() => {
|
const model = createMemo(() => {
|
||||||
if (props.message.role !== "assistant") return ""
|
if (props.message.role !== "assistant") return ""
|
||||||
const message = props.message as AssistantMessage
|
const message = props.message as AssistantMessage
|
||||||
const match = data.store.provider?.all?.find((p) => p.id === message.providerID)
|
const match = data.store.provider?.all?.get(message.providerID)
|
||||||
return match?.models?.[message.modelID]?.name ?? message.modelID
|
return match?.models?.[message.modelID]?.name ?? message.modelID
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
import type { Message, Session, Part, SnapshotFileDiff, SessionStatus, ProviderListResponse } from "@opencode-ai/sdk/v2"
|
import type { Message, Session, Part, SnapshotFileDiff, SessionStatus, Provider } from "@opencode-ai/sdk/v2"
|
||||||
import { createSimpleContext } from "./helper"
|
import { createSimpleContext } from "./helper"
|
||||||
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
|
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
|
||||||
|
|
||||||
|
export type NormalizedProviderListResponse = {
|
||||||
|
all: Map<string, Provider>
|
||||||
|
default: {
|
||||||
|
[key: string]: string
|
||||||
|
}
|
||||||
|
connected: Array<string>
|
||||||
|
}
|
||||||
|
|
||||||
type Data = {
|
type Data = {
|
||||||
agent?: {
|
agent?: {
|
||||||
name: string
|
name: string
|
||||||
color?: string
|
color?: string
|
||||||
}[]
|
}[]
|
||||||
provider?: ProviderListResponse
|
provider?: NormalizedProviderListResponse
|
||||||
session: Session[]
|
session: Session[]
|
||||||
session_status: {
|
session_status: {
|
||||||
[sessionID: string]: SessionStatus
|
[sessionID: string]: SessionStatus
|
||||||
|
|||||||
Reference in New Issue
Block a user