/
Alex_Ural
/
opencode
Обзор
Документация
Войти
/
Alex_Ural
/
opencode
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
packages/core/src/plugin/host.ts
219 строк
9 KB
Kit Langton
refactor(schema): tighten public contracts (#33771)
25 июн 2026, 20:10
Не верифицирован
25 июн 2026, 20:10
9e9d405
Код
Авторство
О чём код?
export * as PluginHost from "./host" import type { PluginContext as Interface } from "@opencode-ai/plugin/v2/effect" import { Effect, Schema } from "effect" import { AgentV2 } from "../agent" import { AISDK } from "../aisdk" import { Catalog } from "../catalog" import { CommandV2 } from "../command" import { Credential } from "../credential" import { Integration } from "../integration" import { ModelV2 } from "../model" import { PluginV2 } from "../plugin" import { ProviderV2 } from "../provider" import { Reference } from "../reference" import type { DeepMutable } from "../schema" import { SkillV2 } from "../skill" const mutable = <T>(value: T) => value as DeepMutable<T> export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Interface) { const agents = yield* AgentV2.Service const aisdk = yield* AISDK.Service const catalog = yield* Catalog.Service const commands = yield* CommandV2.Service const integration = yield* Integration.Service const reference = yield* Reference.Service const skill = yield* SkillV2.Service return { options: {}, agent: { reload: agents.reload, transform: (callback) => agents.transform((draft) => callback({ list: () => mutable(draft.list()), get: (id) => mutable(draft.get(AgentV2.ID.make(id))), default: (id) => draft.default(id === undefined ? undefined : AgentV2.ID.make(id)), update: (id, update) => draft.update(AgentV2.ID.make(id), update), remove: (id) => draft.remove(AgentV2.ID.make(id)), }), ), }, aisdk: { sdk: (callback) => aisdk.hook.sdk((event) => { const output = { model: mutable(event.model), package: event.package, options: event.options, sdk: event.sdk, } const result = callback(output) return Effect.suspend(() => (Effect.isEffect(result) ? result : Effect.void)).pipe( Effect.tap(() => Effect.sync(() => (event.sdk = output.sdk))), ) }), language: (callback) => aisdk.hook.language((event) => { const output = { model: mutable(event.model), sdk: event.sdk, options: event.options, language: event.language, } const result = callback(output) return Effect.suspend(() => (Effect.isEffect(result) ? result : Effect.void)).pipe( Effect.tap(() => Effect.sync(() => (event.language = output.language))), ) }), }, catalog: { reload: catalog.reload, transform: (callback) => catalog.transform((draft) => callback({ provider: { list: () => mutable(draft.provider.list()), get: (id) => mutable(draft.provider.get(ProviderV2.ID.make(id))), update: (id, update) => draft.provider.update(ProviderV2.ID.make(id), update), remove: (id) => draft.provider.remove(ProviderV2.ID.make(id)), }, model: { get: (providerID, modelID) => mutable(draft.model.get(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID))), update: (providerID, modelID, update) => draft.model.update(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID), update), remove: (providerID, modelID) => draft.model.remove(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID)), default: { get: draft.model.default.get, set: (providerID, modelID) => draft.model.default.set(ProviderV2.ID.make(providerID), ModelV2.ID.make(modelID)), }, }, }), ), }, command: { reload: commands.reload, transform: commands.transform, }, integration: { reload: integration.reload, connection: { active: (id) => integration.connection.active(Integration.ID.make(id)), resolve: (connection) => integration.connection.resolve( connection.type === "credential" ? { ...connection, id: Credential.ID.make(connection.id) } : connection, ), }, transform: (callback) => integration.transform((draft) => callback({ list: () => mutable(draft.list()), get: (id) => mutable(draft.get(Integration.ID.make(id))), update: (id, update) => draft.update(Integration.ID.make(id), update), remove: (id) => draft.remove(Integration.ID.make(id)), method: { list: (id) => mutable(draft.method.list(Integration.ID.make(id))), update: (input) => { if ("authorize" in input) { const methodID = Integration.MethodID.make(input.method.id) const refresh = input.refresh draft.method.update({ integrationID: Integration.ID.make(input.integrationID), method: { ...input.method, id: methodID }, authorize: (inputs) => input.authorize(inputs).pipe( Effect.map((authorization) => { if (authorization.mode === "auto") { return { ...authorization, callback: authorization.callback.pipe( Effect.map((credential) => Credential.OAuth.make({ ...credential, methodID: Integration.MethodID.make(credential.methodID), }), ), ), } } return { ...authorization, callback: (code: string) => authorization.callback(code).pipe( Effect.map((credential) => Credential.OAuth.make({ ...credential, methodID: Integration.MethodID.make(credential.methodID), }), ), ), } }), ), ...(refresh ? { refresh: (value: Credential.OAuth) => refresh(value).pipe( Effect.map((next) => Credential.OAuth.make({ ...next, methodID: Integration.MethodID.make(next.methodID), }), ), ), } : {}), ...(input.label ? { label: input.label } : {}), }) return } if (input.method.type === "env") { draft.method.update({ integrationID: Integration.ID.make(input.integrationID), method: { type: "env", names: input.method.names }, }) return } draft.method.update({ integrationID: Integration.ID.make(input.integrationID), method: { type: "key", label: input.method.label }, }) }, remove: (id, method) => draft.method.remove(Integration.ID.make(id), Schema.decodeUnknownSync(Integration.Method)(method)), }, }), ), }, plugin: { add: (input) => plugin.add(PluginV2.ID.make(input.id), input.effect), remove: (id) => plugin.remove(PluginV2.ID.make(id)), }, reference: { reload: reference.reload, transform: (callback) => reference.transform((draft) => callback({ add: (name, source) => draft.add(name, Schema.decodeUnknownSync(Reference.Source)(source)), remove: draft.remove, list: draft.list, }), ), }, skill: { reload: skill.reload, transform: (callback) => skill.transform((draft) => callback({ source: (source) => draft.source(Schema.decodeUnknownSync(SkillV2.Source)(source)), list: draft.list, }), ), }, } satisfies Interface })