diff --git a/packages/opencode/src/project/vcs.ts b/packages/opencode/src/project/vcs.ts index 1b1f21f908e2..aede980d6d08 100644 --- a/packages/opencode/src/project/vcs.ts +++ b/packages/opencode/src/project/vcs.ts @@ -4,7 +4,6 @@ import path from "path" import { Bus } from "@/bus" import { BusEvent } from "@/bus/bus-event" import { InstanceState } from "@/effect/instance-state" -import { makeRuntime } from "@/effect/run-service" import { AppFileSystem } from "@/filesystem" import { FileWatcher } from "@/file/watcher" import { Git } from "@/git" @@ -231,22 +230,4 @@ export namespace Vcs { Layer.provide(AppFileSystem.defaultLayer), Layer.provide(Bus.layer), ) - - const { runPromise } = makeRuntime(Service, defaultLayer) - - export async function init() { - return runPromise((svc) => svc.init()) - } - - export async function branch() { - return runPromise((svc) => svc.branch()) - } - - export async function defaultBranch() { - return runPromise((svc) => svc.defaultBranch()) - } - - export async function diff(mode: Mode) { - return runPromise((svc) => svc.diff(mode)) - } } diff --git a/packages/opencode/src/server/instance/index.ts b/packages/opencode/src/server/instance/index.ts index 2acc424e4ec9..86ff023acf03 100644 --- a/packages/opencode/src/server/instance/index.ts +++ b/packages/opencode/src/server/instance/index.ts @@ -1,6 +1,7 @@ import { describeRoute, resolver, validator } from "hono-openapi" import { Hono } from "hono" import type { UpgradeWebSocket } from "hono/ws" +import { Effect } from "effect" import z from "zod" import { Format } from "../../format" import { TuiRoutes } from "./tui" @@ -119,11 +120,17 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => }, }), async (c) => { - const [branch, default_branch] = await Promise.all([Vcs.branch(), Vcs.defaultBranch()]) - return c.json({ - branch, - default_branch, - }) + return c.json( + await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + const [branch, default_branch] = yield* Effect.all([vcs.branch(), vcs.defaultBranch()], { + concurrency: 2, + }) + return { branch, default_branch } + }), + ), + ) }, ) .get( @@ -150,7 +157,14 @@ export const InstanceRoutes = (upgrade: UpgradeWebSocket): Hono => }), ), async (c) => { - return c.json(await Vcs.diff(c.req.valid("query").mode)) + return c.json( + await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.diff(c.req.valid("query").mode) + }), + ), + ) }, ) .get( diff --git a/packages/opencode/test/project/vcs.test.ts b/packages/opencode/test/project/vcs.test.ts index 1610902af571..5461de5c33c8 100644 --- a/packages/opencode/test/project/vcs.test.ts +++ b/packages/opencode/test/project/vcs.test.ts @@ -1,5 +1,6 @@ import { $ } from "bun" import { afterEach, describe, expect, test } from "bun:test" +import { Effect } from "effect" import fs from "fs/promises" import path from "path" import { tmpdir } from "../fixture/fixture" @@ -20,8 +21,14 @@ async function withVcs(directory: string, body: () => Promise) { return Instance.provide({ directory, fn: async () => { - void AppRuntime.runPromise(FileWatcher.Service.use((svc) => svc.init())) - Vcs.init() + await AppRuntime.runPromise( + Effect.gen(function* () { + const watcher = yield* FileWatcher.Service + const vcs = yield* Vcs.Service + yield* watcher.init() + yield* vcs.init() + }), + ) await Bun.sleep(500) await body() }, @@ -32,7 +39,12 @@ function withVcsOnly(directory: string, body: () => Promise) { return Instance.provide({ directory, fn: async () => { - Vcs.init() + await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + yield* vcs.init() + }), + ) await body() }, }) @@ -80,7 +92,12 @@ describeVcs("Vcs", () => { await using tmp = await tmpdir({ git: true }) await withVcs(tmp.path, async () => { - const branch = await Vcs.branch() + const branch = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.branch() + }), + ) expect(branch).toBeDefined() expect(typeof branch).toBe("string") }) @@ -90,7 +107,12 @@ describeVcs("Vcs", () => { await using tmp = await tmpdir() await withVcs(tmp.path, async () => { - const branch = await Vcs.branch() + const branch = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.branch() + }), + ) expect(branch).toBeUndefined() }) }) @@ -123,7 +145,12 @@ describeVcs("Vcs", () => { await fs.writeFile(head, `ref: refs/heads/${branch}\n`) await pending - const current = await Vcs.branch() + const current = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.branch() + }), + ) expect(current).toBe(branch) }) }) @@ -139,7 +166,12 @@ describe("Vcs diff", () => { await $`git branch -M main`.cwd(tmp.path).quiet() await withVcsOnly(tmp.path, async () => { - const branch = await Vcs.defaultBranch() + const branch = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.defaultBranch() + }), + ) expect(branch).toBe("main") }) }) @@ -150,7 +182,12 @@ describe("Vcs diff", () => { await $`git config init.defaultBranch trunk`.cwd(tmp.path).quiet() await withVcsOnly(tmp.path, async () => { - const branch = await Vcs.defaultBranch() + const branch = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.defaultBranch() + }), + ) expect(branch).toBe("trunk") }) }) @@ -163,7 +200,12 @@ describe("Vcs diff", () => { await $`git worktree add -b feature/test ${dir} HEAD`.cwd(tmp.path).quiet() await withVcsOnly(dir, async () => { - const [branch, base] = await Promise.all([Vcs.branch(), Vcs.defaultBranch()]) + const [branch, base] = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* Effect.all([vcs.branch(), vcs.defaultBranch()], { concurrency: 2 }) + }), + ) expect(branch).toBe("feature/test") expect(base).toBe("main") }) @@ -177,7 +219,12 @@ describe("Vcs diff", () => { await fs.writeFile(path.join(tmp.path, "file.txt"), "changed\n", "utf-8") await withVcsOnly(tmp.path, async () => { - const diff = await Vcs.diff("git") + const diff = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.diff("git") + }), + ) expect(diff).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -194,7 +241,12 @@ describe("Vcs diff", () => { await fs.writeFile(path.join(tmp.path, weird), "hello\n", "utf-8") await withVcsOnly(tmp.path, async () => { - const diff = await Vcs.diff("git") + const diff = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.diff("git") + }), + ) expect(diff).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -215,7 +267,12 @@ describe("Vcs diff", () => { await $`git commit --no-gpg-sign -m "branch file"`.cwd(tmp.path).quiet() await withVcsOnly(tmp.path, async () => { - const diff = await Vcs.diff("branch") + const diff = await AppRuntime.runPromise( + Effect.gen(function* () { + const vcs = yield* Vcs.Service + return yield* vcs.diff("branch") + }), + ) expect(diff).toEqual( expect.arrayContaining([ expect.objectContaining({