Răsfoiți Sursa

fix(effect): preserve logger context in prompt runs

Kit Langton 2 zile în urmă
părinte
comite
1c059ae0d5

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

@@ -49,7 +49,7 @@ import { ShareNext } from "@/share/share-next"
 import { SessionShare } from "@/share/session"
 
 export const AppLayer = Layer.mergeAll(
-  // Observability.layer,
+  Observability.layer,
   AppFileSystem.defaultLayer,
   Bus.defaultLayer,
   Auth.defaultLayer,
@@ -95,6 +95,6 @@ export const AppLayer = Layer.mergeAll(
   Installation.defaultLayer,
   ShareNext.defaultLayer,
   SessionShare.defaultLayer,
-).pipe(Layer.provide(Observability.layer))
+)
 
 export const AppRuntime = ManagedRuntime.make(AppLayer, { memoMap })

+ 3 - 3
packages/opencode/src/session/prompt.ts

@@ -104,11 +104,11 @@ export namespace SessionPrompt {
       const summary = yield* SessionSummary.Service
       const sys = yield* SystemPrompt.Service
       const llm = yield* LLM.Service
+      const ctx = yield* Effect.context<any>()
 
       const run = {
-        promise: <A, E>(effect: Effect.Effect<A, E>) =>
-          Effect.runPromise(effect.pipe(Effect.provide(EffectLogger.layer))),
-        fork: <A, E>(effect: Effect.Effect<A, E>) => Effect.runFork(effect.pipe(Effect.provide(EffectLogger.layer))),
+        promise: <A, E>(effect: Effect.Effect<A, E>) => Effect.runPromiseWith(ctx)(effect),
+        fork: <A, E>(effect: Effect.Effect<A, E>) => Effect.runForkWith(ctx)(effect),
       }
 
       const cancel = Effect.fn("SessionPrompt.cancel")(function* (sessionID: SessionID) {

+ 42 - 0
packages/opencode/test/effect/app-runtime-logger.test.ts

@@ -0,0 +1,42 @@
+import { expect, test } from "bun:test"
+import { Context, Effect, Layer, Logger } from "effect"
+import { AppRuntime } from "../../src/effect/app-runtime"
+import { makeRuntime } from "../../src/effect/run-service"
+import { EffectLogger } from "../../src/effect/logger"
+
+function check(loggers: ReadonlySet<Logger.Logger<unknown, any>>) {
+  return {
+    defaultLogger: loggers.has(Logger.defaultLogger),
+    tracerLogger: loggers.has(Logger.tracerLogger),
+    effectLogger: loggers.has(EffectLogger.logger),
+    size: loggers.size,
+  }
+}
+
+test("makeRuntime installs EffectLogger through Observability.layer", async () => {
+  class Dummy extends Context.Service<Dummy, { readonly current: () => Effect.Effect<ReturnType<typeof check>> }>()(
+    "@test/Dummy",
+  ) {}
+
+  const layer = Layer.effect(
+    Dummy,
+    Effect.gen(function* () {
+      return Dummy.of({
+        current: () => Effect.map(Effect.service(Logger.CurrentLoggers), check),
+      })
+    }),
+  )
+
+  const rt = makeRuntime(Dummy, layer)
+  const current = await rt.runPromise((svc) => svc.current())
+
+  expect(current.effectLogger).toBe(true)
+  expect(current.defaultLogger).toBe(false)
+})
+
+test("AppRuntime also installs EffectLogger through Observability.layer", async () => {
+  const current = await AppRuntime.runPromise(Effect.map(Effect.service(Logger.CurrentLoggers), check))
+
+  expect(current.effectLogger).toBe(true)
+  expect(current.defaultLogger).toBe(false)
+})