From 5a23bdcb69d1b737377a653b98e3131a1d1227c3 Mon Sep 17 00:00:00 2001 From: James Long Date: Tue, 30 Jun 2026 13:05:15 -0400 Subject: [PATCH] refactor(core): remove domain layer exports (#34625) --- packages/core/src/agent.ts | 2 +- packages/core/src/aisdk.ts | 2 - packages/core/src/catalog.ts | 2 +- packages/core/src/command.ts | 2 +- packages/core/src/config.ts | 2 +- packages/core/src/file-mutation.ts | 2 +- packages/core/src/image.ts | 2 +- packages/core/src/instruction-context.ts | 2 +- packages/core/src/location-mutation.ts | 2 +- packages/core/src/location.ts | 2 +- packages/core/src/permission.ts | 2 +- packages/core/src/plugin.ts | 2 +- packages/core/src/policy.ts | 2 +- packages/core/src/project/copy.ts | 2 +- packages/core/src/pty.ts | 2 +- packages/core/src/pty/ticket.ts | 3 +- packages/core/src/question.ts | 2 +- packages/core/src/reference.ts | 2 +- packages/core/src/reference/guidance.ts | 2 +- packages/core/src/skill.ts | 2 +- packages/core/src/skill/guidance.ts | 2 +- packages/core/src/snapshot.ts | 2 +- packages/core/src/system-context/builtins.ts | 8 +- packages/core/src/system-context/registry.ts | 2 +- .../opencode/src/control-plane/workspace.ts | 10 +-- .../src/effect/app-node-builder-v1.ts | 12 +++ packages/opencode/src/effect/app-runtime.ts | 8 +- .../opencode/src/effect/config-service.ts | 12 +-- packages/opencode/src/effect/runtime-flags.ts | 4 +- .../server/routes/instance/httpapi/server.ts | 28 +++---- packages/opencode/src/session/session.ts | 74 ------------------- .../test/effect/config-service.test.ts | 8 +- .../test/effect/runtime-flags.test.ts | 6 +- .../test/server/httpapi-authorization.test.ts | 6 +- .../test/server/httpapi-control-plane.test.ts | 2 +- .../test/server/httpapi-global.test.ts | 2 +- .../opencode/test/server/httpapi-ui.test.ts | 2 +- .../opencode/test/session/llm-native.test.ts | 5 +- 38 files changed, 81 insertions(+), 153 deletions(-) create mode 100644 packages/opencode/src/effect/app-node-builder-v1.ts diff --git a/packages/core/src/agent.ts b/packages/core/src/agent.ts index ebdecb5c4c..da86cf809b 100644 --- a/packages/core/src/agent.ts +++ b/packages/core/src/agent.ts @@ -42,7 +42,7 @@ export interface Interface extends State.Transformable { export class Service extends Context.Service()("@opencode/v2/Agent") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const state = State.create({ diff --git a/packages/core/src/aisdk.ts b/packages/core/src/aisdk.ts index 485faaa233..b604dac664 100644 --- a/packages/core/src/aisdk.ts +++ b/packages/core/src/aisdk.ts @@ -233,5 +233,3 @@ export const locationLayer = Layer.effect( ) export const node = makeLocationNode({ service: Service, layer: locationLayer, deps: [] }) - -export const defaultLayer = locationLayer diff --git a/packages/core/src/catalog.ts b/packages/core/src/catalog.ts index 459ceb1805..1945024b54 100644 --- a/packages/core/src/catalog.ts +++ b/packages/core/src/catalog.ts @@ -61,7 +61,7 @@ export interface Interface extends State.Transformable { export class Service extends Context.Service()("@opencode/v2/Catalog") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/src/command.ts b/packages/core/src/command.ts index e54dfe0786..cb082a9f47 100644 --- a/packages/core/src/command.ts +++ b/packages/core/src/command.ts @@ -26,7 +26,7 @@ export interface Interface extends State.Transformable { export class Service extends Context.Service()("@opencode/v2/Command") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.sync(() => { const state = State.create({ diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index f289a68e2f..c76486968b 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -132,7 +132,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/Config") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const fs = yield* FSUtil.Service diff --git a/packages/core/src/file-mutation.ts b/packages/core/src/file-mutation.ts index 91bea030ac..80a3a449f6 100644 --- a/packages/core/src/file-mutation.ts +++ b/packages/core/src/file-mutation.ts @@ -71,7 +71,7 @@ export class Service extends Context.Service()("@opencode/v2 * write under the same process-local lock so cooperating OpenCode mutations do * not overwrite changes made from the same stale content. */ -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const fs = yield* FSUtil.Service diff --git a/packages/core/src/image.ts b/packages/core/src/image.ts index d4d489e4f5..304277669e 100644 --- a/packages/core/src/image.ts +++ b/packages/core/src/image.ts @@ -44,7 +44,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/Image") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const config = yield* Config.Service diff --git a/packages/core/src/instruction-context.ts b/packages/core/src/instruction-context.ts index c87248aa24..b0cc330678 100644 --- a/packages/core/src/instruction-context.ts +++ b/packages/core/src/instruction-context.ts @@ -19,7 +19,7 @@ class File extends Schema.Class("InstructionContext.File")({ const Files = Schema.Array(File) const key = SystemContext.Key.make("core/instructions") -export const layer = Layer.effectDiscard( +const layer = Layer.effectDiscard( Effect.gen(function* () { const fs = yield* FSUtil.Service const global = yield* Global.Service diff --git a/packages/core/src/location-mutation.ts b/packages/core/src/location-mutation.ts index c832477fbf..5f410b95b1 100644 --- a/packages/core/src/location-mutation.ts +++ b/packages/core/src/location-mutation.ts @@ -76,7 +76,7 @@ interface ResolvedPath { const slash = (value: string) => value.replaceAll("\\", "/") -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const fs = yield* FSUtil.Service diff --git a/packages/core/src/location.ts b/packages/core/src/location.ts index 345e41626b..8228b8599e 100644 --- a/packages/core/src/location.ts +++ b/packages/core/src/location.ts @@ -16,7 +16,7 @@ export class Service extends Context.Service()("@opencode/Lo export const node = LayerNode.unbound(Service, tags.values.location) -export const layer = (ref: Ref) => +const layer = (ref: Ref) => Layer.effect( Service, Effect.gen(function* () { diff --git a/packages/core/src/permission.ts b/packages/core/src/permission.ts index cc9351ede6..95219e1514 100644 --- a/packages/core/src/permission.ts +++ b/packages/core/src/permission.ts @@ -106,7 +106,7 @@ interface Pending { readonly deferred: Deferred.Deferred } -export const layer = Layer.effect( +const layer = Layer.effect( Service, EffectRuntime.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/src/plugin.ts b/packages/core/src/plugin.ts index 4c0bb8d831..a89cdfda5f 100644 --- a/packages/core/src/plugin.ts +++ b/packages/core/src/plugin.ts @@ -28,7 +28,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/Plugin") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/src/policy.ts b/packages/core/src/policy.ts index 96f64701cd..a2adebb54e 100644 --- a/packages/core/src/policy.ts +++ b/packages/core/src/policy.ts @@ -22,7 +22,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/Policy") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, EffectRuntime.gen(function* () { let statements: Info[] = [] diff --git a/packages/core/src/project/copy.ts b/packages/core/src/project/copy.ts index 66a633af5b..5b2f95655a 100644 --- a/packages/core/src/project/copy.ts +++ b/packages/core/src/project/copy.ts @@ -125,7 +125,7 @@ export const refreshAfterBoot = Effect.gen(function* () { ) }) -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const fs = yield* FSUtil.Service diff --git a/packages/core/src/pty.ts b/packages/core/src/pty.ts index 828161b427..e5be4d4b64 100644 --- a/packages/core/src/pty.ts +++ b/packages/core/src/pty.ts @@ -89,7 +89,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/Pty") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/src/pty/ticket.ts b/packages/core/src/pty/ticket.ts index 53da8f5ec5..07838b1415 100644 --- a/packages/core/src/pty/ticket.ts +++ b/packages/core/src/pty/ticket.ts @@ -51,7 +51,6 @@ export const make = (ttl: Duration.Input = DEFAULT_TTL) => }) }) -export const layer = Layer.effect(Service, make()) +const layer = Layer.effect(Service, make()) -export const defaultLayer = layer export const node = makeGlobalNode({ service: Service, layer: layer, deps: [] }) diff --git a/packages/core/src/question.ts b/packages/core/src/question.ts index 9140ee3d23..79e0ea5e03 100644 --- a/packages/core/src/question.ts +++ b/packages/core/src/question.ts @@ -72,7 +72,7 @@ interface Pending { * layer once per embedded Location so replies cannot settle another Location's * deferred request. */ -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/src/reference.ts b/packages/core/src/reference.ts index 0d1dbab57e..5303dbd955 100644 --- a/packages/core/src/reference.ts +++ b/packages/core/src/reference.ts @@ -40,7 +40,7 @@ export interface Interface extends State.Transformable { export class Service extends Context.Service()("@opencode/v2/Reference") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const global = yield* Global.Service diff --git a/packages/core/src/reference/guidance.ts b/packages/core/src/reference/guidance.ts index b98e50ef39..25566e2f2f 100644 --- a/packages/core/src/reference/guidance.ts +++ b/packages/core/src/reference/guidance.ts @@ -31,7 +31,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/ReferenceGuidance") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const references = yield* Reference.Service diff --git a/packages/core/src/skill.ts b/packages/core/src/skill.ts index 86253208cc..be1cd1d49a 100644 --- a/packages/core/src/skill.ts +++ b/packages/core/src/skill.ts @@ -53,7 +53,7 @@ export interface Interface extends State.Transformable { export class Service extends Context.Service()("@opencode/v2/Skill") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const discovery = yield* SkillDiscovery.Service diff --git a/packages/core/src/skill/guidance.ts b/packages/core/src/skill/guidance.ts index 4f4be39e39..347179dbfb 100644 --- a/packages/core/src/skill/guidance.ts +++ b/packages/core/src/skill/guidance.ts @@ -37,7 +37,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/SkillGuidance") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const skills = yield* SkillV2.Service diff --git a/packages/core/src/snapshot.ts b/packages/core/src/snapshot.ts index 34f55ee347..de5962b483 100644 --- a/packages/core/src/snapshot.ts +++ b/packages/core/src/snapshot.ts @@ -83,7 +83,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/Snapshot") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const config = yield* Config.Service diff --git a/packages/core/src/system-context/builtins.ts b/packages/core/src/system-context/builtins.ts index 60629ba981..b8b50577cc 100644 --- a/packages/core/src/system-context/builtins.ts +++ b/packages/core/src/system-context/builtins.ts @@ -43,14 +43,8 @@ const builtIns = Layer.effectDiscard( }), ) -export const layer = Layer.mergeAll(builtIns, InstructionContext.layer).pipe( - Layer.provideMerge(SystemContextRegistry.layer), -) - -export const locationLayer = layer - export const node = makeLocationNode({ name: "system-context-builtins", - layer, + layer: builtIns, deps: [Location.node, SystemContextRegistry.node, InstructionContext.node, FSUtil.node, Global.node], }) diff --git a/packages/core/src/system-context/registry.ts b/packages/core/src/system-context/registry.ts index d464f98fc2..c1e7ca5e85 100644 --- a/packages/core/src/system-context/registry.ts +++ b/packages/core/src/system-context/registry.ts @@ -16,7 +16,7 @@ export interface Interface { export class Service extends Context.Service()("@opencode/v2/SystemContextRegistry") {} -export const layer = Layer.effect( +const layer = Layer.effect( Service, Effect.gen(function* () { const entries = yield* Ref.make>([]) diff --git a/packages/opencode/src/control-plane/workspace.ts b/packages/opencode/src/control-plane/workspace.ts index a11af085f1..236d2d40ab 100644 --- a/packages/opencode/src/control-plane/workspace.ts +++ b/packages/opencode/src/control-plane/workspace.ts @@ -31,8 +31,8 @@ import { waitEvent } from "./util" import { WorkspaceRef } from "@/effect/instance-ref" import { Vcs } from "@/project/vcs" import { InstanceStore } from "@/project/instance-store" -import { InstanceBootstrap } from "@/project/bootstrap" import { WorkspaceAdapterRuntime } from "./workspace-adapter-runtime" +import { AppNodeBuilderV1 } from "@/effect/app-node-builder-v1" import { WorkspaceEvent } from "@opencode-ai/schema/workspace-event" export const Info = Schema.Struct({ @@ -602,9 +602,7 @@ const layer = Layer.effect( fallback: "", response: "text", }).pipe( - Effect.provide( - LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]]), - ), + Effect.provide(AppNodeBuilderV1.build(InstanceStore.node)), ) : "" @@ -622,9 +620,7 @@ const layer = Layer.effect( }), fallback: { applied: false }, }).pipe( - Effect.provide( - LayerNode.compile(InstanceStore.node, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]]), - ), + Effect.provide(AppNodeBuilderV1.build(InstanceStore.node)), ) } diff --git a/packages/opencode/src/effect/app-node-builder-v1.ts b/packages/opencode/src/effect/app-node-builder-v1.ts new file mode 100644 index 0000000000..7573475d9a --- /dev/null +++ b/packages/opencode/src/effect/app-node-builder-v1.ts @@ -0,0 +1,12 @@ +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { LayerNode } from "@opencode-ai/core/effect/layer-node" +import { InstanceBootstrap } from "@/project/bootstrap" +import { InstanceStore } from "@/project/instance-store" + +const bootstrapReplacement = [InstanceStore.bootstrapNode, InstanceBootstrap.node] as const + +export function build(root: LayerNode.Node, replacements: LayerNode.Replacements = []) { + return AppNodeBuilder.build(root, replacements.concat([bootstrapReplacement])) +} + +export * as AppNodeBuilderV1 from "./app-node-builder-v1" diff --git a/packages/opencode/src/effect/app-runtime.ts b/packages/opencode/src/effect/app-runtime.ts index 437e6a3493..d17326966f 100644 --- a/packages/opencode/src/effect/app-runtime.ts +++ b/packages/opencode/src/effect/app-runtime.ts @@ -38,7 +38,6 @@ import { Command } from "@/command" import { Truncate } from "@/tool/truncate" import { ToolRegistry } from "@/tool/registry" import { Format } from "@/format" -import { InstanceBootstrap } from "@/project/bootstrap" import { InstanceStore } from "@/project/instance-store" import { Project } from "@/project/project" import { Vcs } from "@/project/vcs" @@ -53,10 +52,10 @@ import { BackgroundJob } from "@/background/job" import { RuntimeFlags } from "@/effect/runtime-flags" import { EventV2Bridge } from "@/event-v2-bridge" import { LayerNode } from "@opencode-ai/core/effect/layer-node" -import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { AppNodeBuilderV1 } from "./app-node-builder-v1" import { SessionProjector } from "@opencode-ai/core/session/projector" -export const AppLayer = AppNodeBuilder.build( +export const AppLayer = AppNodeBuilderV1.build( LayerNode.group([ Npm.node, FSUtil.node, @@ -107,8 +106,7 @@ export const AppLayer = AppNodeBuilder.build( ShareNext.node, SessionShare.node, ]), - [[InstanceStore.bootstrapNode, InstanceBootstrap.node]], -).pipe(Layer.provideMerge(AppNodeBuilder.build(Ripgrep.node)), Layer.provideMerge(Observability.layer)) +).pipe(Layer.provideMerge(AppNodeBuilderV1.build(Ripgrep.node)), Layer.provideMerge(Observability.layer)) const rt = ManagedRuntime.make(AppLayer, { memoMap }) type Runtime = Pick diff --git a/packages/opencode/src/effect/config-service.ts b/packages/opencode/src/effect/config-service.ts index 3c13afc12a..516c040f57 100644 --- a/packages/opencode/src/effect/config-service.ts +++ b/packages/opencode/src/effect/config-service.ts @@ -14,9 +14,9 @@ export type Shape = { */ export type ServiceClass = Context.ServiceClass & { /** Provide already-parsed config, useful in tests. */ - readonly layer: (input: Service) => Layer.Layer + readonly configLayer: (input: Service) => Layer.Layer /** Parse config once from the active Effect ConfigProvider and provide the service. */ - readonly defaultLayer: Layer.Layer + readonly layer: Layer.Layer } /** @@ -35,19 +35,19 @@ export type ServiceClass = Context.ServiceClas * }, * ) {} * - * const live = ServerAuthConfig.defaultLayer - * const test = ServerAuthConfig.layer({ password: Option.some("secret"), username: "kit" }) + * const live = ServerAuthConfig.layer + * const test = ServerAuthConfig.configLayer({ password: Option.some("secret"), username: "kit" }) * ``` */ export const Service = () => (id: Id, fields: Fields) => { class ConfigTag extends Context.Service>()(id) { - static layer(input: Shape) { + static configLayer(input: Shape) { return Layer.succeed(this, this.of(input)) } - static get defaultLayer() { + static get layer() { const tag = this return Layer.effect( tag, diff --git a/packages/opencode/src/effect/runtime-flags.ts b/packages/opencode/src/effect/runtime-flags.ts index f2e5e53192..4baf867db6 100644 --- a/packages/opencode/src/effect/runtime-flags.ts +++ b/packages/opencode/src/effect/runtime-flags.ts @@ -57,7 +57,7 @@ export class Service extends ConfigService.Service()("@opencode/Runtime export type Info = Context.Service.Shape -const emptyConfigLayer = Service.defaultLayer.pipe( +const emptyConfigLayer = Service.layer.pipe( Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown({}))), Layer.orDie, ) @@ -71,7 +71,7 @@ export const layer = (overrides: Partial = {}) => }), ).pipe(Layer.provide(emptyConfigLayer)) -export const node = LayerNode.make({ service: Service, layer: Service.defaultLayer.pipe(Layer.orDie), deps: [] }) +export const node = LayerNode.make({ service: Service, layer: Service.layer.pipe(Layer.orDie), deps: [] }) export * as RuntimeFlags from "./runtime-flags" import { LayerNode } from "@opencode-ai/core/effect/layer-node" diff --git a/packages/opencode/src/server/routes/instance/httpapi/server.ts b/packages/opencode/src/server/routes/instance/httpapi/server.ts index 127a159304..61e8df7d11 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/server.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/server.ts @@ -22,7 +22,6 @@ import { McpAuth } from "@/mcp/auth" import { Permission } from "@/permission" import { Plugin } from "@/plugin" import { PluginPtyEnvironment } from "@/plugin/pty-environment" -import { InstanceBootstrap } from "@/project/bootstrap" import { InstanceStore } from "@/project/instance-store" import { Project } from "@/project/project" import { Vcs } from "@/project/vcs" @@ -52,7 +51,7 @@ import { Worktree } from "@/worktree" import { RuntimeFlags } from "@/effect/runtime-flags" import { MoveSession } from "@opencode-ai/core/control-plane/move-session" import { Database } from "@opencode-ai/core/database/database" -import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { AppNodeBuilderV1 } from "@/effect/app-node-builder-v1" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { httpClient } from "@opencode-ai/core/effect/app-node-platform" import { EventV2 } from "@opencode-ai/core/event" @@ -101,7 +100,7 @@ import { sessionHandlers } from "./handlers/session" import { syncHandlers } from "./handlers/sync" import { tuiHandlers } from "./handlers/tui" import { handlers } from "@opencode-ai/server/handlers" -import { locationServiceMapLayer } from "@opencode-ai/core/location-services" +import { buildLocationServiceMap, LocationServiceMap } from "@opencode-ai/core/location-services" import { layer as locationLayer } from "@opencode-ai/server/location" import { sessionLocationLayer } from "@opencode-ai/server/middleware/session-location" import { PtyEnvironment } from "@opencode-ai/server/pty-environment" @@ -134,10 +133,10 @@ const cors = (corsOptions?: CorsOptions) => // - ptyConnectApiRoutes: typed WebSocket upgrade route with ticket-aware auth. // - instanceApiRoutes: remaining typed instance routes. // - uiRoute: raw catch-all fallback; auth is router middleware so public static assets can bypass it. -const authOnlyRouterLayer = authorizationRouterMiddleware.layer.pipe(Layer.provide(ServerAuth.Config.defaultLayer)) -const httpApiAuthLayer = authorizationLayer.pipe(Layer.provide(ServerAuth.Config.defaultLayer)) -const ptyConnectHttpApiAuthLayer = ptyConnectAuthorizationLayer.pipe(Layer.provide(ServerAuth.Config.defaultLayer)) -const serverHttpApiAuthLayer = serverAuthorizationLayer.pipe(Layer.provide(ServerAuth.Config.defaultLayer)) +const authOnlyRouterLayer = authorizationRouterMiddleware.layer.pipe(Layer.provide(ServerAuth.Config.layer)) +const httpApiAuthLayer = authorizationLayer.pipe(Layer.provide(ServerAuth.Config.layer)) +const ptyConnectHttpApiAuthLayer = ptyConnectAuthorizationLayer.pipe(Layer.provide(ServerAuth.Config.layer)) +const serverHttpApiAuthLayer = serverAuthorizationLayer.pipe(Layer.provide(ServerAuth.Config.layer)) const workspaceRoutingLive = workspaceRoutingLayer.pipe(Layer.provide(Socket.layerWebSocketConstructorGlobal)) const rootApiRoutes = HttpApiBuilder.layer(RootHttpApi).pipe( Layer.provide([controlHandlers, controlPlaneHandlers, globalHandlers]), @@ -272,6 +271,8 @@ const app = LayerNode.group([ export function createRoutes( corsOptions?: CorsOptions, ): Layer.Layer { + const locationServiceMapV2 = buildLocationServiceMap() + return Layer.mergeAll( rootApiRoutes, eventApiRoutes, @@ -287,7 +288,7 @@ export function createRoutes( corsVaryFix, fenceLayer, cors(corsOptions), - AppNodeBuilder.build(MoveSession.node), + AppNodeBuilderV1.build(MoveSession.node, [[LocationServiceMap.node, locationServiceMapV2]]), HttpServer.layerServices, ]), Layer.provide(Layer.succeed(CorsConfig)(corsOptions)), @@ -297,13 +298,14 @@ export function createRoutes( Layer.provide(locationLayer), Layer.provide(PtyEnvironment.layer), Layer.provide( - AppNodeBuilder.build(SessionV2.node, [[SessionExecution.node, SessionExecutionLocal.node]]).pipe( - Layer.provide(locationServiceMapLayer), - ), + AppNodeBuilderV1.build(SessionV2.node, [ + [LocationServiceMap.node, locationServiceMapV2], + [SessionExecution.node, SessionExecutionLocal.node], + ]), ), - Layer.provide(locationServiceMapLayer), + Layer.provide(locationServiceMapV2), - Layer.provide(LayerNode.compile(app, [[InstanceStore.bootstrapNode, InstanceBootstrap.node]])), + Layer.provide(AppNodeBuilderV1.build(app)), ) } diff --git a/packages/opencode/src/session/session.ts b/packages/opencode/src/session/session.ts index ede9b77f0b..de8c3dc4cb 100644 --- a/packages/opencode/src/session/session.ts +++ b/packages/opencode/src/session/session.ts @@ -1,5 +1,4 @@ import { LayerNode } from "@opencode-ai/core/effect/layer-node" -import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { PermissionV1 } from "@opencode-ai/core/v1/permission" import { Slug } from "@opencode-ai/core/util/slug" import { SessionV1 } from "@opencode-ai/core/v1/session" @@ -10,7 +9,6 @@ import { Decimal } from "decimal.js" import type { ProviderMetadata, Usage } from "@opencode-ai/llm" import { InstallationVersion } from "@opencode-ai/core/installation/version" import { Database } from "@opencode-ai/core/database/database" -import { makeRuntime } from "@opencode-ai/core/effect/runtime" import { EventV2Bridge } from "@/event-v2-bridge" import { SessionV2 } from "@opencode-ai/core/session" import * as SessionExecutionLocal from "@opencode-ai/core/session/execution/local" @@ -47,8 +45,6 @@ import { ProviderV2 } from "@opencode-ai/core/provider" import { ModelV2 } from "@opencode-ai/core/model" import { SessionMessage } from "@opencode-ai/schema/session-message" -const runtime = makeRuntime(Database.Service, AppNodeBuilder.build(Database.node)) - const parentTitlePrefix = "New session - " const childTitlePrefix = "Child session - " @@ -1013,76 +1009,6 @@ function listByProject( ) } -export function* listGlobal(input?: { - directory?: string - roots?: boolean - start?: number - cursor?: number - search?: string - limit?: number - archived?: boolean -}) { - const conditions: SQL[] = [] - - if (input?.directory) { - conditions.push(eq(SessionTable.directory, input.directory)) - } - if (input?.roots) { - conditions.push(isNull(SessionTable.parent_id)) - } - if (input?.start) { - conditions.push(gte(SessionTable.time_updated, input.start)) - } - if (input?.cursor) { - conditions.push(lt(SessionTable.time_updated, input.cursor)) - } - if (input?.search) { - conditions.push(like(SessionTable.title, `%${input.search}%`)) - } - if (!input?.archived) { - conditions.push(isNull(SessionTable.time_archived)) - } - - const limit = input?.limit ?? 100 - - const rows = runtime.runSync(({ db }) => { - const query = - conditions.length > 0 - ? db - .select() - .from(SessionTable) - .where(and(...conditions)) - : db.select().from(SessionTable) - return query.orderBy(desc(SessionTable.time_updated), desc(SessionTable.id)).limit(limit).all().pipe(Effect.orDie) - }) - - const ids = [...new Set(rows.map((row) => row.project_id))] - const projects = new Map() - - if (ids.length > 0) { - const items = runtime.runSync(({ db }) => - db - .select({ id: ProjectTable.id, name: ProjectTable.name, worktree: ProjectTable.worktree }) - .from(ProjectTable) - .where(inArray(ProjectTable.id, ids)) - .all() - .pipe(Effect.orDie), - ) - for (const item of items) { - projects.set(item.id, { - id: item.id, - name: item.name ?? undefined, - worktree: item.worktree, - }) - } - } - - for (const row of rows) { - const project = projects.get(row.project_id) ?? null - yield { ...fromRow(row), project } - } -} - export const node = LayerNode.make({ service: Service, layer: layer, diff --git a/packages/opencode/test/effect/config-service.test.ts b/packages/opencode/test/effect/config-service.test.ts index be6f977363..0a1fc605ea 100644 --- a/packages/opencode/test/effect/config-service.test.ts +++ b/packages/opencode/test/effect/config-service.test.ts @@ -10,12 +10,12 @@ class TestConfig extends ConfigService.Service()("@test/ConfigServic }) {} const fromConfig = (input: Record) => - TestConfig.defaultLayer.pipe(Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown(input)))) + TestConfig.layer.pipe(Layer.provide(ConfigProvider.layer(ConfigProvider.fromUnknown(input)))) const readConfig = TestConfig.useSync((config) => config) describe("ConfigService", () => { - it.effect("defaultLayer parses values from the active ConfigProvider", () => + it.effect("layer parses values from the active ConfigProvider", () => Effect.gen(function* () { const config = yield* readConfig.pipe( Effect.provide( @@ -33,7 +33,7 @@ describe("ConfigService", () => { }), ) - it.effect("defaultLayer applies Effect Config defaults", () => + it.effect("layer applies Effect Config defaults", () => Effect.gen(function* () { const config = yield* readConfig.pipe(Effect.provide(fromConfig({ NAME: "kit" }))) @@ -47,7 +47,7 @@ describe("ConfigService", () => { Effect.gen(function* () { const config = yield* readConfig.pipe( Effect.provide( - TestConfig.layer({ + TestConfig.configLayer({ name: "direct", token: Option.some("parsed"), port: 9000, diff --git a/packages/opencode/test/effect/runtime-flags.test.ts b/packages/opencode/test/effect/runtime-flags.test.ts index 19b249182b..ca5ca1d7b0 100644 --- a/packages/opencode/test/effect/runtime-flags.test.ts +++ b/packages/opencode/test/effect/runtime-flags.test.ts @@ -10,7 +10,7 @@ const fromConfig = (input: Record) => const readFlags = RuntimeFlags.Service.useSync((flags) => flags) describe("RuntimeFlags", () => { - it.effect("defaultLayer defaults autoShare to false", () => + it.effect("layer defaults autoShare to false", () => Effect.gen(function* () { const flags = yield* readFlags.pipe(Effect.provide(fromConfig({}))) @@ -18,7 +18,7 @@ describe("RuntimeFlags", () => { }), ) - it.effect("defaultLayer parses plugin flags from the active ConfigProvider", () => + it.effect("layer parses plugin flags from the active ConfigProvider", () => Effect.gen(function* () { const flags = yield* readFlags.pipe( Effect.provide( @@ -65,7 +65,7 @@ describe("RuntimeFlags", () => { }), ) - it.effect("defaultLayer parses OPENCODE_EXPERIMENTAL_LSP_TY", () => + it.effect("layer parses OPENCODE_EXPERIMENTAL_LSP_TY", () => Effect.gen(function* () { const flags = yield* readFlags.pipe( Effect.provide( diff --git a/packages/opencode/test/server/httpapi-authorization.test.ts b/packages/opencode/test/server/httpapi-authorization.test.ts index 2fb6c4ac1b..211b2e1884 100644 --- a/packages/opencode/test/server/httpapi-authorization.test.ts +++ b/packages/opencode/test/server/httpapi-authorization.test.ts @@ -56,9 +56,9 @@ const v2ApiLayer = HttpRouter.serve( { disableListenLog: true, disableLogger: true }, ).pipe(Layer.provideMerge(NodeHttpServer.layerTest)) -const noAuthLayer = ServerAuth.Config.layer({ password: Option.none(), username: "opencode" }) -const secretLayer = ServerAuth.Config.layer({ password: Option.some("secret"), username: "opencode" }) -const kitSecretLayer = ServerAuth.Config.layer({ password: Option.some("secret"), username: "kit" }) +const noAuthLayer = ServerAuth.Config.configLayer({ password: Option.none(), username: "opencode" }) +const secretLayer = ServerAuth.Config.configLayer({ password: Option.some("secret"), username: "opencode" }) +const kitSecretLayer = ServerAuth.Config.configLayer({ password: Option.some("secret"), username: "kit" }) const it = testEffect(apiLayer.pipe(Layer.provide(noAuthLayer))) const itSecret = testEffect(apiLayer.pipe(Layer.provide(secretLayer))) diff --git a/packages/opencode/test/server/httpapi-control-plane.test.ts b/packages/opencode/test/server/httpapi-control-plane.test.ts index 2ddbe532cb..b837bf7556 100644 --- a/packages/opencode/test/server/httpapi-control-plane.test.ts +++ b/packages/opencode/test/server/httpapi-control-plane.test.ts @@ -44,7 +44,7 @@ const apiLayer = HttpRouter.serve( moveSession: (value) => Ref.set(called, value), }), ), - Layer.provide(ServerAuth.Config.layer({ password: Option.none(), username: "opencode" })), + Layer.provide(ServerAuth.Config.configLayer({ password: Option.none(), username: "opencode" })), ) const it = testEffect(apiLayer) diff --git a/packages/opencode/test/server/httpapi-global.test.ts b/packages/opencode/test/server/httpapi-global.test.ts index 91c5b48314..bcbe7aecbb 100644 --- a/packages/opencode/test/server/httpapi-global.test.ts +++ b/packages/opencode/test/server/httpapi-global.test.ts @@ -38,7 +38,7 @@ const apiLayer = HttpRouter.serve( upgrade: () => Effect.void, }), ), - Layer.provide(ServerAuth.Config.layer({ password: Option.none(), username: "opencode" })), + Layer.provide(ServerAuth.Config.configLayer({ password: Option.none(), username: "opencode" })), ) const it = testEffect(apiLayer) diff --git a/packages/opencode/test/server/httpapi-ui.test.ts b/packages/opencode/test/server/httpapi-ui.test.ts index e90220817d..2f10193f3d 100644 --- a/packages/opencode/test/server/httpapi-ui.test.ts +++ b/packages/opencode/test/server/httpapi-ui.test.ts @@ -44,7 +44,7 @@ const fsUtilLayer = AppNodeBuilder.build(FSUtil.node) const it = testEffect(Layer.mergeAll(testStateLayer, fsUtilLayer, RuntimeFlags.layer())) function authConfigLayer(input?: { password?: string; username?: string }) { - return ServerAuth.Config.layer({ + return ServerAuth.Config.configLayer({ password: input?.password === undefined ? Option.none() : Option.some(input.password), username: input?.username ?? "opencode", }) diff --git a/packages/opencode/test/session/llm-native.test.ts b/packages/opencode/test/session/llm-native.test.ts index 2bb15567af..4d1cb8eeee 100644 --- a/packages/opencode/test/session/llm-native.test.ts +++ b/packages/opencode/test/session/llm-native.test.ts @@ -3,6 +3,7 @@ import { LLMEvent, ToolFailure } from "@opencode-ai/llm" import { LLMClient, RequestExecutor, WebSocketExecutor, type LLMClientShape } from "@opencode-ai/llm/route" import { jsonSchema, tool, type ModelMessage, type Tool } from "ai" import { Effect, Fiber, Layer, Stream } from "effect" +import { FetchHttpClient } from "effect/unstable/http" import { LLMNative } from "@/session/llm/native-request" import { LLMNativeRuntime } from "@/session/llm/native-runtime" import type { Provider } from "@/provider/provider" @@ -73,7 +74,9 @@ const providerInfo: Provider.Info = { } const it = testEffect( - LLMClient.layer.pipe(Layer.provide(Layer.mergeAll(RequestExecutor.defaultLayer, WebSocketExecutor.layer))), + LLMClient.layer.pipe( + Layer.provide(Layer.mergeAll(RequestExecutor.layer.pipe(Layer.provide(FetchHttpClient.layer)), WebSocketExecutor.layer)), + ), ) function responsesStream(chunks: unknown[]) {