"""记忆中间件:默认加载主记忆,并按需检索主题记忆与活动记录。""" import asyncio import json import os import re from collections.abc import Awaitable, Callable, Iterable, Iterator from datetime import datetime, timedelta from functools import partial from pathlib import Path from typing import Annotated, Any, Literal, NotRequired, Optional, TypedDict import anyio from anyio import Path as AsyncPath from langchain.agents.middleware.types import ( AgentMiddleware, AgentState, ContextT, ModelRequest, ModelResponse, PrivateStateAttr, # noqa ResponseT, ToolCallRequest, ) from langchain_core.messages import AIMessage, HumanMessage, ToolMessage from langchain_core.runnables import RunnableConfig from langchain_core.tools import StructuredTool from langgraph.runtime import Runtime from pydantic import BaseModel, Field from app.agent.middleware.utils import append_to_system_message from app.agent.policy.sanitizer import ( sanitize_for_host, summarize_error, summarize_result, ) from app.agent.tools.tags import ToolTag from app.runtime.log import logger from app.runtime.tasks import TaskRegistry, get_task_registry MAX_MEMORY_FILE_SIZE = 100 * 1024 """默认主记忆文件允许注入上下文的最大字节数。""" MAX_SEARCH_FILE_SIZE = 2 * 1024 * 1024 """按需检索单次读取的文件大小上限。""" MAX_SEARCH_LINE_CHARS = 1200 """记忆检索结果中单行文本的最大字符数。""" MAX_SEARCH_RESULT_CHARS = 32 * 1024 """记忆检索工具单次返回正文的最大字符数。""" DEFAULT_MEMORY_FILE = "MEMORY.md" """保存跨任务稳定偏好与规则的主记忆文件名。""" SEARCH_MEMORY_TOOL_NAME = "search_memory" """统一记忆检索工具名。""" DEFAULT_SEARCH_DAYS = 7 """未指定日期时活动记忆默认检索的最近天数。""" DEFAULT_SEARCH_LIMIT = 20 """记忆检索默认返回条数。""" MAX_SEARCH_LIMIT = 50 """记忆检索单次最多返回条数。""" DEFAULT_RETENTION_DAYS = 7 """活动记忆默认保留天数。""" MAX_LOG_FILE_SIZE = 256 * 1024 """单日活动记忆文件最大字节数。""" MAX_CONTEXT_FOR_SUMMARY = 4000 """生成活动摘要时允许使用的本轮对话最大字符数。""" SUMMARY_SKIP_MARKER = "SKIP" ACTIVITY_ENTRY_PATTERN = re.compile(r"^-\s+\*\*(?P