mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-21 10:16:03 +00:00
refactor(server): inject runtime options
This commit is contained in:
@@ -61,7 +61,12 @@ Effect.logInfo("cli starting", {
|
||||
Effect.provide(Config.layer),
|
||||
Effect.provide(Updater.layer),
|
||||
Effect.provide(LayerNode.compile(LayerNode.group([Global.node, AppProcess.node, Npm.node]))),
|
||||
Effect.provide(Observability.layer),
|
||||
Effect.provide(
|
||||
Observability.layer({
|
||||
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
||||
headers: process.env.OTEL_EXPORTER_OTLP_HEADERS,
|
||||
}),
|
||||
),
|
||||
Effect.provide(NodeServices.layer),
|
||||
Effect.scoped,
|
||||
Effect.tap(() => Effect.sync(() => process.exit(process.exitCode ?? 0))),
|
||||
|
||||
@@ -71,7 +71,20 @@ const processEffect = Effect.fnUntraced(function* (options: Options) {
|
||||
models: {
|
||||
url: process.env.OPENCODE_MODELS_URL,
|
||||
file: process.env.OPENCODE_MODELS_PATH,
|
||||
fetch: !["1", "true"].includes(process.env.OPENCODE_DISABLE_MODELS_FETCH?.toLowerCase() ?? ""),
|
||||
fetch: !truthy(process.env.OPENCODE_DISABLE_MODELS_FETCH),
|
||||
},
|
||||
observability: {
|
||||
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
||||
headers: process.env.OTEL_EXPORTER_OTLP_HEADERS,
|
||||
},
|
||||
fs: {
|
||||
filewatcher: !truthy(
|
||||
process.env.OPENCODE_FILEWATCHER_DISABLE ?? process.env.OPENCODE_DISABLE_FILEWATCHER,
|
||||
),
|
||||
fff:
|
||||
process.env.OPENCODE_DISABLE_FFF === undefined
|
||||
? process.platform !== "win32"
|
||||
: !truthy(process.env.OPENCODE_DISABLE_FFF),
|
||||
},
|
||||
},
|
||||
serviceOptions === undefined
|
||||
@@ -177,6 +190,10 @@ function serviceURL(hostname: string, port: number) {
|
||||
return `http://${hostname.includes(":") ? `[${hostname}]` : hostname}:${port}`
|
||||
}
|
||||
|
||||
function truthy(value?: string) {
|
||||
return value === "1" || value?.toLowerCase() === "true"
|
||||
}
|
||||
|
||||
function addressInUse(error: unknown): boolean {
|
||||
if (typeof error !== "object" || error === null) return false
|
||||
if ("code" in error && error.code === "EADDRINUSE") return true
|
||||
|
||||
@@ -2,7 +2,7 @@ export * as Database from "./database"
|
||||
|
||||
import { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
|
||||
import { sqliteLayer } from "#sqlite"
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { Context, Effect, Layer, Schema } from "effect"
|
||||
import { Global } from "../global"
|
||||
import { isAbsolute, join } from "path"
|
||||
import { DatabaseMigration } from "./migration"
|
||||
@@ -16,9 +16,10 @@ export interface Interface {
|
||||
db: DatabaseShape
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
readonly path?: string
|
||||
}
|
||||
export const Options = Schema.Struct({
|
||||
path: Schema.optional(Schema.String),
|
||||
})
|
||||
export type Options = typeof Options.Type
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/storage/Database") {}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Observability } from "../observability"
|
||||
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
|
||||
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
|
||||
const getRuntime = () =>
|
||||
(rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer) as Layer.Layer<I, E>, {
|
||||
(rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer()) as Layer.Layer<I, E>, {
|
||||
memoMap,
|
||||
}))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ export * as FileSystemSearch from "./search"
|
||||
|
||||
import { makeLocationNode } from "../effect/app-node"
|
||||
import path from "path"
|
||||
import { Context, Effect, Layer, Scope } from "effect"
|
||||
import { Context, Effect, Layer, Schema, Scope } from "effect"
|
||||
import { Fff } from "#fff"
|
||||
import fuzzysort from "fuzzysort"
|
||||
import { FileSystem } from "../filesystem"
|
||||
@@ -10,7 +10,6 @@ import { FSUtil } from "../fs-util"
|
||||
import { Location } from "../location"
|
||||
import { Ripgrep } from "../ripgrep"
|
||||
import { RelativePath } from "../schema"
|
||||
import { Flag } from "../flag/flag"
|
||||
|
||||
export interface Interface {
|
||||
readonly find: (input: FileSystem.FindInput) => Effect.Effect<FileSystem.Entry[]>
|
||||
@@ -18,6 +17,11 @@ export interface Interface {
|
||||
readonly grep: (input: FileSystem.GrepInput) => Effect.Effect<readonly FileSystem.Match[]>
|
||||
}
|
||||
|
||||
export const Options = Schema.Struct({
|
||||
fff: Schema.optional(Schema.Boolean),
|
||||
})
|
||||
export type Options = typeof Options.Type
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/FileSystem/Search") {}
|
||||
|
||||
export const ripgrepLayer = Layer.effect(
|
||||
@@ -232,13 +236,18 @@ export const fffLayer = Layer.effect(
|
||||
}),
|
||||
)
|
||||
|
||||
const layer = Layer.unwrap(
|
||||
export const layer = (options?: Options) => Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
if (Flag.OPENCODE_DISABLE_FFF || !Fff.available()) return ripgrepLayer
|
||||
if (options?.fff === false || (options?.fff === undefined && process.platform === "win32") || !Fff.available())
|
||||
return ripgrepLayer
|
||||
const location = yield* Location.Service
|
||||
// Non-VCS locations can contain many repositories, so avoid eagerly content-indexing the entire aggregate tree.
|
||||
return location.vcs ? fffLayer : ripgrepLayer
|
||||
}),
|
||||
)
|
||||
|
||||
export const node = makeLocationNode({ service: Service, layer, deps: [FSUtil.node, Location.node, Ripgrep.node] })
|
||||
export function nodeWith(options?: Options) {
|
||||
return makeLocationNode({ service: Service, layer: layer(options), deps: [FSUtil.node, Location.node, Ripgrep.node] })
|
||||
}
|
||||
|
||||
export const node = nodeWith()
|
||||
|
||||
@@ -5,9 +5,8 @@ import { createWrapper } from "@parcel/watcher/wrapper"
|
||||
import type ParcelWatcher from "@parcel/watcher"
|
||||
import { FileSystem } from "@opencode-ai/schema/filesystem"
|
||||
import { makeGlobalNode } from "../effect/app-node"
|
||||
import { Cause, Context, Effect, Layer, PubSub, Scope, Stream } from "effect"
|
||||
import { Cause, Context, Effect, Layer, PubSub, Schema, Scope, Stream } from "effect"
|
||||
import { KeyedMutex } from "../effect/keyed-mutex"
|
||||
import { Flag } from "../flag/flag"
|
||||
import { lazy } from "../util/lazy"
|
||||
import { watch as watchFileSystem } from "node:fs"
|
||||
import path from "path"
|
||||
@@ -50,14 +49,19 @@ export interface Interface {
|
||||
readonly subscribe: (input: WatchInput) => Stream.Stream<Update>
|
||||
}
|
||||
|
||||
export const Options = Schema.Struct({
|
||||
enabled: Schema.optional(Schema.Boolean),
|
||||
})
|
||||
export type Options = typeof Options.Type
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/Watcher") {}
|
||||
|
||||
const layer = Layer.effect(
|
||||
export const layer = (options?: Options) => Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const backend = getBackend()
|
||||
const native = watcher()
|
||||
if (Flag.OPENCODE_DISABLE_FILEWATCHER) {
|
||||
if (options?.enabled === false) {
|
||||
return Service.of({ subscribe: () => Stream.empty })
|
||||
}
|
||||
|
||||
@@ -140,7 +144,11 @@ const layer = Layer.effect(
|
||||
}),
|
||||
)
|
||||
|
||||
export const node = makeGlobalNode({ service: Service, layer, deps: [] })
|
||||
export function nodeWith(options?: Options) {
|
||||
return makeGlobalNode({ service: Service, layer: layer(options), deps: [] })
|
||||
}
|
||||
|
||||
export const node = nodeWith()
|
||||
|
||||
function subscribeDirectory(
|
||||
native: typeof import("@parcel/watcher") | undefined,
|
||||
|
||||
@@ -530,11 +530,12 @@ export interface Interface {
|
||||
readonly refresh: (force?: boolean) => Effect.Effect<void>
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
readonly url?: string
|
||||
readonly file?: string
|
||||
readonly fetch?: boolean
|
||||
}
|
||||
export const Options = Schema.Struct({
|
||||
url: Schema.optional(Schema.String),
|
||||
file: Schema.optional(Schema.String),
|
||||
fetch: Schema.optional(Schema.Boolean),
|
||||
})
|
||||
export type Options = typeof Options.Type
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/ModelsDev") {}
|
||||
|
||||
|
||||
@@ -2,29 +2,41 @@ export * as Observability from "./observability"
|
||||
|
||||
import { NodeFileSystem } from "@effect/platform-node"
|
||||
import { LayerNode } from "./effect/layer-node"
|
||||
import { Effect, Layer, Logger, References } from "effect"
|
||||
import { Effect, Layer, Logger, References, Schema } from "effect"
|
||||
import { FetchHttpClient } from "effect/unstable/http"
|
||||
import { OtlpSerialization } from "effect/unstable/observability"
|
||||
import { Logging } from "./observability/logging"
|
||||
import { Otlp } from "./observability/otlp"
|
||||
|
||||
const local = Logger.layer(Logging.loggers(), { mergeWithExisting: false }).pipe(
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.orDie,
|
||||
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
|
||||
)
|
||||
export const Options = Schema.Struct({
|
||||
endpoint: Schema.optional(Schema.String),
|
||||
headers: Schema.optional(Schema.String),
|
||||
})
|
||||
export type Options = typeof Options.Type
|
||||
|
||||
export const layer = Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
const logs = Logger.layer([...Logging.loggers(), ...Otlp.loggers()], { mergeWithExisting: false }).pipe(
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.provide(OtlpSerialization.layerJson),
|
||||
Layer.provide(FetchHttpClient.layer),
|
||||
Layer.orDie,
|
||||
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
|
||||
)
|
||||
return Layer.merge(logs, yield* Effect.promise(Otlp.tracingLayer))
|
||||
}),
|
||||
).pipe(Layer.catchCause(() => local))
|
||||
export function layer(
|
||||
options: Options = {
|
||||
endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
||||
headers: process.env.OTEL_EXPORTER_OTLP_HEADERS,
|
||||
},
|
||||
) {
|
||||
const local = Logger.layer(Logging.loggers(), { mergeWithExisting: false }).pipe(
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.orDie,
|
||||
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
|
||||
)
|
||||
return Layer.unwrap(
|
||||
Effect.gen(function* () {
|
||||
const logs = Logger.layer([...Logging.loggers(), ...Otlp.loggers(options)], { mergeWithExisting: false }).pipe(
|
||||
Layer.provide(NodeFileSystem.layer),
|
||||
Layer.provide(OtlpSerialization.layerJson),
|
||||
Layer.provide(FetchHttpClient.layer),
|
||||
Layer.orDie,
|
||||
Layer.merge(Layer.succeed(References.MinimumLogLevel, Logging.minimumLogLevel())),
|
||||
)
|
||||
return Layer.merge(logs, yield* Effect.promise(() => Otlp.tracingLayer(options)))
|
||||
}),
|
||||
).pipe(Layer.catchCause(() => local))
|
||||
}
|
||||
|
||||
export const node = LayerNode.make({ name: "observability", layer, deps: [] })
|
||||
export const node = LayerNode.make({ name: "observability", layer: layer(), deps: [] })
|
||||
|
||||
@@ -4,10 +4,14 @@ import { Flag } from "../flag/flag"
|
||||
import { InstallationChannel, InstallationVersion } from "../installation/version"
|
||||
import { runID } from "./shared"
|
||||
|
||||
const endpoint = Flag.OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
export interface Options {
|
||||
readonly endpoint?: string
|
||||
readonly headers?: string
|
||||
}
|
||||
|
||||
const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
|
||||
? Flag.OTEL_EXPORTER_OTLP_HEADERS.split(",").reduce(
|
||||
function parseHeaders(value?: string) {
|
||||
return value
|
||||
? value.split(",").reduce(
|
||||
(acc, entry) => {
|
||||
const [key, ...value] = entry.split("=")
|
||||
acc[key] = value.join("=")
|
||||
@@ -15,7 +19,8 @@ const headers = Flag.OTEL_EXPORTER_OTLP_HEADERS
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
)
|
||||
: undefined
|
||||
: undefined
|
||||
}
|
||||
|
||||
function resourceAttributes() {
|
||||
const value = process.env.OTEL_RESOURCE_ATTRIBUTES
|
||||
@@ -47,13 +52,15 @@ export function resource(): { serviceName: string; serviceVersion: string; attri
|
||||
}
|
||||
}
|
||||
|
||||
export function loggers() {
|
||||
if (!endpoint) return []
|
||||
return [OtlpLogger.make({ url: `${endpoint}/v1/logs`, resource: resource(), headers })]
|
||||
export function loggers(options?: Options) {
|
||||
if (!options?.endpoint) return []
|
||||
return [
|
||||
OtlpLogger.make({ url: `${options.endpoint}/v1/logs`, resource: resource(), headers: parseHeaders(options.headers) }),
|
||||
]
|
||||
}
|
||||
|
||||
export async function tracingLayer() {
|
||||
if (!endpoint) return Layer.empty
|
||||
export async function tracingLayer(options?: Options) {
|
||||
if (!options?.endpoint) return Layer.empty
|
||||
const NodeSdk = await import("@effect/opentelemetry/NodeSdk")
|
||||
const OTLP = await import("@opentelemetry/exporter-trace-otlp-http")
|
||||
const SdkBase = await import("@opentelemetry/sdk-trace-base")
|
||||
@@ -69,8 +76,8 @@ export async function tracingLayer() {
|
||||
resource: resource(),
|
||||
spanProcessor: new SdkBase.BatchSpanProcessor(
|
||||
new OTLP.OTLPTraceExporter({
|
||||
url: `${endpoint}/v1/traces`,
|
||||
headers,
|
||||
url: `${options.endpoint}/v1/traces`,
|
||||
headers: parseHeaders(options.headers),
|
||||
}),
|
||||
),
|
||||
}))
|
||||
|
||||
@@ -66,7 +66,7 @@ test("falls back to local logging when OTLP initialization fails", async () => {
|
||||
`
|
||||
import { Effect } from "effect"
|
||||
import { Observability } from "./src/observability.ts"
|
||||
await Effect.void.pipe(Effect.provide(Observability.layer), Effect.scoped, Effect.runPromise)
|
||||
await Effect.void.pipe(Effect.provide(Observability.layer()), Effect.scoped, Effect.runPromise)
|
||||
`,
|
||||
],
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ export const AppLayer = AppNodeBuilderV1.build(
|
||||
ShareNext.node,
|
||||
SessionShare.node,
|
||||
]),
|
||||
).pipe(Layer.provideMerge(AppNodeBuilderV1.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<typeof rt, "runSync" | "runPromise" | "runPromiseExit" | "runFork" | "runCallback" | "dispose">
|
||||
|
||||
@@ -14,6 +14,6 @@ import { memoMap } from "@opencode-ai/core/effect/memo-map"
|
||||
|
||||
export const BootstrapLayer = AppNodeBuilder.build(
|
||||
LayerNode.group([Config.node, Plugin.node, ShareNext.node, Format.node, LSP.node, Vcs.node, Snapshot.node]),
|
||||
).pipe(Layer.provide(Observability.layer))
|
||||
).pipe(Layer.provide(Observability.layer()))
|
||||
|
||||
export const BootstrapRuntime = ManagedRuntime.make(BootstrapLayer, { memoMap })
|
||||
|
||||
@@ -32,7 +32,7 @@ export function attach<A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A
|
||||
|
||||
export function makeRuntime<I, S, E>(service: Context.Service<I, S>, layer: Layer.Layer<I, E>) {
|
||||
let rt: ManagedRuntime.ManagedRuntime<I, E> | undefined
|
||||
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer), { memoMap }))
|
||||
const getRuntime = () => (rt ??= ManagedRuntime.make(Layer.provideMerge(layer, Observability.layer()), { memoMap }))
|
||||
|
||||
return {
|
||||
runSync: <A, Err>(fn: (svc: S) => Effect.Effect<A, Err, I>) => getRuntime().runSync(attach(service.use(fn))),
|
||||
|
||||
@@ -305,7 +305,7 @@ export function createRoutes(
|
||||
Layer.provide(locationServiceMapV2),
|
||||
|
||||
Layer.provide(AppNodeBuilderV1.build(app)),
|
||||
Layer.provideMerge(Observability.layer),
|
||||
Layer.provideMerge(Observability.layer()),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { OpenCode } from "@opencode-ai/client/effect"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { SdkPlugins } from "@opencode-ai/core/plugin/sdk"
|
||||
import { ModelsDev } from "@opencode-ai/core/models-dev"
|
||||
import { createEmbeddedRoutes } from "@opencode-ai/server/routes"
|
||||
import type { ServerOptions } from "@opencode-ai/server/options"
|
||||
import { Context, Effect, Layer, ManagedRuntime } from "effect"
|
||||
import { FetchHttpClient, HttpEffect, HttpRouter, HttpServer } from "effect/unstable/http"
|
||||
|
||||
export const create = Effect.fn("OpenCode.create")(function* (options: {
|
||||
readonly database?: Database.Options
|
||||
readonly models?: ModelsDev.Options
|
||||
} = {}) {
|
||||
export const create = Effect.fn("OpenCode.create")(function* (options: ServerOptions = {}) {
|
||||
const runtime = yield* Effect.acquireRelease(
|
||||
Effect.sync(() =>
|
||||
ManagedRuntime.make(
|
||||
createEmbeddedRoutes({ database: { path: ":memory:", ...options.database }, models: options.models }).pipe(
|
||||
createEmbeddedRoutes({ ...options, database: { path: ":memory:", ...options.database } }).pipe(
|
||||
Layer.provide(HttpServer.layerServices),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
import type { Database } from "@opencode-ai/core/database/database"
|
||||
import type { ModelsDev } from "@opencode-ai/core/models-dev"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { ModelsDev } from "@opencode-ai/core/models-dev"
|
||||
import { Observability } from "@opencode-ai/core/observability"
|
||||
import { Schema } from "effect"
|
||||
|
||||
export interface ServerOptions {
|
||||
readonly hostname?: string
|
||||
readonly port?: number
|
||||
readonly password?: string
|
||||
readonly database?: Database.Options
|
||||
readonly models?: ModelsDev.Options
|
||||
}
|
||||
export const ServerOptions = Schema.Struct({
|
||||
hostname: Schema.optional(Schema.String),
|
||||
port: Schema.optional(
|
||||
Schema.Int.check(Schema.isGreaterThanOrEqualTo(1), Schema.isLessThanOrEqualTo(65_535)),
|
||||
),
|
||||
password: Schema.optional(Schema.String),
|
||||
database: Schema.optional(Database.Options),
|
||||
models: Schema.optional(ModelsDev.Options),
|
||||
observability: Schema.optional(Observability.Options),
|
||||
fs: Schema.optional(
|
||||
Schema.Struct({
|
||||
filewatcher: Schema.optional(Schema.Boolean),
|
||||
fff: Schema.optional(Schema.Boolean),
|
||||
}),
|
||||
),
|
||||
})
|
||||
export type ServerOptions = typeof ServerOptions.Type
|
||||
|
||||
@@ -4,6 +4,7 @@ import { httpClient } from "@opencode-ai/core/effect/app-node-platform"
|
||||
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
|
||||
import { EventV2 } from "@opencode-ai/core/event"
|
||||
import { EventLogger } from "@opencode-ai/core/event-logger"
|
||||
import { FileSystemSearch } from "@opencode-ai/core/filesystem/search"
|
||||
import { Observability } from "@opencode-ai/core/observability"
|
||||
import { Credential } from "@opencode-ai/core/credential"
|
||||
import { PermissionSaved } from "@opencode-ai/core/permission/saved"
|
||||
@@ -18,6 +19,7 @@ import { PluginRuntime } from "@opencode-ai/core/plugin/runtime"
|
||||
import { SdkPlugins } from "@opencode-ai/core/plugin/sdk"
|
||||
import { ToolOutputStore } from "@opencode-ai/core/tool-output-store"
|
||||
import { WellKnown } from "@opencode-ai/core/wellknown"
|
||||
import { Watcher } from "@opencode-ai/core/filesystem/watcher"
|
||||
import { HttpRouter, HttpServer } from "effect/unstable/http"
|
||||
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
||||
import { Context, Effect, Layer, Option } from "effect"
|
||||
@@ -76,6 +78,8 @@ function makeRoutes<AuthError, AuthServices>(
|
||||
const replacements: LayerNode.Replacements = [
|
||||
[Database.node, Database.layer(options.database)],
|
||||
[ModelsDev.node, ModelsDev.nodeWith(options.models)],
|
||||
[Watcher.node, Watcher.nodeWith({ enabled: options.fs?.filewatcher })],
|
||||
[FileSystemSearch.node, FileSystemSearch.nodeWith({ fff: options.fs?.fff })],
|
||||
[PluginRuntime.node, PluginRuntime.layerWithCell(pluginRuntimeCell)],
|
||||
[PluginRuntime.providerNode, PluginRuntime.providerNodeWithCell(pluginRuntimeCell)],
|
||||
]
|
||||
@@ -104,7 +108,7 @@ function makeRoutes<AuthError, AuthServices>(
|
||||
Layer.provide(authorizationLayer),
|
||||
Layer.provide(schemaErrorLayer),
|
||||
Layer.provide(auth),
|
||||
Layer.provide(Observability.layer),
|
||||
Layer.provide(Observability.layer(options.observability)),
|
||||
HttpRouter.provideRequest(requestServices),
|
||||
Layer.provideMerge(services),
|
||||
Layer.provideMerge(HttpRouter.layer),
|
||||
|
||||
Reference in New Issue
Block a user