Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129export * as Reference from "./reference.js"
import { makeLocationNode } from "@opencode/util/effect/app-node"import { Context, Effect, Layer, Scope } from "effect"import { Reference } from "@opencode/schema/reference"import { Global } from "@opencode/util/global"import { Bus } from "./bus.js"import { Repository } from "./repository.js"import { RepositoryCache } from "./repository-cache.js"import { AbsolutePath } from "./schema.js"import { State } from "./state.js"
export const LocalSource = Reference.LocalSourceexport type LocalSource = Reference.LocalSource
export const GitSource = Reference.GitSourceexport type GitSource = Reference.GitSource
export const Source = Reference.Sourceexport type Source = Reference.Source
export { Event } from "@opencode/schema/reference"
export const Info = Reference.Infoexport type Info = Reference.Info
type Data = { sources: Map<string, Source>}
type Editor = { add(name: string, source: Source): void remove(name: string): void list(): readonly [string, Source][] get(name: string): Source | undefined}
export interface Interface extends State.Transformable<Editor> { readonly list: () => Effect.Effect<Info[]>}
export class Service extends Context.Service<Service, Interface>()("@opencode/Reference") {}
const layer = Layer.effect( Service, Effect.gen(function* () { const global = yield* Global.Service const bus = yield* Bus.Service const cache = yield* RepositoryCache.Service const scope = yield* Scope.Scope const list = (): Info[] => Array.from(state.get().sources).flatMap(([name, source]) => { const info = { name, source, ...(source.description === undefined ? {} : { description: source.description }), ...(source.hidden === undefined ? {} : { hidden: source.hidden }), } if (source.type === "local") return [Info.make({ ...info, path: source.path })] const repository = Repository.parse(source.repository) if (!repository || !Repository.isRemote(repository)) return [] if (source.branch) { try { Repository.validateBranch(source.branch) } catch { return [] } } return [ Info.make({ ...info, path: AbsolutePath.make(Repository.cachePath(global.repos, repository, source.branch)), }), ] }) const refresh = Effect.fn("Reference.refresh")(function* () { yield* Effect.forEach( list(), (reference) => Effect.gen(function* () { if (reference.source.type !== "git") return yield* cache.ensure({ reference: Repository.parseRemote(reference.source.repository), branch: reference.source.branch, refresh: "daily", }) }).pipe( Effect.catchCause((cause) => Effect.logWarning("failed to materialize reference", { name: reference.name, cause }), ), ), { concurrency: 4, discard: true }, ) }) const state = State.create<Data, Editor>({ name: "reference", initial: () => ({ sources: new Map() }), editor: (editor) => ({ add: (name, source) => editor.sources.set(name, source), remove: (name) => editor.sources.delete(name), list: () => Array.from(editor.sources), get: (name) => editor.sources.get(name), }), notify: () => Effect.gen(function* () { yield* refresh().pipe(Effect.forkIn(scope)) yield* bus.publish(Reference.Event.Updated, {}) }), })
// Check independently of session activity; the shared cache throttles Git work daily. yield* Effect.sleep("1 hour").pipe(Effect.andThen(refresh()), Effect.forever, Effect.forkScoped)
return Service.of({ transform: state.transform, reload: state.reload, list: Effect.fn("Reference.list")(function* () { return list() }), }) }),)
export const node = makeLocationNode({ service: Service, layer, deps: [Global.node, Bus.node, RepositoryCache.node],})