mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-10 07:11:25 +03:00
93 lines
4.0 KiB
TypeScript
93 lines
4.0 KiB
TypeScript
import fs from "fs/promises"
|
|
import { expect } from "bun:test"
|
|
import { App } from "@opencode/core/app"
|
|
import { Bus } from "@opencode/core/bus"
|
|
import { Database } from "@opencode/core/database/database"
|
|
import { Watcher } from "@opencode/core/filesystem/watcher"
|
|
import { LocationServiceMap } from "@opencode/core/location-service-map"
|
|
import { ModelsDev } from "@opencode/core/models-dev"
|
|
import { Session } from "@opencode/core/session"
|
|
import { SessionExecution } from "@opencode/core/session/execution"
|
|
import { Location } from "@opencode/schema/location"
|
|
import { AbsolutePath } from "@opencode/schema/schema"
|
|
import { LayerNode } from "@opencode/util/effect/layer-node"
|
|
import { Global } from "@opencode/util/global"
|
|
import { Context, Effect, Layer, RcMap } from "effect"
|
|
import { HttpEffect, HttpRouter, HttpServer } from "effect/http"
|
|
import { tempGlobalLayer } from "../../core/test/fixture/global"
|
|
import { tmpdirScoped } from "../../core/test/fixture/tmpdir"
|
|
import { it } from "../../core/test/lib/effect"
|
|
import { createEmbeddedRoutes } from "../src/routes"
|
|
|
|
it.live("admits synthetic messages and compaction requests without booting or requiring the session Location", () =>
|
|
Effect.gen(function* () {
|
|
const activeDir = yield* tmpdirScoped()
|
|
const deletedDir = yield* tmpdirScoped()
|
|
const activeLocation = LocationServiceMap.canonical(
|
|
Location.Ref.make({ directory: AbsolutePath.make(activeDir.path) }),
|
|
)
|
|
const deletedLocation = LocationServiceMap.canonical(
|
|
Location.Ref.make({ directory: AbsolutePath.make(deletedDir.path) }),
|
|
)
|
|
|
|
const replacements: LayerNode.Replacements = [
|
|
Global.node.replace(tempGlobalLayer),
|
|
Database.node.replace(Database.node),
|
|
Bus.node.replace(Bus.node),
|
|
App.node.replace(App.node),
|
|
ModelsDev.node.replace(ModelsDev.configured({ fetch: false })),
|
|
Watcher.node.replace(Watcher.configured({ enabled: false })),
|
|
SessionExecution.node.replace(SessionExecution.noopLayer),
|
|
]
|
|
|
|
const context = yield* Layer.build(
|
|
createEmbeddedRoutes({}, replacements).pipe(Layer.provide(HttpServer.layerServices)),
|
|
)
|
|
const sessions = Context.get(context, Session.Service)
|
|
const locations = Context.get(context, LocationServiceMap.Service)
|
|
const handler = Context.get(context, HttpRouter.HttpRouter)
|
|
.asHttpEffect()
|
|
.pipe(HttpEffect.toWebHandlerWith(context))
|
|
|
|
const post = (route: string, body: unknown) =>
|
|
Effect.promise(() =>
|
|
handler(
|
|
new Request(`http://opencode.local${route}`, {
|
|
method: "POST",
|
|
headers: { "content-type": "application/json" },
|
|
body: JSON.stringify(body),
|
|
}),
|
|
),
|
|
)
|
|
|
|
const coldSession = yield* sessions.create({ location: activeLocation, title: "cold" })
|
|
const strandedSession = yield* sessions.create({ location: deletedLocation, title: "stranded" })
|
|
|
|
// Remove the worktree directory after session creation to model a pruned worktree.
|
|
yield* Effect.promise(() => fs.rm(deletedDir.path, { recursive: true, force: true }))
|
|
expect(Array.from(yield* RcMap.keys(locations.rcMap))).toEqual([])
|
|
|
|
const coldSynthetic = yield* post(`/api/session/${coldSession.id}/synthetic`, {
|
|
text: "background notice",
|
|
resume: false,
|
|
})
|
|
expect(coldSynthetic.status).toBe(200)
|
|
expect(Array.from(yield* RcMap.keys(locations.rcMap))).toEqual([])
|
|
|
|
const coldCompact = yield* post(`/api/session/${coldSession.id}/compact`, {})
|
|
expect(coldCompact.status).toBe(200)
|
|
expect(Array.from(yield* RcMap.keys(locations.rcMap))).toEqual([])
|
|
|
|
const strandedSynthetic = yield* post(`/api/session/${strandedSession.id}/synthetic`, {
|
|
text: "note on deleted worktree",
|
|
resume: false,
|
|
})
|
|
expect(strandedSynthetic.status).toBe(200)
|
|
|
|
const strandedCompact = yield* post(`/api/session/${strandedSession.id}/compact`, {})
|
|
expect(strandedCompact.status).toBe(200)
|
|
|
|
expect((yield* sessions.inbox(strandedSession.id)).map((item) => item.type)).toEqual(["synthetic", "compaction"])
|
|
}),
|
|
)
|