feat(desktop): preserve session model selection
This commit is contained in:
parent
b329fcceb2
commit
c97eb2d6fc
1 changed files with 35 additions and 18 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||||
import { base64Encode } from "@opencode-ai/core/util/encode"
|
import { base64Encode } from "@opencode-ai/core/util/encode"
|
||||||
import { useParams } from "@solidjs/router"
|
import { useParams, useSearchParams } from "@solidjs/router"
|
||||||
import { batch, createEffect, createMemo, startTransition } from "solid-js"
|
import { batch, createEffect, createMemo, startTransition } from "solid-js"
|
||||||
import { createStore } from "solid-js/store"
|
import { createStore } from "solid-js/store"
|
||||||
import { useModels } from "@/context/models"
|
import { useModels } from "@/context/models"
|
||||||
|
|
@ -18,10 +18,12 @@ type State = {
|
||||||
agent?: string
|
agent?: string
|
||||||
model?: ModelKey
|
model?: ModelKey
|
||||||
variant?: string | null
|
variant?: string | null
|
||||||
|
source?: "manual" | "message"
|
||||||
}
|
}
|
||||||
|
|
||||||
type Saved = {
|
type Saved = {
|
||||||
session: Record<string, State | undefined>
|
session: Record<string, State | undefined>
|
||||||
|
draft?: State
|
||||||
}
|
}
|
||||||
|
|
||||||
const WORKSPACE_KEY = "__workspace__"
|
const WORKSPACE_KEY = "__workspace__"
|
||||||
|
|
@ -37,11 +39,13 @@ const migrate = (value: unknown) => {
|
||||||
pick?: Record<string, State | undefined>
|
pick?: Record<string, State | undefined>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.session && typeof item.session === "object") return { session: item.session }
|
const draft = "draft" in item && item.draft && typeof item.draft === "object" ? (item.draft as State) : undefined
|
||||||
|
if (item.session && typeof item.session === "object") return { session: item.session, draft }
|
||||||
if (!item.pick || typeof item.pick !== "object") return { session: {} }
|
if (!item.pick || typeof item.pick !== "object") return { session: {} }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
session: Object.fromEntries(Object.entries(item.pick).filter(([key]) => key !== WORKSPACE_KEY)),
|
session: Object.fromEntries(Object.entries(item.pick).filter(([key]) => key !== WORKSPACE_KEY)),
|
||||||
|
draft,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,6 +61,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
name: "Local",
|
name: "Local",
|
||||||
init: () => {
|
init: () => {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
|
const [search] = useSearchParams<{ draftId?: string }>()
|
||||||
const sdk = useSDK()
|
const sdk = useSDK()
|
||||||
const sync = useSync()
|
const sync = useSync()
|
||||||
const serverSDK = useServerSDK()
|
const serverSDK = useServerSDK()
|
||||||
|
|
@ -64,12 +69,15 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
const models = useModels()
|
const models = useModels()
|
||||||
|
|
||||||
const id = createMemo(() => params.id || undefined)
|
const id = createMemo(() => params.id || undefined)
|
||||||
|
const draftID = createMemo(() => search.draftId || undefined)
|
||||||
const list = createMemo(() => sync().data.agent.filter((item) => item.mode !== "subagent" && !item.hidden))
|
const list = createMemo(() => sync().data.agent.filter((item) => item.mode !== "subagent" && !item.hidden))
|
||||||
const connected = createMemo(() => new Set(providers.connected().map((item) => item.id)))
|
const connected = createMemo(() => new Set(providers.connected().map((item) => item.id)))
|
||||||
|
|
||||||
const [saved, setSaved] = persisted(
|
const [saved, setSaved] = persisted(
|
||||||
{
|
{
|
||||||
...Persist.serverWorkspace(serverSDK().scope, sdk().directory, "model-selection", ["model-selection.v1"]),
|
...(draftID()
|
||||||
|
? Persist.draft(draftID()!, "model-selection")
|
||||||
|
: Persist.serverWorkspace(serverSDK().scope, sdk().directory, "model-selection", ["model-selection.v1"])),
|
||||||
migrate,
|
migrate,
|
||||||
},
|
},
|
||||||
createStore<Saved>({
|
createStore<Saved>({
|
||||||
|
|
@ -124,7 +132,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
|
|
||||||
const scope = createMemo<State | undefined>(() => {
|
const scope = createMemo<State | undefined>(() => {
|
||||||
const session = id()
|
const session = id()
|
||||||
if (!session) return store.draft ?? store.promoting
|
if (!session) return saved.draft ?? store.draft ?? store.promoting
|
||||||
return saved.session[session] ?? handoff.get(handoffKey(serverSDK().scope, sdk().directory, session))
|
return saved.session[session] ?? handoff.get(handoffKey(serverSDK().scope, sdk().directory, session))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -178,6 +186,19 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
|
|
||||||
const fallback = createMemo<ModelKey | undefined>(() => configuredModel() ?? recentModel() ?? defaultModel())
|
const fallback = createMemo<ModelKey | undefined>(() => configuredModel() ?? recentModel() ?? defaultModel())
|
||||||
|
|
||||||
|
const save = (state: State) => {
|
||||||
|
const session = id()
|
||||||
|
if (session) {
|
||||||
|
setSaved("session", session, state)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (draftID()) {
|
||||||
|
setSaved("draft", state)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setStore("draft", state)
|
||||||
|
}
|
||||||
|
|
||||||
const agent = {
|
const agent = {
|
||||||
list,
|
list,
|
||||||
current() {
|
current() {
|
||||||
|
|
@ -203,13 +224,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
agent: item.name,
|
agent: item.name,
|
||||||
model: item.model ?? prev?.model,
|
model: item.model ?? prev?.model,
|
||||||
variant: item.variant ?? prev?.variant,
|
variant: item.variant ?? prev?.variant,
|
||||||
|
source: "manual",
|
||||||
} satisfies State
|
} satisfies State
|
||||||
const session = id()
|
save(next)
|
||||||
if (session) {
|
|
||||||
setSaved("session", session, next)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setStore("draft", next)
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
move(direction: 1 | -1) {
|
move(direction: 1 | -1) {
|
||||||
|
|
@ -263,14 +280,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
const state = {
|
const state = {
|
||||||
...(scope() ?? { agent: agent.current()?.name }),
|
...(scope() ?? { agent: agent.current()?.name }),
|
||||||
...next,
|
...next,
|
||||||
|
source: "manual",
|
||||||
} satisfies State
|
} satisfies State
|
||||||
|
|
||||||
const session = id()
|
save(state)
|
||||||
if (session) {
|
|
||||||
setSaved("session", session, state)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setStore("draft", state)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const recent = createMemo(() => models.recent.list().map(models.find).filter(Boolean))
|
const recent = createMemo(() => models.recent.list().map(models.find).filter(Boolean))
|
||||||
|
|
@ -377,10 +390,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
session: {
|
session: {
|
||||||
reset() {
|
reset() {
|
||||||
setStore({ draft: undefined, promoting: undefined })
|
setStore({ draft: undefined, promoting: undefined })
|
||||||
|
if (draftID()) setSaved("draft", undefined)
|
||||||
},
|
},
|
||||||
promote(dir: string, session: string) {
|
promote(dir: string, session: string) {
|
||||||
const next = clone(snapshot())
|
const next = clone(snapshot())
|
||||||
if (!next) return
|
if (!next) return
|
||||||
|
next.source = "manual"
|
||||||
const key = handoffKey(serverSDK().scope, dir, session)
|
const key = handoffKey(serverSDK().scope, dir, session)
|
||||||
handoff.set(key, next)
|
handoff.set(key, next)
|
||||||
|
|
||||||
|
|
@ -391,17 +406,19 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
|
||||||
setStore("promoting", next)
|
setStore("promoting", next)
|
||||||
setStore("draft", undefined)
|
setStore("draft", undefined)
|
||||||
},
|
},
|
||||||
restore(msg: { sessionID: string; agent: string; model: ModelKey }) {
|
restore(msg: { id?: string; sessionID: string; agent: string; model: ModelKey }) {
|
||||||
const session = id()
|
const session = id()
|
||||||
if (!session) return
|
if (!session) return
|
||||||
if (msg.sessionID !== session) return
|
if (msg.sessionID !== session) return
|
||||||
if (saved.session[session] !== undefined) return
|
const current = saved.session[session]
|
||||||
|
if (current?.source === "manual") return
|
||||||
if (handoff.has(handoffKey(serverSDK().scope, sdk().directory, session))) return
|
if (handoff.has(handoffKey(serverSDK().scope, sdk().directory, session))) return
|
||||||
|
|
||||||
setSaved("session", session, {
|
setSaved("session", session, {
|
||||||
agent: msg.agent,
|
agent: msg.agent,
|
||||||
model: msg.model,
|
model: msg.model,
|
||||||
variant: msg.model?.variant ?? null,
|
variant: msg.model?.variant ?? null,
|
||||||
|
source: "message",
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue