fix: preserve bus instance context (#28051)

This commit is contained in:
Dax 2026-05-17 12:56:42 -04:00 committed by GitHub
parent 5060577ee1
commit 23b594de6e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 37 additions and 49 deletions

View file

@ -6,6 +6,8 @@ import { GlobalBus } from "./global"
import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service"
import { Identifier } from "@/id/id"
import type { InstanceContext } from "@/project/instance-context"
import { InstanceRef } from "@/effect/instance-ref"
const log = Log.create({ service: "bus" })
@ -185,11 +187,12 @@ export function createID() {
}
export async function publish<D extends BusEvent.Definition>(
ctx: InstanceContext,
def: D,
properties: BusProperties<D>,
options?: { id?: string },
) {
return runPromise((svc) => svc.publish(def, properties, options))
return runPromise((svc) => svc.publish(def, properties, options).pipe(Effect.provideService(InstanceRef, ctx)))
}
export function subscribe<D extends BusEvent.Definition>(def: D, callback: (event: Payload<D>) => unknown) {

View file

@ -859,6 +859,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
})
event.on("installation.update-available", async (evt) => {
console.log("installation.update-available", evt)
const version = evt.properties.version
const skipped = kv.get("skipped_version")

View file

@ -1,9 +1,9 @@
import { Bus } from "@/bus"
import { Config } from "@/config/config"
import { AppRuntime } from "@/effect/app-runtime"
import { Flag } from "@opencode-ai/core/flag/flag"
import { Installation } from "@/installation"
import { InstallationVersion } from "@opencode-ai/core/installation/version"
import { GlobalBus } from "@/bus/global"
export async function upgrade() {
const config = await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.getGlobal()))
@ -13,7 +13,13 @@ export async function upgrade() {
if (!latest) return
if (Flag.OPENCODE_ALWAYS_NOTIFY_UPDATE) {
await Bus.publish(Installation.Event.UpdateAvailable, { version: latest })
GlobalBus.emit("event", {
directory: "global",
payload: {
type: Installation.Event.UpdateAvailable.type,
properties: { version: latest },
},
})
return
}
@ -22,12 +28,26 @@ export async function upgrade() {
const kind = Installation.getReleaseType(InstallationVersion, latest)
if (config.autoupdate === "notify" || kind !== "patch") {
await Bus.publish(Installation.Event.UpdateAvailable, { version: latest })
GlobalBus.emit("event", {
directory: "global",
payload: {
type: Installation.Event.UpdateAvailable.type,
properties: { version: latest },
},
})
return
}
if (method === "unknown") return
await Installation.upgrade(method, latest)
.then(() => Bus.publish(Installation.Event.Updated, { version: latest }))
.then(() =>
GlobalBus.emit("event", {
directory: "global",
payload: {
type: Installation.Event.Updated.type,
properties: { version: latest },
},
}),
)
.catch(() => {})
}

View file

@ -1,10 +1,8 @@
export * as ConfigAgent from "./agent"
import { Exit, Schema, SchemaGetter } from "effect"
import { Bus } from "@/bus"
import { PositiveInt } from "@opencode-ai/core/schema"
import * as Log from "@opencode-ai/core/util/log"
import { NamedError } from "@opencode-ai/core/util/error"
import { Glob } from "@opencode-ai/core/util/glob"
import { configEntryNameFromPath } from "./entry-name"
import * as ConfigMarkdown from "./markdown"
@ -112,12 +110,7 @@ export async function load(dir: string) {
dot: true,
symlink: true,
})) {
const md = await ConfigMarkdown.parse(item).catch(async (err) => {
const message = ConfigMarkdown.FrontmatterError.isInstance(err)
? err.data.message
: `Failed to parse agent ${item}`
const { Session } = await import("@/session/session")
void Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
const md = await ConfigMarkdown.parse(item).catch((err) => {
log.error("failed to load agent", { agent: item, err })
return undefined
})
@ -144,12 +137,7 @@ export async function loadMode(dir: string) {
dot: true,
symlink: true,
})) {
const md = await ConfigMarkdown.parse(item).catch(async (err) => {
const message = ConfigMarkdown.FrontmatterError.isInstance(err)
? err.data.message
: `Failed to parse mode ${item}`
const { Session } = await import("@/session/session")
void Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
const md = await ConfigMarkdown.parse(item).catch((err) => {
log.error("failed to load mode", { mode: item, err })
return undefined
})

View file

@ -2,9 +2,7 @@ export * as ConfigCommand from "./command"
import * as Log from "@opencode-ai/core/util/log"
import { Cause, Exit, Schema } from "effect"
import { NamedError } from "@opencode-ai/core/util/error"
import { Glob } from "@opencode-ai/core/util/glob"
import { Bus } from "@/bus"
import { configEntryNameFromPath } from "./entry-name"
import { InvalidError } from "./error"
import * as ConfigMarkdown from "./markdown"
@ -32,12 +30,7 @@ export async function load(dir: string) {
dot: true,
symlink: true,
})) {
const md = await ConfigMarkdown.parse(item).catch(async (err) => {
const message = ConfigMarkdown.FrontmatterError.isInstance(err)
? err.data.message
: `Failed to parse command ${item}`
const { Session } = await import("@/session/session")
void Bus.publish(Session.Event.Error, { error: new NamedError.Unknown({ message }).toObject() })
const md = await ConfigMarkdown.parse(item).catch((err) => {
log.error("failed to load command", { command: item, err })
return undefined
})

View file

@ -96,11 +96,11 @@ export const layer = Layer.effect(
)
const cb: ParcelWatcher.SubscribeCallback = bridge.bind((err, evts) => {
if (err) return
// if (err) return
for (const evt of evts) {
if (evt.type === "create") void Bus.publish(Event.Updated, { file: evt.path, event: "add" })
if (evt.type === "update") void Bus.publish(Event.Updated, { file: evt.path, event: "change" })
if (evt.type === "delete") void Bus.publish(Event.Updated, { file: evt.path, event: "unlink" })
if (evt.type === "create") void Bus.publish(ctx, Event.Updated, { file: evt.path, event: "add" })
if (evt.type === "update") void Bus.publish(ctx, Event.Updated, { file: evt.path, event: "change" })
if (evt.type === "delete") void Bus.publish(ctx, Event.Updated, { file: evt.path, event: "unlink" })
}
})

View file

@ -13,11 +13,8 @@ import { InstanceState } from "@/effect/instance-state"
import { containsPath } from "@/project/instance-context"
import { NonNegativeInt } from "@opencode-ai/core/schema"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { InstanceRef } from "@/effect/instance-ref"
import { makeRuntime } from "@/effect/run-service"
const log = Log.create({ service: "lsp" })
const busRuntime = makeRuntime(Bus.Service, Bus.layer)
export const Event = {
Updated: BusEvent.define("lsp.updated", Schema.Struct({})),
@ -294,9 +291,7 @@ export const layer = Layer.effect(
if (!client) continue
result.push(client)
void busRuntime.runPromise((bus) =>
bus.publish(Event.Updated, {}).pipe(Effect.provideService(InstanceRef, ctx)),
)
await Bus.publish(ctx, Event.Updated, {})
}
return result

View file

@ -16,10 +16,8 @@ import { Effect, Layer, Context, Schema } from "effect"
import * as DateTime from "effect/DateTime"
import { InstanceState } from "@/effect/instance-state"
import { isOverflow as overflow, usable } from "./overflow"
import { makeRuntime } from "@/effect/run-service"
import { serviceUse } from "@/effect/service-use"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { EventV2 } from "@opencode-ai/core/event"
import { EventV2Bridge } from "@/event-v2-bridge"
import { SessionEvent } from "@opencode-ai/core/session-event"
@ -638,14 +636,4 @@ export const defaultLayer = Layer.suspend(() =>
),
)
const { runPromise } = makeRuntime(Service, defaultLayer)
export async function isOverflow(input: { tokens: MessageV2.Assistant["tokens"]; model: Provider.Model }) {
return runPromise((svc) => svc.isOverflow(input))
}
export async function prune(input: { sessionID: SessionID }) {
return runPromise((svc) => svc.prune(input))
}
export * as SessionCompaction from "./compaction"