package com.easyagents.agent.runtime.agentscope;

import com.easyagents.agent.runtime.AgentRuntimeException;
import com.easyagents.agent.runtime.AgentRuntimeExecutionContext;
import com.easyagents.agent.runtime.event.*;
import com.easyagents.agent.runtime.hitl.AgentPendingState;
import com.easyagents.agent.runtime.hitl.AgentToolApprovalCoordinator;
import com.easyagents.agent.runtime.hitl.AgentToolApprovalRejectedException;
import com.easyagents.agent.runtime.skill.AgentSkillBinding;
import com.easyagents.agent.runtime.skill.AgentSkillRuntimeContext;
import com.easyagents.agent.runtime.tool.AgentToolContext;
import com.easyagents.agent.runtime.tool.AgentToolInvoker;
import com.easyagents.agent.runtime.tool.AgentToolResult;
import com.easyagents.agent.runtime.tool.AgentToolSpec;
import io.agentscope.core.message.TextBlock;
import io.agentscope.core.message.ToolResultBlock;
import io.agentscope.core.message.ToolUseBlock;
import io.agentscope.core.tool.AgentTool;
import io.agentscope.core.tool.ToolCallParam;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;

import java.time.Instant;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 将运行时工具适配为 AgentScope 工具。
 */
public class AgentScopeToolAdapter {

