"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateAiCacheService = generateAiCacheService;
function generateAiCacheService() {
    return /* ts */ `
import { Injectable } from '@nestjs/common'

import { AiConfig } from './ai-config'
import type { ChatMessage } from './model-provider/model-provider.interface'

export type ConversationState = {
  actorKey: string
  pendingToolCallId?: string
  messages: ChatMessage[]
  expiresAt: number
  updatedAt: number
}

@Injectable()
export class AiCacheService {
  private readonly conversationCache = new Map<string, ConversationState>()
  private readonly actorRateLimit = new Map<string, { windowStart: number; requestCount: number }>()

  constructor(private readonly aiConfig: AiConfig) {}

  public createConversation(value: { actorKey: string; pendingToolCallId?: string; messages: ChatMessage[] }): string {
    const conversation = globalThis.crypto.randomUUID() as string
    this.upsertConversation(conversation, value)
    return conversation
  }

  public upsertConversation(
    conversation: string,
    value: { actorKey: string; pendingToolCallId?: string; messages: ChatMessage[] },
  ) {
    const now = Date.now()
    this.pruneConversationCache(now)

    this.conversationCache.set(conversation, {
      ...value,
      updatedAt: now,
      expiresAt: now + this.aiConfig.config.conversationTtlMs,
    })
  }

  public getConversation(conversation: string, actorKey: string): ConversationState | undefined {
    const now = Date.now()
    const value = this.conversationCache.get(conversation)
    if (!value) {
      return undefined
    }
    if (value.actorKey !== actorKey) {
      return undefined
    }
    if (value.expiresAt <= now) {
      this.conversationCache.delete(conversation)
      return undefined
    }

    value.updatedAt = now
    value.expiresAt = now + this.aiConfig.config.conversationTtlMs
    this.conversationCache.set(conversation, value)
    return value
  }

  public deleteConversation(conversation: string, actorKey: string): boolean {
    const history = this.conversationCache.get(conversation)
    if (history?.actorKey !== actorKey) {
      return false
    }

    return this.conversationCache.delete(conversation)
  }

  public assertWithinRateLimit(actorKey: string, now = Date.now()) {
    const current = this.actorRateLimit.get(actorKey)
    if (!current || now - current.windowStart >= this.aiConfig.config.rateLimitWindowMs) {
      this.actorRateLimit.set(actorKey, { windowStart: now, requestCount: 1 })
      return
    }

    current.requestCount += 1
    if (current.requestCount > this.aiConfig.config.rateLimitMaxRequests) {
      throw new Error('AI rate limit exceeded for current user. Please retry shortly.')
    }

    this.actorRateLimit.set(actorKey, current)
  }

  public pruneConversationCache(now = Date.now()) {
    for (const [conversation, value] of this.conversationCache.entries()) {
      if (value.expiresAt <= now) {
        this.conversationCache.delete(conversation)
      }
    }

    if (this.conversationCache.size <= this.aiConfig.config.conversationCacheMaxSize) {
      return
    }

    const entries = [...this.conversationCache.entries()].sort((left, right) => left[1].updatedAt - right[1].updatedAt)
    const excess = this.conversationCache.size - this.aiConfig.config.conversationCacheMaxSize
    for (const [conversation] of entries.slice(0, excess)) {
      this.conversationCache.delete(conversation)
    }
  }
}
`;
}
//# sourceMappingURL=ai-cache-service.generator.js.map