diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt index c0c9eeb..082ed6f 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/Main.kt @@ -202,6 +202,8 @@ fun main() { reflectionInterval = config.reflectionInterval, skillMiner = skillMiner, skillMiningInterval = config.skillMiningInterval, + // Демо-тулсет для e2e проверки механики toolsets (AGENTIK_DEMO_TOOLSET=1) + toolsets = if (config.demoToolset) listOf(pw.binom.agentik.standalone.toolsets.DemoToolset.contribution()) else emptyList(), ) // Куратор памяти: фоновая архивация stale-заметок. Поднимается до server'а, diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/config/AgentikConfig.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/config/AgentikConfig.kt index cbd49d3..e4797cb 100644 --- a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/config/AgentikConfig.kt +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/config/AgentikConfig.kt @@ -115,6 +115,17 @@ data class AgentikConfig( * отладка: `AGENTIK_DEBUG_ENDPOINTS=1`. */ val debugEndpoints: Boolean = false, + /** + * Регистрирует демонстрационный тулсет ("media" с парой stub-инструментов) + * в агенте. Полезно для проверки механики toolsets в e2e без подключения + * реальных тулсетов: модель видит секцию Toolsets в system prompt и + * может вызвать enable_toolset/disable_toolset. Тулы в демо-тулсете + * возвращают безопасные stub-результаты и НЕ выполняют реальных действий. + * + * Opt-in: `AGENTIK_DEMO_TOOLSET=1`. По умолчанию выключен (агент не знает + * о механике toolsets вообще — per design contract A1-α). + */ + val demoToolset: Boolean = false, ) { /** Бэкенд долговременной памяти. */ @Serializable @@ -173,6 +184,9 @@ data class AgentikConfig( debugEndpoints = env("AGENTIK_DEBUG_ENDPOINTS")?.let { it.equals("1", ignoreCase = true) || it.equals("true", ignoreCase = true) } ?: false, + demoToolset = env("AGENTIK_DEMO_TOOLSET")?.let { + it.equals("1", ignoreCase = true) || it.equals("true", ignoreCase = true) + } ?: false, ) } } diff --git a/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/toolsets/DemoToolset.kt b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/toolsets/DemoToolset.kt new file mode 100644 index 0000000..21915d0 --- /dev/null +++ b/standalone/src/jvmMain/kotlin/pw/binom/agentik/standalone/toolsets/DemoToolset.kt @@ -0,0 +1,50 @@ +package pw.binom.agentik.standalone.toolsets + +import pw.binom.agentik.toolsets.ToolsetContribution +import pw.binom.litert.LiteTool + +/** + * Демонстрационный тулсет `media` — используется в e2e для проверки механики + * toolsets без подключения реальных тулсетов (image processing, web fetch). + * + * Тулы возвращают безопасные stub-результаты: `resize_image` пишет что уменьшил + * картинку до 100x100, `fetch_url` возвращает заглушку с URL. Реальных + * побочных эффектов нет — модель видит тулсет, активирует/деактивирует + * через enable_toolset/disable_toolset, и видит корректные результаты. + * + * Включается через `AGENTIK_DEMO_TOOLSET=1`. По умолчанию выключен — + * механика toolsets полностью невидима для модели (per design contract A1-α). + */ +object DemoToolset { + + const val NAME = "media" + const val DESCRIPTION = "image and URL helpers (stub tools for testing toolset mechanics)" + + fun contribution(): ToolsetContribution = ToolsetContribution( + name = NAME, + description = DESCRIPTION, + tools = listOf( + ToolsetContribution.ToolEntry("resize_image", ResizeImageTool), + ToolsetContribution.ToolEntry("fetch_url", FetchUrlTool), + ), + ) + + private object ResizeImageTool : LiteTool { + override fun describe(): String = """ + {"name":"resize_image","description":"Resize an image to 100x100 px (stub).","parameters":{"type":"object","properties":{"image_id":{"type":"string","description":"Image identifier (e.g. file path or URL)."}},"required":["image_id"]}} + """.trimIndent() + + override fun invoke(arguments: String): String = + // Просто принимаем любые аргументы и возвращаем заглушку — никаких реальных файловых IO. + """{"status":"ok","result":"image resized to 100x100","args":${arguments}}""" + } + + private object FetchUrlTool : LiteTool { + override fun describe(): String = """ + {"name":"fetch_url","description":"Fetch a web page and return its title (stub).","parameters":{"type":"object","properties":{"url":{"type":"string","description":"URL to fetch."}},"required":["url"]}} + """.trimIndent() + + override fun invoke(arguments: String): String = + """{"status":"ok","title":"stub title","content":"(stubbed page body)","args":${arguments}}""" + } +}