Quellcode durchsuchen

fix(tui): gate Zed context on terminal env (#28517)

Kit Langton vor 3 Monaten
Ursprung
Commit
43c24d8d0f

+ 4 - 0
packages/opencode/src/cli/cmd/tui/context/editor-zed.ts

@@ -195,6 +195,10 @@ export function resolveZedDbPath() {
   return candidates.find((item) => isFile(item))
 }
 
+export function isZedTerminal() {
+  return process.env.ZED_TERM === "true" || process.env.TERM_PROGRAM?.toLowerCase() === "zed"
+}
+
 function isFile(item: string) {
   try {
     return Filesystem.stat(item)?.isFile() === true

+ 8 - 2
packages/opencode/src/cli/cmd/tui/context/editor.ts

@@ -6,7 +6,7 @@ import { createStore } from "solid-js/store"
 import { Option, Schema, SchemaGetter } from "effect"
 import { isRecord } from "@/util/record"
 import { createSimpleContext } from "./helper"
-import { resolveZedDbPath, resolveZedSelection } from "./editor-zed"
+import { isZedTerminal, resolveZedDbPath, resolveZedSelection } from "./editor-zed"
 
 const MCP_PROTOCOL_VERSION = "2025-11-25"
 
@@ -173,6 +173,12 @@ export const { use: useEditorContext, provider: EditorContextProvider } = create
 
       const connection = resolveEditorConnection(directory)
       if (!connection) {
+        if (!isZedTerminal()) {
+          setStore("status", "disabled")
+          scheduleReconnect()
+          return
+        }
+
         const dbPath = resolveZedDbPath()
         if (!dbPath) {
           setStore("status", "disabled")
@@ -311,7 +317,7 @@ export const { use: useEditorContext, provider: EditorContextProvider } = create
 
     return {
       enabled() {
-        return Boolean(resolveEditorConnection(directory) || resolveZedDbPath())
+        return Boolean(resolveEditorConnection(directory) || (isZedTerminal() && resolveZedDbPath()))
       },
       connected() {
         return store.status === "connected"

+ 6 - 4
packages/opencode/src/effect/config-service.ts

@@ -48,12 +48,14 @@ export const Service =
       }
 
       static get defaultLayer() {
+        const tag = this
         return Layer.effect(
-          this,
-          Config.all(fields).pipe(
+          tag,
+          Effect.gen(function* () {
+            const config = yield* Config.all(fields)
             // oxlint-disable-next-line typescript-eslint/no-unsafe-type-assertion -- Config.all preserves the field shape, but its conditional return type also supports iterable inputs.
-            Effect.map((config) => this.of(config as Shape<Fields>)),
-          ),
+            return tag.of(config as Shape<Fields>)
+          }),
         )
       }
     }

+ 30 - 2
packages/opencode/test/cli/tui/editor-context-zed.test.ts

@@ -2,10 +2,25 @@ import { Database } from "bun:sqlite"
 import { mkdir, symlink } from "node:fs/promises"
 import os from "node:os"
 import path from "node:path"
-import { expect, spyOn, test } from "bun:test"
-import { offsetToPosition, resolveZedDbPath, resolveZedSelection } from "../../../src/cli/cmd/tui/context/editor-zed"
+import { afterEach, expect, spyOn, test } from "bun:test"
+import {
+  isZedTerminal,
+  offsetToPosition,
+  resolveZedDbPath,
+  resolveZedSelection,
+} from "../../../src/cli/cmd/tui/context/editor-zed"
 import { tmpdir } from "../../fixture/fixture"
 
+const originalZedTerm = process.env.ZED_TERM
+const originalTermProgram = process.env.TERM_PROGRAM
+
+afterEach(() => {
+  if (originalZedTerm === undefined) delete process.env.ZED_TERM
+  else process.env.ZED_TERM = originalZedTerm
+  if (originalTermProgram === undefined) delete process.env.TERM_PROGRAM
+  else process.env.TERM_PROGRAM = originalTermProgram
+})
+
 type ZedFixtureOptions = {
   workspacePaths?: string | null
   itemKind?: string
@@ -85,6 +100,19 @@ test("resolveZedDbPath skips candidates that cannot be stated", async () => {
   }
 })
 
+test("isZedTerminal only returns true for Zed terminal environments", () => {
+  delete process.env.ZED_TERM
+  delete process.env.TERM_PROGRAM
+  expect(isZedTerminal()).toBeFalse()
+
+  process.env.ZED_TERM = "true"
+  expect(isZedTerminal()).toBeTrue()
+
+  process.env.ZED_TERM = "false"
+  process.env.TERM_PROGRAM = "zed"
+  expect(isZedTerminal()).toBeTrue()
+})
+
 test("resolveZedSelection returns active editor selection", async () => {
   await using tmp = await tmpdir()
   const fixture = await writeZedFixture(tmp.path)