diff --git a/packages/opencode/src/reference.ts b/packages/opencode/src/reference.ts index 4dd5c4780e1..e602e25b36b 100644 --- a/packages/opencode/src/reference.ts +++ b/packages/opencode/src/reference.ts @@ -9,7 +9,7 @@ import { ProjectReference } from "@opencode-ai/core/project-reference" import { ConfigReference } from "@opencode-ai/core/config/reference" import { RepositoryCache } from "@opencode-ai/core/repository-cache" import { AbsolutePath } from "@opencode-ai/core/schema" -import { Context, Effect, Layer, Schema, Scope } from "effect" +import { Context, Effect, Layer, Schema } from "effect" export type Resolved = ProjectReference.Resolved @@ -51,7 +51,6 @@ export const layer = Layer.effect( Service, Effect.gen(function* () { const config = yield* Config.Service - const scope = yield* Scope.Scope const state = yield* InstanceState.make( Effect.fn("Reference.state")(function* (ctx) { const { Config: ConfigV2 } = yield* Effect.promise(() => import("@opencode-ai/core/config")) @@ -93,7 +92,7 @@ export const layer = Layer.effect( return Service.of({ init: Effect.fn("Reference.init")(function* () { - yield* ensure().pipe(Effect.forkIn(scope), Effect.asVoid) + yield* InstanceState.get(state) }), list: Effect.fn("Reference.list")(function* () { return yield* InstanceState.useEffect(state, (service) => service.list()) diff --git a/packages/opencode/test/reference/reference.test.ts b/packages/opencode/test/reference/reference.test.ts index 03068638a25..4cc5eb4506e 100644 --- a/packages/opencode/test/reference/reference.test.ts +++ b/packages/opencode/test/reference/reference.test.ts @@ -89,7 +89,7 @@ const waitForContent = ( fs: FSUtil.Interface, file: string, content: string, - attempts = 300, + attempts = 50, ): Effect.Effect => Effect.gen(function* () { if ((yield* fs.readFileStringSafe(file)) === content) return @@ -190,6 +190,32 @@ describe("reference", () => { ), ) + references.live("resolves configured remotes before init returns", () => + withReferences( + provideTmpdirInstance( + (_dir) => + Effect.gen(function* () { + const remoteRoot = yield* tmpdirScoped() + const reference = yield* Reference.Service + yield* githubBase(`file://${remoteRoot}/`, reference.init()) + + const resolved = yield* reference.get("docs") + expect(resolved?.kind).toBe("git") + if (resolved?.kind === "git") { + expect(resolved.reference.remote).toBe(`file://${remoteRoot}/opencode-reference-init/repo.git`) + } + }), + { + config: { + reference: { + docs: "opencode-reference-init/repo", + }, + }, + }, + ), + ), + ) + it.live("marks same-cache references with different branches invalid", () => Effect.gen(function* () { const root = path.resolve("opencode-reference-root") @@ -233,124 +259,118 @@ describe("reference", () => { }), ) - references.live( - "materializes configured git references during init", - () => - withReferences( - provideTmpdirInstance( - (_dir) => - Effect.gen(function* () { - const fs = yield* FSUtil.Service - const cache = path.join(Global.Path.repos, "github.com", "opencode-reference-test", "repo") - yield* fs.remove(cache, { recursive: true }).pipe(Effect.ignore) - yield* Effect.addFinalizer(() => fs.remove(cache, { recursive: true }).pipe(Effect.ignore)) + references.live("materializes configured git references during init", () => + withReferences( + provideTmpdirInstance( + (_dir) => + Effect.gen(function* () { + const fs = yield* FSUtil.Service + const cache = path.join(Global.Path.repos, "github.com", "opencode-reference-test", "repo") + yield* fs.remove(cache, { recursive: true }).pipe(Effect.ignore) + yield* Effect.addFinalizer(() => fs.remove(cache, { recursive: true }).pipe(Effect.ignore)) - const source = yield* tmpdirScoped({ git: true }) - const remoteRoot = yield* tmpdirScoped() - const remoteDir = path.join(remoteRoot, "opencode-reference-test") - const remoteRepo = path.join(remoteDir, "repo.git") + const source = yield* tmpdirScoped({ git: true }) + const remoteRoot = yield* tmpdirScoped() + const remoteDir = path.join(remoteRoot, "opencode-reference-test") + const remoteRepo = path.join(remoteDir, "repo.git") - yield* Effect.promise(() => Bun.write(path.join(source, "README.md"), "configured\n")) - yield* git(source, ["add", "."]) - yield* git(source, ["commit", "-m", "add readme"]) - yield* fs.makeDirectory(remoteDir, { recursive: true }).pipe(Effect.orDie) - yield* git(remoteRoot, ["clone", "--bare", source, remoteRepo]) + yield* Effect.promise(() => Bun.write(path.join(source, "README.md"), "configured\n")) + yield* git(source, ["add", "."]) + yield* git(source, ["commit", "-m", "add readme"]) + yield* fs.makeDirectory(remoteDir, { recursive: true }).pipe(Effect.orDie) + yield* git(remoteRoot, ["clone", "--bare", source, remoteRepo]) - const reference = yield* Reference.Service - yield* githubBase( - `file://${remoteRoot}/`, - Effect.gen(function* () { - yield* reference.init() - yield* waitForContent(fs, path.join(cache, "README.md"), "configured\n") - }), - ) + const reference = yield* Reference.Service + yield* githubBase( + `file://${remoteRoot}/`, + Effect.gen(function* () { + yield* reference.init() + yield* waitForContent(fs, path.join(cache, "README.md"), "configured\n") + }), + ) - expect(yield* fs.existsSafe(path.join(cache, ".git"))).toBe(true) - expect(yield* fs.readFileString(path.join(cache, "README.md"))).toBe("configured\n") + expect(yield* fs.existsSafe(path.join(cache, ".git"))).toBe(true) + expect(yield* fs.readFileString(path.join(cache, "README.md"))).toBe("configured\n") - const resolved = yield* reference.get("docs") - expect(resolved?.kind).toBe("git") - if (resolved?.kind === "git") expect(resolved.path).toBe(cache) - }), - { - config: { - reference: { - docs: "opencode-reference-test/repo", - }, + const resolved = yield* reference.get("docs") + expect(resolved?.kind).toBe("git") + if (resolved?.kind === "git") expect(resolved.path).toBe(cache) + }), + { + config: { + reference: { + docs: "opencode-reference-test/repo", }, }, - ), + }, ), - { timeout: 40_000 }, + ), ) - references.live( - "refreshes configured git references on new instance init", - () => - withReferences( - Effect.gen(function* () { - const fs = yield* FSUtil.Service - const cache = path.join(Global.Path.repos, "github.com", "opencode-reference-refresh", "repo") - yield* fs.remove(cache, { recursive: true }).pipe(Effect.ignore) - yield* Effect.addFinalizer(() => fs.remove(cache, { recursive: true }).pipe(Effect.ignore)) + references.live("refreshes configured git references on new instance init", () => + withReferences( + Effect.gen(function* () { + const fs = yield* FSUtil.Service + const cache = path.join(Global.Path.repos, "github.com", "opencode-reference-refresh", "repo") + yield* fs.remove(cache, { recursive: true }).pipe(Effect.ignore) + yield* Effect.addFinalizer(() => fs.remove(cache, { recursive: true }).pipe(Effect.ignore)) - const source = yield* tmpdirScoped({ git: true }) - const remoteRoot = yield* tmpdirScoped() - const remoteDir = path.join(remoteRoot, "opencode-reference-refresh") - const remoteRepo = path.join(remoteDir, "repo.git") + const source = yield* tmpdirScoped({ git: true }) + const remoteRoot = yield* tmpdirScoped() + const remoteDir = path.join(remoteRoot, "opencode-reference-refresh") + const remoteRepo = path.join(remoteDir, "repo.git") - yield* Effect.promise(() => Bun.write(path.join(source, "README.md"), "v1\n")) - yield* git(source, ["add", "."]) - yield* git(source, ["commit", "-m", "add readme"]) - yield* fs.makeDirectory(remoteDir, { recursive: true }).pipe(Effect.orDie) - yield* git(remoteRoot, ["clone", "--bare", source, remoteRepo]) + yield* Effect.promise(() => Bun.write(path.join(source, "README.md"), "v1\n")) + yield* git(source, ["add", "."]) + yield* git(source, ["commit", "-m", "add readme"]) + yield* fs.makeDirectory(remoteDir, { recursive: true }).pipe(Effect.orDie) + yield* git(remoteRoot, ["clone", "--bare", source, remoteRepo]) - yield* githubBase( - `file://${remoteRoot}/`, - provideTmpdirInstance( - (_dir) => - Effect.gen(function* () { - const reference = yield* Reference.Service - yield* reference.init() - yield* waitForContent(fs, path.join(cache, "README.md"), "v1\n") - }), - { - config: { - reference: { - docs: "opencode-reference-refresh/repo", - }, + yield* githubBase( + `file://${remoteRoot}/`, + provideTmpdirInstance( + (_dir) => + Effect.gen(function* () { + const reference = yield* Reference.Service + yield* reference.init() + yield* waitForContent(fs, path.join(cache, "README.md"), "v1\n") + }), + { + config: { + reference: { + docs: "opencode-reference-refresh/repo", }, }, - ), - ) + }, + ), + ) - const branch = yield* git(source, ["branch", "--show-current"]) - yield* git(source, ["remote", "add", "origin", remoteRepo]) - yield* Effect.promise(() => Bun.write(path.join(source, "README.md"), "v2\n")) - yield* git(source, ["add", "."]) - yield* git(source, ["commit", "-m", "update readme"]) - yield* git(source, ["push", "origin", `${branch}:${branch}`]) + const branch = yield* git(source, ["branch", "--show-current"]) + yield* git(source, ["remote", "add", "origin", remoteRepo]) + yield* Effect.promise(() => Bun.write(path.join(source, "README.md"), "v2\n")) + yield* git(source, ["add", "."]) + yield* git(source, ["commit", "-m", "update readme"]) + yield* git(source, ["push", "origin", `${branch}:${branch}`]) - yield* githubBase( - `file://${remoteRoot}/`, - provideTmpdirInstance( - (_dir) => - Effect.gen(function* () { - const reference = yield* Reference.Service - yield* reference.init() - yield* waitForContent(fs, path.join(cache, "README.md"), "v2\n") - }), - { - config: { - reference: { - docs: "opencode-reference-refresh/repo", - }, + yield* githubBase( + `file://${remoteRoot}/`, + provideTmpdirInstance( + (_dir) => + Effect.gen(function* () { + const reference = yield* Reference.Service + yield* reference.init() + yield* waitForContent(fs, path.join(cache, "README.md"), "v2\n") + }), + { + config: { + reference: { + docs: "opencode-reference-refresh/repo", }, }, - ), - ) - }), - ), - { timeout: 40_000 }, + }, + ), + ) + }), + ), ) })