Skip to content

Commit 26f64f2

Browse files
committed
refactor(cli): scope server discovery to CLI
1 parent 13822b9 commit 26f64f2

4 files changed

Lines changed: 32 additions & 34 deletions

File tree

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Effect } from "effect"
22
import { Server } from "../../server/server"
3-
import { ServerDiscovery } from "@/server/discovery"
3+
import { ServerDiscovery } from "@/cli/server-discovery"
44
import { effectCmd } from "../effect-cmd"
55
import { withNetworkOptions, resolveNetworkOptions } from "../network"
66
import { Flag } from "@opencode-ai/core/flag/flag"
@@ -17,26 +17,26 @@ export const ServeCommand = effectCmd({
1717
// Server loads instances per-request via x-opencode-directory header — no
1818
// need for an ambient project InstanceContext at startup.
1919
instance: false,
20-
handler: Effect.fn("Cli.serve")(function* (args) {
21-
if (!Flag.OPENCODE_SERVER_PASSWORD) {
22-
console.log("Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.")
23-
}
24-
const opts = yield* resolveNetworkOptions(args)
25-
const server = yield* Effect.promise(() => Server.listen(opts))
26-
if (args.discoverable) {
27-
yield* ServerDiscovery.Service.use((discovery) => discovery.write(server.url))
28-
process.on("exit", ServerDiscovery.removeSync)
29-
}
30-
console.log(`opencode server listening on http://${server.hostname}:${server.port}`)
20+
handler: (args) =>
21+
Effect.gen(function* () {
22+
if (!Flag.OPENCODE_SERVER_PASSWORD) {
23+
console.log("Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.")
24+
}
25+
const opts = yield* resolveNetworkOptions(args)
26+
const server = yield* Effect.promise(() => Server.listen(opts))
27+
const discovery = args.discoverable ? yield* ServerDiscovery.Service : undefined
28+
if (discovery) {
29+
yield* discovery.write(server.url)
30+
process.on("exit", ServerDiscovery.removeSync)
31+
}
32+
console.log(`opencode server listening on http://${server.hostname}:${server.port}`)
3133

32-
yield* Effect.never.pipe(
33-
Effect.ensuring(
34-
args.discoverable
35-
? ServerDiscovery.Service.use((discovery) => discovery.remove()).pipe(
36-
Effect.ensuring(Effect.sync(() => process.off("exit", ServerDiscovery.removeSync))),
37-
)
38-
: Effect.void,
39-
),
40-
)
41-
}),
34+
yield* Effect.never.pipe(
35+
Effect.ensuring(
36+
discovery
37+
? discovery.remove().pipe(Effect.ensuring(Effect.sync(() => process.off("exit", ServerDiscovery.removeSync))))
38+
: Effect.void,
39+
),
40+
)
41+
}).pipe(Effect.provide(ServerDiscovery.defaultLayer)),
4242
})

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { withTimeout } from "@/util/timeout"
1010
import { withNetworkOptions, resolveNetworkOptionsNoConfig } from "@/cli/network"
1111
import { Filesystem } from "@/util/filesystem"
1212
import { ServerAuth } from "@/server/auth"
13-
import { ServerDiscovery } from "@/server/discovery"
13+
import { ServerDiscovery } from "@/cli/server-discovery"
1414
import type { GlobalEvent } from "@opencode-ai/sdk/v2"
1515
import type { EventSource } from "./context/sdk"
1616
import { win32DisableProcessedInput, win32InstallCtrlCGuard } from "./win32"

packages/opencode/src/server/discovery.ts renamed to packages/opencode/src/cli/server-discovery.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
export * as ServerDiscovery from "./discovery"
1+
export * as ServerDiscovery from "./server-discovery"
22

3-
import { ServerAuth } from "@/server/auth"
43
import { makeRuntime } from "@/effect/run-service"
4+
import { ServerAuth } from "@/server/auth"
55
import { AppFileSystem } from "@opencode-ai/core/filesystem"
66
import { Global } from "@opencode-ai/core/global"
77
import { Context, Effect, Layer, Option, Schema } from "effect"
8-
import path from "path"
98
import { readFileSync, unlinkSync } from "fs"
9+
import path from "path"
1010

1111
export const file = path.join(Global.Path.state, "server.json")
1212

@@ -23,36 +23,36 @@ export interface Interface {
2323
readonly find: () => Effect.Effect<string | undefined>
2424
}
2525

26-
export class Service extends Context.Service<Service, Interface>()("@opencode/ServerDiscovery") {}
26+
export class Service extends Context.Service<Service, Interface>()("@opencode/CliServerDiscovery") {}
2727

2828
export const layer = Layer.effect(
2929
Service,
3030
Effect.gen(function* () {
3131
const fs = yield* AppFileSystem.Service
3232

33-
const read = Effect.fn("ServerDiscovery.read")(function* () {
33+
const read = Effect.fn("CliServerDiscovery.read")(function* () {
3434
const entry = yield* fs.readJson(file).pipe(Effect.catch(() => Effect.succeed(undefined)))
3535
return Option.getOrUndefined(decodeEntry(entry))
3636
})
3737

38-
const remove = Effect.fn("ServerDiscovery.remove")(function* () {
38+
const remove = Effect.fn("CliServerDiscovery.remove")(function* () {
3939
const entry = yield* read()
4040
if (entry?.pid !== process.pid) return
4141
yield* fs.remove(file).pipe(Effect.ignore)
4242
})
4343

44-
const removeStale = Effect.fn("ServerDiscovery.removeStale")(function* (entry: Entry) {
44+
const removeStale = Effect.fn("CliServerDiscovery.removeStale")(function* (entry: Entry) {
4545
const current = yield* read()
4646
if (current?.pid !== entry.pid || current.url !== entry.url) return
4747
yield* fs.remove(file).pipe(Effect.ignore)
4848
})
4949

5050
return Service.of({
51-
write: Effect.fn("ServerDiscovery.write")(function* (url) {
51+
write: Effect.fn("CliServerDiscovery.write")(function* (url) {
5252
yield* fs.writeJson(file, { url: localURL(url).toString(), pid: process.pid }, 0o600).pipe(Effect.orDie)
5353
}),
5454
remove,
55-
find: Effect.fn("ServerDiscovery.find")(function* () {
55+
find: Effect.fn("CliServerDiscovery.find")(function* () {
5656
const entry = yield* read()
5757
if (!entry) return undefined
5858
const url = yield* healthy(entry.url)

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ import { DataMigration } from "@/data-migration"
5858
import { BackgroundJob } from "@/background/job"
5959
import { EventV2Bridge } from "@/event-v2-bridge"
6060
import { RuntimeFlags } from "@/effect/runtime-flags"
61-
import { ServerDiscovery } from "@/server/discovery"
6261

6362
export const AppLayer = Layer.mergeAll(
6463
Npm.defaultLayer,
@@ -115,7 +114,6 @@ export const AppLayer = Layer.mergeAll(
115114
SyncEvent.defaultLayer,
116115
EventV2Bridge.defaultLayer,
117116
DataMigration.defaultLayer,
118-
ServerDiscovery.defaultLayer,
119117
).pipe(Layer.provideMerge(InstanceLayer.layer), Layer.provideMerge(Observability.layer))
120118

121119
const rt = ManagedRuntime.make(AppLayer, { memoMap })

0 commit comments

Comments
 (0)