Упрощение проверки связи: удалён временный диалог, оставлен запрос информации об агенте
This commit is contained in:
@@ -6,6 +6,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import pw.binom.agentik.client.AgentikAgent
|
||||
import pw.binom.agentik.desktop.settings.AgentConfig
|
||||
import pw.binom.agentik.proto.Agent
|
||||
|
||||
/** Один шаг проверки связи. */
|
||||
data class CheckStep(
|
||||
@@ -28,58 +29,56 @@ data class ConnectionReport(
|
||||
/**
|
||||
* Проверка связи с агентом без открытия полноценного [AgentConnection]:
|
||||
* отдельное «одноразовое» подключение, которое закрывается сразу после
|
||||
* прогона шагов.
|
||||
* прогона шага.
|
||||
*
|
||||
* Шаги:
|
||||
* 1. **Ответ сервера** — `GET {baseUrl}` за `AgentInfo` (имя/описание).
|
||||
* 2. **Диалог** — создать временный диалог и удалить его (проверяет
|
||||
* conversation-роуты, не тратит токены LLM).
|
||||
* Единственный шаг — **запрос информации об агенте**: конструктор
|
||||
* [AgentikAgent] синхронно делает `GET {baseUrl}` за `AgentInfo`
|
||||
* (имя/описание). Успешный ответ и есть «сервер жив и отвечает на своём
|
||||
* API» — без единого побочного эффекта на стороне сервера.
|
||||
*
|
||||
* Сознательно **не** отправляем реальный ход: это дёргает модель (время,
|
||||
* стоимость, побочные эффекты в истории). Проверки маршрутов достаточно,
|
||||
* чтобы отличить «связи нет» от «связь есть».
|
||||
* Сознательно **не** создаём временный диалог и **не** отправляем реальный
|
||||
* ход: временный диалог — это мусор в истории сервера (и лишний визит к БД),
|
||||
* а ход ещё и дёргает модель (время, стоимость, след в журнале). Для ответа
|
||||
* «связь есть / связи нет» достаточно ответа на запрос информации.
|
||||
*/
|
||||
class ConnectionChecker(
|
||||
private val engineFactory: HttpClientEngineFactory<*> = CIO,
|
||||
private val timeoutMillis: Long = 15_000,
|
||||
) {
|
||||
|
||||
suspend fun check(config: AgentConfig, clientId: String): ConnectionReport = withContext(Dispatchers.IO) {
|
||||
val steps = mutableListOf<CheckStep>()
|
||||
var agent: pw.binom.agentik.proto.Agent? = null
|
||||
var name: String? = null
|
||||
|
||||
val t0 = System.nanoTime()
|
||||
try {
|
||||
agent = AgentikAgent(
|
||||
val agent: Agent = try {
|
||||
AgentikAgent(
|
||||
id = clientId,
|
||||
baseUrl = config.baseUrl,
|
||||
engineFactory = engineFactory,
|
||||
token = config.token,
|
||||
)
|
||||
name = agent.info.name
|
||||
steps += CheckStep("Ответ сервера", true, elapsed(t0), runCatching { agent.info.description }.getOrNull())
|
||||
} catch (t: Throwable) {
|
||||
steps += CheckStep("Ответ сервера", false, elapsed(t0), t.message ?: t::class.simpleName)
|
||||
return@withContext ConnectionReport(config.baseUrl, steps, name)
|
||||
return@withContext ConnectionReport(
|
||||
baseUrl = config.baseUrl,
|
||||
steps = listOf(CheckStep(STEP_AGENT_INFO, false, elapsed(t0), t.message ?: t::class.simpleName)),
|
||||
)
|
||||
}
|
||||
|
||||
val a = agent
|
||||
val t1 = System.nanoTime()
|
||||
try {
|
||||
val conv = a.createConversation(temp = true)
|
||||
val id = conv.id
|
||||
conv.close()
|
||||
a.deleteConversation(id)
|
||||
steps += CheckStep("Создание диалога", true, elapsed(t1))
|
||||
} catch (t: Throwable) {
|
||||
steps += CheckStep("Создание диалога", false, elapsed(t1), t.message ?: t::class.simpleName)
|
||||
val info = agent.info
|
||||
ConnectionReport(
|
||||
baseUrl = config.baseUrl,
|
||||
steps = listOf(
|
||||
CheckStep(STEP_AGENT_INFO, true, elapsed(t0), runCatching { info.description }.getOrNull()),
|
||||
),
|
||||
agentName = info.name,
|
||||
)
|
||||
} finally {
|
||||
runCatching { a.close() }
|
||||
runCatching { agent.close() }
|
||||
}
|
||||
|
||||
ConnectionReport(config.baseUrl, steps, name)
|
||||
}
|
||||
|
||||
private fun elapsed(fromNanos: Long): Long = (System.nanoTime() - fromNanos) / 1_000_000
|
||||
|
||||
companion object {
|
||||
/** Заголовок единственного шага проверки в отчёте/UI. */
|
||||
const val STEP_AGENT_INFO = "Информация об агенте"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ class AppState(
|
||||
/** Проверка связи для формы агента — вызывается UI из своей корутины. */
|
||||
suspend fun checkConnection(config: AgentConfig): ConnectionReport =
|
||||
runCatching { checker.check(config, settingsState.clientId) }
|
||||
.getOrElse { ConnectionReport(config.baseUrl, listOf(CheckStep("Ответ сервера", false, 0, it.message))) }
|
||||
.getOrElse { ConnectionReport(config.baseUrl, listOf(CheckStep(ConnectionChecker.STEP_AGENT_INFO, false, 0, it.message))) }
|
||||
|
||||
// ───── conversations ─────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user