From 3f260f3ac88956b0412e4c01f9dff36d45e75c7a Mon Sep 17 00:00:00 2001 From: subochev Date: Sun, 20 Sep 2026 20:47:13 +0300 Subject: [PATCH] refactor(client): drop agentikHttpClient factory, accept HttpClient directly - Remove agentikHttpClient(engineFactory: HttpClientEngineFactory, ...) factory from :client; the typed factory parameter pulled engine-specific config (HttpClientConfig.engine { ... }) and made the library's factory API look engine-coupled even though the factory itself was engine-agnostic. - KDoc and SseTimeout no longer reference CIO as the canonical example. - :client still exports applyAgentikDefaults(HttpClientConfig<*>) extension; consumers build HttpClient themselves with their chosen engine. - :agentik-cli/defaultCliHttpClient updated to construct HttpClient(CIO) itself and apply agentik defaults inline; CIO-specific config (requestTimeout = 0) stays in the same block. --- .../pw/binom/agentik/cli/AgentikHttpClient.kt | 9 ++--- .../pw/binom/agentik/client/AgentikAgent.kt | 11 +++--- .../binom/agentik/client/HttpClientFactory.kt | 34 +++++-------------- .../pw/binom/agentik/client/SseTimeout.kt | 2 +- 4 files changed, 22 insertions(+), 34 deletions(-) diff --git a/agentik-cli/src/commonMain/kotlin/pw/binom/agentik/cli/AgentikHttpClient.kt b/agentik-cli/src/commonMain/kotlin/pw/binom/agentik/cli/AgentikHttpClient.kt index 07d4ff3..d3ae2c3 100644 --- a/agentik-cli/src/commonMain/kotlin/pw/binom/agentik/cli/AgentikHttpClient.kt +++ b/agentik-cli/src/commonMain/kotlin/pw/binom/agentik/cli/AgentikHttpClient.kt @@ -2,12 +2,12 @@ package pw.binom.agentik.cli import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO -import pw.binom.agentik.client.agentikHttpClient +import pw.binom.agentik.client.applyAgentikDefaults /** * HTTP-клиент CLI: движок CIO + конфигурация agentik. * - * Движок живёт здесь, а не в `:client`: библиотека не выбирает транспорт за + * Движок выбирается здесь, а не в `:client`: библиотека не выбирает транспорт за * потребителя. Таргеты `:agentik-cli` (jvm + linuxX64/macosX64/macosArm64/mingwX64) * покрываются CIO. * @@ -18,6 +18,7 @@ import pw.binom.agentik.client.agentikHttpClient * [token] = `null` — авторизация выключена. */ internal fun defaultCliHttpClient(token: String? = null): HttpClient = - agentikHttpClient(engineFactory = CIO, token = token) { + HttpClient(CIO) { + applyAgentikDefaults(token) engine { requestTimeout = 0 } - } \ No newline at end of file + } diff --git a/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentikAgent.kt b/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentikAgent.kt index 412aeb1..ebe6a36 100644 --- a/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentikAgent.kt +++ b/client/src/commonMain/kotlin/pw/binom/agentik/client/AgentikAgent.kt @@ -8,7 +8,11 @@ import pw.binom.agentik.proto.Agent * (модуль `:server`). * * ``` - * val http = HttpClient(CIO) { applyAgentikDefaults(token = "s3cret") } + * val http = HttpClient(engine) { + * applyAgentikDefaults(token = "s3cret") + * // engine — на выбор потребителя (CIO, OkHttp, Darwin, ...); + * // движковые настройки (requestTimeout и пр.) — там же + * } * val client = AgentikAgent( * id = "my-agent", * baseUrl = "http://localhost:8080/agentik", @@ -23,9 +27,8 @@ import pw.binom.agentik.proto.Agent * агента не знает, поэтому клиент должен её знать сам (или взять из * конфига). * - * Клиент приходит снаружи: `:client` не выбирает движок. Собрать [HttpClient] - * можно через [agentikHttpClient] (фабрика движка + опциональные движковые - * настройки) или вручную, применив к блоку конфигурации [applyAgentikDefaults] + * `:client` НЕ выбирает движок: [HttpClient] (с уже созданным engine'ом) + * приходит снаружи. К блоку конфигурации применяется [applyAgentikDefaults] * (JSON + опциональный Bearer-токен). */ fun AgentikAgent( diff --git a/client/src/commonMain/kotlin/pw/binom/agentik/client/HttpClientFactory.kt b/client/src/commonMain/kotlin/pw/binom/agentik/client/HttpClientFactory.kt index 269a6a9..d656f1e 100644 --- a/client/src/commonMain/kotlin/pw/binom/agentik/client/HttpClientFactory.kt +++ b/client/src/commonMain/kotlin/pw/binom/agentik/client/HttpClientFactory.kt @@ -2,8 +2,6 @@ package pw.binom.agentik.client import io.ktor.client.HttpClient import io.ktor.client.HttpClientConfig -import io.ktor.client.engine.HttpClientEngineConfig -import io.ktor.client.engine.HttpClientEngineFactory import io.ktor.client.plugins.DefaultRequest import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.request.header @@ -22,13 +20,19 @@ import io.ktor.serialization.kotlinx.json.json * * `null` — авторизация выключена, заголовок не отправляется. * - * Потребитель, знающий свой движок, добавляет к этому движковые настройки, напр.: + * Применяется к уже сконструированному [HttpClient]: * ``` - * val http = HttpClient(CIO) { - * engine { requestTimeout = 0 } // CIO-специфика, живёт у потребителя + * val engine = HttpClientEngineFactory().create() // потребитель выбирает движок + * val http = HttpClient(engine) { * applyAgentikDefaults(token) + * // движковые настройки (requestTimeout и пр.) — потребитель знает свой движок * } * ``` + * + * Раньше `:client` экспортировал фабрику `agentikHttpClient(engineFactory, ...)`, + * но она навязывала тип-параметр `HttpClientEngineFactory` и неявно тянула за + * собой конкретный движок в виде примера в KDoc. Сейчас фабрики нет — потребитель + * сам создаёт [HttpClient] и накатывает на блок конфигурации [applyAgentikDefaults]. */ fun HttpClientConfig<*>.applyAgentikDefaults(token: String? = null) { install(ContentNegotiation) { json(agentikJson) } @@ -38,23 +42,3 @@ fun HttpClientConfig<*>.applyAgentikDefaults(token: String? = null) { } } } - -/** - * Создаёт [HttpClient] из фабрики движка потребителя и сразу применяет к нему - * конфигурацию agentik ([applyAgentikDefaults]). - * - * Это точка, где `:client` НЕ привязан к реализации транспорта: [engineFactory] - * выбирает потребитель (CIO, OkHttp, Darwin, …), а `:client` только конфигурирует - * созданный клиент. - * - * [configure] — опциональный последний штрих потребителя (движковые настройки: - * таймауты, прокси, логирование). Вызывается ПОСЛЕ [applyAgentikDefaults]. - */ -fun agentikHttpClient( - engineFactory: HttpClientEngineFactory, - token: String? = null, - configure: (HttpClientConfig.() -> Unit)? = null, -): HttpClient = HttpClient(engineFactory) { - applyAgentikDefaults(token) - configure?.invoke(this) -} \ No newline at end of file diff --git a/client/src/commonMain/kotlin/pw/binom/agentik/client/SseTimeout.kt b/client/src/commonMain/kotlin/pw/binom/agentik/client/SseTimeout.kt index d15e7d5..fd28041 100644 --- a/client/src/commonMain/kotlin/pw/binom/agentik/client/SseTimeout.kt +++ b/client/src/commonMain/kotlin/pw/binom/agentik/client/SseTimeout.kt @@ -12,7 +12,7 @@ import io.ktor.client.request.HttpRequestBuilder * использует плагин `SSE`, поэтому движок не считает запрос SSE-шным * (`HttpRequestBuilder.supportsRequestTimeout` проверяет * `body is SSEClientContent`, а у нас тело — обычный GET без тела). - * Без capability встроенный `CIOEngineConfig.requestTimeout` (по умолчанию + * Без capability встроенный `HttpTimeoutPlugin.requestTimeoutMillis` (по умолчанию * **15000 мс**) молча убивает долгий idle-стрим через 15 секунд. * * Конфиг создаётся заново на каждый вызов — плагин `HttpTimeout` при