refactor(core): move database schema ownership (#29068)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { afterEach, describe, expect, mock, test } from "bun:test"
|
||||
import { SessionLegacy } from "@opencode-ai/core/session/legacy"
|
||||
import { Database } from "@opencode-ai/core/database/database"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { APICallError } from "ai"
|
||||
import { Cause, Deferred, Effect, Exit, Fiber, Layer, Schema } from "effect"
|
||||
import * as Stream from "effect/Stream"
|
||||
import { Bus } from "../../src/bus"
|
||||
import { Config } from "@/config/config"
|
||||
import { Image } from "@/image/image"
|
||||
import { Agent } from "../../src/agent/agent"
|
||||
@@ -18,8 +20,8 @@ import { MessageV2 } from "../../src/session/message-v2"
|
||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||
import { SessionStatus } from "../../src/session/status"
|
||||
import { SessionSummary } from "../../src/session/summary"
|
||||
import { SessionV2 } from "../../src/v2/session"
|
||||
import { ModelID, ProviderID } from "../../src/provider/schema"
|
||||
import { SessionV2 } from "@opencode-ai/core/session"
|
||||
|
||||
import type { Provider } from "@/provider/provider"
|
||||
import * as SessionProcessorModule from "../../src/session/processor"
|
||||
import { Snapshot } from "../../src/snapshot"
|
||||
@@ -27,10 +29,9 @@ import { ProviderTest } from "../fake/provider"
|
||||
import { testEffect } from "../lib/effect"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { TestConfig } from "../fixture/config"
|
||||
import { SyncEvent } from "@/sync"
|
||||
import { RuntimeFlags } from "@/effect/runtime-flags"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { LLMEvent, Usage } from "@opencode-ai/llm"
|
||||
import { ProviderV2 } from "@opencode-ai/core/provider"
|
||||
|
||||
void Log.init({ print: false })
|
||||
|
||||
@@ -44,8 +45,8 @@ const summary = Layer.succeed(
|
||||
)
|
||||
|
||||
const ref = {
|
||||
providerID: ProviderID.make("test"),
|
||||
modelID: ModelID.make("test-model"),
|
||||
providerID: ProviderV2.ID.make("test"),
|
||||
modelID: ProviderV2.ModelID.make("test-model"),
|
||||
}
|
||||
|
||||
const usage = (input: ConstructorParameters<typeof Usage>[0]) => new Usage(input)
|
||||
@@ -229,22 +230,24 @@ const deps = Layer.mergeAll(
|
||||
layer("continue"),
|
||||
Agent.defaultLayer,
|
||||
Plugin.defaultLayer,
|
||||
Bus.layer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
Config.defaultLayer,
|
||||
SyncEvent.defaultLayer,
|
||||
RuntimeFlags.layer({ experimentalEventSystem: true }),
|
||||
Database.defaultLayer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
)
|
||||
|
||||
const env = Layer.mergeAll(
|
||||
SessionNs.defaultLayer,
|
||||
Database.defaultLayer,
|
||||
EventV2Bridge.defaultLayer,
|
||||
CrossSpawnSpawner.defaultLayer,
|
||||
SessionCompaction.layer.pipe(Layer.provide(SessionNs.defaultLayer), Layer.provideMerge(deps)),
|
||||
)
|
||||
|
||||
const it = testEffect(env)
|
||||
|
||||
const compactionEnv = Layer.mergeAll(SessionNs.defaultLayer, CrossSpawnSpawner.defaultLayer)
|
||||
const compactionEnv = Layer.mergeAll(SessionNs.defaultLayer, Database.defaultLayer, EventV2Bridge.defaultLayer, CrossSpawnSpawner.defaultLayer)
|
||||
const itCompaction = testEffect(compactionEnv)
|
||||
|
||||
type CompactionProcessOptions = {
|
||||
@@ -260,8 +263,8 @@ function withCompaction(options?: CompactionProcessOptions) {
|
||||
}
|
||||
|
||||
function compactionProcessLayer(options?: CompactionProcessOptions) {
|
||||
const bus = Bus.layer
|
||||
const status = SessionStatus.layer.pipe(Layer.provide(bus))
|
||||
const events = EventV2Bridge.defaultLayer
|
||||
const status = SessionStatus.layer.pipe(Layer.provide(events))
|
||||
const processor = options?.llm
|
||||
? SessionProcessorModule.SessionProcessor.layer.pipe(
|
||||
Layer.provide(summary),
|
||||
@@ -270,7 +273,7 @@ function compactionProcessLayer(options?: CompactionProcessOptions) {
|
||||
Layer.provide(status),
|
||||
)
|
||||
: layer(options?.result ?? "continue")
|
||||
return Layer.mergeAll(SessionCompaction.layer.pipe(Layer.provide(processor)), processor, bus, status).pipe(
|
||||
return Layer.mergeAll(SessionCompaction.layer.pipe(Layer.provide(processor)), processor, events, status).pipe(
|
||||
Layer.provide(SessionNs.defaultLayer),
|
||||
Layer.provide((options?.provider ?? wide()).layer),
|
||||
Layer.provide(Snapshot.defaultLayer),
|
||||
@@ -279,9 +282,8 @@ function compactionProcessLayer(options?: CompactionProcessOptions) {
|
||||
Layer.provide(Agent.defaultLayer),
|
||||
Layer.provide(options?.plugin ?? Plugin.defaultLayer),
|
||||
Layer.provide(status),
|
||||
Layer.provide(bus),
|
||||
Layer.provide(events),
|
||||
Layer.provide(options?.config ?? Config.defaultLayer),
|
||||
Layer.provide(SyncEvent.defaultLayer),
|
||||
Layer.provide(RuntimeFlags.layer({ experimentalEventSystem: true })),
|
||||
Layer.provide(EventV2Bridge.defaultLayer),
|
||||
)
|
||||
@@ -296,7 +298,7 @@ function readCompactionPart(sessionID: SessionID) {
|
||||
.messages({ sessionID })
|
||||
.pipe(
|
||||
Effect.map((messages) =>
|
||||
messages.at(-2)?.parts.find((item): item is MessageV2.CompactionPart => item.type === "compaction"),
|
||||
messages.at(-2)?.parts.find((item): item is SessionLegacy.CompactionPart => item.type === "compaction"),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -586,6 +588,26 @@ describe("session.compaction.create", () => {
|
||||
overflow: true,
|
||||
})
|
||||
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
it.live.skip(
|
||||
"projects a compaction message to v2 (v2 projector disabled)",
|
||||
provideTmpdirInstance(() =>
|
||||
Effect.gen(function* () {
|
||||
const compact = yield* SessionCompaction.Service
|
||||
const ssn = yield* SessionNs.Service
|
||||
const info = yield* ssn.create({})
|
||||
|
||||
yield* compact.create({
|
||||
sessionID: info.id,
|
||||
agent: "build",
|
||||
model: ref,
|
||||
auto: true,
|
||||
overflow: true,
|
||||
})
|
||||
|
||||
const v2 = yield* SessionV2.Service.use((svc) => svc.messages({ sessionID: info.id })).pipe(
|
||||
Effect.provide(SessionV2.defaultLayer),
|
||||
)
|
||||
@@ -623,7 +645,7 @@ describe("session.compaction.prune", () => {
|
||||
type: "text",
|
||||
text: "first",
|
||||
})
|
||||
const b: MessageV2.Assistant = {
|
||||
const b: SessionLegacy.Assistant = {
|
||||
id: MessageID.ascending(),
|
||||
role: "assistant",
|
||||
sessionID: info.id,
|
||||
@@ -719,7 +741,7 @@ describe("session.compaction.prune", () => {
|
||||
type: "text",
|
||||
text: "first",
|
||||
})
|
||||
const b: MessageV2.Assistant = {
|
||||
const b: SessionLegacy.Assistant = {
|
||||
id: MessageID.ascending(),
|
||||
role: "assistant",
|
||||
sessionID: info.id,
|
||||
@@ -821,19 +843,21 @@ describe("session.compaction.process", () => {
|
||||
it.instance(
|
||||
"publishes compacted event on continue",
|
||||
Effect.gen(function* () {
|
||||
const bus = yield* Bus.Service
|
||||
const events = yield* EventV2Bridge.Service
|
||||
const ssn = yield* SessionNs.Service
|
||||
const session = yield* ssn.create({})
|
||||
const msg = yield* createUserMessage(session.id, "hello")
|
||||
const msgs = yield* ssn.messages({ sessionID: session.id })
|
||||
const done = yield* Deferred.make<void, Error>()
|
||||
let seen = false
|
||||
const unsub = yield* bus.subscribeCallback(SessionCompaction.Event.Compacted, (evt) => {
|
||||
if (evt.properties.sessionID !== session.id) return
|
||||
const unsub = yield* events.listen((evt) => {
|
||||
if (evt.type !== SessionCompaction.Event.Compacted.type) return Effect.void
|
||||
if ((evt.data as typeof SessionCompaction.Event.Compacted.data.Type).sessionID !== session.id) return Effect.void
|
||||
seen = true
|
||||
Deferred.doneUnsafe(done, Effect.void)
|
||||
return Effect.void
|
||||
})
|
||||
yield* Effect.addFinalizer(() => Effect.sync(unsub))
|
||||
yield* Effect.addFinalizer(() => unsub)
|
||||
|
||||
const result = yield* SessionCompaction.use.process({
|
||||
parentID: msg.id,
|
||||
@@ -1064,7 +1088,7 @@ describe("session.compaction.process", () => {
|
||||
expect(captured).toContain("zzzz")
|
||||
expect(captured).not.toContain("keep tail")
|
||||
|
||||
const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id))
|
||||
const filtered = MessageV2.filterCompacted(yield* MessageV2.stream(session.id))
|
||||
expect(filtered.map((msg) => msg.info.id).slice(0, 3)).toEqual([parent!, expect.any(String), keep.id])
|
||||
expect(filtered[1]?.info.role).toBe("assistant")
|
||||
expect(filtered[1]?.info.role === "assistant" ? filtered[1].info.summary : false).toBe(true)
|
||||
@@ -1197,17 +1221,19 @@ describe("session.compaction.process", () => {
|
||||
|
||||
return Effect.gen(function* () {
|
||||
const ssn = yield* SessionNs.Service
|
||||
const bus = yield* Bus.Service
|
||||
const events = yield* EventV2Bridge.Service
|
||||
const ready = yield* Deferred.make<void>()
|
||||
const session = yield* ssn.create({})
|
||||
const msg = yield* createUserMessage(session.id, "hello")
|
||||
const msgs = yield* ssn.messages({ sessionID: session.id })
|
||||
const off = yield* bus.subscribeCallback(SessionStatus.Event.Status, (evt) => {
|
||||
if (evt.properties.sessionID !== session.id) return
|
||||
if (evt.properties.status.type !== "retry") return
|
||||
const off = yield* events.listen((evt) => {
|
||||
if (evt.type !== SessionStatus.Event.Status.type) return Effect.void
|
||||
const data = evt.data as typeof SessionStatus.Event.Status.data.Type
|
||||
if (data.sessionID !== session.id || data.status.type !== "retry") return Effect.void
|
||||
Deferred.doneUnsafe(ready, Effect.void)
|
||||
return Effect.void
|
||||
})
|
||||
yield* Effect.addFinalizer(() => Effect.sync(off))
|
||||
yield* Effect.addFinalizer(() => off)
|
||||
|
||||
const fiber = yield* SessionCompaction.use
|
||||
.process({
|
||||
@@ -1405,7 +1431,7 @@ describe("session.compaction.process", () => {
|
||||
yield* createUserMessage(session.id, "latest turn")
|
||||
yield* createCompactionMarker(session.id)
|
||||
|
||||
msgs = MessageV2.filterCompacted(MessageV2.stream(session.id))
|
||||
msgs = MessageV2.filterCompacted(yield* MessageV2.stream(session.id))
|
||||
parent = msgs.at(-1)?.info.id
|
||||
expect(parent).toBeTruthy()
|
||||
yield* SessionCompaction.use.process({ parentID: parent!, messages: msgs, sessionID: session.id, auto: false })
|
||||
@@ -1441,12 +1467,12 @@ describe("session.compaction.process", () => {
|
||||
const u4 = yield* createUserMessage(session.id, "four")
|
||||
yield* createCompactionMarker(session.id)
|
||||
|
||||
msgs = MessageV2.filterCompacted(MessageV2.stream(session.id))
|
||||
msgs = MessageV2.filterCompacted(yield* MessageV2.stream(session.id))
|
||||
parent = msgs.at(-1)?.info.id
|
||||
expect(parent).toBeTruthy()
|
||||
yield* SessionCompaction.use.process({ parentID: parent!, messages: msgs, sessionID: session.id, auto: false })
|
||||
|
||||
const filtered = MessageV2.filterCompacted(MessageV2.stream(session.id))
|
||||
const filtered = MessageV2.filterCompacted(yield* MessageV2.stream(session.id))
|
||||
const ids = filtered.map((msg) => msg.info.id)
|
||||
|
||||
expect(ids).not.toContain(u1.id)
|
||||
|
||||
Reference in New Issue
Block a user