agent-toolsets: SystemPromptToolsetSection + интеграция в ChatAgent
Добавлен SystemPromptToolsetSection — рендер markdown-секции для system prompt. Контракт: - toolsets пустой → null (секция не добавляется, агент не знает о механике) - иначе → краткое описание концепции + список 'name — description' для активных и неактивных (одинаковый формат per design contract) - auto-activation НЕ упоминается в промпте (только в dispatch) Интеграция в ChatAgent: - Добавлен параметр toolsets: List<ToolsetContribution> = emptyList() - При пустом списке — enable_toolset/disable_toolset НЕ регистрируются, секция в system prompt НЕ появляется (полная невидимость per A1-α) - При непустом — тулы регистрируются, секция добавляется - ToolsetRegistry + ToolsetDispatchPolicy создаются per-agent (один реестр на все диалоги — состояние 'активные тулсеты' общее) Интеграция в ChatConversation: - Новый параметр toolsetDispatch: ToolsetDispatchPolicy? = null - runToolAndPersist: если задан — вызов идёт через policy (auto-activate неактивных тулсетов, fallback в base dispatcher для плоских тулов) - Иначе — старое поведение через toolsByName Тесты: - 7 новых в :agent-toolsets (SystemPromptToolsetSection): пустые списки, только активные, только неактивные, оба, проверка отсутствия auto-activation упоминания, registry-based рендер, пустой реестр - 5 новых в :standalone (ChatAgentToolsetsTest): default (пустой) — нет тулов и секции; non-empty — тулы и секция есть; enable_toolset активирует; вызов тула из неактивного тулсета — auto-activate; disable_toolset снимает из active set (но auto-activate на следующем вызове — by design) Tests: 340/340 green (335 ранее + 5 новых ChatAgent integration)
This commit is contained in:
+54
@@ -0,0 +1,54 @@
|
||||
package pw.binom.agentik.toolsets
|
||||
|
||||
/**
|
||||
* Markdown-секция для system prompt, описывающая доступные тулсеты.
|
||||
*
|
||||
* Контракт (зафиксирован в дизайн-доке `docs/TOOLSETS-PLAN.md`):
|
||||
* - **Если toolsets пустой** → `null` (секция не добавляется, агент не знает
|
||||
* о механике toolsets вообще; тулы enable_toolset/disable_toolset тоже
|
||||
* не регистрируются — полная невидимость).
|
||||
* - **Иначе** → короткое описание концепции + список всех тулсетов
|
||||
* в формате `name — description`, активные и неактивные одинаково
|
||||
* (модель видит за что каждый отвечает).
|
||||
*
|
||||
* Auto-activation НЕ упоминается в prompt — только в dispatch (если модель
|
||||
* случайно вызвала тул из выключенного тулсета, диспетчер сам активирует).
|
||||
* Это чтобы не давать модели ложную опцию "не буду enable, а просто вызову".
|
||||
*/
|
||||
object SystemPromptToolsetSection {
|
||||
|
||||
fun render(
|
||||
active: List<ToolsetContribution>,
|
||||
inactive: List<ToolsetContribution>,
|
||||
): String? {
|
||||
if (active.isEmpty() && inactive.isEmpty()) return null
|
||||
return buildString {
|
||||
appendLine("## Toolsets")
|
||||
appendLine()
|
||||
appendLine("Toolsets group related tools. Use enable_toolset to activate one; its tools become available. Use disable_toolset to deactivate.")
|
||||
appendLine()
|
||||
if (active.isNotEmpty()) {
|
||||
appendLine("Active:")
|
||||
for (c in active) appendLine("- ${c.name} — ${c.description}")
|
||||
appendLine()
|
||||
}
|
||||
if (inactive.isNotEmpty()) {
|
||||
appendLine("Inactive:")
|
||||
for (c in inactive) appendLine("- ${c.name} — ${c.description}")
|
||||
appendLine()
|
||||
}
|
||||
}.trim()
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience: рендер по [ToolsetRegistry] (синхронный — без activeTools(),
|
||||
* только имена и описания).
|
||||
*/
|
||||
fun render(registry: ToolsetRegistry, activeNames: Set<String>): String? {
|
||||
val all = registry.all()
|
||||
if (all.isEmpty()) return null
|
||||
val active = all.filter { it.name in activeNames }
|
||||
val inactive = all.filter { it.name !in activeNames }
|
||||
return render(active, inactive)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user