openAgent
gitlabThe open source UNIVERSAL agent.
clone
https://gitlab.com/bitzzdev/openAgent.gitAIagentautomationopen-sourceuniversal-agent
import { describe, expect } from "bun:test"import { Effect, Layer, Schema } from "effect"import { Database } from "@opencode-ai/core/database/database"import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"import { LayerNode } from "@opencode-ai/core/effect/layer-node"import { EventV2 } from "@opencode-ai/core/event"import { Location } from "@opencode-ai/core/location"import { ProjectV2 } from "@opencode-ai/core/project"import { ProjectTable } from "@opencode-ai/core/project/sql"import { AbsolutePath } from "@opencode-ai/core/schema"import { SessionV2 } from "@opencode-ai/core/session"import { SessionExecution } from "@opencode-ai/core/session/execution"import { SessionProjector } from "@opencode-ai/core/session/projector"import { SessionStore } from "@opencode-ai/core/session/store"import { SessionTable } from "@opencode-ai/core/session/sql"import { testEffect } from "./lib/effect"const projects = Layer.succeed(ProjectV2.Service,ProjectV2.Service.of({resolve: (directory) => Effect.succeed({ id: ProjectV2.ID.global, directory }),directories: () => Effect.succeed([]),commit: () => Effect.void,}),)const it = testEffect(AppNodeBuilder.build(LayerNode.group([Database.node, EventV2.node, SessionProjector.node, SessionStore.node, SessionV2.node]),[[ProjectV2.node, projects],[SessionExecution.node, SessionExecution.noopLayer],],),)const location = Location.Ref.make({ directory: AbsolutePath.make("/project") })const GapEvent = EventV2.define({type: "test.session.history.gap",durable: { aggregate: "sessionID", version: 1 },schema: { sessionID: SessionV2.ID, value: Schema.String },})describe("SessionV2.history", () => {it.effect("returns an exhausted page for a migrated Session with no event sequence", () =>Effect.gen(function* () {const db = (yield* Database.Service).dbconst session = yield* SessionV2.Serviceconst sessionID = SessionV2.ID.make("ses_empty_history")yield* db.insert(ProjectTable).values({ id: ProjectV2.ID.global, worktree: AbsolutePath.make("/project"), sandboxes: [] }).onConflictDoNothing().run()yield* db.insert(SessionTable).values({id: sessionID,project_id: ProjectV2.ID.global,slug: "empty-history",directory: "/project",title: "Empty history",version: "test",}).run()const first = yield* session.history({ sessionID, limit: 10 })expect(first).toEqual({ events: [], hasMore: false })}),)it.effect("treats after as an exclusive aggregate sequence", () =>Effect.gen(function* () {const session = yield* SessionV2.Serviceconst created = yield* session.create({ location })yield* session.switchAgent({ sessionID: created.id, agent: "one" })yield* session.switchAgent({ sessionID: created.id, agent: "two" })const page = yield* session.history({ sessionID: created.id, after: 1, limit: 10 })expect(page.events.map((event) => event.durable?.seq)).toEqual([2])expect(page.hasMore).toBe(false)}),)it.effect("paginates public events in aggregate order across filtered gaps without duplicates", () =>Effect.gen(function* () {const session = yield* SessionV2.Serviceconst events = yield* EventV2.Serviceconst created = yield* session.create({ location })yield* session.switchAgent({ sessionID: created.id, agent: "one" })yield* events.publish(GapEvent, { sessionID: created.id, value: "filtered" })yield* session.switchAgent({ sessionID: created.id, agent: "two" })yield* session.switchAgent({ sessionID: created.id, agent: "three" })const first = yield* session.history({ sessionID: created.id, limit: 2 })const after = first.events.at(-1)?.durable?.seqconst second = yield* session.history({sessionID: created.id,after,limit: 2,})const sequence = [...first.events, ...second.events].map((event) => event.durable?.seq)expect(first.hasMore).toBe(true)expect(second.hasMore).toBe(false)expect(sequence).toEqual([1, 3, 4])expect(new Set(sequence).size).toBe(sequence.length)}),)it.effect("includes events committed between pages", () =>Effect.gen(function* () {const session = yield* SessionV2.Serviceconst created = yield* session.create({ location })yield* session.switchAgent({ sessionID: created.id, agent: "one" })yield* session.switchAgent({ sessionID: created.id, agent: "two" })const first = yield* session.history({ sessionID: created.id, limit: 1 })yield* session.switchAgent({ sessionID: created.id, agent: "later" })const second = yield* session.history({sessionID: created.id,after: first.events.at(-1)?.durable?.seq,limit: 10,})expect(first.hasMore).toBe(true)expect([...first.events, ...second.events].map((event) => event.durable?.seq)).toEqual([1, 2, 3])expect(second.hasMore).toBe(false)}),)it.effect("reports exhaustion for exact-limit and limit-plus-one pages", () =>Effect.gen(function* () {const session = yield* SessionV2.Serviceconst created = yield* session.create({ location })yield* session.switchAgent({ sessionID: created.id, agent: "one" })yield* session.switchAgent({ sessionID: created.id, agent: "two" })const exact = yield* session.history({ sessionID: created.id, limit: 2 })const oneMore = yield* session.history({ sessionID: created.id, limit: 1 })const exhausted = yield* session.history({sessionID: created.id,after: oneMore.events.at(-1)?.durable?.seq,limit: 1,})expect(exact.events).toHaveLength(2)expect(exact.hasMore).toBe(false)expect(oneMore.events).toHaveLength(1)expect(oneMore.hasMore).toBe(true)expect(exhausted.events).toHaveLength(1)expect(exhausted.hasMore).toBe(false)}),)it.effect("fails with NotFoundError for a missing Session", () =>Effect.gen(function* () {const session = yield* SessionV2.Serviceconst error = yield* session.history({ sessionID: SessionV2.ID.make("ses_missing"), limit: 10 }).pipe(Effect.flip)expect(error._tag).toBe("Session.NotFoundError")}),)})