import { createHash } from "node:crypto";
const SESSION_TTL_MS = 5 * 60 * 1e3;
const CLEANUP_INTERVAL_MS = 2 * 60 * 1e3;
const MAX_SEARCH_ENTRIES = 50;
const MAX_MEMORY_CONTEXT_LENGTH = 500;
const TOOL_CALL_HARD_CAP = 10;
const TOOL_CALL_WINDOW_MS = 60 * 1e3;
const sessions = /* @__PURE__ */ new Map();
function getOrCreateSession(token) {
  let session = sessions.get(token);
  if (!session) {
    session = {
      searchCache: /* @__PURE__ */ new Map(),
      createdAt: Date.now(),
      lastAccessedAt: Date.now(),
      toolCallCount: 0,
      toolCallWindowStart: Date.now()
    };
    sessions.set(token, session);
  }
  session.lastAccessedAt = Date.now();
  return session;
}
function hashCode(code) {
  return createHash("sha256").update(code).digest("hex").slice(0, 16);
}
function evictOldest(map, maxSize) {
  if (map.size <= maxSize) return;
  let oldestKey = null;
  let oldestTime = Infinity;
  for (const [key, entry] of map) {
    if (entry.timestamp < oldestTime) {
      oldestTime = entry.timestamp;
      oldestKey = key;
    }
  }
  if (oldestKey) {
    map.delete(oldestKey);
  }
}
function lookupSearchCache(token, code) {
  const session = sessions.get(token);
  if (!session) return null;
  session.lastAccessedAt = Date.now();
  const key = hashCode(code);
  return session.searchCache.get(key) ?? null;
}
function storeSearchResult(token, code, result, label) {
  const session = getOrCreateSession(token);
  const key = hashCode(code);
  evictOldest(session.searchCache, MAX_SEARCH_ENTRIES);
  session.searchCache.set(key, { result, timestamp: Date.now(), label });
}
function incrementToolCallCount(token) {
  const session = getOrCreateSession(token);
  const now = Date.now();
  if (now - session.toolCallWindowStart > TOOL_CALL_WINDOW_MS) {
    session.toolCallCount = 0;
    session.toolCallWindowStart = now;
  }
  session.toolCallCount++;
  return {
    count: session.toolCallCount,
    exceeded: session.toolCallCount > TOOL_CALL_HARD_CAP
  };
}
function buildMemoryContext(token) {
  const session = sessions.get(token);
  if (!session) return "";
  const searchCount = session.searchCache.size;
  if (searchCount === 0) return "";
  const labels = Array.from(session.searchCache.values()).slice(-3).map((e) => e.label).join(", ");
  const context = `[Memory: ${searchCount} schema searches cached (${labels}). Reuse previous schema results instead of re-calling.]`;
  if (context.length > MAX_MEMORY_CONTEXT_LENGTH) {
    return context.slice(0, MAX_MEMORY_CONTEXT_LENGTH - 3) + "...]";
  }
  return context;
}
function buildSearchLabel(code) {
  const helperMatch = code.match(/spec\.(findEndpoints|describeEndpoint|describeEntity)\s*\(([^)]*)\)/);
  if (helperMatch) {
    return `${helperMatch[1]}(${helperMatch[2].slice(0, 30)})`;
  }
  const cleaned = code.replace(/async\s*\(\)\s*=>\s*/, "").trim();
  return cleaned.slice(0, 40);
}
const cleanupTimer = setInterval(() => {
  const now = Date.now();
  for (const [token, session] of sessions) {
    if (now - session.lastAccessedAt > SESSION_TTL_MS) {
      sessions.delete(token);
    }
  }
}, CLEANUP_INTERVAL_MS);
cleanupTimer.unref();
export {
  buildMemoryContext,
  buildSearchLabel,
  incrementToolCallCount,
  lookupSearchCache,
  storeSearchResult
};
//# sourceMappingURL=session-memory.js.map
