mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-14 00:10:03 +00:00
remove repeated memoized-task boilerplate
This commit is contained in:
parent
737b2c4156
commit
c7532b20d7
3 changed files with 30 additions and 53 deletions
|
|
@ -6,6 +6,7 @@
|
|||
// history ring. All are async because they read config or hit the SDK, but
|
||||
// none block each other.
|
||||
import { TuiConfig } from "../tui/config/tui"
|
||||
import { reusePendingTask } from "./runtime.shared"
|
||||
import { resolveSession, sessionHistory } from "./session.shared"
|
||||
import type { FooterKeybinds, RunDiffStyle, RunInput, RunPrompt } from "./types"
|
||||
import { pickVariant } from "./variant.shared"
|
||||
|
|
@ -20,28 +21,10 @@ const DEFAULT_KEYBINDS: FooterKeybinds = {
|
|||
inputNewline: "shift+return,ctrl+return,alt+return,ctrl+j",
|
||||
}
|
||||
|
||||
let configTask: Promise<Awaited<ReturnType<typeof TuiConfig.get>>> | undefined
|
||||
const configTask: { current?: ReturnType<typeof TuiConfig.get> } = {}
|
||||
|
||||
function loadConfig() {
|
||||
if (configTask) {
|
||||
return configTask
|
||||
}
|
||||
|
||||
const task = TuiConfig.get()
|
||||
configTask = task
|
||||
task.then(
|
||||
() => {
|
||||
if (configTask === task) {
|
||||
configTask = undefined
|
||||
}
|
||||
},
|
||||
() => {
|
||||
if (configTask === task) {
|
||||
configTask = undefined
|
||||
}
|
||||
},
|
||||
)
|
||||
return task
|
||||
return reusePendingTask(configTask, () => TuiConfig.get())
|
||||
}
|
||||
|
||||
export type ModelInfo = {
|
||||
|
|
|
|||
17
packages/opencode/src/cli/cmd/run/runtime.shared.ts
Normal file
17
packages/opencode/src/cli/cmd/run/runtime.shared.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
type PendingTask<T> = {
|
||||
current?: Promise<T>
|
||||
}
|
||||
|
||||
export function reusePendingTask<T>(slot: PendingTask<T>, run: () => Promise<T>) {
|
||||
if (slot.current) {
|
||||
return slot.current
|
||||
}
|
||||
|
||||
const task = run().finally(() => {
|
||||
if (slot.current === task) {
|
||||
slot.current = undefined
|
||||
}
|
||||
})
|
||||
slot.current = task
|
||||
return task
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import { Flag } from "@/flag/flag"
|
|||
import { createRunDemo } from "./demo"
|
||||
import { resolveDiffStyle, resolveFooterKeybinds, resolveModelInfo, resolveSessionInfo } from "./runtime.boot"
|
||||
import { createRuntimeLifecycle } from "./runtime.lifecycle"
|
||||
import { reusePendingTask } from "./runtime.shared"
|
||||
import { trace } from "./trace"
|
||||
import { cycleVariant, formatModelLabel, resolveSavedVariant, resolveVariant, saveVariant } from "./variant.shared"
|
||||
import type { RunInput } from "./types"
|
||||
|
|
@ -61,6 +62,11 @@ type RunLocalInput = {
|
|||
demoText?: RunInput["demoText"]
|
||||
}
|
||||
|
||||
type StreamState = {
|
||||
mod: Awaited<typeof import("./stream.transport")>
|
||||
handle: Awaited<ReturnType<Awaited<typeof import("./stream.transport")>["createSessionTransport"]>>
|
||||
}
|
||||
|
||||
// Core runtime loop. Boot resolves the SDK context, then we set up the
|
||||
// lifecycle (renderer + footer), wire the stream transport for SDK events,
|
||||
// and feed prompts through the queue until the user exits.
|
||||
|
|
@ -291,28 +297,14 @@ async function runInteractiveRuntime(input: RunRuntimeInput): Promise<void> {
|
|||
})
|
||||
|
||||
const streamTask = import("./stream.transport")
|
||||
let stream:
|
||||
| {
|
||||
mod: Awaited<typeof import("./stream.transport")>
|
||||
handle: Awaited<ReturnType<Awaited<typeof import("./stream.transport")>["createSessionTransport"]>>
|
||||
}
|
||||
| undefined
|
||||
let loading:
|
||||
| Promise<{
|
||||
mod: Awaited<typeof import("./stream.transport")>
|
||||
handle: Awaited<ReturnType<Awaited<typeof import("./stream.transport")>["createSessionTransport"]>>
|
||||
}>
|
||||
| undefined
|
||||
let stream: StreamState | undefined
|
||||
const loading: { current?: Promise<StreamState> } = {}
|
||||
const ensureStream = () => {
|
||||
if (stream) {
|
||||
return Promise.resolve(stream)
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return loading
|
||||
}
|
||||
|
||||
const task = (async () => {
|
||||
return reusePendingTask(loading, async () => {
|
||||
await ensureSession()
|
||||
if (footer.isClosed) {
|
||||
throw new Error("runtime closed")
|
||||
|
|
@ -340,22 +332,7 @@ async function runInteractiveRuntime(input: RunRuntimeInput): Promise<void> {
|
|||
const next = { mod, handle }
|
||||
stream = next
|
||||
return next
|
||||
})()
|
||||
|
||||
loading = task
|
||||
task.then(
|
||||
() => {
|
||||
if (loading === task) {
|
||||
loading = undefined
|
||||
}
|
||||
},
|
||||
() => {
|
||||
if (loading === task) {
|
||||
loading = undefined
|
||||
}
|
||||
},
|
||||
)
|
||||
return task
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue