package com.xly.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ChatMessageDeserializer;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.ToolExecutionResultMessage;
import dev.langchain4j.data.message.UserMessage;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 事件日志的**唯一**投影/渲染器 —— 前端历史与 LLM 上下文同源于 {@link LedgerService} 的事件流,
* 文案在这一处生成,不再散落在各控制器里。
*
*
LLM 上下文四段式({@link #project}):
*
* - 稳定 system prompt(KV 前缀稳定);
* - 进行中流程卡(激活 skill 全文 + 在办单据状态)——钉在 system 尾部,不参与截断,
* 提议 executed/cancelled 或新 skill 激活时摘下;
* - 往事摘要区:预算外旧轮 → 确定性一行摘要(零模型调用);
* - 近期原文区:约 charBudget 字符按**整轮**纳入;旧轮工具结果压 {@value #TOOL_DIGEST_LEN} 字;
* 当前轮(最后一个用户事件起)原样载荷精确重建,工具调用/结果配对不可破坏。
*
*/
@Service
public class EventProjectionService {
public static final int TOOL_DIGEST_LEN = 120;
private static final int DIGEST_TURNS_MAX = 40;
private static final int DIGEST_LINE_LEN = 90;
private final ObjectMapper mapper;
public EventProjectionService(ObjectMapper mapper) {
this.mapper = mapper;
}
// ---------------------------------------------------------------- LLM 投影
/** 四段式 LLM 上下文。systemText 为空时不出 system 消息(如测试)。 */
public List project(String systemText, List