@deep-assistant/agent
Version:
A minimal, public domain AI CLI agent compatible with OpenCode's JSON interface. Bun-only runtime.
68 lines (65 loc) • 1.96 kB
text/typescript
import { Log } from "../util/log"
import { Context } from "../util/context"
import { Project } from "./project"
import { State } from "./state"
import { iife } from "../util/iife"
interface Context {
directory: string
worktree: string
project: Project.Info
}
const context = Context.create<Context>("instance")
const cache = new Map<string, Promise<Context>>()
export const Instance = {
async provide<R>(input: { directory: string; init?: () => Promise<any>; fn: () => R }): Promise<R> {
let existing = cache.get(input.directory)
if (!existing) {
Log.Default.info("creating instance", { directory: input.directory })
existing = iife(async () => {
const project = await Project.fromDirectory(input.directory)
const ctx = {
directory: input.directory,
worktree: project.worktree,
project,
}
await context.provide(ctx, async () => {
await input.init?.()
})
return ctx
})
cache.set(input.directory, existing)
}
const ctx = await existing
return context.provide(ctx, async () => {
return input.fn()
})
},
get directory() {
return context.use().directory
},
get worktree() {
return context.use().worktree
},
get project() {
return context.use().project
},
state<S>(init: () => S, dispose?: (state: Awaited<S>) => Promise<void>): () => S {
return State.create(() => Instance.directory, init, dispose)
},
async dispose() {
Log.Default.info("disposing instance", { directory: Instance.directory })
await State.dispose(Instance.directory)
},
async disposeAll() {
Log.Default.info("disposing all instances")
for (const [_key, value] of cache) {
const awaited = await value.catch(() => {})
if (awaited) {
await context.provide(await value, async () => {
await Instance.dispose()
})
}
}
cache.clear()
},
}