    /**
     * 将运行时工具声明和调用器转换为 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行请求
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec, AgentToolInvoker invoker, AgentRuntimeExecutionContext request) {
        return adapt(toolSpec, invoker, request, AgentToolApprovalCoordinator.disabled(),
                (Sinks.Many<AgentRuntimeEvent>) null);
    }

    /**
     * 将运行时工具声明和调用器转换为带事件 sink 的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行请求
     * @param eventSink 事件 sink
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           Sinks.Many<AgentRuntimeEvent> eventSink) {
        return adapt(toolSpec, invoker, request, AgentToolApprovalCoordinator.disabled(), fixedHolder(request, eventSink),
                null, null);
    }

    /**
     * 将运行时工具声明和调用器转换为带审批协调器和事件 sink 的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行请求
     * @param approvalCoordinator 审批协调器
     * @param eventSink 事件 sink
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           Sinks.Many<AgentRuntimeEvent> eventSink) {
        return adapt(toolSpec, invoker, request, approvalCoordinator, fixedHolder(request, eventSink), null, null);
    }

    /**
     * 将运行时工具声明和调用器转换为带 Skill 归属的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行请求
     * @param approvalCoordinator 审批协调器
     * @param eventSink 事件 sink
     * @param skillBinding Skill 绑定关系
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           Sinks.Many<AgentRuntimeEvent> eventSink,
                           AgentSkillBinding skillBinding) {
        return adapt(toolSpec, invoker, request, approvalCoordinator, fixedHolder(request, eventSink), null, skillBinding);
    }

    /**
     * 将运行时工具声明和调用器转换为带 Skill 上下文的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行请求
     * @param approvalCoordinator 审批协调器
     * @param eventSink 事件 sink
     * @param skillContext Skill 运行时上下文
     * @param skillBinding Skill 静态绑定关系
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           Sinks.Many<AgentRuntimeEvent> eventSink,
                           AgentSkillRuntimeContext skillContext,
                           AgentSkillBinding skillBinding) {
        return adapt(toolSpec, invoker, request, approvalCoordinator, fixedHolder(request, eventSink), skillContext, skillBinding);
    }

    /**
     * 将运行时工具声明和调用器转换为可读取当前运行轮次的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行时级上下文
     * @param approvalCoordinator 审批协调器
     * @param turnContextHolder 当前运行轮次上下文持有器
     * @param skillContext Skill 运行时上下文
     * @param skillBinding Skill 静态绑定关系
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           AgentRuntimeTurnContextHolder turnContextHolder,
                           AgentSkillRuntimeContext skillContext,
                           AgentSkillBinding skillBinding) {
        return adapt(toolSpec, invoker, request, approvalCoordinator, turnContextHolder, skillContext, skillBinding, true);
    }

    /**
     * 将运行时工具声明和调用器转换为可读取当前运行轮次的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行时级上下文
     * @param approvalCoordinator 审批协调器
     * @param turnContextHolder 当前运行轮次上下文持有器
     * @param skillContext Skill 运行时上下文
     * @param skillBinding Skill 静态绑定关系
     * @param emitNormalToolResult 是否由 adapter 发出普通工具结果旁路事件
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           AgentRuntimeTurnContextHolder turnContextHolder,
                           AgentSkillRuntimeContext skillContext,
                           AgentSkillBinding skillBinding,
                           boolean emitNormalToolResult) {
        if (toolSpec == null || toolSpec.getName() == null) {
            throw new AgentRuntimeException("Agent tool spec and name are required.");
        }
        if (invoker == null) {
            throw new AgentRuntimeException("Agent tool invoker is required: " + toolSpec.getName());
        }
        return new RuntimeAgentTool(toolSpec, invoker, request, approvalCoordinator, turnContextHolder,
                skillContext, skillBinding, emitNormalToolResult, true, true,
                resolveInvocationClassLoader(invoker));
    }

    /**
     * 将运行时工具声明和调用器转换为可读取当前运行轮次的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行时级上下文
     * @param approvalCoordinator 审批协调器
     * @param turnContextHolder 当前运行轮次上下文持有器
     * @param skillContext Skill 运行时上下文
     * @param skillBinding Skill 静态绑定关系
     * @param emitNormalToolResult 是否由 adapter 发出普通工具结果旁路事件
     * @param emitSkillStep 是否由 adapter 发出 Skill 步骤旁路事件
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           AgentRuntimeTurnContextHolder turnContextHolder,
                           AgentSkillRuntimeContext skillContext,
                           AgentSkillBinding skillBinding,
                           boolean emitNormalToolResult,
                           boolean emitSkillStep) {
        if (toolSpec == null || toolSpec.getName() == null) {
            throw new AgentRuntimeException("Agent tool spec and name are required.");
        }
        if (invoker == null) {
            throw new AgentRuntimeException("Agent tool invoker is required: " + toolSpec.getName());
        }
        return new RuntimeAgentTool(toolSpec, invoker, request, approvalCoordinator, turnContextHolder,
                skillContext, skillBinding, emitNormalToolResult, emitSkillStep, true,
                resolveInvocationClassLoader(invoker));
    }

    /**
     * 将运行时工具声明和调用器转换为可读取当前运行轮次的 AgentScope AgentTool。
     *
     * @param toolSpec 工具声明
     * @param invoker 工具调用器
     * @param request 运行时级上下文
     * @param approvalCoordinator 审批协调器
     * @param turnContextHolder 当前运行轮次上下文持有器
     * @param skillContext Skill 运行时上下文
     * @param skillBinding Skill 静态绑定关系
     * @param emitNormalToolResult 是否由 adapter 发出普通工具结果旁路事件
     * @param emitSkillStep 是否由 adapter 发出 Skill 步骤旁路事件
     * @param handleApprovalInTool 是否在工具执行阶段处理审批
     * @return AgentScope 工具
     */
    public AgentTool adapt(AgentToolSpec toolSpec,
                           AgentToolInvoker invoker,
                           AgentRuntimeExecutionContext request,
                           AgentToolApprovalCoordinator approvalCoordinator,
                           AgentRuntimeTurnContextHolder turnContextHolder,
                           AgentSkillRuntimeContext skillContext,
                           AgentSkillBinding skillBinding,
                           boolean emitNormalToolResult,
                           boolean emitSkillStep,
                           boolean handleApprovalInTool) {
        if (toolSpec == null || toolSpec.getName() == null) {
            throw new AgentRuntimeException("Agent tool spec and name are required.");
        }
        if (invoker == null) {
            throw new AgentRuntimeException("Agent tool invoker is required: " + toolSpec.getName());
        }
        return new RuntimeAgentTool(toolSpec, invoker, request, approvalCoordinator, turnContextHolder,
                skillContext, skillBinding, emitNormalToolResult, emitSkillStep, handleApprovalInTool,
                resolveInvocationClassLoader(invoker));
    }

