Normalize instance lifecycle wiring (#25501)
This commit is contained in:
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import z from "zod"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Project } from "@/project/project"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
@@ -28,11 +29,11 @@ describe("session.listGlobal", () => {
|
||||
await using first = await tmpdir({ git: true })
|
||||
await using second = await tmpdir({ git: true })
|
||||
|
||||
const firstSession = await Instance.provide({
|
||||
const firstSession = await WithInstance.provide({
|
||||
directory: first.path,
|
||||
fn: async () => svc.create({ title: "first-session" }),
|
||||
})
|
||||
const secondSession = await Instance.provide({
|
||||
const secondSession = await WithInstance.provide({
|
||||
directory: second.path,
|
||||
fn: async () => svc.create({ title: "second-session" }),
|
||||
})
|
||||
@@ -58,12 +59,12 @@ describe("session.listGlobal", () => {
|
||||
test("excludes archived sessions by default", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
|
||||
const archived = await Instance.provide({
|
||||
const archived = await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => svc.create({ title: "archived-session" }),
|
||||
})
|
||||
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => svc.setArchived({ sessionID: archived.id, time: Date.now() }),
|
||||
})
|
||||
@@ -82,12 +83,12 @@ describe("session.listGlobal", () => {
|
||||
test("supports cursor pagination", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
|
||||
const first = await Instance.provide({
|
||||
const first = await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => svc.create({ title: "page-one" }),
|
||||
})
|
||||
await new Promise((resolve) => setTimeout(resolve, 5))
|
||||
const second = await Instance.provide({
|
||||
const second = await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => svc.create({ title: "page-two" }),
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { ExperimentalPaths } from "../../src/server/routes/instance/httpapi/groups/experimental"
|
||||
import { Session } from "@/session/session"
|
||||
@@ -126,12 +127,12 @@ describe("experimental HttpApi", () => {
|
||||
test("serves global session list through Hono bridge", async () => {
|
||||
await using tmp = await tmpdir({ git: true, config: { formatter: false, lsp: false } })
|
||||
|
||||
const first = await Instance.provide({
|
||||
const first = await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => createSession({ title: "page-one" }),
|
||||
})
|
||||
await new Promise((resolve) => setTimeout(resolve, 5))
|
||||
const second = await Instance.provide({
|
||||
const second = await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => createSession({ title: "page-two" }),
|
||||
})
|
||||
|
||||
@@ -10,8 +10,8 @@ import { registerAdapter } from "../../src/control-plane/adapters"
|
||||
import type { WorkspaceAdapter } from "../../src/control-plane/types"
|
||||
import { Workspace } from "../../src/control-plane/workspace"
|
||||
import { InstanceRef, WorkspaceRef } from "../../src/effect/instance-ref"
|
||||
import { InstanceRuntime } from "../../src/project/instance-runtime"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { InstanceLayer } from "../../src/project/instance-layer"
|
||||
import { Project } from "../../src/project/project"
|
||||
import { disposeMiddleware, markInstanceForDisposal } from "../../src/server/routes/instance/httpapi/lifecycle"
|
||||
import { instanceRouterMiddleware } from "../../src/server/routes/instance/httpapi/middleware/instance-context"
|
||||
@@ -41,7 +41,7 @@ const it = testEffect(
|
||||
testStateLayer,
|
||||
NodeHttpServer.layerTest,
|
||||
NodeServices.layer,
|
||||
InstanceRuntime.layer,
|
||||
InstanceLayer.layer,
|
||||
Project.defaultLayer,
|
||||
Workspace.defaultLayer,
|
||||
),
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { ExperimentalHttpApiServer } from "../../src/server/routes/instance/httpapi/server"
|
||||
import { McpPaths } from "../../src/server/routes/instance/httpapi/groups/mcp"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { InstanceRuntime } from "../../src/project/instance-runtime"
|
||||
import { Server } from "../../src/server/server"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
@@ -59,7 +60,7 @@ function withMcpProject<A, E, R>(self: (dir: string) => Effect.Effect<A, E, R>)
|
||||
)
|
||||
yield* Effect.addFinalizer(() =>
|
||||
Effect.promise(() =>
|
||||
Instance.provide({ directory: dir, fn: () => InstanceRuntime.disposeInstance(Instance.current) }),
|
||||
WithInstance.provide({ directory: dir, fn: () => InstanceRuntime.disposeInstance(Instance.current) }),
|
||||
).pipe(Effect.ignore),
|
||||
)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Effect, FileSystem, Layer, Path } from "effect"
|
||||
import { NodeFileSystem, NodePath } from "@effect/platform-node"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { InstanceRuntime } from "../../src/project/instance-runtime"
|
||||
import { Server } from "../../src/server/server"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
@@ -91,7 +92,7 @@ function withProviderProject<A, E, R>(self: (dir: string) => Effect.Effect<A, E,
|
||||
yield* writeProviderAuthPlugin(dir)
|
||||
yield* Effect.addFinalizer(() =>
|
||||
Effect.promise(() =>
|
||||
Instance.provide({ directory: dir, fn: () => InstanceRuntime.disposeInstance(Instance.current) }),
|
||||
WithInstance.provide({ directory: dir, fn: () => InstanceRuntime.disposeInstance(Instance.current) }),
|
||||
).pipe(Effect.ignore),
|
||||
)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { HttpRouter } from "effect/unstable/http"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { createOpencodeClient } from "@opencode-ai/sdk/v2"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { ExperimentalHttpApiServer } from "../../src/server/routes/instance/httpapi/server"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
@@ -226,7 +227,7 @@ function seedMessage(directory: string, sessionID: string) {
|
||||
const id = SessionID.make(sessionID)
|
||||
return call(
|
||||
async () =>
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory,
|
||||
fn: () =>
|
||||
Effect.runPromise(
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Workspace } from "../../src/control-plane/workspace"
|
||||
import { PermissionID } from "../../src/permission/schema"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Project } from "../../src/project/project"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { SessionPaths } from "../../src/server/routes/instance/httpapi/groups/session"
|
||||
@@ -44,7 +45,7 @@ function pathFor(path: string, params: Record<string, string>) {
|
||||
function createSession(directory: string, input?: Session.CreateInput) {
|
||||
return Effect.promise(
|
||||
async () =>
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory,
|
||||
fn: () => runSession(Session.Service.use((svc) => svc.create(input))),
|
||||
}),
|
||||
@@ -54,7 +55,7 @@ function createSession(directory: string, input?: Session.CreateInput) {
|
||||
function createTextMessage(directory: string, sessionID: SessionID, text: string) {
|
||||
return Effect.promise(
|
||||
async () =>
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory,
|
||||
fn: () =>
|
||||
runSession(
|
||||
|
||||
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { SyncPaths } from "../../src/server/routes/instance/httpapi/groups/sync"
|
||||
import { Session } from "@/session/session"
|
||||
@@ -38,7 +39,7 @@ describe("sync HttpApi", () => {
|
||||
const headers = { "x-opencode-directory": tmp.path, "content-type": "application/json" }
|
||||
const info = spyOn(Log.create({ service: "server.sync" }), "info")
|
||||
|
||||
const session = await Instance.provide({
|
||||
const session = await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => runSession(Session.Service.use((svc) => svc.create({ title: "sync" }))),
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { afterEach, describe, expect, mock, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
import type { SessionID } from "../../src/session/schema"
|
||||
@@ -31,7 +32,7 @@ afterEach(async () => {
|
||||
describe("session action routes", () => {
|
||||
test("abort route returns success", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const session = await svc.create({})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { disposeAllInstances, tmpdir } from "../fixture/fixture"
|
||||
@@ -40,20 +41,20 @@ describe("session.list", () => {
|
||||
await mkdir(path.join(tmp.path, "packages", "opencode"), { recursive: true })
|
||||
await mkdir(path.join(tmp.path, "packages", "app"), { recursive: true })
|
||||
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const root = await svc.create({ title: "root" })
|
||||
|
||||
const parent = await Instance.provide({
|
||||
const parent = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages"),
|
||||
fn: async () => svc.create({ title: "parent" }),
|
||||
})
|
||||
const current = await Instance.provide({
|
||||
const current = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "opencode"),
|
||||
fn: async () => svc.create({ title: "current" }),
|
||||
})
|
||||
const sibling = await Instance.provide({
|
||||
const sibling = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "app"),
|
||||
fn: async () => svc.create({ title: "sibling" }),
|
||||
})
|
||||
@@ -73,20 +74,20 @@ describe("session.list", () => {
|
||||
await mkdir(path.join(tmp.path, "packages", "opencode"), { recursive: true })
|
||||
await mkdir(path.join(tmp.path, "packages", "app"), { recursive: true })
|
||||
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const root = await svc.create({ title: "root" })
|
||||
|
||||
const parent = await Instance.provide({
|
||||
const parent = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages"),
|
||||
fn: async () => svc.create({ title: "parent" }),
|
||||
})
|
||||
const current = await Instance.provide({
|
||||
const current = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "opencode"),
|
||||
fn: async () => svc.create({ title: "current" }),
|
||||
})
|
||||
const sibling = await Instance.provide({
|
||||
const sibling = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "app"),
|
||||
fn: async () => svc.create({ title: "sibling" }),
|
||||
})
|
||||
@@ -106,22 +107,22 @@ describe("session.list", () => {
|
||||
await mkdir(path.join(tmp.path, "packages", "opencode", "src", "deep"), { recursive: true })
|
||||
await mkdir(path.join(tmp.path, "packages", "app"), { recursive: true })
|
||||
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const parent = await Instance.provide({
|
||||
const parent = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "opencode"),
|
||||
fn: async () => svc.create({ title: "parent" }),
|
||||
})
|
||||
const current = await Instance.provide({
|
||||
const current = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "opencode", "src"),
|
||||
fn: async () => svc.create({ title: "current" }),
|
||||
})
|
||||
const deeper = await Instance.provide({
|
||||
const deeper = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "opencode", "src", "deep"),
|
||||
fn: async () => svc.create({ title: "deeper" }),
|
||||
})
|
||||
const sibling = await Instance.provide({
|
||||
const sibling = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "app"),
|
||||
fn: async () => svc.create({ title: "sibling" }),
|
||||
})
|
||||
@@ -146,14 +147,14 @@ describe("session.list", () => {
|
||||
await mkdir(path.join(tmp.path, "packages", "opencode", "src"), { recursive: true })
|
||||
await mkdir(path.join(tmp.path, "packages", "app"), { recursive: true })
|
||||
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const current = await Instance.provide({
|
||||
const current = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "opencode", "src"),
|
||||
fn: async () => svc.create({ title: "legacy-current" }),
|
||||
})
|
||||
const sibling = await Instance.provide({
|
||||
const sibling = await WithInstance.provide({
|
||||
directory: path.join(tmp.path, "packages", "app"),
|
||||
fn: async () => svc.create({ title: "legacy-sibling" }),
|
||||
})
|
||||
@@ -175,7 +176,7 @@ describe("session.list", () => {
|
||||
|
||||
test("filters root sessions", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const root = await svc.create({ title: "root-session" })
|
||||
@@ -192,7 +193,7 @@ describe("session.list", () => {
|
||||
|
||||
test("filters by start time", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
await svc.create({ title: "new-session" })
|
||||
@@ -206,7 +207,7 @@ describe("session.list", () => {
|
||||
|
||||
test("filters by search term", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
await svc.create({ title: "unique-search-term-abc" })
|
||||
@@ -223,7 +224,7 @@ describe("session.list", () => {
|
||||
|
||||
test("respects limit parameter", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
await svc.create({ title: "session-1" })
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { Session as SessionNs } from "@/session/session"
|
||||
import { MessageV2 } from "../../src/session/message-v2"
|
||||
@@ -76,7 +77,7 @@ describe("session messages endpoint", () => {
|
||||
test("returns cursor headers for older pages", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await withoutWatcher(() =>
|
||||
Instance.provide({
|
||||
WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const session = await svc.create({})
|
||||
@@ -105,7 +106,7 @@ describe("session messages endpoint", () => {
|
||||
test("keeps full-history responses when limit is omitted", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await withoutWatcher(() =>
|
||||
Instance.provide({
|
||||
WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const session = await svc.create({})
|
||||
@@ -126,7 +127,7 @@ describe("session messages endpoint", () => {
|
||||
test("rejects invalid cursors and missing sessions", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await withoutWatcher(() =>
|
||||
Instance.provide({
|
||||
WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const session = await svc.create({})
|
||||
@@ -147,7 +148,7 @@ describe("session messages endpoint", () => {
|
||||
test("does not truncate large legacy limit requests", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await withoutWatcher(() =>
|
||||
Instance.provide({
|
||||
WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const session = await svc.create({})
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Session as SessionNs } from "@/session/session"
|
||||
import type { SessionID } from "../../src/session/schema"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { Instance } from "../../src/project/instance"
|
||||
import { WithInstance } from "../../src/project/with-instance"
|
||||
import { Server } from "../../src/server/server"
|
||||
import { disposeAllInstances, tmpdir } from "../fixture/fixture"
|
||||
|
||||
@@ -30,7 +31,7 @@ afterEach(async () => {
|
||||
describe("tui.selectSession endpoint", () => {
|
||||
test("should return 200 when called with valid session", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
// #given
|
||||
@@ -56,7 +57,7 @@ describe("tui.selectSession endpoint", () => {
|
||||
|
||||
test("should return 404 when session does not exist", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
// #given
|
||||
@@ -78,7 +79,7 @@ describe("tui.selectSession endpoint", () => {
|
||||
|
||||
test("should return 400 when session ID format is invalid", async () => {
|
||||
await using tmp = await tmpdir({ git: true })
|
||||
await Instance.provide({
|
||||
await WithInstance.provide({
|
||||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
// #given
|
||||
|
||||
Reference in New Issue
Block a user