Remove :storage-inmemory module, tests, and related code.
ci / JVM build + tests (push) Successful in 6m46s
ci / JVM build + tests (push) Successful in 6m46s
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
plugins {
|
||||
alias(libs.plugins.kotlin.multiplatform)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
|
||||
jvm()
|
||||
macosX64()
|
||||
macosArm64()
|
||||
iosX64()
|
||||
iosArm64()
|
||||
iosSimulatorArm64()
|
||||
linuxX64()
|
||||
linuxArm64()
|
||||
mingwX64()
|
||||
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
// :proto — read-only Agent interface, который MutableAgent расширяет.
|
||||
// Через api(), иначе downstream-impl ChatAgent не сможет
|
||||
// override suspend-методы Agent.
|
||||
api(project(":proto"))
|
||||
// :memory-api — typealias ConversationTurn на memory-api одноимённый
|
||||
// класс, иначе пер-конво компоненты (skill mining, reflection) не
|
||||
// смогут передать его в SkillMiner.mine() напрямую.
|
||||
api(project(":memory-api"))
|
||||
// :litert-api — отсюда LiteTool, который ToolProvider.getTools()
|
||||
// возвращает напрямую. До v9 интерфейс не имел поля name, и был
|
||||
// промежуточный NamedTool(name, LiteTool); после v9 — лишний слой.
|
||||
api(libs.litert.api)
|
||||
// SystemPromptProvider.section() и другие нон-suspend сигнатуры пока
|
||||
// не дёргают корутины; kotlinx-coroutines нужен на будущее (suspend event
|
||||
// listener) — оставлен как api, чтобы downstream не забывал объявить.
|
||||
api(libs.kotlinx.coroutines.core)
|
||||
}
|
||||
commonTest.dependencies {
|
||||
implementation(kotlin("test"))
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package pw.binom.agentik.agent
|
||||
|
||||
/**
|
||||
* Нашлёпка поверх [MutableAgent].
|
||||
*
|
||||
* Компонент сам регистрирует в агенте свои capability-провайдеры
|
||||
* при [install] и снимает их при [uninstall]. Агент не знает заранее
|
||||
* ни о структуре компонента, ни о его провайдерах — это просто
|
||||
* хук для свободной композиции.
|
||||
*
|
||||
* Ktor-style API:
|
||||
* ```
|
||||
* val agent = ChatAgent(...)
|
||||
* .install(SkillComponent(store, miner))
|
||||
* .install(ReflectionComponent(reflectionStore, reflector))
|
||||
* .install(MemoryComponent(memorySystem))
|
||||
* ```
|
||||
*
|
||||
* Контракт:
|
||||
* - [install] **синхронен**: компонент добавляет свои провайдеры в
|
||||
* `agent.systemProviders` / `agent.toolProviders` сразу. Если нужны
|
||||
* фоновые корутины — компонент запускает их через свой собственный
|
||||
* [kotlinx.coroutines.CoroutineScope], переданный в конструктор.
|
||||
* - [uninstall] **синхронен и идемпотентен**: компонент убирает ровно
|
||||
* те провайдеры, которые добавил. Можно вызвать повторно — без эффекта.
|
||||
* - Агент гарантирует, что [uninstall] будет вызван (через [MutableAgent.close]
|
||||
* или явный [MutableAgent.uninstall]) перед завершением хост-процесса.
|
||||
*/
|
||||
interface Component {
|
||||
|
||||
/**
|
||||
* Вызывается агентом при [MutableAgent.install].
|
||||
*
|
||||
* Типичные действия: добавить [SystemPromptProvider] в
|
||||
* `agent.systemProviders`, добавить [ToolProvider] в
|
||||
* `agent.toolProviders`, запустить фоновые джобы через свой scope.
|
||||
*/
|
||||
fun install(agent: MutableAgent)
|
||||
|
||||
/**
|
||||
* Вызывается агентом при [MutableAgent.uninstall] или при
|
||||
* [MutableAgent.close]. Компонент должен убрать ровно те провайдеры,
|
||||
* которые добавил в [install], и остановить фоновые джобы.
|
||||
*/
|
||||
fun uninstall(agent: MutableAgent)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package pw.binom.agentik.agent
|
||||
|
||||
/**
|
||||
* Хук, через который per-conversation компоненты ([SkillMiningComponent],
|
||||
* рефлексия и т.п.) подключаются к жизненному циклу разговора.
|
||||
*
|
||||
* [MutableAgent] при создании/закрытии разговора вызывает
|
||||
* [attachConversation] / [detachConversation] на каждом компоненте,
|
||||
* реализующем этот интерфейс. Внутри компонент хранит
|
||||
* [ConversationHandle] (или контекст вокруг него) и подписывается на
|
||||
* нужные события.
|
||||
*
|
||||
* Компонент без [ConversationAware] остаётся чисто agent-level — он
|
||||
* не получает per-conversation хуков.
|
||||
*/
|
||||
interface ConversationAware {
|
||||
fun attachConversation(handle: ConversationHandle)
|
||||
fun detachConversation(handle: ConversationHandle)
|
||||
}
|
||||
|
||||
/**
|
||||
* Минимальное окно в разговор, которое компонент видит через
|
||||
* [ConversationAware]. Содержит только то, что нужно большинству
|
||||
* per-conversation компонентов:
|
||||
* - идентификатор (для подписки на события),
|
||||
* - признак временности (для решения "тратить ли ресурсы на mining/reflection"),
|
||||
* - последние N turns (для LlmReflector / SkillMiner).
|
||||
*
|
||||
* Сознательно НЕ даёт доступ к [MutableAgent] или [ChatConversation] —
|
||||
* чтобы компонент не лез в чужие обязанности.
|
||||
*/
|
||||
interface ConversationHandle : AutoCloseable {
|
||||
val id: String
|
||||
val isTemporal: Boolean
|
||||
|
||||
/** Последние [limit] turns в разговоре, в хронологическом порядке. */
|
||||
suspend fun recentTurns(limit: Int): List<ConversationTurn>
|
||||
|
||||
override fun close()
|
||||
}
|
||||
|
||||
/**
|
||||
* Минимальная проекция turn'а для компонентов: пара user-message + ответ
|
||||
* assistant'а. Типо-алиас на [pw.binom.agentik.memory.ConversationTurn], чтобы
|
||||
* компоненты (skill mining, reflection) могли передавать его напрямую
|
||||
* в [pw.binom.agentik.llm.tools.SkillMiner.mine] и аналогичные API без
|
||||
* конвертации.
|
||||
*/
|
||||
typealias ConversationTurn = pw.binom.agentik.memory.ConversationTurn
|
||||
@@ -0,0 +1,78 @@
|
||||
package pw.binom.agentik.agent
|
||||
|
||||
import pw.binom.agentik.proto.Agent
|
||||
|
||||
/**
|
||||
* Настраиваемая версия [Agent]: расширяет публичный contract агента
|
||||
* install/uninstall-механикой компонентов ([Component]).
|
||||
*
|
||||
* Клиенты видят [Agent] через `:server` / `:client` / `:a2a` — они работают
|
||||
* с `MutableAgent` через базовый интерфейс и не знают про компоненты.
|
||||
* Внутри JVM-процесса (`:standalone`, потенциально `:irc-server`, Android-agent)
|
||||
* хост собирает агента через `MutableAgent` и наращивает его компонентами.
|
||||
*
|
||||
* Контракт:
|
||||
* - [systemProviders] и [toolProviders] — открытые мутабельные списки,
|
||||
* компонент сам добавляет/убирает свои capability при [install]/[uninstall];
|
||||
* - [install] / [uninstall] — просто хелперы, делегирующие в `component.{install,uninstall}(this)`;
|
||||
* - [close] освобождает ресурсы агента и снимает все установленные компоненты.
|
||||
*
|
||||
* Состояние порядка: провайдеры исполняются в порядке добавления (порядок
|
||||
* install-ов компонентов). Если когда-то потребуется приоритизация — расширим
|
||||
* позже, в v1 держим KISS.
|
||||
*/
|
||||
interface MutableAgent : Agent {
|
||||
/**
|
||||
* Провайдеры секций system prompt, регистрируются компонентами через [install].
|
||||
* Каждый [SystemPromptProvider.section] вызывается при каждом построении
|
||||
* system prompt конкретной беседы; возвращает `null`, если у него нет
|
||||
* релевантной секции для данного контекста.
|
||||
*
|
||||
* Изменяется **только внутри `Component.install(this)` /
|
||||
* `Component.uninstall(this)`**. Host-код (например, [Main][pw.binom.agentik.standalone.Main])
|
||||
* напрямую в список не лезет.
|
||||
*/
|
||||
val systemProviders: MutableList<SystemPromptProvider>
|
||||
|
||||
/**
|
||||
* Провайдеры tools, регистрируются компонентами через [install].
|
||||
* [ToolProvider.tools] вызывается при формировании набора тулов
|
||||
* для конкретной беседы; компонент решает сам, какие тулы отдавать
|
||||
* (например, разворачивая skill-каталог в `read_skill` / `skill_save`).
|
||||
*/
|
||||
val toolProviders: MutableList<ToolProvider>
|
||||
|
||||
/**
|
||||
* Устанавливает [component] в агент: `component.install(this)` +
|
||||
* агент запоминает компонент, чтобы при [close] корректно его снять.
|
||||
*
|
||||
* Возвращает `this` — для fluent-цепочек:
|
||||
* ```
|
||||
* ChatAgent(...).install(McpBridgeComponent(reg)).install(MemoryComponent(...))
|
||||
* ```
|
||||
*/
|
||||
fun install(component: Component): MutableAgent
|
||||
|
||||
/**
|
||||
* Снимает [component]: `component.uninstall(this)` + забывает.
|
||||
* Идемпотентно — повторный `uninstall` для того же компонента безопасен.
|
||||
*/
|
||||
fun uninstall(component: Component): MutableAgent
|
||||
|
||||
/**
|
||||
* Оповещает все установленные компоненты, реализующие [ConversationAware],
|
||||
* о появлении нового разговора. Компонент может подписаться на события,
|
||||
* запустить фоновые задачи, проиндексировать turns и т.п.
|
||||
*/
|
||||
fun attachConversation(handle: ConversationHandle)
|
||||
|
||||
/** Оповещает [ConversationAware] компоненты о закрытии разговора. */
|
||||
fun detachConversation(handle: ConversationHandle)
|
||||
|
||||
/**
|
||||
* Освобождает ресурсы агента и снимает все установленные компоненты
|
||||
* (в обратном порядке, чтобы последний установленный закрыл свои ресурсы
|
||||
* первым). Idempotent.
|
||||
*/
|
||||
override fun close()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package pw.binom.agentik.agent
|
||||
|
||||
/**
|
||||
* Провайдер одной секции system prompt конкретной беседы.
|
||||
*
|
||||
* Вызывается [MutableAgent] при каждом построении system prompt
|
||||
* (на старте беседы и после значимых изменений контекста). Возвращает
|
||||
* либо markdown-строку секции (будет вставлена в system prompt в порядке
|
||||
* `base → systemProviders[0].section → systemProviders[1].section → ...`),
|
||||
* либо `null`, если у провайдера нет релевантной секции для данного
|
||||
* контекста (например, skill-каталог пуст).
|
||||
*
|
||||
* Не-suspend: типичная реализация читает in-memory state (skill-каталог,
|
||||
* memory-префетч, reflection-снэпшот). Если нужна async-работа — компонент
|
||||
* сам решает: либо кэширует результат в `AtomicReference` и обновляет из
|
||||
* своей фоновой корутины, либо использует `runBlocking { ... }` (на свой
|
||||
* страх и риск, **не** рекомендуется в v1).
|
||||
*/
|
||||
fun interface SystemPromptProvider {
|
||||
|
||||
/**
|
||||
* Возвращает markdown-секцию для system prompt или `null`, если секции нет.
|
||||
*
|
||||
* [ctx] передаёт контекст беседы ([SystemPromptContext.conversationId])
|
||||
* и базовый system prompt ([SystemPromptContext.baseSystemPrompt]) —
|
||||
* если провайдер хочет делать per-conversation разделение, он может.
|
||||
*/
|
||||
fun getSection(conversationId: String): String
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package pw.binom.agentik.agent
|
||||
|
||||
import pw.binom.litert.LiteTool
|
||||
|
||||
/**
|
||||
* Провайдер набора тулов конкретной беседы.
|
||||
*
|
||||
* Вызывается [MutableAgent] при формировании списка тулов, доступных
|
||||
* модели в данной беседе (на старте и при пересборке после существенных
|
||||
* изменений контекста). Возвращает [LiteTool] напрямую — имя берётся
|
||||
* из `LiteTool.name` (с v9 это поле часть контракта), а описание и вызов —
|
||||
* из `describe()` / `invoke()` того же объекта.
|
||||
*
|
||||
* Не-suspend: типичная реализация строит список тулов из in-memory state
|
||||
* (MCP-реестр, skill-каталог, жёстко зашитый набор). Для async-доступа
|
||||
* к state компонент использует свой собственный scope и кэш.
|
||||
*
|
||||
* До v9 [pw.binom.litert] интерфейс [LiteTool] не имел поля `name`, и
|
||||
* здесь была обёртка `NamedTool(name, LiteTool)`. После обновления до v9
|
||||
* `LiteTool.name` стал частью контракта — отдельный `NamedTool` стал
|
||||
* лишним слоем и удалён.
|
||||
*/
|
||||
fun interface ToolProvider {
|
||||
|
||||
/**
|
||||
* Возвращает список тулов, доступных модели в беседе [conversationId].
|
||||
*
|
||||
* Провайдер может делать per-conversation фильтрацию (например, скрывать
|
||||
* `skill_save` в read-only-режиме). Если для беседы ничего нет — возвращает
|
||||
* пустой список.
|
||||
*/
|
||||
fun getTools(conversationId: String): List<LiteTool>
|
||||
}
|
||||
Reference in New Issue
Block a user