Start effect-style compaction tests
This commit is contained in:
@@ -18,6 +18,7 @@ import * as DateTime from "effect/DateTime"
|
|||||||
import { InstanceState } from "@/effect/instance-state"
|
import { InstanceState } from "@/effect/instance-state"
|
||||||
import { isOverflow as overflow, usable } from "./overflow"
|
import { isOverflow as overflow, usable } from "./overflow"
|
||||||
import { makeRuntime } from "@/effect/run-service"
|
import { makeRuntime } from "@/effect/run-service"
|
||||||
|
import { serviceUse } from "@/effect/service-use"
|
||||||
import { fn } from "@/util/fn"
|
import { fn } from "@/util/fn"
|
||||||
import { EventV2 } from "@/v2/event"
|
import { EventV2 } from "@/v2/event"
|
||||||
import { SessionEvent } from "@/v2/session-event"
|
import { SessionEvent } from "@/v2/session-event"
|
||||||
@@ -208,6 +209,8 @@ export interface Interface {
|
|||||||
|
|
||||||
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionCompaction") {}
|
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionCompaction") {}
|
||||||
|
|
||||||
|
export const use = serviceUse(Service)
|
||||||
|
|
||||||
export const layer: Layer.Layer<
|
export const layer: Layer.Layer<
|
||||||
Service,
|
Service,
|
||||||
never,
|
never,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { WithInstance } from "../../src/project/with-instance"
|
|||||||
import * as Log from "@opencode-ai/core/util/log"
|
import * as Log from "@opencode-ai/core/util/log"
|
||||||
import { Permission } from "../../src/permission"
|
import { Permission } from "../../src/permission"
|
||||||
import { Plugin } from "../../src/plugin"
|
import { Plugin } from "../../src/plugin"
|
||||||
import { provideTmpdirInstance, tmpdir } from "../fixture/fixture"
|
import { provideTmpdirInstance, TestInstance, tmpdir } from "../fixture/fixture"
|
||||||
import { Session as SessionNs } from "@/session/session"
|
import { Session as SessionNs } from "@/session/session"
|
||||||
import { MessageV2 } from "../../src/session/message-v2"
|
import { MessageV2 } from "../../src/session/message-v2"
|
||||||
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
import { MessageID, PartID, SessionID } from "../../src/session/schema"
|
||||||
@@ -147,6 +147,53 @@ async function assistant(sessionID: SessionID, parentID: MessageID, root: string
|
|||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createUserMessage(sessionID: SessionID, text: string) {
|
||||||
|
return Effect.gen(function* () {
|
||||||
|
const ssn = yield* SessionNs.Service
|
||||||
|
const msg = yield* ssn.updateMessage({
|
||||||
|
id: MessageID.ascending(),
|
||||||
|
role: "user",
|
||||||
|
sessionID,
|
||||||
|
agent: "build",
|
||||||
|
model: ref,
|
||||||
|
time: { created: Date.now() },
|
||||||
|
})
|
||||||
|
yield* ssn.updatePart({
|
||||||
|
id: PartID.ascending(),
|
||||||
|
messageID: msg.id,
|
||||||
|
sessionID,
|
||||||
|
type: "text",
|
||||||
|
text,
|
||||||
|
})
|
||||||
|
return msg
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function createAssistantMessage(sessionID: SessionID, parentID: MessageID, root: string) {
|
||||||
|
return SessionNs.Service.use((ssn) =>
|
||||||
|
ssn.updateMessage({
|
||||||
|
id: MessageID.ascending(),
|
||||||
|
role: "assistant",
|
||||||
|
sessionID,
|
||||||
|
mode: "build",
|
||||||
|
agent: "build",
|
||||||
|
path: { cwd: root, root },
|
||||||
|
cost: 0,
|
||||||
|
tokens: {
|
||||||
|
output: 0,
|
||||||
|
input: 0,
|
||||||
|
reasoning: 0,
|
||||||
|
cache: { read: 0, write: 0 },
|
||||||
|
},
|
||||||
|
modelID: ref.modelID,
|
||||||
|
providerID: ref.providerID,
|
||||||
|
parentID,
|
||||||
|
time: { created: Date.now() },
|
||||||
|
finish: "end_turn",
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async function summaryAssistant(sessionID: SessionID, parentID: MessageID, root: string, text: string) {
|
async function summaryAssistant(sessionID: SessionID, parentID: MessageID, root: string, text: string) {
|
||||||
const msg: MessageV2.Assistant = {
|
const msg: MessageV2.Assistant = {
|
||||||
id: MessageID.ascending(),
|
id: MessageID.ascending(),
|
||||||
@@ -805,35 +852,35 @@ describe("session.compaction.prune", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe("session.compaction.process", () => {
|
describe("session.compaction.process", () => {
|
||||||
test("throws when parent is not a user message", async () => {
|
it.instance(
|
||||||
await using tmp = await tmpdir()
|
"throws when parent is not a user message",
|
||||||
await WithInstance.provide({
|
Effect.gen(function* () {
|
||||||
directory: tmp.path,
|
const test = yield* TestInstance
|
||||||
fn: async () => {
|
const ssn = yield* SessionNs.Service
|
||||||
const session = await svc.create({})
|
const session = yield* ssn.create({})
|
||||||
const msg = await user(session.id, "hello")
|
const msg = yield* createUserMessage(session.id, "hello")
|
||||||
const reply = await assistant(session.id, msg.id, tmp.path)
|
const reply = yield* createAssistantMessage(session.id, msg.id, test.directory)
|
||||||
const rt = runtime("continue")
|
const msgs = yield* ssn.messages({ sessionID: session.id })
|
||||||
try {
|
|
||||||
const msgs = await svc.messages({ sessionID: session.id })
|
const exit = yield* Effect.exit(
|
||||||
await expect(
|
SessionCompaction.use.process({
|
||||||
rt.runPromise(
|
parentID: reply.id,
|
||||||
SessionCompaction.Service.use((svc) =>
|
messages: msgs,
|
||||||
svc.process({
|
sessionID: session.id,
|
||||||
parentID: reply.id,
|
auto: false,
|
||||||
messages: msgs,
|
}),
|
||||||
sessionID: session.id,
|
)
|
||||||
auto: false,
|
|
||||||
}),
|
expect(Exit.isFailure(exit)).toBe(true)
|
||||||
),
|
if (Exit.isFailure(exit)) {
|
||||||
),
|
const error = Cause.squash(exit.cause)
|
||||||
).rejects.toThrow(`Compaction parent must be a user message: ${reply.id}`)
|
expect(error).toBeInstanceOf(Error)
|
||||||
} finally {
|
if (error instanceof Error) {
|
||||||
await rt.dispose()
|
expect(error.message).toContain(`Compaction parent must be a user message: ${reply.id}`)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
})
|
}),
|
||||||
})
|
)
|
||||||
|
|
||||||
test("publishes compacted event on continue", async () => {
|
test("publishes compacted event on continue", async () => {
|
||||||
await using tmp = await tmpdir()
|
await using tmp = await tmpdir()
|
||||||
|
|||||||
Reference in New Issue
Block a user