    /**
     * 解析工具执行时应使用的应用类加载器。
     *
     * <p>AgentScope 可能在 Reactor 工作线程执行工具。Spring Boot 可执行包中的业务类依赖
     * 注册工具时的应用类加载器，不能依赖工作线程可能继承到的系统类加载器。</p>
     *
     * @param invoker 工具调用器
     * @return 工具调用器所属类加载器；无法取得时回退到当前线程上下文类加载器
     */
    private ClassLoader resolveInvocationClassLoader(AgentToolInvoker invoker) {
        ClassLoader invokerClassLoader = invoker.getClass().getClassLoader();
        return invokerClassLoader == null
                ? Thread.currentThread().getContextClassLoader()
                : invokerClassLoader;
    }

    private AgentRuntimeTurnContextHolder fixedHolder(AgentRuntimeExecutionContext request,
                                                      Sinks.Many<AgentRuntimeEvent> eventSink) {
        AgentRuntimeTurnContextHolder holder = new AgentRuntimeTurnContextHolder();
        AgentRuntimeEventBridge bridge = new AgentRuntimeEventBridge(request, holder);
        holder.set(new AgentRuntimeTurnContext(null, eventSink, bridge));
        return holder;
    }

    private record RuntimeAgentTool(AgentToolSpec toolSpec,
                                    AgentToolInvoker invoker,
                                    AgentRuntimeExecutionContext request,
                                    AgentToolApprovalCoordinator approvalCoordinator,
                                    AgentRuntimeTurnContextHolder turnContextHolder,
                                    AgentSkillRuntimeContext skillContext,
                                    AgentSkillBinding skillBinding,
                                    boolean emitNormalToolResult,
                                    boolean emitSkillStep,
                                    boolean handleApprovalInTool,
                                    ClassLoader invocationClassLoader) implements AgentTool {

            /**
             * 获取工具名称。
             *
             * @return 工具名称
             */
            @Override
            public String getName() {
                return toolSpec.getName();
            }

            /**
             * 获取工具描述。
             *
             * @return 工具描述
             */
            @Override
            public String getDescription() {
                return toolSpec.getDescription();
            }

            /**
             * 获取工具参数 Schema。
             *
             * @return 参数 Schema
             */
            @Override
            public Map<String, Object> getParameters() {
                return toolSpec.getParametersSchema();
            }

            /**
             * 获取输出 Schema。
             *
             * @return 输出 Schema
             */
            @Override
            public Map<String, Object> getOutputSchema() {
                return toolSpec.getOutputSchema();
            }

            /**
             * 调用运行时工具。
             *
             * @param param 工具调用参数
             * @return 工具结果块
             */
            @Override
            public Mono<ToolResultBlock> callAsync(ToolCallParam param) {
                AgentRuntimeEvent startEvent = toolExecutionStartEvent(param == null ? null : param.getToolUseBlock());
                if (startEvent != null) {
                    emit(startEvent);
                }
                Map<String, Object> input = param == null || param.getInput() == null
                    ? new LinkedHashMap<>()
                    : new LinkedHashMap<>(param.getInput());
                if (handleApprovalInTool && toolSpec.isApprovalRequired()) {
                    if (approvalCoordinator == null) {
                        throw new AgentRuntimeException("Agent tool approval coordinator is required: " + toolSpec.getName());
                    }
                    Instant expiresAt = Instant.now().plus(
                            toolSpec.getApprovalRequest() != null && toolSpec.getApprovalRequest().getTimeout() != null
                                    ? toolSpec.getApprovalRequest().getTimeout()
                                    : java.time.Duration.ofMinutes(30));
                    AgentPendingState pendingState = approvalCoordinator.register(
                            request.getSessionId(),
                            request.getAgentDefinition().getAgentId(),
                            param != null && param.getToolUseBlock() != null ? param.getToolUseBlock().getId() : null,
                            toolSpec.getName(),
                            approvalPrompt(toolSpec.getApprovalRequest() == null ? null : toolSpec.getApprovalRequest().getApprovalPrompt()),
                            input,
                            toolSpec.getApprovalRequest() == null ? new LinkedHashMap<>() : toolSpec.getApprovalRequest().getMetadata(),
                            expiresAt);
                    AgentRuntimeEvent approvalEvent = toolApprovalRequiredEvent(param == null ? null : param.getToolUseBlock(), pendingState);
                    pendingState.setEventId(approvalEvent.getEventId());
                    emit(approvalEvent);
                    return approvalCoordinator.await(pendingState.getResumeToken())
                            .flatMap(response -> {
                                if (!response.isApproved()) {
                                    return Mono.error(new AgentToolApprovalRejectedException(
                                        response.getRejectReason()));
                                }
                                return Mono.fromCallable(() -> invokeTool(param, input));
                            });
                }
                return Mono.fromCallable(() -> invokeTool(param, input));
            }

            /**
             * 构建中立工具上下文。
             *
             * @param param 工具调用参数
             * @return 工具上下文
             */
            private AgentToolContext buildContext(ToolCallParam param) {
                AgentRuntimeExecutionContext currentRequest = currentRequest();
                AgentToolContext context = new AgentToolContext();
                context.setRequestId(currentRequest.getRequestId());
                context.setTraceId(currentRequest.getTraceId());
                context.setSessionId(currentRequest.getSessionId());
                context.setAgentId(currentRequest.getAgentDefinition().getAgentId());
                context.setRuntimeContext(currentRequest.getRuntimeContext());
                if (param != null && param.getToolUseBlock() != null) {
                    context.setToolCallId(param.getToolUseBlock().getId());
                }
                context.setEventEmitter(this::emit);
                context.getMetadata().put("toolName", toolSpec.getName());
                context.getMetadata().put("category", toolSpec.getCategory());
                appendSkillPayload(context.getMetadata(), activeSkillBinding());
                context.getMetadata().putAll(toolSpec.getMetadata());
                return context;
            }

            /**
             * 将 AgentToolResult 转换为 AgentScope 结果块。
             *
             * @param param  工具调用参数
             * @param result 运行时结果
             * @return AgentScope 结果块
             */
            private ToolResultBlock toToolResultBlock(ToolCallParam param, AgentToolResult result) {
                AgentToolResult safeResult = result == null ? AgentToolResult.failure("Tool returned null result.") : result;
                Map<String, Object> metadata = new LinkedHashMap<>(safeResult.getMetadata());
                metadata.put("success", safeResult.isSuccess());
                metadata.put("visibility", toolSpec.getVisibility().name());
                metadata.put("displayContent", safeResult.getDisplayContent());
                appendSkillPayload(metadata, activeSkillBinding());
                String output = safeResult.getModelContent();
                if (output == null || output.isEmpty()) {
                    output = safeResult.isSuccess() ? "" : safeResult.getErrorMessage();
                }
                String id = param != null && param.getToolUseBlock() != null ? param.getToolUseBlock().getId() : null;
                return ToolResultBlock.of(id, toolSpec.getName(), TextBlock.builder().text(output).build(), metadata);
            }

            /**
             * 执行真实工具。
             *
             * @param param 工具调用参数
             * @param input 工具输入
             * @return 工具结果块
             */
            private ToolResultBlock invokeTool(ToolCallParam param, Map<String, Object> input) {
                Thread currentThread = Thread.currentThread();
                ClassLoader originalClassLoader = currentThread.getContextClassLoader();
                boolean switchClassLoader = invocationClassLoader != null
                        && invocationClassLoader != originalClassLoader;
                if (switchClassLoader) {
                    currentThread.setContextClassLoader(invocationClassLoader);
                }
                try {
                    AgentToolContext context = buildContext(param);
                    AgentToolResult result = invoker.invoke(input, context);
                    ToolResultBlock block = toToolResultBlock(param, result);
                    // 有状态 runtime 中，普通工具结果由 AgentScope 原生 PostActingEvent
                    // 旁路观察器统一发出；旧 sink 辅助路径没有统一 hook，因此仍允许 adapter 兼容发射。
                    if (emitNormalToolResult || (emitSkillStep && activeSkillBinding() != null)) {
                        emit(toolResultEvent(block));
                    }
                    return block;
                } finally {
                    if (switchClassLoader) {
                        currentThread.setContextClassLoader(originalClassLoader);
                    }
                }
            }

            /**
             * 通过旁路事件桥发射事件。
             *
             * <p>这里发射的是 Easy-Agents 对调用方的监察/交互事件，不是 AgentScope
             * 主线路消息。主线路的 tool_call/tool_result 顺序仍由 AgentScope 自己维护。</p>
             *
             * @param event 事件
             */
            private void emit(AgentRuntimeEvent event) {
                currentEventBridge().emit(event);
            }

            /**
             * 构建工具执行开始事件。
             * 普通工具调用由 AgentScope stream 的 ToolUseBlock 表达，这里仅为已激活 Skill 发射步骤事件。
             *
             * @param block 工具使用块
             * @return Skill 步骤事件，普通工具返回 null
             */
            private AgentRuntimeEvent toolExecutionStartEvent(ToolUseBlock block) {
                AgentSkillBinding activeBinding = activeSkillBinding();
                if (!emitSkillStep || activeBinding == null) {
                    return null;
                }
                AgentRuntimeEvent event = baseEvent(AgentRuntimeEventType.SKILL_STEP);
                if (block != null) {
                    event.setToolCallId(block.getId());
                    event.getPayload().put("name", block.getName());
                    event.getPayload().put("toolName", block.getName());
                    event.getPayload().put("input", block.getInput());
                    event.getPayload().put("content", block.getContent());
                    event.getMetadata().putAll(block.getMetadata() == null ? new LinkedHashMap<>() : block.getMetadata());
                } else {
                    event.getPayload().put("name", toolSpec.getName());
                    event.getPayload().put("toolName", toolSpec.getName());
                }
                if (activeBinding != null) {
                    appendSkillPayload(event.getPayload(), activeBinding);
                    event.getPayload().put("stepType", "TOOL_CALL");
                    event.getPayload().put("stepName", toolSpec.getName());
                    event.getPayload().put("status", "RUNNING");
                }
                return event;
            }

            /**
             * 构建工具结果事件。
             *
             * @param block 工具结果块
             * @return 运行时事件
             */
            private AgentRuntimeEvent toolResultEvent(ToolResultBlock block) {
                AgentSkillBinding activeBinding = activeSkillBinding();
                AgentRuntimeEvent event = baseEvent(activeBinding == null
                        ? AgentRuntimeEventType.TOOL_RESULT
                        : AgentRuntimeEventType.SKILL_STEP);
                if (block != null) {
                    event.setToolCallId(block.getId());
                    event.getPayload().put("name", block.getName());
                    event.getPayload().put("toolName", block.getName());
                    event.getPayload().put("text", block.toString());
                    event.getPayload().put("suspended", block.isSuspended());
                    event.getMetadata().putAll(block.getMetadata() == null ? new LinkedHashMap<>() : block.getMetadata());
                }
                if (activeBinding != null) {
                    appendSkillPayload(event.getPayload(), activeBinding);
                    event.getPayload().put("stepType", "TOOL_RESULT");
                    event.getPayload().put("stepName", toolSpec.getName());
                    event.getPayload().put("status", success(event) ? "SUCCESS" : "FAILED");
                    event.getPayload().put("success", success(event));
                }
                return event;
            }

            /**
             * 根据挂起的工具结果构建工具审批事件。
             *
             * @param toolUseBlock 工具使用块
             * @param resultBlock  工具结果块
             * @return 工具审批事件
             */
            private AgentRuntimeEvent toolApprovalRequiredEvent(ToolUseBlock toolUseBlock, AgentPendingState pendingState) {
                AgentRuntimeExecutionContext currentRequest = currentRequest();
                AgentRuntimeEvent event = baseEvent(AgentRuntimeEventType.TOOL_APPROVAL_REQUIRED);
                if (pendingState != null && pendingState.getToolCallId() != null) {
                    event.setToolCallId(pendingState.getToolCallId());
                }
                Map<String, Object> payload = new LinkedHashMap<>();
                payload.put("resumeToken", pendingState == null || pendingState.getResumeToken() == null
                        ? UUID.randomUUID().toString()
                        : pendingState.getResumeToken().getValue());
                payload.put("sessionId", currentRequest.getSessionId());
                payload.put("agentId", currentRequest.getAgentDefinition().getAgentId());
                payload.put("approvalPrompt", approvalPrompt(pendingState == null ? null : pendingState.getApprovalPrompt()));
                payload.put("approvalMetadata", pendingState == null ? new LinkedHashMap<>() : pendingState.getMetadata());
                payload.put("toolInput", pendingState == null ? new LinkedHashMap<>() : pendingState.getToolInput());
                payload.put("toolName", pendingState == null ? toolSpec.getName() : pendingState.getToolName());
                payload.put("expiresAt", pendingState == null || pendingState.getExpiresAt() == null ? null : pendingState.getExpiresAt().toString());
                appendSkillPayload(payload, activeSkillBinding());
                if (toolUseBlock != null) {
                    payload.put("toolCallId", toolUseBlock.getId());
                    payload.put("toolName", toolUseBlock.getName());
                    payload.put("input", toolUseBlock.getInput());
                }
                event.setPayload(payload);
                return event;
            }

            /**
             * 解析审批文案。
             *
             * @param approvalPrompt 审批文案
             * @return 审批文案
             */
            private String approvalPrompt(String approvalPrompt) {
                if (approvalPrompt != null && !approvalPrompt.isBlank()) {
                    return approvalPrompt;
                }
                return "是否批准执行该工具？";
            }

            /**
             * 构建带请求身份信息的事件。
             *
             * @param type 事件类型
             * @return 运行时事件
             */
            private AgentRuntimeEvent baseEvent(AgentRuntimeEventType type) {
                AgentRuntimeExecutionContext currentRequest = currentRequest();
                AgentRuntimeEvent event = currentEventBridge().event(type);
                event.getMetadata().put("toolCategory", toolSpec.getCategory().name());
                event.getMetadata().put("visibility", toolSpec.getVisibility().name());
                appendSkillPayload(event.getMetadata(), activeSkillBinding());
                return event;
            }

            /**
             * 追加 Skill 归属字段。
             *
             * @param target 目标 Map
             * @param binding Skill 绑定关系
             */
            private void appendSkillPayload(Map<String, Object> target, AgentSkillBinding binding) {
                if (binding == null || target == null) {
                    return;
                }
                target.put("skillId", binding.getSkillId());
                target.put("skillName", binding.getSkillName());
                target.put("skillDisplayName", binding.getSkillDisplayName());
                target.put("skillBoxId", binding.getSkillBoxId());
            }

            /**
             * 获取当前已激活的 Skill 绑定关系。
             *
             * @return 已激活绑定关系
             */
            private AgentSkillBinding activeSkillBinding() {
                if (skillBinding == null) {
                    return null;
                }
                if (skillContext == null) {
                    return skillBinding;
                }
                return skillContext.getActiveToolBinding(toolSpec.getName());
            }

            /**
             * 从事件元数据判断工具结果是否成功。
             *
             * @param event 运行时事件
             * @return 成功时为 true
             */
            private boolean success(AgentRuntimeEvent event) {
                Object success = event.getMetadata().get("success");
                return !(success instanceof Boolean) || Boolean.TRUE.equals(success);
            }

            private AgentRuntimeExecutionContext currentRequest() {
                return turnContextHolder == null ? request : turnContextHolder.executionContext(request);
            }

            private AgentRuntimeEventBridge currentEventBridge() {
                if (turnContextHolder != null && turnContextHolder.eventBridge().isPresent()) {
                    return turnContextHolder.eventBridge().get();
                }
                return new AgentRuntimeEventBridge(request, turnContextHolder);
            }
        }
}
