package cc.unitmesh.agent.tool import cc.unitmesh.agent.tool.schema.ToolCategory import cc.unitmesh.agent.tool.schema.ToolSchema import kotlinx.serialization.Serializable /** * Base interface for all tools in the Agent system. * Tools provide specific functionality that can be invoked by agents. */ interface Tool { val name: String val description: String } /** * Metadata for a tool including UI/display information */ data class ToolMetadata( val displayName: String, val tuiEmoji: String, val composeIcon: String, val category: ToolCategory, val schema: ToolSchema ) /** * Serializable representation of an agent tool with metadata */ @Serializable data class AgentTool( override val name: String, override val description: String, val example: String = "", val isMcp: Boolean = false, val completion: String = "", val mcpGroup: String = "", val isDevIns: Boolean = false, val devinScriptPath: String = "", ) : Tool { override fun toString(): String { val descAttr = if (description.isNotEmpty()) " description=\"$description\"" else "" val exampleContent = if (example.isNotEmpty()) """ $example """ else "" return """$exampleContent """ } } /** * Result of a tool execution */ @Serializable sealed class ToolResult { @Serializable data class Success(val content: String, val metadata: Map = emptyMap()) : ToolResult() @Serializable data class Error( val message: String, val errorType: String = "UNKNOWN", val metadata: Map = emptyMap() ) : ToolResult() /** * Agent 结果 - 包含结构化数据 * 用于 Agent 执行结果,可以携带额外的元数据 */ @Serializable data class AgentResult( val success: Boolean, val content: String, val metadata: Map = emptyMap() ) : ToolResult() /** * Pending 结果 - 表示异步执行中的工具调用 * 用于 Shell 等需要实时输出的工具,UI 可以通过 sessionId 跟踪执行状态 * * @param sessionId 会话 ID,用于跟踪和更新执行状态 * @param toolName 工具名称 * @param command 执行的命令(用于显示) * @param message 状态消息 * @param metadata 额外的元数据 */ @Serializable data class Pending( val sessionId: String, val toolName: String, val command: String = "", val message: String = "Executing...", val metadata: Map = emptyMap() ) : ToolResult() fun isSuccess(): Boolean = this is Success || (this is AgentResult && this.success) fun isError(): Boolean = this is Error || (this is AgentResult && !this.success) fun isPending(): Boolean = this is Pending fun getOutput(): String = when (this) { is Success -> content is AgentResult -> content is Error -> "" is Pending -> message } fun getError(): String = when (this) { is Success -> "" is AgentResult -> if (!success) content else "" is Error -> message is Pending -> "" } fun extractMetadata(): Map = when (this) { is Success -> metadata is AgentResult -> metadata is Error -> metadata is Pending -> metadata } } /** * Represents a location that a tool will affect (file path, directory, etc.) */ @Serializable data class ToolLocation( val path: String, val type: LocationType = LocationType.FILE ) @Serializable enum class LocationType { FILE, DIRECTORY, URL, OTHER } /** * Parameters for tool execution context */ data class ToolExecutionContext( val workingDirectory: String? = null, val environment: Map = emptyMap(), val timeout: Long = 30000L, // 30 seconds default val metadata: Map = emptyMap() ) /** * Represents a validated and ready-to-execute tool call. * Similar to Gemini CLI's ToolInvocation interface. */ interface ToolInvocation { /** * The validated parameters for this specific invocation. */ val params: TParams /** * The tool that created this invocation */ val tool: ExecutableTool /** * Gets a pre-execution description of the tool operation. */ fun getDescription(): String /** * Determines what file system paths the tool will affect. */ fun getToolLocations(): List /** * Executes the tool with the validated parameters. */ suspend fun execute(context: ToolExecutionContext = ToolExecutionContext()): TResult } /** * Base implementation of ToolInvocation */ abstract class BaseToolInvocation( override val params: TParams, override val tool: ExecutableTool ) : ToolInvocation { override fun getToolLocations(): List = emptyList() override fun getDescription(): String = "${tool.name} with params: $params" } /** * A tool that can be executed with specific parameters. * Similar to Gemini CLI's DeclarativeTool concept. * * Tools are now self-describing with metadata for UI/TUI display, * categorization, and schema information. */ interface ExecutableTool : Tool { /** * Tool metadata including display name, icon, category, and schema */ val metadata: ToolMetadata /** * Validates parameters and creates a tool invocation */ fun createInvocation(params: TParams): ToolInvocation /** * Gets the parameter class for this tool */ fun getParameterClass(): String } abstract class BaseExecutableTool : ExecutableTool { abstract override val metadata: ToolMetadata override fun createInvocation(params: TParams): ToolInvocation { return createToolInvocation(params) } protected abstract fun createToolInvocation(params: TParams): ToolInvocation }