from __future__ import annotations from typing import Any from .client import MemoryGatewayClient from .config import PluginConfig, load_config from .policy import build_episode_summary, should_append_episode, should_commit_session, should_search_memory from .tools import memory_append_episode, memory_commit_session, memory_search def _get(context: dict[str, Any], key: str, default: str = "") -> str: value = context.get(key, default) return "" if value is None else str(value) def compact_memory_context(search_result: dict[str, Any], limit: int = 5) -> str: if not search_result.get("ok"): return "" data = search_result.get("data", {}) rows = [] for item in data.get("results", [])[:limit]: memory = item.get("memory") or item.get("openviking") or {} summary = memory.get("summary") or memory.get("abstract") or memory.get("content") or "" namespace = memory.get("namespace", "") memory_id = memory.get("id") or memory.get("uri") or "" if summary: rows.append(f"- {memory_id} [{namespace}]: {summary[:240]}") return "\n".join(rows) def on_conversation_start(context: dict[str, Any], client: MemoryGatewayClient | None = None, config: PluginConfig | None = None) -> dict[str, Any]: cfg = config or load_config() user_message = _get(context, "user_message") or _get(context, "query") if not should_search_memory(user_message, context, cfg): return {"ok": True, "memory_context": ""} user_id = _get(context, "user_id", cfg.default_user_id) if not user_id: return {"ok": False, "error": "user_id_required"} try: limit_val = int(context.get("limit", 5)) except (ValueError, TypeError): limit_val = 5 result = memory_search( query=user_message, user_id=user_id, agent_id=_get(context, "agent_id", cfg.default_agent_id), workspace_id=_get(context, "workspace_id", cfg.default_workspace_id), session_id=_get(context, "session_id"), limit=limit_val, client=client, ) return {"ok": result.get("ok", False), "memory_context": compact_memory_context(result), "raw": result} def after_user_message(context: dict[str, Any], client: MemoryGatewayClient | None = None, config: PluginConfig | None = None) -> dict[str, Any]: cfg = config or load_config() user_message = _get(context, "user_message") assistant_response = _get(context, "assistant_response") if not should_append_episode(user_message, assistant_response, context, cfg): return {"ok": True, "appended": False, "reason": "policy_skip"} user_id = _get(context, "user_id", cfg.default_user_id) session_id = _get(context, "session_id") if not user_id or not session_id: return {"ok": False, "error": "user_id_and_session_id_required"} summary = build_episode_summary(user_message, assistant_response, context) result = memory_append_episode( user_id=user_id, agent_id=_get(context, "agent_id", cfg.default_agent_id), workspace_id=_get(context, "workspace_id", cfg.default_workspace_id), session_id=session_id, episode_summary=summary, tags=["plugin-candidate"], client=client, ) return {"ok": result.get("ok", False), "appended": result.get("ok", False), "raw": result} def after_task_complete(context: dict[str, Any], client: MemoryGatewayClient | None = None, config: PluginConfig | None = None) -> dict[str, Any]: return _maybe_commit(context, client, config) def on_session_end(context: dict[str, Any], client: MemoryGatewayClient | None = None, config: PluginConfig | None = None) -> dict[str, Any]: return _maybe_commit(context, client, config) def _maybe_commit(context: dict[str, Any], client: MemoryGatewayClient | None, config: PluginConfig | None) -> dict[str, Any]: cfg = config or load_config() if not should_commit_session(context, cfg): return {"ok": True, "committed": False, "reason": "auto_commit_disabled"} user_id = _get(context, "user_id", cfg.default_user_id) session_id = _get(context, "session_id") if not user_id or not session_id: return {"ok": False, "error": "user_id_and_session_id_required"} try: min_importance_val = float(context.get("min_importance", 0.6)) except (ValueError, TypeError): min_importance_val = 0.6 result = memory_commit_session( user_id=user_id, agent_id=_get(context, "agent_id", cfg.default_agent_id), workspace_id=_get(context, "workspace_id", cfg.default_workspace_id), session_id=session_id, min_importance=min_importance_val, client=client, ) return {"ok": result.get("ok", False), "committed": result.get("ok", False), "raw": result}