fix: defer catalog validation to session execution (#38258)
This commit is contained in:
parent
691a7d93c8
commit
8bb1cfaa3b
14 changed files with 229 additions and 304 deletions
|
|
@ -85,67 +85,6 @@ export function runProviders(providers: CurrentProvider[], models: CurrentModel[
|
|||
return [...grouped.values()]
|
||||
}
|
||||
|
||||
export async function waitForDefaultModel(input: {
|
||||
sdk: OpenCodeClient
|
||||
location: LocationRef
|
||||
timeoutMs?: number
|
||||
requestTimeoutMs?: number
|
||||
active?: () => boolean
|
||||
signal?: AbortSignal
|
||||
}): Promise<{ providerID: string; modelID: string } | undefined> {
|
||||
const deadline = Date.now() + (input.timeoutMs ?? 5_000)
|
||||
while (Date.now() < deadline && !input.signal?.aborted && (input.active?.() ?? true)) {
|
||||
const controller = new AbortController()
|
||||
const timeout = setTimeout(
|
||||
() => controller.abort(),
|
||||
Math.min(input.requestTimeoutMs ?? 1_000, Math.max(1, deadline - Date.now())),
|
||||
)
|
||||
const abort = () => controller.abort()
|
||||
input.signal?.addEventListener("abort", abort, { once: true })
|
||||
const model = await abortable(
|
||||
input.sdk.model
|
||||
.default(location(input.location), { signal: controller.signal })
|
||||
.then((result) => result.data)
|
||||
.catch(() => undefined),
|
||||
controller.signal,
|
||||
).finally(() => {
|
||||
clearTimeout(timeout)
|
||||
input.signal?.removeEventListener("abort", abort)
|
||||
})
|
||||
if (model) return { providerID: model.providerID, modelID: model.id }
|
||||
await wait(25, input.signal)
|
||||
}
|
||||
}
|
||||
|
||||
function abortable<A>(task: Promise<A>, signal: AbortSignal): Promise<A | undefined> {
|
||||
if (signal.aborted) return Promise.resolve(undefined)
|
||||
return new Promise((resolve) => {
|
||||
const abort = () => {
|
||||
signal.removeEventListener("abort", abort)
|
||||
resolve(undefined)
|
||||
}
|
||||
signal.addEventListener("abort", abort, { once: true })
|
||||
void task.then((value) => {
|
||||
signal.removeEventListener("abort", abort)
|
||||
resolve(value)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function wait(delay: number, signal?: AbortSignal) {
|
||||
if (!signal) return new Promise<void>((resolve) => setTimeout(resolve, delay))
|
||||
if (signal.aborted) return Promise.resolve()
|
||||
return new Promise<void>((resolve) => {
|
||||
const timer = setTimeout(done, delay)
|
||||
signal.addEventListener("abort", done, { once: true })
|
||||
function done() {
|
||||
clearTimeout(timer)
|
||||
signal?.removeEventListener("abort", done)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function loadRunAgents(sdk: OpenCodeClient, ref: LocationRef, signal?: AbortSignal): Promise<RunAgent[]> {
|
||||
const result = await sdk.agent.list(location(ref), ...requestOptions(signal))
|
||||
return result.data.map(runAgent)
|
||||
|
|
|
|||
|
|
@ -425,7 +425,7 @@ export function RunFooterView(props: RunFooterViewProps) {
|
|||
return props.mono ? usage().replaceAll(" · ", " - ") : usage()
|
||||
})
|
||||
const modelStatus = createMemo(() => {
|
||||
const current = model()
|
||||
const current = model() ?? props.state().model.trim()
|
||||
if (!footerDetails() || !prompt() || !responsive().statusline.showModel || !current) return
|
||||
return {
|
||||
model: current,
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ function footerLabels(input: Pick<RunInput, "agent" | "model" | "variant">): Foo
|
|||
const agentLabel = Locale.titlecase(input.agent ?? "build")
|
||||
return {
|
||||
agentLabel,
|
||||
modelLabel: input.model ? formatModelLabel(input.model, input.variant) : "",
|
||||
modelLabel: input.model ? formatModelLabel(input.model, input.variant) : "Default model",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
import { SessionMessage } from "@opencode-ai/schema/session-message"
|
||||
import type { LocationRef } from "@opencode-ai/client/promise"
|
||||
import type { Config } from "../config"
|
||||
import { loadRunAgents, loadRunCommands, loadRunReferences, waitForDefaultModel } from "./catalog.shared"
|
||||
import { loadRunAgents, loadRunCommands, loadRunReferences } from "./catalog.shared"
|
||||
import {
|
||||
resolveMiniSettings,
|
||||
resolveModelInfo,
|
||||
|
|
@ -492,39 +492,20 @@ async function runInteractiveRuntime(input: RunRuntimeInput, deps: RunRuntimeDep
|
|||
const signal = AbortSignal.any([runtimeController.signal, controller.signal])
|
||||
modelAttempt = controller
|
||||
try {
|
||||
if (selected) {
|
||||
const info = await abortable(resolveModelInfo(sdk, state.location, signal), signal)
|
||||
if (
|
||||
!info ||
|
||||
!currentModelLoad(generation, sdk) ||
|
||||
state.model?.providerID !== selected.providerID ||
|
||||
state.model.modelID !== selected.modelID
|
||||
)
|
||||
return
|
||||
applyModelInfo(info, session.variant, { sdk, generation, signal }, true, savedVariant)
|
||||
const info = await abortable(resolveModelInfo(sdk, state.location, signal), signal)
|
||||
if (
|
||||
!info ||
|
||||
!currentModelLoad(generation, sdk) ||
|
||||
(selected &&
|
||||
(state.model?.providerID !== selected.providerID || state.model.modelID !== selected.modelID))
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const model = await waitForDefaultModel({
|
||||
sdk,
|
||||
location: state.location,
|
||||
active: () => currentModelLoad(generation, sdk),
|
||||
signal,
|
||||
})
|
||||
if (!currentModelLoad(generation, sdk)) return
|
||||
const [fallbackSavedVariant, info] = await Promise.all([
|
||||
input.host.preferences.resolveVariant(model),
|
||||
abortable(resolveModelInfo(sdk, state.location, signal), signal),
|
||||
])
|
||||
if (!info || !currentModelLoad(generation, sdk)) return
|
||||
if (model && !state.model) state.model = model
|
||||
const boot = !!model && state.model?.providerID === model.providerID && state.model.modelID === model.modelID
|
||||
applyModelInfo(
|
||||
info,
|
||||
boot ? session.variant : state.activeVariant,
|
||||
selected ? session.variant : state.activeVariant,
|
||||
{ sdk, generation, signal },
|
||||
boot,
|
||||
fallbackSavedVariant,
|
||||
!!selected,
|
||||
savedVariant,
|
||||
)
|
||||
} finally {
|
||||
if (modelAttempt === controller) modelAttempt = undefined
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue