|
|
@@ -115,6 +115,7 @@ type RuntimeState = {
|
|
|
shown: boolean
|
|
|
aborting: boolean
|
|
|
model: RunInput["model"]
|
|
|
+ defaultModel: RunInput["model"]
|
|
|
providers: RunProvider[]
|
|
|
variants: string[]
|
|
|
activeVariant: string | undefined
|
|
|
@@ -212,6 +213,7 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
shown: !session.first,
|
|
|
aborting: false,
|
|
|
model: ctx.model ?? session.model,
|
|
|
+ defaultModel: undefined,
|
|
|
providers: [],
|
|
|
variants: [],
|
|
|
activeVariant: resolveVariant(ctx.variant, session.variant, savedVariant, []),
|
|
|
@@ -286,17 +288,19 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
await settleForm(next.sessionID, next.formID)
|
|
|
},
|
|
|
onCycleVariant: () => {
|
|
|
- if (!state.model || state.variants.length === 0) {
|
|
|
+ const model = state.model ?? state.defaultModel
|
|
|
+ if (!model || state.variants.length === 0) {
|
|
|
return {
|
|
|
status: "no variants available",
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (!state.model) state.model = model
|
|
|
state.activeVariant = cycleVariant(state.activeVariant, state.variants)
|
|
|
- void input.host.preferences.saveVariant(state.model, state.activeVariant)
|
|
|
+ void input.host.preferences.saveVariant(model, state.activeVariant)
|
|
|
return {
|
|
|
status: state.activeVariant ? `variant ${state.activeVariant}` : "variant default",
|
|
|
- modelLabel: formatModelLabel(state.model, state.activeVariant, state.providers),
|
|
|
+ modelLabel: formatModelLabel(model, state.activeVariant, state.providers),
|
|
|
variant: state.activeVariant,
|
|
|
}
|
|
|
},
|
|
|
@@ -335,7 +339,8 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
}
|
|
|
},
|
|
|
onVariantSelect: async (variant) => {
|
|
|
- if (!state.model || state.variants.length === 0) {
|
|
|
+ const model = state.model ?? state.defaultModel
|
|
|
+ if (!model || state.variants.length === 0) {
|
|
|
return {
|
|
|
status: "no variants available",
|
|
|
}
|
|
|
@@ -347,11 +352,12 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (!state.model) state.model = model
|
|
|
state.activeVariant = variant
|
|
|
- void input.host.preferences.saveVariant(state.model, state.activeVariant)
|
|
|
+ void input.host.preferences.saveVariant(model, state.activeVariant)
|
|
|
return {
|
|
|
status: state.activeVariant ? `variant ${state.activeVariant}` : "variant default",
|
|
|
- modelLabel: formatModelLabel(state.model, state.activeVariant, state.providers),
|
|
|
+ modelLabel: formatModelLabel(model, state.activeVariant, state.providers),
|
|
|
variant: state.activeVariant,
|
|
|
variants: state.variants,
|
|
|
}
|
|
|
@@ -602,7 +608,8 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
) {
|
|
|
if (!currentClient(attempt)) return
|
|
|
state.providers = info.providers
|
|
|
- state.variants = variantsFor(state.providers, state.model)
|
|
|
+ const model = state.model ?? state.defaultModel
|
|
|
+ state.variants = variantsFor(state.providers, model)
|
|
|
state.activeVariant = boot
|
|
|
? resolveVariant(ctx.variant, current, saved, state.variants)
|
|
|
: current && !state.variants.includes(current)
|
|
|
@@ -611,11 +618,11 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
if (footer.isClosed) return
|
|
|
footer.event({ type: "models", providers: info.providers })
|
|
|
footer.event({ type: "variants", variants: state.variants, current: state.activeVariant })
|
|
|
- if (state.model)
|
|
|
+ if (model)
|
|
|
footer.event({
|
|
|
type: "model",
|
|
|
- model: formatModelLabel(state.model, state.activeVariant, state.providers),
|
|
|
- selection: state.model,
|
|
|
+ model: formatModelLabel(model, state.activeVariant, state.providers),
|
|
|
+ selection: model,
|
|
|
})
|
|
|
}
|
|
|
|
|
|
@@ -627,6 +634,50 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
task: Promise<void>
|
|
|
}
|
|
|
| undefined
|
|
|
+ let defaultModelLoad: Promise<void> | undefined
|
|
|
+ let defaultModelQueued = false
|
|
|
+ const loadDefaultModel = (attempt: ClientAttempt) => {
|
|
|
+ if (state.model || !currentClient(attempt)) return
|
|
|
+ if (defaultModelLoad) {
|
|
|
+ defaultModelQueued = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ defaultModelQueued = false
|
|
|
+ defaultModelLoad = attempt.sdk.model
|
|
|
+ .default(
|
|
|
+ {
|
|
|
+ location: {
|
|
|
+ directory: state.location.directory,
|
|
|
+ workspace: state.location.workspaceID,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ { signal: attempt.signal },
|
|
|
+ )
|
|
|
+ .then(async (result) => {
|
|
|
+ if (!result.data || state.model || !currentClient(attempt)) return
|
|
|
+ const model = { providerID: result.data.providerID, modelID: result.data.id }
|
|
|
+ const changed =
|
|
|
+ state.defaultModel?.providerID !== model.providerID || state.defaultModel.modelID !== model.modelID
|
|
|
+ const saved = changed ? await input.host.preferences.resolveVariant(model) : undefined
|
|
|
+ if (state.model || !currentClient(attempt)) return
|
|
|
+ state.defaultModel = model
|
|
|
+ state.variants = variantsFor(state.providers, model)
|
|
|
+ if (changed)
|
|
|
+ state.activeVariant = resolveVariant(ctx.variant, state.activeVariant, saved, state.variants)
|
|
|
+ if (state.activeVariant) state.model = model
|
|
|
+ footer.event({ type: "variants", variants: state.variants, current: state.activeVariant })
|
|
|
+ footer.event({
|
|
|
+ type: "model",
|
|
|
+ model: formatModelLabel(model, state.activeVariant, state.providers),
|
|
|
+ selection: model,
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ .finally(() => {
|
|
|
+ defaultModelLoad = undefined
|
|
|
+ if (defaultModelQueued) loadDefaultModel(clientAttempt())
|
|
|
+ })
|
|
|
+ }
|
|
|
const requestCatalogRefresh = (signal?: AbortSignal): Promise<void> => {
|
|
|
const attempt = clientAttempt(signal)
|
|
|
if (!currentClient(attempt)) return Promise.resolve()
|
|
|
@@ -658,6 +709,7 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|
|
if (!currentClient(attempt)) return
|
|
|
if (catalog) applyCatalog(catalog, attempt)
|
|
|
if (info) applyModelInfo(info, state.activeVariant, attempt)
|
|
|
+ loadDefaultModel(attempt)
|
|
|
}
|
|
|
})()
|
|
|
refresh.task = task
|