| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- export * as AgentV2 from "./agent"
- import { makeLocationNode } from "./effect/app-node"
- import { Array, Context, Effect, Layer, Types } from "effect"
- import { Agent } from "@opencode-ai/schema/agent"
- import { State } from "./state"
- export const ID = Agent.ID
- export type ID = typeof ID.Type
- export const defaultID = ID.make("build")
- export const Color = Agent.Color
- export const Info = Agent.Info
- export type Info = Agent.Info
- export interface Selection {
- readonly id: ID
- readonly info: Info | undefined
- }
- type Data = {
- agents: Map<ID, Types.DeepMutable<Info>>
- default?: ID
- }
- export type Draft = {
- list: () => readonly Info[]
- get: (id: ID) => Info | undefined
- default: (id: ID | undefined) => void
- update: (id: ID, fn: (agent: Types.DeepMutable<Info>) => void) => void
- remove: (id: ID) => void
- }
- export interface Interface extends State.Transformable<Draft> {
- readonly get: (id: ID) => Effect.Effect<Info | undefined>
- readonly default: () => Effect.Effect<Info | undefined>
- readonly resolve: (id?: ID | string) => Effect.Effect<Info | undefined>
- readonly select: (id?: ID | string) => Effect.Effect<Selection>
- readonly all: () => Effect.Effect<Info[]>
- }
- export class Service extends Context.Service<Service, Interface>()("@opencode/v2/Agent") {}
- const layer = Layer.effect(
- Service,
- Effect.gen(function* () {
- const state = State.create<Data, Draft>({
- initial: () => ({ agents: new Map() }),
- draft: (draft) => ({
- list: () => Array.fromIterable(draft.agents.values()) as Info[],
- get: (id) => draft.agents.get(id),
- default: (id) => {
- draft.default = id
- },
- update: (id, fn) => {
- const current = draft.agents.get(id) ?? (Info.empty(id) as Types.DeepMutable<Info>)
- if (!draft.agents.has(id)) draft.agents.set(id, current)
- fn(current)
- current.id = id
- },
- remove: (id) => {
- draft.agents.delete(id)
- },
- }),
- })
- const selectable = (agent: Info | undefined) =>
- agent && agent.mode !== "subagent" && !agent.hidden ? agent : undefined
- const selectedDefault = () => {
- const data = state.get()
- const configured = data.default ? selectable(data.agents.get(data.default)) : undefined
- if (configured) return configured
- const build = selectable(data.agents.get(ID.make("build")))
- if (build) return build
- for (const agent of data.agents.values()) {
- const fallback = selectable(agent)
- if (fallback) return fallback
- }
- }
- return Service.of({
- transform: state.transform,
- reload: state.reload,
- get: Effect.fn("AgentV2.get")(function* (id) {
- return state.get().agents.get(id)
- }),
- default: Effect.fn("AgentV2.default")(function* () {
- return selectedDefault()
- }),
- resolve: Effect.fn("AgentV2.resolve")(function* (id) {
- if (id !== undefined) return state.get().agents.get(ID.make(id))
- return selectedDefault()
- }),
- select: Effect.fn("AgentV2.select")(function* (id) {
- if (id !== undefined) {
- const selected = ID.make(id)
- return { id: selected, info: state.get().agents.get(selected) }
- }
- const info = selectedDefault()
- return { id: info?.id ?? defaultID, info }
- }),
- all: Effect.fn("AgentV2.all")(function* () {
- return Array.fromIterable(state.get().agents.values())
- }),
- })
- }),
- )
- export const locationLayer = layer
- export const node = makeLocationNode({ service: Service, layer, deps: [] })
|