package com.gzzm.lobster.tool;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * ProgressSink —— 工具层进度推送管道 / Per-tool progress event pipe.
 *
 * <p>长跑工具（{@code code_exec}、document parser 等）借此向前端实时汇报"正在做什么"，
 * 避免 tool_call → tool_result 之间 10-30s 完全静默. AgentRuntime 构造 ToolContext
 * 时绑定实现，桥接到 {@code StreamEmitter.systemHint} + {@code RunEventBus}.
 *
 * <p>设计立场：
 * <ul>
 *   <li>工具不直接持有 StreamEmitter —— 避免工具层知道 SSE 细节；只通过这个极薄接口发事件</li>
 *   <li>Sink 可能为 null（测试 / 非流式场景）；所有 caller 必须 null-safe</li>
 *   <li>payload 仅含 plain map，不含敏感数据；用于前端 UI 提示而非审计</li>
 * </ul>
 */
public interface ProgressSink {

    /**
     * 发一个进度事件到前端.
     *
     * @param stage 阶段标识（形如 {@code "sandbox.staging"} / {@code "sandbox.running"}）
     * @param message 人可读的一句话提示（会显示在前端气泡下方）
     * @param detail 可选结构化附加信息（如 runId / elapsedMs / producedCount 等）
     */
    void emit(String stage, String message, Map<String, Object> detail);

    /** 简化：仅 message 无 detail. */
    default void emit(String stage, String message) {
        emit(stage, message, Collections.<String, Object>emptyMap());
    }

    /** 简化：带 key/value 一对 detail. */
    default void emit(String stage, String message, String key, Object value) {
        Map<String, Object> d = new LinkedHashMap<>();
        d.put(key, value);
        emit(stage, message, d);
    }

    /** 空实现 —— 用在非流式 / 测试路径. */
    ProgressSink NOOP = new ProgressSink() {
        @Override public void emit(String stage, String message, Map<String, Object> detail) { /* no-op */ }
    };
}
