Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 35 additions & 14 deletions packages/opencode/src/cli/cmd/tui/context/local.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,15 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
}
}

// Automatically update model when agent changes
// Show warning for invalid hardcoded agent models
createEffect(() => {
const value = agent.current()
if (value.model) {
if (isModelValid(value.model))
model.set({
providerID: value.model.providerID,
modelID: value.model.modelID,
})
else
toast.show({
variant: "warning",
message: `Agent ${value.name}'s configured model ${value.model.providerID}/${value.model.modelID} is not valid`,
duration: 3000,
})
if (value.model && !isModelValid(value.model)) {
toast.show({
variant: "warning",
message: `Agent ${value.name}'s configured model ${value.model.providerID}/${value.model.modelID} is not valid`,
duration: 3000,
})
}
})

Expand Down Expand Up @@ -128,9 +122,17 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const file = Bun.file(path.join(Global.Path.state, "model.json"))

function save() {
// Skip models for agents with hardcoded models
const filteredModel = Object.fromEntries(
Object.entries(modelStore.model).filter(([agentName]) => {
const agentDef = sync.data.agent.find((a) => a.name === agentName)
return !agentDef?.model
}),
)
Bun.write(
file,
JSON.stringify({
model: filteredModel,
recent: modelStore.recent,
favorite: modelStore.favorite,
}),
Expand All @@ -140,6 +142,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
file
.json()
.then((x) => {
if (x.model && typeof x.model === "object") setModelStore("model", x.model)
if (Array.isArray(x.recent)) setModelStore("recent", x.recent)
if (Array.isArray(x.favorite)) setModelStore("favorite", x.favorite)
})
Expand All @@ -148,6 +151,23 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
setModelStore("ready", true)
})

// Handle the upgrade path to ensure hardcoded models were saved by
// removing them from the store on load.
createEffect(() => {
if (!sync.ready) return
if (Object.keys(modelStore.model).length === 0) return
const filtered = Object.fromEntries(
Object.entries(modelStore.model).filter(([agentName]) => {
const agentDef = sync.data.agent.find((a) => a.name === agentName)
return !agentDef?.model
}),
)
if (Object.keys(filtered).length !== Object.keys(modelStore.model).length) {
setModelStore("model", filtered)
save()
}
})

const args = useArgs()
const fallbackModel = createMemo(() => {
if (args.model) {
Expand Down Expand Up @@ -224,6 +244,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const val = recent[next]
if (!val) return
setModelStore("model", agent.current().name, { ...val })
save()
},
cycleFavorite(direction: 1 | -1) {
const favorites = modelStore.favorite.filter((item) => isModelValid(item))
Expand Down Expand Up @@ -267,8 +288,8 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
const uniq = uniqueBy([model, ...modelStore.recent], (x) => x.providerID + x.modelID)
if (uniq.length > 10) uniq.pop()
setModelStore("recent", uniq)
save()
}
save()
})
},
toggleFavorite(model: { providerID: string; modelID: string }) {
Expand Down