opencode/packages/core/test/session-activation.test.ts

75 lines
2.9 KiB
TypeScript

import { describe, expect, setDefaultTimeout } from "bun:test"
import { Effect } from "effect"
import path from "path"
import { Bus } from "@opencode-ai/core/bus"
import { Database } from "@opencode-ai/core/database/database"
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
import { Watcher } from "@opencode-ai/core/filesystem/watcher"
import { LocationServiceMap } from "@opencode-ai/core/location-service-map"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { Session } from "@opencode-ai/core/session"
import { SessionExecution } from "@opencode-ai/core/session/execution"
import { SessionProjector } from "@opencode-ai/core/session/projector"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Global } from "@opencode-ai/util/global"
import { tempGlobalLayer } from "./fixture/global"
import { offlineModels } from "./fixture/models"
import { tmpdirScoped } from "./fixture/tmpdir"
import { testEffect } from "./lib/effect"
// Real Location boot with plugin discovery, so the first request races the initial plugin activation.
setDefaultTimeout(15_000)
const it = testEffect(
AppNodeBuilder.build(
LayerNode.group([Database.node, Bus.node, SessionProjector.node, Session.node, LocationServiceMap.node]),
[
Global.node.replace(tempGlobalLayer),
offlineModels,
Watcher.node.replace(Watcher.configured({ enabled: false })),
SessionExecution.node.replace(SessionExecution.noopLayer),
],
),
)
const project = Effect.gen(function* () {
const tmp = yield* tmpdirScoped()
yield* Effect.promise(() =>
Bun.write(
path.join(tmp.path, ".opencode/plugins/prompt.ts"),
`export default {
id: "prompt-readiness",
async setup(ctx) {
await ctx.session.hook("prompt", (event) => {
event.prompt.text = "Prepared by plugin"
})
await ctx.command.transform((editor) =>
editor.add({ name: "ready", description: "Registered by plugin", execute: async () => {} }),
)
},
}`,
),
)
return tmp
})
describe("Session waits for plugin activation", () => {
it.live("runs prompt hooks from a cold Location before admitting a prompt", () =>
Effect.gen(function* () {
const tmp = yield* project
const sessions = yield* Session.Service
const session = yield* sessions.create({ location: { directory: AbsolutePath.make(tmp.path) } })
const admitted = yield* sessions.prompt({ sessionID: session.id, text: "Original", resume: false })
expect(admitted.payload.text).toBe("Prepared by plugin")
}),
)
it.live("resolves plugin commands from a cold Location", () =>
Effect.gen(function* () {
const tmp = yield* project
const sessions = yield* Session.Service
const session = yield* sessions.create({ location: { directory: AbsolutePath.make(tmp.path) } })
yield* sessions.command({ sessionID: session.id, command: "ready", text: "now" })
}),
)
})