Skip to content

Commit 8b4b824

Browse files
Apply PR #22753: core: move plugin intialisation to config layer override
2 parents eb6f3af + 9b85d2c commit 8b4b824

5 files changed

Lines changed: 47 additions & 10 deletions

File tree

packages/opencode/src/cli/cmd/serve.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Server } from "../../server/server"
22
import { cmd } from "./cmd"
33
import { withNetworkOptions, resolveNetworkOptions } from "../network"
4+
import { bootstrap } from "../bootstrap"
45
import { Flag } from "@opencode-ai/core/flag/flag"
56

67
export const ServeCommand = cmd({
@@ -11,7 +12,8 @@ export const ServeCommand = cmd({
1112
if (!Flag.OPENCODE_SERVER_PASSWORD) {
1213
console.log("Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.")
1314
}
14-
const opts = await resolveNetworkOptions(args)
15+
16+
const opts = await bootstrap(process.cwd(), () => resolveNetworkOptions(args))
1517
const server = await Server.listen(opts)
1618
console.log(`opencode server listening on http://${server.hostname}:${server.port}`)
1719

packages/opencode/src/cli/cmd/tui/thread.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { UI } from "@/cli/ui"
88
import * as Log from "@opencode-ai/core/util/log"
99
import { errorMessage } from "@/util/error"
1010
import { withTimeout } from "@/util/timeout"
11+
import { Instance } from "@/project/instance"
1112
import { withNetworkOptions, resolveNetworkOptionsNoConfig } from "@/cli/network"
1213
import { Filesystem } from "@/util/filesystem"
1314
import type { GlobalEvent } from "@opencode-ai/sdk/v2"
@@ -190,7 +191,11 @@ export const TuiThreadCommand = cmd({
190191
const prompt = await input(args.prompt)
191192
const config = await TuiConfig.get()
192193

193-
const network = resolveNetworkOptionsNoConfig(args)
194+
const network = await Instance.provide({
195+
directory: cwd,
196+
fn: () => resolveNetworkOptionsNoConfig(args),
197+
})
198+
194199
const external =
195200
process.argv.includes("--port") ||
196201
process.argv.includes("--hostname") ||

packages/opencode/src/cli/cmd/web.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { withNetworkOptions, resolveNetworkOptions } from "../network"
55
import { Flag } from "@opencode-ai/core/flag/flag"
66
import open from "open"
77
import { networkInterfaces } from "os"
8+
import { bootstrap } from "../bootstrap"
89

910
function getNetworkIPs() {
1011
const nets = networkInterfaces()
@@ -36,7 +37,7 @@ export const WebCommand = cmd({
3637
if (!Flag.OPENCODE_SERVER_PASSWORD) {
3738
UI.println(UI.Style.TEXT_WARNING_BOLD + "! OPENCODE_SERVER_PASSWORD is not set; server is unsecured.")
3839
}
39-
const opts = await resolveNetworkOptions(args)
40+
const opts = await bootstrap(process.cwd(), () => resolveNetworkOptions(args))
4041
const server = await Server.listen(opts)
4142
UI.empty()
4243
UI.println(UI.logo(" "))

packages/opencode/src/effect/app-runtime.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,37 @@ import { Workspace } from "@/control-plane/workspace"
4545
import { Worktree } from "@/worktree"
4646
import { Pty } from "@/pty"
4747
import { Installation } from "@/installation"
48+
import * as Effect from "effect/Effect"
4849
import { ShareNext } from "@/share/share-next"
4950
import { SessionShare } from "@/share/session"
5051
import { SyncEvent } from "@/sync"
5152
import { Npm } from "@opencode-ai/core/npm"
5253
import { memoMap } from "@opencode-ai/core/effect/memo-map"
5354

55+
// Adjusts the default Config layer to ensure that plugins are always initialised before
56+
// any other layers read the current config
57+
const ConfigWithPluginPriority = Layer.effect(
58+
Config.Service,
59+
Effect.gen(function* () {
60+
const config = yield* Config.Service
61+
const plugin = yield* Plugin.Service
62+
63+
return {
64+
...config,
65+
get: () => Effect.andThen(plugin.init(), config.get),
66+
getGlobal: () => Effect.andThen(plugin.init(), config.getGlobal),
67+
getConsoleState: () => Effect.andThen(plugin.init(), config.getConsoleState),
68+
}
69+
}),
70+
).pipe(Layer.provide(Layer.merge(Plugin.defaultLayer, Config.defaultLayer)))
71+
5472
export const AppLayer = Layer.mergeAll(
5573
Npm.defaultLayer,
5674
AppFileSystem.defaultLayer,
5775
Bus.defaultLayer,
5876
Auth.defaultLayer,
5977
Account.defaultLayer,
60-
Config.defaultLayer,
78+
ConfigWithPluginPriority,
6179
Git.defaultLayer,
6280
Ripgrep.defaultLayer,
6381
File.defaultLayer,

packages/opencode/src/project/bootstrap.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Plugin } from "../plugin"
21
import { Format } from "../format"
32
import { LSP } from "@/lsp/lsp"
43
import { File } from "../file"
@@ -7,6 +6,7 @@ import * as Project from "./project"
76
import * as Vcs from "./vcs"
87
import { Bus } from "../bus"
98
import { Command } from "../command"
9+
import { Plugin } from "../plugin"
1010
import { InstanceState } from "@/effect/instance-state"
1111
import { FileWatcher } from "@/file/watcher"
1212
import { ShareNext } from "@/share/share-next"
@@ -17,6 +17,21 @@ export interface Interface {
1717
readonly run: Effect.Effect<void>
1818
}
1919

20+
const ConfigWithPluginPriority = Layer.effect(
21+
Config.Service,
22+
Effect.gen(function* () {
23+
const config = yield* Config.Service
24+
const plugin = yield* Plugin.Service
25+
26+
return {
27+
...config,
28+
get: () => Effect.andThen(plugin.init(), config.get),
29+
getGlobal: () => Effect.andThen(plugin.init(), config.getGlobal),
30+
getConsoleState: () => Effect.andThen(plugin.init(), config.getConsoleState),
31+
}
32+
}),
33+
).pipe(Layer.provide(Layer.merge(Plugin.defaultLayer, Config.defaultLayer)))
34+
2035
export class Service extends Context.Service<Service, Interface>()("@opencode/InstanceBootstrap") {}
2136

2237
export const layer = Layer.effect(
@@ -31,7 +46,6 @@ export const layer = Layer.effect(
3146
const fileWatcher = yield* FileWatcher.Service
3247
const format = yield* Format.Service
3348
const lsp = yield* LSP.Service
34-
const plugin = yield* Plugin.Service
3549
const shareNext = yield* ShareNext.Service
3650
const snapshot = yield* Snapshot.Service
3751
const vcs = yield* Vcs.Service
@@ -41,8 +55,6 @@ export const layer = Layer.effect(
4155
yield* Effect.logInfo("bootstrapping", { directory: ctx.directory })
4256
// everything depends on config so eager load it for nice traces
4357
yield* config.get()
44-
// Plugin can mutate config so it has to be initialized before anything else.
45-
yield* plugin.init()
4658
yield* Effect.all(
4759
[lsp, shareNext, format, file, fileWatcher, vcs, snapshot].map((s) => Effect.forkDetach(s.init())),
4860
).pipe(Effect.withSpan("InstanceBootstrap.init"))
@@ -62,12 +74,11 @@ export const layer = Layer.effect(
6274
export const defaultLayer: Layer.Layer<Service> = layer.pipe(
6375
Layer.provide([
6476
Bus.layer,
65-
Config.defaultLayer,
77+
ConfigWithPluginPriority,
6678
File.defaultLayer,
6779
FileWatcher.defaultLayer,
6880
Format.defaultLayer,
6981
LSP.defaultLayer,
70-
Plugin.defaultLayer,
7182
Project.defaultLayer,
7283
ShareNext.defaultLayer,
7384
Snapshot.defaultLayer,

0 commit comments

Comments
 (0)