openAgent
gitlabThe open source UNIVERSAL agent.
clone
https://gitlab.com/bitzzdev/openAgent.gitAIagentautomationopen-sourceuniversal-agent
import { Database } from "bun:sqlite"import { drizzle } from "drizzle-orm/bun-sqlite"import * as Context from "effect/Context"import * as Effect from "effect/Effect"import * as Fiber from "effect/Fiber"import { identity } from "effect/Function"import * as Layer from "effect/Layer"import * as Scope from "effect/Scope"import * as Semaphore from "effect/Semaphore"import * as Stream from "effect/Stream"import * as Reactivity from "effect/unstable/reactivity/Reactivity"import * as Client from "effect/unstable/sql/SqlClient"import type { Connection } from "effect/unstable/sql/SqlConnection"import { classifySqliteError, SqlError } from "effect/unstable/sql/SqlError"import * as Statement from "effect/unstable/sql/Statement"import { Sqlite } from "./sqlite"const ATTR_DB_SYSTEM_NAME = "db.system.name"const TypeId = "~@opencode-ai/core/database/SqliteBun" as consttype TypeId = typeof TypeIdinterface SqliteClient extends Client.SqlClient {readonly [TypeId]: TypeIdreadonly config: Configreadonly export: Effect.Effect<Uint8Array, SqlError>readonly loadExtension: (path: string) => Effect.Effect<void, SqlError>readonly updateValues: never}interface Config {readonly filename: stringreadonly readonly?: booleanreadonly create?: booleanreadonly readwrite?: booleanreadonly disableWAL?: booleanreadonly spanAttributes?: Record<string, unknown>readonly transformResultNames?: (str: string) => stringreadonly transformQueryNames?: (str: string) => string}interface SqliteConnection extends Connection {readonly export: Effect.Effect<Uint8Array, SqlError>readonly loadExtension: (path: string) => Effect.Effect<void, SqlError>}const make = (options: Config) =>Effect.gen(function* () {const native = (yield* Sqlite.Native) as Databaseconst compiler = Statement.makeCompilerSqlite(options.transformQueryNames)const transformRows = options.transformResultNames? Statement.defaultTransforms(options.transformResultNames).array: undefinedconst run = (query: string, params: ReadonlyArray<unknown> = []) =>Effect.withFiber<Array<Record<string, unknown>>, SqlError>((fiber) => {const statement = native.query(query)// @ts-ignore bun-types missing safeIntegers method, fixed in https://github.com/oven-sh/bun/pull/26627statement.safeIntegers(Context.get(fiber.context, Client.SafeIntegers))try {return Effect.succeed((statement.all(...(params as any)) ?? []) as Array<Record<string, unknown>>)} catch (cause) {return Effect.fail(new SqlError({reason: classifySqliteError(cause, { message: "Failed to execute statement", operation: "execute" }),}),)}})const runValues = (query: string, params: ReadonlyArray<unknown> = []) =>Effect.withFiber<Array<unknown[]>, SqlError>((fiber) => {const statement = native.query(query)// @ts-ignore bun-types missing safeIntegers method, fixed in https://github.com/oven-sh/bun/pull/26627statement.safeIntegers(Context.get(fiber.context, Client.SafeIntegers))try {return Effect.succeed((statement.values(...(params as any)) ?? []) as Array<unknown[]>)} catch (cause) {return Effect.fail(new SqlError({reason: classifySqliteError(cause, { message: "Failed to execute statement", operation: "execute" }),}),)}})const connection = identity<SqliteConnection>({execute(query, params, transformRows) {return transformRows ? Effect.map(run(query, params), transformRows) : run(query, params)},executeRaw(query, params) {return run(query, params)},executeValues(query, params) {return runValues(query, params)},executeUnprepared(query, params, transformRows) {return this.execute(query, params, transformRows)},executeStream() {return Stream.die("executeStream not implemented")},export: Effect.try({try: () => native.serialize(),catch: (cause) =>new SqlError({reason: classifySqliteError(cause, { message: "Failed to export database", operation: "export" }),}),}),loadExtension: (path) =>Effect.try({try: () => native.loadExtension(path),catch: (cause) =>new SqlError({reason: classifySqliteError(cause, { message: "Failed to load extension", operation: "loadExtension" }),}),}),})const semaphore = yield* Semaphore.make(1)const acquirer = semaphore.withPermits(1)(Effect.succeed(connection))const transactionAcquirer = Effect.uninterruptibleMask((restore) => {const fiber = Fiber.getCurrent()!const scope = Context.getUnsafe(fiber.context, Scope.Scope)return Effect.as(Effect.tap(restore(semaphore.take(1)), () => Scope.addFinalizer(scope, semaphore.release(1))),connection,)})const client = Object.assign((yield* Client.make({acquirer,compiler,transactionAcquirer,spanAttributes: [...(options.spanAttributes ? Object.entries(options.spanAttributes) : []),[ATTR_DB_SYSTEM_NAME, "sqlite"],],transformRows,})) as SqliteClient,{[TypeId]: TypeId,config: options,export: Effect.flatMap(acquirer, (_) => _.export),loadExtension: (path: string) => Effect.flatMap(acquirer, (_) => _.loadExtension(path)),},)return client})const nativeLayer = (config: Config) =>Layer.effect(Sqlite.Native,Effect.gen(function* () {const native = new Database(config.filename, {readonly: config.readonly,readwrite: config.readwrite ?? true,create: config.create ?? true,})yield* Effect.addFinalizer(() => Effect.sync(() => native.close()))if (config.disableWAL !== true) native.run("PRAGMA journal_mode = WAL;")return native}),)const sqliteLayer = (config: Config) => Layer.effect(Client.SqlClient, make(config))const drizzleLayer = Layer.effect(Sqlite.Drizzle,Effect.gen(function* () {return drizzle({ client: (yield* Sqlite.Native) as Database })}),)export const layer = (config: Config) => {const native = nativeLayer(config)return Layer.merge(native, Layer.merge(sqliteLayer(config), drizzleLayer).pipe(Layer.provide(native))).pipe(Layer.provide(Reactivity.layer),)}