unforgit 0.5.1 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-CKUDYQYP.js +3652 -0
- package/dist/chunk-CKUDYQYP.js.map +1 -0
- package/dist/index.js +167 -237
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +1138 -0
- package/dist/mcp.js.map +1 -0
- package/package.json +18 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../packages/core/src/lifecycle.ts","../../../packages/core/src/lifecycle-scheduler.ts","../../../packages/core/src/recall.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/embeddings.ts","../../../packages/core/src/llm.ts","../../../packages/core/src/quality.ts","../../../packages/core/src/suggestions.ts","../../../packages/core/src/auto-consolidate.ts","../../../packages/core/src/auto-consolidate-remote.ts","../../../packages/core/src/auto-link.ts","../../../packages/core/src/notifications.ts","../../../packages/core/src/lifecycle-maintenance.ts","../../../packages/core/src/sync-service.ts","../../../packages/core/src/templates.ts","../../../packages/config/src/config.ts","../../../packages/config/src/config-schemas.ts","../../../packages/config/src/remote-client.ts","../../../packages/db/src/local.ts","../../../packages/db/src/generated/prisma/client.ts","../../../packages/db/src/generated/prisma/internal/class.ts","../../../packages/db/src/generated/prisma/internal/prismaNamespace.ts","../../../packages/db/src/remote.ts"],"sourcesContent":["import type {\n CreateMemoryInput,\n LifecycleConfig,\n LifecycleMaintenanceConfig,\n LifecycleUsageBoostConfig,\n LifecycleTtlConfig,\n Memory,\n MemoryType,\n} from \"unforgit-shared\";\n\nexport interface ResolvedLifecycleConfig {\n ttlSecondsByType: LifecycleTtlConfig;\n usageBoost: LifecycleUsageBoostConfig;\n maintenance: LifecycleMaintenanceConfig;\n}\n\nconst DEFAULT_TTL_SECONDS_BY_TYPE: LifecycleTtlConfig = {\n episodic: 30 * 24 * 60 * 60,\n semantic: undefined,\n procedural: undefined,\n};\n\nconst DEFAULT_USAGE_BOOST: LifecycleUsageBoostConfig = {\n enabled: true,\n topKToRecord: 5,\n minUsageCount: 2,\n maxBoost: 0.15,\n halfLifeDays: 30,\n};\n\nconst DEFAULT_MAINTENANCE: LifecycleMaintenanceConfig = {\n staleEpisodicDays: 30,\n consolidationThreshold: 0.5,\n consolidationMinGroupSize: 2,\n consolidationMaxGroups: 5,\n promoteRecallCount: 5,\n pinRecallCount: 8,\n dryRunDefault: true,\n autoRunOnStore: true,\n autoRunOnRecall: true,\n debounceMs: 30_000,\n};\n\nexport function resolveLifecycleConfig(\n config?: LifecycleConfig,\n): ResolvedLifecycleConfig {\n return {\n ttlSecondsByType: {\n ...DEFAULT_TTL_SECONDS_BY_TYPE,\n ...(config?.ttlSecondsByType ?? {}),\n },\n usageBoost: {\n ...DEFAULT_USAGE_BOOST,\n ...(config?.usageBoost ?? {}),\n },\n maintenance: {\n ...DEFAULT_MAINTENANCE,\n ...(config?.maintenance ?? {}),\n },\n };\n}\n\nexport function getDefaultTtlSeconds(\n memoryType: MemoryType,\n lifecycle?: LifecycleConfig,\n): number | undefined {\n return resolveLifecycleConfig(lifecycle).ttlSecondsByType[memoryType];\n}\n\nexport function applyLifecycleDefaults(\n input: CreateMemoryInput,\n lifecycle?: LifecycleConfig,\n): CreateMemoryInput {\n if (input.ttlSeconds !== undefined) {\n return input;\n }\n\n const ttlSeconds = getDefaultTtlSeconds(input.memoryType, lifecycle);\n if (ttlSeconds === undefined) {\n return input;\n }\n\n return {\n ...input,\n ttlSeconds,\n };\n}\n\nexport function isExpiredTtl(\n createdAt: Date,\n ttlSeconds?: number,\n now: Date = new Date(),\n): boolean {\n if (!ttlSeconds || ttlSeconds <= 0) {\n return false;\n }\n\n return createdAt.getTime() + ttlSeconds * 1000 <= now.getTime();\n}\n\nexport function isMemoryExpired(\n memory: Pick<Memory, \"createdAt\" | \"ttlSeconds\" | \"status\">,\n now: Date = new Date(),\n): boolean {\n if (memory.status === \"deleted\") {\n return false;\n }\n\n return isExpiredTtl(memory.createdAt, memory.ttlSeconds, now);\n}\n\nexport function computeUsageBoost(\n usageCount: number,\n lastUsed?: Date,\n lifecycle?: LifecycleConfig,\n now: Date = new Date(),\n): number {\n const { usageBoost } = resolveLifecycleConfig(lifecycle);\n\n if (!usageBoost.enabled || usageCount < usageBoost.minUsageCount) {\n return 0;\n }\n\n const effectiveCount = usageCount - usageBoost.minUsageCount + 1;\n const usageFactor = 1 - Math.exp(-effectiveCount / usageBoost.minUsageCount);\n\n const ageDays = lastUsed\n ? Math.max(0, (now.getTime() - lastUsed.getTime()) / (1000 * 60 * 60 * 24))\n : usageBoost.halfLifeDays;\n const recencyFactor = Math.exp(-ageDays / usageBoost.halfLifeDays);\n\n return Math.min(usageBoost.maxBoost, usageBoost.maxBoost * usageFactor * recencyFactor);\n}\n","export interface LifecycleSchedulerOptions {\n debounceMs: number;\n onError?: (error: unknown, context: { orgId: string; repoId: string }) => void;\n}\n\ntype LifecycleRunner = (orgId: string, repoId: string) => Promise<void>;\n\ninterface SchedulerState {\n timer?: ReturnType<typeof setTimeout>;\n running: boolean;\n pending: boolean;\n orgId: string;\n repoId: string;\n}\n\nexport class LifecycleScheduler {\n private states = new Map<string, SchedulerState>();\n\n constructor(\n private readonly runner: LifecycleRunner,\n private readonly options: LifecycleSchedulerOptions,\n ) {}\n\n schedule(orgId: string, repoId: string): void {\n const key = `${orgId}:${repoId}`;\n const state = this.states.get(key) ?? {\n running: false,\n pending: false,\n orgId,\n repoId,\n };\n\n state.orgId = orgId;\n state.repoId = repoId;\n\n if (state.running) {\n state.pending = true;\n this.states.set(key, state);\n return;\n }\n\n if (state.timer) {\n clearTimeout(state.timer);\n }\n\n state.timer = setTimeout(() => {\n void this.run(key);\n }, this.options.debounceMs);\n\n this.states.set(key, state);\n }\n\n dispose(): void {\n for (const state of this.states.values()) {\n if (state.timer) {\n clearTimeout(state.timer);\n }\n }\n\n this.states.clear();\n }\n\n private async run(key: string): Promise<void> {\n const state = this.states.get(key);\n if (!state) {\n return;\n }\n\n state.timer = undefined;\n state.running = true;\n this.states.set(key, state);\n\n try {\n await this.runner(state.orgId, state.repoId);\n } catch (error) {\n this.options.onError?.(error, {\n orgId: state.orgId,\n repoId: state.repoId,\n });\n } finally {\n state.running = false;\n\n if (state.pending) {\n state.pending = false;\n this.states.set(key, state);\n this.schedule(state.orgId, state.repoId);\n } else {\n this.states.delete(key);\n }\n }\n }\n}\n","import type { RecallResult } from \"unforgit-shared\";\n\nfunction recencyScore(createdAt: Date): number {\n const ageMs = Date.now() - createdAt.getTime();\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n return Math.max(0, 1 - ageDays / 365);\n}\n\nexport function rankResults(results: RecallResult[]): RecallResult[] {\n return results.sort((a, b) => b.score - a.score);\n}\n\nexport function computeCompositeScore(\n textScore: number,\n createdAt: Date,\n confidence?: number,\n usageBoost = 0,\n): number {\n const recency = recencyScore(createdAt);\n const conf = confidence ?? 0.5;\n return Math.min(1, textScore * 0.55 + recency * 0.15 + conf * 0.15 + usageBoost);\n}\n\nexport function computeHybridScore(\n ftsScore: number,\n embeddingScore: number,\n createdAt: Date,\n confidence?: number,\n usageBoost = 0,\n): number {\n const recency = recencyScore(createdAt);\n const conf = confidence ?? 0.5;\n return Math.min(\n 1,\n embeddingScore * 0.45 + ftsScore * 0.15 + recency * 0.125 + conf * 0.125 + usageBoost,\n );\n}\n\nexport function normalizeEmbeddingScore(similarity: number): number {\n return Math.max(0, Math.min(1, (similarity + 1) / 2));\n}\n\nexport function deduplicateResults(results: RecallResult[]): RecallResult[] {\n const seen = new Map<string, RecallResult>();\n for (const r of results) {\n const existing = seen.get(r.id);\n if (!existing || r.score > existing.score) {\n seen.set(r.id, r);\n }\n }\n return Array.from(seen.values());\n}\n\nexport function mergeAndRank(\n localResults: RecallResult[],\n remoteResults: RecallResult[],\n k: number,\n): RecallResult[] {\n const all = [...localResults, ...remoteResults];\n const deduped = deduplicateResults(all);\n const ranked = rankResults(deduped);\n return ranked.slice(0, k);\n}\n","import type { CreateMemoryInput, PolicyResult } from \"unforgit-shared\";\n\nconst SENSITIVE_PATTERNS = [\n /password/i,\n /secret/i,\n /api[_-]?key/i,\n /token/i,\n /credential/i,\n /private[_-]?key/i,\n /-----BEGIN/,\n];\n\nconst RULE_LIKE_TAGS = new Set([\n \"decision\",\n \"adr\",\n \"playbook\",\n \"gotcha\",\n \"convention\",\n \"rule\",\n \"standard\",\n \"process\",\n \"checklist\",\n]);\n\nfunction containsSensitive(text: string): boolean {\n return SENSITIVE_PATTERNS.some((p) => p.test(text));\n}\n\nfunction hasRuleLikeTags(tags: string[]): boolean {\n return tags.some((t) => RULE_LIKE_TAGS.has(t.toLowerCase()));\n}\n\nexport function resolveVisibility(input: CreateMemoryInput): PolicyResult {\n if (containsSensitive(input.text)) {\n return { visibility: \"private\" };\n }\n\n if (\n input.memoryType === \"episodic\" &&\n !input.sourceRefs\n ) {\n return { visibility: \"private\" };\n }\n\n const hasSource = input.sourceRefs && Object.keys(input.sourceRefs).length > 0;\n const tags = input.tags ?? [];\n\n if (\n (input.memoryType === \"semantic\" || input.memoryType === \"procedural\") &&\n (hasSource || hasRuleLikeTags(tags))\n ) {\n return { visibility: \"repo\" };\n }\n\n return { visibility: \"private\", suggestion: \"promote\" };\n}\n","import OpenAI from \"openai\";\n\nconst EMBEDDING_MODEL = \"text-embedding-3-small\";\nconst EMBEDDING_DIMENSIONS = 1536;\n\nexport interface EmbeddingResult {\n embedding: number[];\n model: string;\n tokensUsed: number;\n}\n\nexport interface EmbeddingConfig {\n apiKey?: string;\n model?: string;\n}\n\nlet cachedClient: OpenAI | null = null;\n\n/**\n * Check if OpenAI API key is configured.\n * Use this to gracefully skip embedding-related features when not available.\n */\nexport function isOpenAIConfigured(apiKey?: string): boolean {\n const key = apiKey ?? process.env.OPENAI_API_KEY;\n return !!key && key !== \"sk-your-api-key-here\" && key.startsWith(\"sk-\");\n}\n\n/**\n * Get the OpenAI client. Throws if not configured.\n */\nfunction getClient(apiKey?: string): OpenAI {\n const key = apiKey ?? process.env.OPENAI_API_KEY;\n if (!key) {\n throw new Error(\n \"OpenAI API key not configured. Set OPENAI_API_KEY environment variable or pass apiKey option. \" +\n \"Semantic search features are disabled. Unforgit will use FTS-only search.\"\n );\n }\n if (!cachedClient || apiKey) {\n cachedClient = new OpenAI({ apiKey: key });\n }\n return cachedClient;\n}\n\nexport async function generateEmbedding(\n text: string,\n config?: EmbeddingConfig\n): Promise<EmbeddingResult> {\n const client = getClient(config?.apiKey);\n const model = config?.model ?? EMBEDDING_MODEL;\n\n const cleanText = text.trim().slice(0, 8000);\n\n const response = await client.embeddings.create({\n model,\n input: cleanText,\n });\n\n const data = response.data[0];\n if (!data?.embedding) {\n throw new Error(\"OpenAI returned empty embedding\");\n }\n\n return {\n embedding: data.embedding,\n model,\n tokensUsed: response.usage?.total_tokens ?? 0,\n };\n}\n\nexport async function generateEmbeddings(\n texts: string[],\n config?: EmbeddingConfig\n): Promise<EmbeddingResult[]> {\n if (texts.length === 0) return [];\n\n const client = getClient(config?.apiKey);\n const model = config?.model ?? EMBEDDING_MODEL;\n\n const cleanTexts = texts.map((t) => t.trim().slice(0, 8000));\n\n const response = await client.embeddings.create({\n model,\n input: cleanTexts,\n });\n\n return response.data.map((item) => ({\n embedding: item.embedding,\n model,\n tokensUsed: Math.floor((response.usage?.total_tokens ?? 0) / texts.length),\n }));\n}\n\nexport function cosineSimilarity(a: number[], b: number[]): number {\n if (a.length !== b.length) {\n throw new Error(\n `Embedding dimensions mismatch: ${a.length} vs ${b.length}`\n );\n }\n\n let dotProduct = 0;\n let normA = 0;\n let normB = 0;\n\n for (let i = 0; i < a.length; i++) {\n dotProduct += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n\n const magnitude = Math.sqrt(normA) * Math.sqrt(normB);\n if (magnitude === 0) return 0;\n\n return dotProduct / magnitude;\n}\n\nexport function serializeEmbedding(embedding: number[]): Buffer {\n const buffer = Buffer.alloc(embedding.length * 4);\n for (let i = 0; i < embedding.length; i++) {\n buffer.writeFloatLE(embedding[i], i * 4);\n }\n return buffer;\n}\n\nexport function deserializeEmbedding(buffer: Buffer): number[] {\n const embedding: number[] = [];\n const count = buffer.length / 4;\n for (let i = 0; i < count; i++) {\n embedding.push(buffer.readFloatLE(i * 4));\n }\n return embedding;\n}\n\nexport function embeddingToBase64(embedding: number[]): string {\n return serializeEmbedding(embedding).toString(\"base64\");\n}\n\nexport function base64ToEmbedding(base64: string): number[] {\n return deserializeEmbedding(Buffer.from(base64, \"base64\"));\n}\n\nexport function embeddingToPgVector(embedding: number[]): string {\n return `[${embedding.join(\",\")}]`;\n}\n\nexport function pgVectorToEmbedding(pgVector: string): number[] {\n const cleaned = pgVector.replace(/^\\[|\\]$/g, \"\");\n return cleaned.split(\",\").map((n) => parseFloat(n));\n}\n\nexport function findTopKSimilar(\n queryEmbedding: number[],\n candidates: Array<{ id: string; embedding: number[] }>,\n k: number,\n threshold = 0\n): Array<{ id: string; similarity: number }> {\n const scored = candidates.map((c) => ({\n id: c.id,\n similarity: cosineSimilarity(queryEmbedding, c.embedding),\n }));\n\n return scored\n .filter((s) => s.similarity >= threshold)\n .sort((a, b) => b.similarity - a.similarity)\n .slice(0, k);\n}\n\nexport const EMBEDDING_DIMENSIONS_MAP: Record<string, number> = {\n \"text-embedding-3-small\": 1536,\n \"text-embedding-3-large\": 3072,\n \"text-embedding-ada-002\": 1536,\n};\n\nexport function getEmbeddingDimensions(model: string): number {\n return EMBEDDING_DIMENSIONS_MAP[model] ?? EMBEDDING_DIMENSIONS;\n}\n\nexport async function isEmbeddingsAvailable(apiKey?: string): Promise<boolean> {\n try {\n const key = apiKey ?? process.env.OPENAI_API_KEY;\n if (!key) return false;\n return true;\n } catch {\n return false;\n }\n}\n","import OpenAI from \"openai\";\nimport type { Memory, MemoryType } from \"unforgit-shared\";\n\nexport interface ConsolidationInput {\n memories: Array<{\n text: string;\n type: MemoryType;\n tags: string[];\n }>;\n}\n\nexport interface ConsolidationOutput {\n text: string;\n suggestedTags: string[];\n suggestedType: MemoryType;\n}\n\nconst CONSOLIDATION_PROMPT = `You are consolidating multiple related memories into a single unified memory.\n\nSource memories:\n{{MEMORIES}}\n\nInstructions:\n1. Identify the core knowledge/insight shared across these memories\n2. Merge complementary information without losing important details\n3. Remove redundancy while preserving unique facts\n4. Keep the consolidated text concise (ideally under 200 words)\n5. Maintain technical accuracy\n6. Write in the same language as the source memories\n\nOutput format (JSON):\n{\n \"text\": \"The consolidated memory text\",\n \"suggestedTags\": [\"tag1\", \"tag2\"],\n \"suggestedType\": \"semantic\" | \"procedural\" | \"episodic\"\n}\n\nOutput only valid JSON, nothing else.`;\n\nfunction formatMemoriesForPrompt(\n memories: ConsolidationInput[\"memories\"],\n): string {\n return memories\n .map(\n (m, i) =>\n `${i + 1}. [${m.type}] ${m.text}\\n Tags: ${m.tags.length > 0 ? m.tags.join(\", \") : \"none\"}`,\n )\n .join(\"\\n\\n\");\n}\n\nfunction inferMemoryType(memories: ConsolidationInput[\"memories\"]): MemoryType {\n const hasProcedural = memories.some((m) => m.type === \"procedural\");\n const hasSemantic = memories.some((m) => m.type === \"semantic\");\n\n if (hasProcedural) return \"procedural\";\n if (hasSemantic) return \"semantic\";\n return \"episodic\";\n}\n\nfunction mergeTags(memories: ConsolidationInput[\"memories\"]): string[] {\n const tagSet = new Set<string>();\n for (const m of memories) {\n for (const tag of m.tags) {\n tagSet.add(tag);\n }\n }\n return Array.from(tagSet);\n}\n\nexport async function generateConsolidatedText(\n input: ConsolidationInput,\n options?: {\n apiKey?: string;\n model?: string;\n },\n): Promise<ConsolidationOutput> {\n const apiKey = options?.apiKey ?? process.env.OPENAI_API_KEY;\n\n if (!apiKey) {\n throw new Error(\n \"OpenAI API key not configured. Set OPENAI_API_KEY environment variable.\",\n );\n }\n\n const client = new OpenAI({ apiKey });\n const model = options?.model ?? \"gpt-5.4\";\n\n const memoriesText = formatMemoriesForPrompt(input.memories);\n const prompt = CONSOLIDATION_PROMPT.replace(\"{{MEMORIES}}\", memoriesText);\n\n const response = await client.chat.completions.create({\n model,\n messages: [\n {\n role: \"user\",\n content: prompt,\n },\n ],\n temperature: 0.3,\n max_completion_tokens: 1000,\n });\n\n const content = response.choices[0]?.message?.content;\n\n if (!content) {\n throw new Error(\"OpenAI returned empty response\");\n }\n\n try {\n const parsed = JSON.parse(content) as {\n text?: string;\n suggestedTags?: string[];\n suggestedType?: string;\n };\n\n if (!parsed.text || typeof parsed.text !== \"string\") {\n throw new Error(\"Invalid response: missing text field\");\n }\n\n const validTypes: MemoryType[] = [\"episodic\", \"semantic\", \"procedural\"];\n const suggestedType =\n parsed.suggestedType && validTypes.includes(parsed.suggestedType as MemoryType)\n ? (parsed.suggestedType as MemoryType)\n : inferMemoryType(input.memories);\n\n return {\n text: parsed.text,\n suggestedTags: Array.isArray(parsed.suggestedTags)\n ? parsed.suggestedTags.filter((t): t is string => typeof t === \"string\")\n : mergeTags(input.memories),\n suggestedType,\n };\n } catch (_parseError) {\n const textMatch = content.match(/\"text\"\\s*:\\s*\"([^\"]+)\"/);\n if (textMatch) {\n return {\n text: textMatch[1],\n suggestedTags: mergeTags(input.memories),\n suggestedType: inferMemoryType(input.memories),\n };\n }\n\n return {\n text: content.trim(),\n suggestedTags: mergeTags(input.memories),\n suggestedType: inferMemoryType(input.memories),\n };\n }\n}\n\nexport function memoriesToConsolidationInput(\n memories: Memory[],\n): ConsolidationInput {\n return {\n memories: memories.map((m) => ({\n text: m.text,\n type: m.memoryType,\n tags: m.tags,\n })),\n };\n}\n","import type { Memory } from \"unforgit-shared\";\n\nexport interface QualityFactors {\n textQuality: number;\n recallCount: number;\n consolidationStatus: number;\n age: number;\n hasLinks: number;\n hasTags: number;\n hasEmbedding: number;\n}\n\nexport interface QualityScore {\n overall: number;\n factors: QualityFactors;\n suggestions: string[];\n}\n\nexport interface MemoryStats {\n recallCount: number;\n linkCount: number;\n hasEmbedding: boolean;\n daysSinceCreation: number;\n daysSinceLastRecall: number | null;\n}\n\nconst QUALITY_WEIGHTS = {\n textQuality: 0.20,\n recallCount: 0.25,\n consolidationStatus: 0.10,\n age: 0.15,\n hasLinks: 0.10,\n hasTags: 0.10,\n hasEmbedding: 0.10,\n};\n\nexport function computeTextQuality(text: string): number {\n const length = text.trim().length;\n\n if (length < 20) return 0.2;\n if (length < 50) return 0.4;\n if (length < 100) return 0.6;\n if (length < 300) return 0.9;\n if (length < 500) return 1.0;\n if (length < 1000) return 0.9;\n return 0.7;\n}\n\nexport function computeRecallScore(recallCount: number): number {\n if (recallCount === 0) return 0;\n if (recallCount < 3) return 0.3;\n if (recallCount < 10) return 0.6;\n if (recallCount < 25) return 0.8;\n return 1.0;\n}\n\nexport function computeAgeScore(daysSinceCreation: number, daysSinceLastRecall: number | null): number {\n if (daysSinceLastRecall !== null && daysSinceLastRecall < 7) {\n return 1.0;\n }\n\n if (daysSinceCreation < 7) return 1.0;\n if (daysSinceCreation < 30) return 0.9;\n if (daysSinceCreation < 90) return 0.7;\n if (daysSinceCreation < 180) return 0.5;\n if (daysSinceCreation < 365) return 0.3;\n return 0.1;\n}\n\nexport function computeConsolidationScore(memory: Memory): number {\n if (memory.isConsolidation) return 1.0;\n if (memory.status === \"superseded\") return 0.3;\n if (memory.status === \"deprecated\") return 0.1;\n return 0.7;\n}\n\nexport function computeQualityScore(memory: Memory, stats: MemoryStats): QualityScore {\n const factors: QualityFactors = {\n textQuality: computeTextQuality(memory.text),\n recallCount: computeRecallScore(stats.recallCount),\n consolidationStatus: computeConsolidationScore(memory),\n age: computeAgeScore(stats.daysSinceCreation, stats.daysSinceLastRecall),\n hasLinks: stats.linkCount > 0 ? 1.0 : 0.3,\n hasTags: memory.tags.length > 0 ? 1.0 : 0.3,\n hasEmbedding: stats.hasEmbedding ? 1.0 : 0.5,\n };\n\n const overall =\n factors.textQuality * QUALITY_WEIGHTS.textQuality +\n factors.recallCount * QUALITY_WEIGHTS.recallCount +\n factors.consolidationStatus * QUALITY_WEIGHTS.consolidationStatus +\n factors.age * QUALITY_WEIGHTS.age +\n factors.hasLinks * QUALITY_WEIGHTS.hasLinks +\n factors.hasTags * QUALITY_WEIGHTS.hasTags +\n factors.hasEmbedding * QUALITY_WEIGHTS.hasEmbedding;\n\n const suggestions: string[] = [];\n\n if (factors.textQuality < 0.5) {\n suggestions.push(\"Consider expanding this memory with more detail\");\n }\n if (factors.recallCount < 0.3 && stats.daysSinceCreation > 30) {\n suggestions.push(\"This memory has never been recalled - consider deprecating if no longer relevant\");\n }\n if (factors.hasLinks < 0.5) {\n suggestions.push(\"Consider linking this memory to related memories\");\n }\n if (factors.hasTags < 0.5) {\n suggestions.push(\"Add tags to improve discoverability\");\n }\n if (!stats.hasEmbedding) {\n suggestions.push(\"Generate embedding for better semantic search\");\n }\n if (stats.daysSinceCreation > 180 && stats.daysSinceLastRecall === null) {\n suggestions.push(\"Old memory with no recalls - review for deprecation\");\n }\n\n return {\n overall: Math.round(overall * 100) / 100,\n factors,\n suggestions,\n };\n}\n\nexport function getHealthStatus(score: number): \"healthy\" | \"needs_attention\" | \"critical\" {\n if (score >= 0.7) return \"healthy\";\n if (score >= 0.4) return \"needs_attention\";\n return \"critical\";\n}\n\nexport interface RepositoryHealth {\n overallScore: number;\n status: \"healthy\" | \"needs_attention\" | \"critical\";\n memoryCounts: {\n total: number;\n healthy: number;\n needs_attention: number;\n critical: number;\n };\n topIssues: Array<{\n type: string;\n count: number;\n description: string;\n }>;\n}\n\nexport function computeRepositoryHealth(\n memories: Array<{ memory: Memory; stats: MemoryStats }>\n): RepositoryHealth {\n if (memories.length === 0) {\n return {\n overallScore: 1.0,\n status: \"healthy\",\n memoryCounts: { total: 0, healthy: 0, needs_attention: 0, critical: 0 },\n topIssues: [],\n };\n }\n\n const scores = memories.map(({ memory, stats }) =>\n computeQualityScore(memory, stats)\n );\n\n const totalScore = scores.reduce((sum, s) => sum + s.overall, 0);\n const overallScore = Math.round((totalScore / scores.length) * 100) / 100;\n\n const counts = { healthy: 0, needs_attention: 0, critical: 0 };\n for (const score of scores) {\n const status = getHealthStatus(score.overall);\n counts[status]++;\n }\n\n const issueCount: Record<string, number> = {};\n for (const score of scores) {\n for (const suggestion of score.suggestions) {\n issueCount[suggestion] = (issueCount[suggestion] || 0) + 1;\n }\n }\n\n const topIssues = Object.entries(issueCount)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 5)\n .map(([description, count]) => ({\n type: categorizeIssue(description),\n count,\n description,\n }));\n\n return {\n overallScore,\n status: getHealthStatus(overallScore),\n memoryCounts: {\n total: memories.length,\n ...counts,\n },\n topIssues,\n };\n}\n\nfunction categorizeIssue(description: string): string {\n if (description.includes(\"tag\")) return \"tagging\";\n if (description.includes(\"link\")) return \"linking\";\n if (description.includes(\"embedding\")) return \"embedding\";\n if (description.includes(\"deprecat\") || description.includes(\"recall\")) return \"maintenance\";\n if (description.includes(\"detail\") || description.includes(\"expand\")) return \"content\";\n return \"other\";\n}\n","import type { ILocalStore } from \"unforgit-shared\";\nimport type { Memory } from \"unforgit-shared\";\nimport { computeQualityScore, type MemoryStats, type QualityScore } from \"./quality.js\";\n\nexport type SuggestionType =\n | \"consolidate\"\n | \"deprecate\"\n | \"delete\"\n | \"add_tags\"\n | \"add_links\"\n | \"review\"\n | \"promote\"\n | \"generate_embedding\";\n\nexport interface Suggestion {\n id: string;\n type: SuggestionType;\n priority: \"high\" | \"medium\" | \"low\";\n memoryIds: string[];\n reason: string;\n confidence: number;\n action?: {\n command: string;\n description: string;\n };\n}\n\nexport interface SuggestionResult {\n suggestions: Suggestion[];\n stats: {\n totalMemories: number;\n memoriesAnalyzed: number;\n suggestionsGenerated: number;\n };\n}\n\nexport function generateSuggestions(\n store: ILocalStore,\n orgId: string,\n repoId: string,\n options?: {\n maxSuggestions?: number;\n includeTypes?: SuggestionType[];\n }\n): SuggestionResult {\n const maxSuggestions = options?.maxSuggestions ?? 20;\n const suggestions: Suggestion[] = [];\n\n const memories = store.list({\n orgId,\n repoId,\n status: [\"active\"],\n limit: 500,\n });\n\n const usageStats = store.getUsageStats(orgId, repoId);\n const usageMap = new Map(usageStats.map((s) => [s.memoryId, s]));\n\n const memoryData: Array<{\n memory: Memory;\n stats: MemoryStats;\n quality: QualityScore;\n }> = [];\n\n for (const memory of memories) {\n const usage = usageMap.get(memory.id);\n const links = store.getLinks({ memoryId: memory.id });\n const hasEmbedding = store.hasEmbedding(memory.id);\n\n const stats: MemoryStats = {\n recallCount: usage?.count ?? 0,\n linkCount: links.length,\n hasEmbedding,\n daysSinceCreation: Math.floor(\n (Date.now() - memory.createdAt.getTime()) / (1000 * 60 * 60 * 24)\n ),\n daysSinceLastRecall: usage\n ? Math.floor(\n (Date.now() - usage.lastUsed.getTime()) / (1000 * 60 * 60 * 24)\n )\n : null,\n };\n\n const quality = computeQualityScore(memory, stats);\n\n memoryData.push({ memory, stats, quality });\n }\n\n const similarPairs = findSimilarMemoryPairs(store, memoryData, orgId, repoId);\n for (const pair of similarPairs.slice(0, 5)) {\n suggestions.push({\n id: `consolidate-${pair.id1.slice(0, 8)}-${pair.id2.slice(0, 8)}`,\n type: \"consolidate\",\n priority: pair.similarity > 0.8 ? \"high\" : \"medium\",\n memoryIds: [pair.id1, pair.id2],\n reason: `These memories are ${Math.round(pair.similarity * 100)}% similar and could be merged`,\n confidence: pair.similarity,\n action: {\n command: `unforgit merge ${pair.id1} ${pair.id2}`,\n description: \"Merge these memories into one\",\n },\n });\n }\n\n const staleMemories = memoryData.filter(\n ({ stats, quality }) =>\n stats.daysSinceCreation > 90 &&\n stats.recallCount === 0 &&\n quality.overall < 0.5\n );\n\n for (const { memory } of staleMemories.slice(0, 5)) {\n suggestions.push({\n id: `deprecate-${memory.id.slice(0, 8)}`,\n type: \"deprecate\",\n priority: \"medium\",\n memoryIds: [memory.id],\n reason: \"No recalls in 90+ days with low quality score\",\n confidence: 0.7,\n action: {\n command: `unforgit deprecate ${memory.id}`,\n description: \"Mark as deprecated\",\n },\n });\n }\n\n const untagged = memoryData.filter(({ memory }) => memory.tags.length === 0);\n if (untagged.length > 0) {\n const ids = untagged.slice(0, 10).map(({ memory }) => memory.id);\n suggestions.push({\n id: \"add-tags-batch\",\n type: \"add_tags\",\n priority: \"low\",\n memoryIds: ids,\n reason: `${untagged.length} memories have no tags`,\n confidence: 0.9,\n action: {\n command: \"unforgit web\",\n description: \"Open dashboard to add tags\",\n },\n });\n }\n\n const unlinked = memoryData.filter(\n ({ stats, memory }) =>\n stats.linkCount === 0 &&\n !memory.isConsolidation &&\n stats.daysSinceCreation > 7\n );\n if (unlinked.length > 5) {\n suggestions.push({\n id: \"add-links-batch\",\n type: \"add_links\",\n priority: \"low\",\n memoryIds: unlinked.slice(0, 10).map(({ memory }) => memory.id),\n reason: `${unlinked.length} memories are isolated (no links)`,\n confidence: 0.8,\n action: {\n command: \"unforgit web\",\n description: \"Open graph view to create links\",\n },\n });\n }\n\n const withoutEmbedding = memoryData.filter(({ stats }) => !stats.hasEmbedding);\n if (withoutEmbedding.length > 0) {\n suggestions.push({\n id: \"generate-embeddings\",\n type: \"generate_embedding\",\n priority: withoutEmbedding.length > 10 ? \"high\" : \"medium\",\n memoryIds: withoutEmbedding.map(({ memory }) => memory.id),\n reason: `${withoutEmbedding.length} memories lack embeddings for semantic search`,\n confidence: 1.0,\n action: {\n command: \"unforgit embeddings backfill\",\n description: \"Generate embeddings for all memories\",\n },\n });\n }\n\n const popularPrivate = memoryData.filter(\n ({ memory, stats }) =>\n memory.visibility === \"private\" &&\n stats.recallCount >= 5\n );\n for (const { memory, stats } of popularPrivate.slice(0, 3)) {\n suggestions.push({\n id: `promote-${memory.id.slice(0, 8)}`,\n type: \"promote\",\n priority: \"medium\",\n memoryIds: [memory.id],\n reason: `Private memory with ${stats.recallCount} recalls - consider sharing with team`,\n confidence: 0.75,\n action: {\n command: `unforgit promote ${memory.id}`,\n description: \"Promote to shared visibility\",\n },\n });\n }\n\n const sorted = suggestions\n .sort((a, b) => {\n const priorityOrder = { high: 0, medium: 1, low: 2 };\n if (priorityOrder[a.priority] !== priorityOrder[b.priority]) {\n return priorityOrder[a.priority] - priorityOrder[b.priority];\n }\n return b.confidence - a.confidence;\n })\n .slice(0, maxSuggestions);\n\n return {\n suggestions: sorted,\n stats: {\n totalMemories: memories.length,\n memoriesAnalyzed: memoryData.length,\n suggestionsGenerated: sorted.length,\n },\n };\n}\n\nfunction findSimilarMemoryPairs(\n store: ILocalStore,\n memoryData: Array<{ memory: Memory; stats: MemoryStats }>,\n orgId: string,\n repoId: string\n): Array<{ id1: string; id2: string; similarity: number }> {\n const pairs: Array<{ id1: string; id2: string; similarity: number }> = [];\n const seen = new Set<string>();\n\n for (const { memory } of memoryData.slice(0, 50)) {\n try {\n const similar = store.findSimilar({\n orgId,\n repoId,\n memoryId: memory.id,\n threshold: 0.6,\n k: 3,\n });\n\n for (const match of similar) {\n const pairKey = [memory.id, match.id].sort().join(\"-\");\n if (seen.has(pairKey)) continue;\n seen.add(pairKey);\n\n pairs.push({\n id1: memory.id,\n id2: match.id,\n similarity: match.score,\n });\n }\n } catch {\n continue;\n }\n }\n\n return pairs.sort((a, b) => b.similarity - a.similarity);\n}\n\nexport interface PersistReviewableSuggestionsResult {\n created: number;\n skippedExisting: number;\n}\n\nexport function persistReviewableSuggestions(\n store: ILocalStore,\n orgId: string,\n repoId: string,\n suggestions: Suggestion[],\n options: { createdBy?: string } = {},\n): PersistReviewableSuggestionsResult {\n const existingPending = store.listCurationSuggestions({\n orgId,\n repoId,\n status: [\"pending\"],\n limit: 500,\n });\n\n const existingKeys = new Set(\n existingPending.map((suggestion) =>\n reviewableSuggestionKey(suggestion.type, suggestion.memoryIds),\n ),\n );\n\n let created = 0;\n let skippedExisting = 0;\n\n for (const suggestion of suggestions) {\n const key = reviewableSuggestionKey(suggestion.type, suggestion.memoryIds);\n if (existingKeys.has(key)) {\n skippedExisting++;\n continue;\n }\n\n store.createCurationSuggestion({\n orgId,\n repoId,\n type: suggestion.type,\n priority: suggestion.priority,\n memoryIds: suggestion.memoryIds,\n reason: suggestion.reason,\n confidence: suggestion.confidence,\n createdBy: options.createdBy,\n payload: {\n sourceSuggestionId: suggestion.id,\n ...(suggestion.action ? { action: suggestion.action } : {}),\n },\n });\n existingKeys.add(key);\n created++;\n }\n\n return { created, skippedExisting };\n}\n\nfunction reviewableSuggestionKey(type: string, memoryIds: string[]): string {\n return `${type}:${[...memoryIds].sort().join(\",\")}`;\n}\n\nexport function formatSuggestion(suggestion: Suggestion): string {\n const priorityEmoji = {\n high: \"🔴\",\n medium: \"🟡\",\n low: \"🟢\",\n };\n\n const lines = [\n `${priorityEmoji[suggestion.priority]} [${suggestion.type}] ${suggestion.reason}`,\n ` Confidence: ${Math.round(suggestion.confidence * 100)}%`,\n ` Memories: ${suggestion.memoryIds.map((id) => id.slice(0, 8)).join(\", \")}`,\n ];\n\n if (suggestion.action) {\n lines.push(` Action: ${suggestion.action.command}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import type { Memory, MemoryType } from \"unforgit-shared\";\nimport type { ILocalStore } from \"unforgit-shared\";\nimport {\n generateConsolidatedText,\n memoriesToConsolidationInput,\n} from \"./llm.js\";\n\nexport interface ConsolidationCandidate {\n memories: Memory[];\n reason: string;\n suggestedTags: string[];\n averageScore: number;\n}\n\nexport interface AutoConsolidateOptions {\n threshold?: number;\n minGroupSize?: number;\n maxGroups?: number;\n types?: MemoryType[];\n excludeConsolidations?: boolean;\n}\n\nexport interface AutoConsolidateResult {\n candidates: ConsolidationCandidate[];\n totalMemoriesScanned: number;\n totalCandidateGroups: number;\n}\n\nexport interface ExecuteConsolidationOptions {\n apiKey?: string;\n model?: string;\n preserveOriginals?: boolean;\n}\n\nexport interface ExecuteConsolidationResult {\n consolidatedId: string;\n sourceIds: string[];\n generatedText: string;\n suggestedTags: string[];\n memoryType: MemoryType;\n}\n\nexport function findConsolidationCandidates(\n store: ILocalStore,\n orgId: string,\n repoId: string,\n options: AutoConsolidateOptions = {},\n): AutoConsolidateResult {\n const {\n threshold = 0.4,\n minGroupSize = 2,\n maxGroups = 10,\n types,\n excludeConsolidations = true,\n } = options;\n\n const memories = store.list({\n orgId,\n repoId,\n status: [\"active\"],\n types,\n limit: 1000,\n });\n\n const filteredMemories = excludeConsolidations\n ? memories.filter((m) => !m.isConsolidation)\n : memories;\n\n if (filteredMemories.length < 2) {\n return {\n candidates: [],\n totalMemoriesScanned: filteredMemories.length,\n totalCandidateGroups: 0,\n };\n }\n\n const similarityScores = new Map<string, Map<string, number>>();\n const memoryMap = new Map(filteredMemories.map((m) => [m.id, m]));\n\n for (const memory of filteredMemories) {\n try {\n const similar = store.findSimilar({\n orgId,\n repoId,\n memoryId: memory.id,\n threshold,\n k: 10,\n });\n\n for (const sim of similar) {\n const targetMemory = memoryMap.get(sim.id);\n if (!targetMemory) continue;\n if (excludeConsolidations && targetMemory.isConsolidation) continue;\n\n if (!similarityScores.has(memory.id)) {\n similarityScores.set(memory.id, new Map());\n }\n similarityScores.get(memory.id)!.set(sim.id, sim.score);\n }\n } catch {\n continue;\n }\n }\n\n const used = new Set<string>();\n const groups: Array<{ ids: string[]; avgScore: number }> = [];\n\n const sortedMemories = [...filteredMemories].sort((a, b) => {\n const aCount = similarityScores.get(a.id)?.size ?? 0;\n const bCount = similarityScores.get(b.id)?.size ?? 0;\n return bCount - aCount;\n });\n\n for (const seed of sortedMemories) {\n if (used.has(seed.id)) continue;\n\n const seedSimilar = similarityScores.get(seed.id);\n if (!seedSimilar || seedSimilar.size === 0) continue;\n\n const group: string[] = [seed.id];\n let totalScore = 0;\n let scoreCount = 0;\n\n const candidates = Array.from(seedSimilar.entries())\n .filter(([id]) => !used.has(id))\n .sort((a, b) => b[1] - a[1]);\n\n for (const [candidateId, score] of candidates) {\n if (group.length >= 5) break;\n\n let isCompatible = true;\n for (const memberId of group) {\n if (memberId === seed.id) continue;\n\n const memberSimilar = similarityScores.get(memberId);\n const reverseScore = memberSimilar?.get(candidateId);\n const candidateSimilar = similarityScores.get(candidateId);\n const forwardScore = candidateSimilar?.get(memberId);\n\n const pairScore = Math.max(reverseScore ?? 0, forwardScore ?? 0);\n if (pairScore < threshold * 0.8) {\n isCompatible = false;\n break;\n }\n }\n\n if (isCompatible) {\n group.push(candidateId);\n totalScore += score;\n scoreCount++;\n }\n }\n\n if (group.length >= minGroupSize) {\n for (const id of group) {\n used.add(id);\n }\n groups.push({\n ids: group,\n avgScore: scoreCount > 0 ? totalScore / scoreCount : threshold,\n });\n }\n }\n\n const candidates: ConsolidationCandidate[] = [];\n\n for (const group of groups) {\n const groupMemories = group.ids\n .map((id) => memoryMap.get(id))\n .filter((m): m is Memory => m !== undefined);\n\n if (groupMemories.length < minGroupSize) continue;\n\n const allTags = new Set<string>();\n for (const m of groupMemories) {\n for (const tag of m.tags) {\n allTags.add(tag);\n }\n }\n\n const typeCount: Record<string, number> = {};\n for (const m of groupMemories) {\n typeCount[m.memoryType] = (typeCount[m.memoryType] || 0) + 1;\n }\n const dominantType = Object.entries(typeCount).sort(\n (a, b) => b[1] - a[1],\n )[0]?.[0] as MemoryType | undefined;\n\n candidates.push({\n memories: groupMemories.sort(\n (a, b) => b.createdAt.getTime() - a.createdAt.getTime(),\n ),\n reason: `${groupMemories.length} similar ${dominantType ?? \"mixed\"} memories with avg similarity ${group.avgScore.toFixed(2)}`,\n suggestedTags: Array.from(allTags),\n averageScore: group.avgScore,\n });\n }\n\n candidates.sort((a, b) => {\n if (b.memories.length !== a.memories.length) {\n return b.memories.length - a.memories.length;\n }\n return b.averageScore - a.averageScore;\n });\n\n return {\n candidates: candidates.slice(0, maxGroups),\n totalMemoriesScanned: filteredMemories.length,\n totalCandidateGroups: candidates.length,\n };\n}\n\nexport async function executeConsolidation(\n store: ILocalStore,\n candidate: ConsolidationCandidate,\n orgId: string,\n repoId: string,\n options: ExecuteConsolidationOptions = {},\n): Promise<ExecuteConsolidationResult> {\n const { apiKey, model, preserveOriginals = true } = options;\n\n const input = memoriesToConsolidationInput(candidate.memories);\n\n const llmResult = await generateConsolidatedText(input, { apiKey, model });\n\n const sourceIds = candidate.memories.map((m) => m.id);\n\n const result = store.consolidateMemories({\n orgId,\n repoId,\n sourceIds,\n consolidatedText: llmResult.text,\n memoryType: llmResult.suggestedType,\n tags: llmResult.suggestedTags,\n preserveOriginals,\n });\n\n return {\n consolidatedId: result.consolidatedId,\n sourceIds,\n generatedText: llmResult.text,\n suggestedTags: llmResult.suggestedTags,\n memoryType: llmResult.suggestedType,\n };\n}\n\nexport async function autoConsolidate(\n store: ILocalStore,\n orgId: string,\n repoId: string,\n options: AutoConsolidateOptions & ExecuteConsolidationOptions = {},\n): Promise<{\n executed: ExecuteConsolidationResult[];\n skipped: ConsolidationCandidate[];\n errors: Array<{ candidate: ConsolidationCandidate; error: string }>;\n}> {\n const { candidates } = findConsolidationCandidates(store, orgId, repoId, options);\n\n const executed: ExecuteConsolidationResult[] = [];\n const skipped: ConsolidationCandidate[] = [];\n const errors: Array<{ candidate: ConsolidationCandidate; error: string }> = [];\n\n for (const candidate of candidates) {\n try {\n const result = await executeConsolidation(store, candidate, orgId, repoId, options);\n executed.push(result);\n } catch (err) {\n errors.push({\n candidate,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return { executed, skipped, errors };\n}\n\nexport function formatCandidatePreview(candidate: ConsolidationCandidate): string {\n const lines: string[] = [];\n lines.push(`Group: ${candidate.reason}`);\n lines.push(`Tags: ${candidate.suggestedTags.join(\", \") || \"none\"}`);\n lines.push(\"Memories:\");\n\n for (const mem of candidate.memories) {\n const preview = mem.text.length > 80 ? mem.text.slice(0, 80) + \"...\" : mem.text;\n lines.push(` - [${mem.memoryType}] ${mem.id.slice(0, 8)}: ${preview}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import type { Memory, MemoryType } from \"unforgit-shared\";\nimport type { IRemoteStore } from \"unforgit-shared\";\nimport {\n generateConsolidatedText,\n memoriesToConsolidationInput,\n} from \"./llm.js\";\n\nexport interface ConsolidationCandidate {\n memories: Memory[];\n reason: string;\n suggestedTags: string[];\n averageScore: number;\n}\n\nexport interface AutoConsolidateOptions {\n threshold?: number;\n minGroupSize?: number;\n maxGroups?: number;\n types?: MemoryType[];\n excludeConsolidations?: boolean;\n}\n\nexport interface AutoConsolidateResult {\n candidates: ConsolidationCandidate[];\n totalMemoriesScanned: number;\n totalCandidateGroups: number;\n}\n\nexport interface ExecuteConsolidationOptions {\n apiKey?: string;\n model?: string;\n preserveOriginals?: boolean;\n}\n\nexport interface ExecuteConsolidationResult {\n consolidatedId: string;\n sourceIds: string[];\n generatedText: string;\n suggestedTags: string[];\n memoryType: MemoryType;\n}\n\nexport async function findConsolidationCandidatesRemote(\n store: IRemoteStore,\n orgId: string,\n repoId: string,\n options: AutoConsolidateOptions = {}\n): Promise<AutoConsolidateResult> {\n const {\n threshold = 0.4,\n minGroupSize = 2,\n maxGroups = 10,\n types,\n excludeConsolidations = true,\n } = options;\n\n const memories = await store.list({\n orgId,\n repoId,\n status: [\"active\"],\n types,\n limit: 1000,\n });\n\n const filteredMemories = excludeConsolidations\n ? memories.filter((m) => {\n const sourceRefs = m.sourceRefs as Record<string, unknown> | undefined;\n return !sourceRefs?.consolidated_from;\n })\n : memories;\n\n if (filteredMemories.length < 2) {\n return {\n candidates: [],\n totalMemoriesScanned: filteredMemories.length,\n totalCandidateGroups: 0,\n };\n }\n\n const similarityScores = new Map<string, Map<string, number>>();\n const memoryMap = new Map(filteredMemories.map((m) => [m.id, m]));\n\n for (const memory of filteredMemories) {\n try {\n const similar = await store.findSimilar({\n orgId,\n repoId,\n memoryId: memory.id,\n threshold,\n k: 10,\n });\n\n for (const sim of similar) {\n const targetMemory = memoryMap.get(sim.id);\n if (!targetMemory) continue;\n\n const sourceRefs = targetMemory.sourceRefs as Record<string, unknown> | undefined;\n if (excludeConsolidations && sourceRefs?.consolidated_from) continue;\n\n if (!similarityScores.has(memory.id)) {\n similarityScores.set(memory.id, new Map());\n }\n similarityScores.get(memory.id)!.set(sim.id, sim.score);\n }\n } catch {\n continue;\n }\n }\n\n const used = new Set<string>();\n const groups: Array<{ ids: string[]; avgScore: number }> = [];\n\n const sortedMemories = [...filteredMemories].sort((a, b) => {\n const aCount = similarityScores.get(a.id)?.size ?? 0;\n const bCount = similarityScores.get(b.id)?.size ?? 0;\n return bCount - aCount;\n });\n\n for (const seed of sortedMemories) {\n if (used.has(seed.id)) continue;\n\n const seedSimilar = similarityScores.get(seed.id);\n if (!seedSimilar || seedSimilar.size === 0) continue;\n\n const group: string[] = [seed.id];\n let totalScore = 0;\n let scoreCount = 0;\n\n const candidates = Array.from(seedSimilar.entries())\n .filter(([id]) => !used.has(id))\n .sort((a, b) => b[1] - a[1]);\n\n for (const [candidateId, score] of candidates) {\n if (group.length >= 5) break;\n\n let isCompatible = true;\n for (const memberId of group) {\n if (memberId === seed.id) continue;\n\n const memberSimilar = similarityScores.get(memberId);\n const reverseScore = memberSimilar?.get(candidateId);\n const candidateSimilar = similarityScores.get(candidateId);\n const forwardScore = candidateSimilar?.get(memberId);\n\n const pairScore = Math.max(reverseScore ?? 0, forwardScore ?? 0);\n if (pairScore < threshold * 0.8) {\n isCompatible = false;\n break;\n }\n }\n\n if (isCompatible) {\n group.push(candidateId);\n totalScore += score;\n scoreCount++;\n }\n }\n\n if (group.length >= minGroupSize) {\n for (const id of group) {\n used.add(id);\n }\n groups.push({\n ids: group,\n avgScore: scoreCount > 0 ? totalScore / scoreCount : threshold,\n });\n }\n }\n\n const candidateResults: ConsolidationCandidate[] = [];\n\n for (const group of groups) {\n const groupMemories = group.ids\n .map((id) => memoryMap.get(id))\n .filter((m): m is Memory => m !== undefined);\n\n if (groupMemories.length < minGroupSize) continue;\n\n const allTags = new Set<string>();\n for (const m of groupMemories) {\n for (const tag of m.tags) {\n allTags.add(tag);\n }\n }\n\n const typeCount: Record<string, number> = {};\n for (const m of groupMemories) {\n typeCount[m.memoryType] = (typeCount[m.memoryType] || 0) + 1;\n }\n const dominantType = Object.entries(typeCount).sort(\n (a, b) => b[1] - a[1]\n )[0]?.[0] as MemoryType | undefined;\n\n candidateResults.push({\n memories: groupMemories.sort(\n (a, b) => b.createdAt.getTime() - a.createdAt.getTime()\n ),\n reason: `${groupMemories.length} similar ${dominantType ?? \"mixed\"} memories with avg similarity ${group.avgScore.toFixed(2)}`,\n suggestedTags: Array.from(allTags),\n averageScore: group.avgScore,\n });\n }\n\n candidateResults.sort((a, b) => {\n if (b.memories.length !== a.memories.length) {\n return b.memories.length - a.memories.length;\n }\n return b.averageScore - a.averageScore;\n });\n\n return {\n candidates: candidateResults.slice(0, maxGroups),\n totalMemoriesScanned: filteredMemories.length,\n totalCandidateGroups: candidateResults.length,\n };\n}\n\nexport async function executeConsolidationRemote(\n store: IRemoteStore,\n candidate: ConsolidationCandidate,\n orgId: string,\n repoId: string,\n options: ExecuteConsolidationOptions = {}\n): Promise<ExecuteConsolidationResult> {\n const { apiKey, model, preserveOriginals = true } = options;\n\n const input = memoriesToConsolidationInput(candidate.memories);\n\n const llmResult = await generateConsolidatedText(input, { apiKey, model });\n\n const sourceIds = candidate.memories.map((m) => m.id);\n\n const result = await store.consolidateMemories({\n orgId,\n repoId,\n sourceIds,\n consolidatedText: llmResult.text,\n memoryType: llmResult.suggestedType,\n tags: llmResult.suggestedTags,\n preserveOriginals,\n });\n\n return {\n consolidatedId: result.consolidatedId,\n sourceIds,\n generatedText: llmResult.text,\n suggestedTags: llmResult.suggestedTags,\n memoryType: llmResult.suggestedType,\n };\n}\n\nexport async function autoConsolidateRemote(\n store: IRemoteStore,\n orgId: string,\n repoId: string,\n options: AutoConsolidateOptions & ExecuteConsolidationOptions = {}\n): Promise<{\n executed: ExecuteConsolidationResult[];\n skipped: ConsolidationCandidate[];\n errors: Array<{ candidate: ConsolidationCandidate; error: string }>;\n}> {\n const { candidates } = await findConsolidationCandidatesRemote(\n store,\n orgId,\n repoId,\n options\n );\n\n const executed: ExecuteConsolidationResult[] = [];\n const skipped: ConsolidationCandidate[] = [];\n const errors: Array<{ candidate: ConsolidationCandidate; error: string }> = [];\n\n for (const candidate of candidates) {\n try {\n const result = await executeConsolidationRemote(\n store,\n candidate,\n orgId,\n repoId,\n options\n );\n executed.push(result);\n } catch (err) {\n errors.push({\n candidate,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return { executed, skipped, errors };\n}\n\nexport function formatCandidatePreview(candidate: ConsolidationCandidate): string {\n const lines: string[] = [];\n lines.push(`Group: ${candidate.reason}`);\n lines.push(`Tags: ${candidate.suggestedTags.join(\", \") || \"none\"}`);\n lines.push(\"Memories:\");\n\n for (const mem of candidate.memories) {\n const preview = mem.text.length > 80 ? mem.text.slice(0, 80) + \"...\" : mem.text;\n lines.push(` - [${mem.memoryType}] ${mem.id.slice(0, 8)}: ${preview}`);\n }\n\n return lines.join(\"\\n\");\n}\n","const AUTO_LINK_STOP_WORDS = new Set([\n \"the\", \"a\", \"an\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\n \"have\", \"has\", \"had\", \"do\", \"does\", \"did\", \"will\", \"would\", \"could\",\n \"should\", \"may\", \"might\", \"must\", \"shall\", \"can\", \"to\", \"of\", \"in\",\n \"for\", \"on\", \"with\", \"at\", \"by\", \"from\", \"as\", \"into\", \"through\",\n \"during\", \"before\", \"after\", \"above\", \"below\", \"between\", \"under\",\n \"again\", \"further\", \"then\", \"once\", \"here\", \"there\", \"when\", \"where\",\n \"why\", \"how\", \"all\", \"each\", \"few\", \"more\", \"most\", \"other\", \"some\",\n \"such\", \"no\", \"nor\", \"not\", \"only\", \"own\", \"same\", \"so\", \"than\", \"too\",\n \"very\", \"just\", \"and\", \"but\", \"if\", \"or\", \"because\", \"until\", \"while\",\n \"this\", \"that\", \"these\", \"those\", \"it\", \"its\",\n]);\n\nexport function buildAutoLinkQuery(\n text: string,\n maxTerms = 10,\n): string | undefined {\n const terms = text\n .toLowerCase()\n .replace(/[_-]/g, \" \")\n .replace(/[^\\w\\s]/g, \" \")\n .split(/\\s+/)\n .filter((word) => word.length > 2)\n .filter((word) => !AUTO_LINK_STOP_WORDS.has(word))\n .filter((word) => word !== \"or\" && word !== \"and\");\n\n const uniqueTerms = [...new Set(terms)].slice(0, maxTerms);\n if (uniqueTerms.length === 0) {\n return undefined;\n }\n\n // Use plain whitespace-separated terms. LocalStore.recall() already builds\n // the FTS query operators; passing raw \"OR\" tokens here creates invalid SQL.\n return uniqueTerms.join(\" \");\n}\n","import type { ILocalStore } from \"unforgit-shared\";\nimport { generateSuggestions } from \"./suggestions.js\";\n\nexport type NotificationType =\n | \"pending_suggestions\"\n | \"sync_stale\"\n | \"conflicts_pending\"\n | \"embeddings_missing\"\n | \"maintenance_needed\";\n\nexport interface Notification {\n id: string;\n type: NotificationType;\n priority: \"high\" | \"medium\" | \"low\";\n title: string;\n message: string;\n action?: {\n command: string;\n description: string;\n };\n createdAt: Date;\n}\n\nexport interface NotificationResult {\n notifications: Notification[];\n summary: {\n total: number;\n high: number;\n medium: number;\n low: number;\n };\n}\n\nexport function getNotifications(\n store: ILocalStore,\n orgId: string,\n repoId: string\n): NotificationResult {\n const notifications: Notification[] = [];\n const now = new Date();\n\n const syncSummary = store.getSyncSummary(orgId, repoId);\n\n if (syncSummary.conflicts > 0) {\n notifications.push({\n id: \"conflicts-pending\",\n type: \"conflicts_pending\",\n priority: \"high\",\n title: \"Sync Conflicts\",\n message: `You have ${syncSummary.conflicts} unresolved sync conflict(s) that need attention.`,\n action: {\n command: \"unforgit status\",\n description: \"View conflicts\",\n },\n createdAt: now,\n });\n }\n\n const embeddingStats = store.getEmbeddingStats(orgId, repoId);\n\n if (embeddingStats.withoutEmbedding > 10) {\n notifications.push({\n id: \"embeddings-missing\",\n type: \"embeddings_missing\",\n priority: \"medium\",\n title: \"Missing Embeddings\",\n message: `${embeddingStats.withoutEmbedding} memories lack embeddings. Semantic search quality is reduced.`,\n action: {\n command: \"unforgit embeddings backfill\",\n description: \"Generate missing embeddings\",\n },\n createdAt: now,\n });\n }\n\n const suggestions = generateSuggestions(store, orgId, repoId, { maxSuggestions: 10 });\n\n const highPrioritySuggestions = suggestions.suggestions.filter(\n (s) => s.priority === \"high\"\n ).length;\n\n if (highPrioritySuggestions > 0) {\n notifications.push({\n id: \"suggestions-high-priority\",\n type: \"pending_suggestions\",\n priority: \"medium\",\n title: \"Curation Suggestions\",\n message: `${highPrioritySuggestions} high-priority curation suggestion(s) available.`,\n action: {\n command: \"unforgit web\",\n description: \"Open curation dashboard\",\n },\n createdAt: now,\n });\n }\n\n if (syncSummary.pendingPush > 20) {\n notifications.push({\n id: \"sync-stale\",\n type: \"sync_stale\",\n priority: \"low\",\n title: \"Pending Sync\",\n message: `${syncSummary.pendingPush} memories waiting to be pushed to remote.`,\n action: {\n command: \"unforgit push\",\n description: \"Push changes to remote\",\n },\n createdAt: now,\n });\n }\n\n const unusedMemories = store.getUnusedMemories(orgId, repoId, 90);\n if (unusedMemories.length > 10) {\n notifications.push({\n id: \"maintenance-unused\",\n type: \"maintenance_needed\",\n priority: \"low\",\n title: \"Maintenance Recommended\",\n message: `${unusedMemories.length} memories haven't been recalled in 90+ days. Consider reviewing or deprecating.`,\n action: {\n command: \"unforgit web\",\n description: \"Open curation dashboard\",\n },\n createdAt: now,\n });\n }\n\n notifications.sort((a, b) => {\n const priorityOrder = { high: 0, medium: 1, low: 2 };\n return priorityOrder[a.priority] - priorityOrder[b.priority];\n });\n\n const summary = {\n total: notifications.length,\n high: notifications.filter((n) => n.priority === \"high\").length,\n medium: notifications.filter((n) => n.priority === \"medium\").length,\n low: notifications.filter((n) => n.priority === \"low\").length,\n };\n\n return { notifications, summary };\n}\n\nexport function formatNotification(notification: Notification): string {\n const priorityEmoji = {\n high: \"🔴\",\n medium: \"🟡\",\n low: \"🟢\",\n };\n\n const lines = [\n `${priorityEmoji[notification.priority]} ${notification.title}`,\n ` ${notification.message}`,\n ];\n\n if (notification.action) {\n lines.push(` → ${notification.action.command}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function formatNotificationsSummary(result: NotificationResult): string {\n if (result.notifications.length === 0) {\n return \"No notifications. Everything is up to date!\";\n }\n\n const parts = [\n `${result.summary.total} notification(s):`,\n ` High: ${result.summary.high}`,\n ` Medium: ${result.summary.medium}`,\n ` Low: ${result.summary.low}`,\n \"\",\n ...result.notifications.map(formatNotification),\n ];\n\n return parts.join(\"\\n\");\n}\n","import { findConsolidationCandidates, executeConsolidation } from \"./auto-consolidate.js\";\nimport {\n executeConsolidationRemote,\n findConsolidationCandidatesRemote,\n type ConsolidationCandidate,\n type ExecuteConsolidationResult,\n} from \"./auto-consolidate-remote.js\";\nimport { resolveLifecycleConfig, isMemoryExpired } from \"./lifecycle.js\";\nimport { isOpenAIConfigured } from \"./embeddings.js\";\nimport type { LifecycleConfig, Memory } from \"unforgit-shared\";\nimport type { ILocalStore } from \"unforgit-shared\";\nimport type { IRemoteStore } from \"unforgit-shared\";\n\nexport interface StrengthenedMemoryCandidate {\n id: string;\n usageCount: number;\n lastUsed?: Date;\n recommendedAction: \"promote\" | \"pin\";\n reason: string;\n textPreview: string;\n}\n\nexport interface ExpiringMemoryCandidate {\n id: string;\n ttlSeconds: number;\n reason: string;\n textPreview: string;\n}\n\nexport interface LifecycleMaintenanceResult {\n dryRun: boolean;\n totalActiveMemories: number;\n expiredCandidates: ExpiringMemoryCandidate[];\n expiredCount: number;\n strengthenedCandidates: StrengthenedMemoryCandidate[];\n consolidationCandidates: ConsolidationCandidate[];\n executedConsolidations: ExecuteConsolidationResult[];\n warnings: string[];\n errors: string[];\n}\n\nexport interface LifecycleMaintenanceOptions {\n dryRun?: boolean;\n model?: string;\n preserveOriginals?: boolean;\n lifecycle?: LifecycleConfig;\n}\n\nfunction preview(text: string): string {\n return text.length > 120 ? `${text.slice(0, 120)}...` : text;\n}\n\nfunction getExpiringCandidates(\n memories: Memory[],\n): ExpiringMemoryCandidate[] {\n return memories\n .filter(\n (memory) =>\n memory.memoryType === \"episodic\" &&\n memory.status === \"active\" &&\n memory.ttlSeconds !== undefined &&\n isMemoryExpired(memory),\n )\n .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())\n .map((memory) => ({\n id: memory.id,\n ttlSeconds: memory.ttlSeconds!,\n reason: `Expired after ${memory.ttlSeconds} seconds without consolidation`,\n textPreview: preview(memory.text),\n }));\n}\n\nfunction getStrengthenedCandidates(\n memories: Memory[],\n usageStats: Array<{ memoryId: string; count: number; lastUsed: Date }>,\n lifecycle?: LifecycleConfig,\n): StrengthenedMemoryCandidate[] {\n const config = resolveLifecycleConfig(lifecycle);\n const usageMap = new Map(usageStats.map((stat) => [stat.memoryId, stat]));\n\n return memories\n .filter((memory) => memory.memoryType === \"episodic\" && memory.status === \"active\")\n .map((memory): StrengthenedMemoryCandidate | undefined => {\n const usage = usageMap.get(memory.id);\n if (!usage || usage.count < config.maintenance.promoteRecallCount) {\n return undefined;\n }\n\n const isPinned = memory.tags.includes(\"pinned\");\n const recommendedAction =\n usage.count >= config.maintenance.pinRecallCount && !isPinned\n ? \"pin\"\n : \"promote\";\n\n return {\n id: memory.id,\n usageCount: usage.count,\n lastUsed: usage.lastUsed,\n recommendedAction,\n reason:\n recommendedAction === \"pin\"\n ? `Frequently reused episodic memory (${usage.count} recalls); consider pinning it`\n : `Frequently reused episodic memory (${usage.count} recalls); consider promoting it`,\n textPreview: preview(memory.text),\n } satisfies StrengthenedMemoryCandidate;\n })\n .filter((candidate): candidate is StrengthenedMemoryCandidate => candidate !== undefined)\n .sort((a, b) => b.usageCount - a.usageCount);\n}\n\nexport async function runLocalLifecycleMaintenance(\n store: ILocalStore,\n orgId: string,\n repoId: string,\n options: LifecycleMaintenanceOptions = {},\n): Promise<LifecycleMaintenanceResult> {\n const lifecycle = resolveLifecycleConfig(options.lifecycle);\n const dryRun = options.dryRun ?? lifecycle.maintenance.dryRunDefault;\n const activeMemories = store.list({\n orgId,\n repoId,\n status: [\"active\"],\n includeExpired: true,\n limit: 1000,\n });\n const usageStats = store.getUsageStats(orgId, repoId);\n const expiredCandidates = getExpiringCandidates(activeMemories);\n const strengthenedCandidates = getStrengthenedCandidates(\n activeMemories.filter((memory) => !isMemoryExpired(memory)),\n usageStats,\n lifecycle,\n );\n const consolidationPreview = findConsolidationCandidates(store, orgId, repoId, {\n threshold: lifecycle.maintenance.consolidationThreshold,\n minGroupSize: lifecycle.maintenance.consolidationMinGroupSize,\n maxGroups: lifecycle.maintenance.consolidationMaxGroups,\n types: [\"episodic\"],\n excludeConsolidations: true,\n });\n\n const warnings: string[] = [];\n const errors: string[] = [];\n const executedConsolidations: ExecuteConsolidationResult[] = [];\n\n if (!dryRun) {\n store.expireExpiredMemories(orgId, repoId);\n\n if (consolidationPreview.candidates.length > 0) {\n if (!isOpenAIConfigured()) {\n warnings.push(\n \"Skipping consolidation execution because OpenAI is not configured.\",\n );\n } else {\n for (const candidate of consolidationPreview.candidates) {\n try {\n const result = await executeConsolidation(store, candidate, orgId, repoId, {\n model: options.model,\n preserveOriginals: options.preserveOriginals,\n });\n executedConsolidations.push(result);\n } catch (error) {\n errors.push(\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n }\n }\n }\n\n return {\n dryRun,\n totalActiveMemories: activeMemories.length,\n expiredCandidates,\n expiredCount: dryRun ? expiredCandidates.length : expiredCandidates.length,\n strengthenedCandidates,\n consolidationCandidates: consolidationPreview.candidates,\n executedConsolidations,\n warnings,\n errors,\n };\n}\n\nexport async function runRemoteLifecycleMaintenance(\n store: IRemoteStore,\n orgId: string,\n repoId: string,\n options: LifecycleMaintenanceOptions = {},\n): Promise<LifecycleMaintenanceResult> {\n const lifecycle = resolveLifecycleConfig(options.lifecycle);\n const dryRun = options.dryRun ?? lifecycle.maintenance.dryRunDefault;\n const activeMemories = await store.list({\n orgId,\n repoId,\n status: [\"active\"],\n includeExpired: true,\n limit: 1000,\n });\n const usageStats = await store.getUsageStats(orgId, repoId);\n const expiredCandidates = getExpiringCandidates(activeMemories);\n const strengthenedCandidates = getStrengthenedCandidates(\n activeMemories.filter((memory) => !isMemoryExpired(memory)),\n usageStats,\n lifecycle,\n );\n const consolidationPreview = await findConsolidationCandidatesRemote(\n store,\n orgId,\n repoId,\n {\n threshold: lifecycle.maintenance.consolidationThreshold,\n minGroupSize: lifecycle.maintenance.consolidationMinGroupSize,\n maxGroups: lifecycle.maintenance.consolidationMaxGroups,\n types: [\"episodic\"],\n excludeConsolidations: true,\n },\n );\n\n const warnings: string[] = [];\n const errors: string[] = [];\n const executedConsolidations: ExecuteConsolidationResult[] = [];\n\n if (!dryRun) {\n await store.expireExpiredMemories(orgId, repoId);\n\n if (consolidationPreview.candidates.length > 0) {\n if (!isOpenAIConfigured()) {\n warnings.push(\n \"Skipping consolidation execution because OpenAI is not configured.\",\n );\n } else {\n for (const candidate of consolidationPreview.candidates) {\n try {\n const result = await executeConsolidationRemote(\n store,\n candidate,\n orgId,\n repoId,\n {\n model: options.model,\n preserveOriginals: options.preserveOriginals,\n },\n );\n executedConsolidations.push(result);\n } catch (error) {\n errors.push(\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n }\n }\n }\n\n return {\n dryRun,\n totalActiveMemories: activeMemories.length,\n expiredCandidates,\n expiredCount: dryRun ? expiredCandidates.length : expiredCandidates.length,\n strengthenedCandidates,\n consolidationCandidates: consolidationPreview.candidates,\n executedConsolidations,\n warnings,\n errors,\n };\n}\n","import { EventEmitter } from \"events\";\nimport type { ILocalStore } from \"unforgit-shared\";\n\nexport interface SyncConfig {\n enabled: boolean;\n intervalMs: number;\n debounceMs: number;\n autoResolveConflicts: \"last_write_wins\" | \"local_wins\" | \"remote_wins\" | \"manual\";\n}\n\nexport interface SyncServiceOptions {\n store: ILocalStore;\n orgId: string;\n repoId: string;\n config?: Partial<SyncConfig>;\n onSync?: (result: SyncServiceResult) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface SyncServiceResult {\n timestamp: Date;\n pushed: number;\n pulled: number;\n conflicts: number;\n errors: string[];\n}\n\nexport interface SyncServiceStatus {\n isRunning: boolean;\n lastSyncAt: Date | null;\n lastResult: SyncServiceResult | null;\n pendingChanges: number;\n conflicts: number;\n nextSyncAt: Date | null;\n}\n\nconst DEFAULT_CONFIG: SyncConfig = {\n enabled: true,\n intervalMs: 60000,\n debounceMs: 5000,\n autoResolveConflicts: \"last_write_wins\",\n};\n\nexport class SyncService extends EventEmitter {\n private store: ILocalStore;\n private orgId: string;\n private repoId: string;\n private config: SyncConfig;\n\n private syncInterval: NodeJS.Timeout | null = null;\n private debounceTimer: NodeJS.Timeout | null = null;\n private isRunning = false;\n private isSyncing = false;\n\n private lastSyncAt: Date | null = null;\n private lastResult: SyncServiceResult | null = null;\n private nextSyncAt: Date | null = null;\n\n constructor(options: SyncServiceOptions) {\n super();\n this.store = options.store;\n this.orgId = options.orgId;\n this.repoId = options.repoId;\n this.config = { ...DEFAULT_CONFIG, ...options.config };\n\n if (options.onSync) {\n this.on(\"sync\", options.onSync);\n }\n if (options.onError) {\n this.on(\"error\", options.onError);\n }\n }\n\n start(): void {\n if (this.isRunning || !this.config.enabled) {\n return;\n }\n\n this.isRunning = true;\n this.scheduleNextSync();\n\n this.emit(\"started\");\n }\n\n stop(): void {\n if (!this.isRunning) {\n return;\n }\n\n this.isRunning = false;\n\n if (this.syncInterval) {\n clearTimeout(this.syncInterval);\n this.syncInterval = null;\n }\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n this.nextSyncAt = null;\n this.emit(\"stopped\");\n }\n\n onMemoryChange(): void {\n if (!this.isRunning || !this.config.enabled) {\n return;\n }\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.triggerSync();\n }, this.config.debounceMs);\n }\n\n async triggerSync(): Promise<SyncServiceResult | null> {\n if (this.isSyncing) {\n return null;\n }\n\n this.isSyncing = true;\n this.emit(\"sync:start\");\n\n try {\n const result = await this.performSync();\n\n this.lastSyncAt = new Date();\n this.lastResult = result;\n\n this.emit(\"sync\", result);\n return result;\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.emit(\"error\", err);\n return null;\n } finally {\n this.isSyncing = false;\n this.emit(\"sync:end\");\n\n if (this.isRunning) {\n this.scheduleNextSync();\n }\n }\n }\n\n getStatus(): SyncServiceStatus {\n const summary = this.store.getSyncSummary(this.orgId, this.repoId);\n\n return {\n isRunning: this.isRunning,\n lastSyncAt: this.lastSyncAt,\n lastResult: this.lastResult,\n pendingChanges: summary.pendingPush,\n conflicts: summary.conflicts,\n nextSyncAt: this.nextSyncAt,\n };\n }\n\n private scheduleNextSync(): void {\n if (this.syncInterval) {\n clearTimeout(this.syncInterval);\n }\n\n this.nextSyncAt = new Date(Date.now() + this.config.intervalMs);\n\n this.syncInterval = setTimeout(() => {\n this.syncInterval = null;\n this.triggerSync();\n }, this.config.intervalMs);\n }\n\n private async performSync(): Promise<SyncServiceResult> {\n const errors: string[] = [];\n let pushed = 0;\n const pulled = 0;\n let conflicts = 0;\n\n const pendingPush = this.store.getPendingPush();\n pushed = pendingPush.length;\n\n const conflictMemories = this.store.getConflicts();\n conflicts = conflictMemories.length;\n\n if (this.config.autoResolveConflicts !== \"manual\" && conflicts > 0) {\n for (const { memory, syncState } of conflictMemories) {\n try {\n this.resolveConflict(memory.id, syncState);\n } catch (err) {\n errors.push(`Conflict resolution failed for ${memory.id}: ${err}`);\n }\n }\n }\n\n return {\n timestamp: new Date(),\n pushed,\n pulled,\n conflicts,\n errors,\n };\n }\n\n private resolveConflict(memoryId: string, syncState: { localVersion: number; remoteVersion?: number }): void {\n switch (this.config.autoResolveConflicts) {\n case \"local_wins\":\n this.store.setSyncState({\n memoryId,\n localVersion: syncState.localVersion,\n remoteVersion: syncState.remoteVersion,\n syncStatus: \"pending_push\",\n });\n break;\n\n case \"remote_wins\":\n this.store.setSyncState({\n memoryId,\n localVersion: syncState.localVersion,\n remoteVersion: syncState.remoteVersion,\n syncStatus: \"pending_pull\",\n });\n break;\n\n case \"last_write_wins\":\n default:\n this.store.setSyncState({\n memoryId,\n localVersion: syncState.localVersion + 1,\n remoteVersion: syncState.remoteVersion,\n syncStatus: \"pending_push\",\n });\n break;\n }\n }\n\n updateConfig(config: Partial<SyncConfig>): void {\n const wasRunning = this.isRunning;\n\n if (wasRunning) {\n this.stop();\n }\n\n this.config = { ...this.config, ...config };\n\n if (wasRunning && this.config.enabled) {\n this.start();\n }\n }\n\n getConfig(): SyncConfig {\n return { ...this.config };\n }\n}\n\nexport function createSyncService(options: SyncServiceOptions): SyncService {\n return new SyncService(options);\n}\n","import type { MemoryType } from \"unforgit-shared\";\n\nexport interface MemoryTemplate {\n name: string;\n description: string;\n memoryType: MemoryType;\n defaultTags: string[];\n prefix?: string;\n visibility: \"private\" | \"repo\" | \"auto\";\n}\n\nexport const MEMORY_TEMPLATES: Record<string, MemoryTemplate> = {\n decision: {\n name: \"Decision\",\n description: \"Technical or architectural decision\",\n memoryType: \"semantic\",\n defaultTags: [\"decision\"],\n prefix: \"Decision:\",\n visibility: \"repo\",\n },\n adr: {\n name: \"ADR\",\n description: \"Architecture Decision Record\",\n memoryType: \"semantic\",\n defaultTags: [\"adr\", \"architecture\", \"decision\"],\n prefix: \"ADR:\",\n visibility: \"repo\",\n },\n gotcha: {\n name: \"Gotcha\",\n description: \"Non-obvious issue or caveat discovered\",\n memoryType: \"episodic\",\n defaultTags: [\"gotcha\", \"warning\"],\n prefix: \"Gotcha:\",\n visibility: \"repo\",\n },\n bug: {\n name: \"Bug\",\n description: \"Bug found and fixed\",\n memoryType: \"episodic\",\n defaultTags: [\"bug\", \"fix\"],\n prefix: \"Bug:\",\n visibility: \"private\",\n },\n playbook: {\n name: \"Playbook\",\n description: \"Step-by-step procedure or workflow\",\n memoryType: \"procedural\",\n defaultTags: [\"playbook\", \"howto\"],\n prefix: \"Playbook:\",\n visibility: \"repo\",\n },\n deploy: {\n name: \"Deploy\",\n description: \"Deployment procedure or notes\",\n memoryType: \"procedural\",\n defaultTags: [\"deploy\", \"ops\"],\n prefix: \"Deploy:\",\n visibility: \"repo\",\n },\n convention: {\n name: \"Convention\",\n description: \"Coding convention or standard\",\n memoryType: \"semantic\",\n defaultTags: [\"convention\", \"standard\"],\n prefix: \"Convention:\",\n visibility: \"repo\",\n },\n api: {\n name: \"API\",\n description: \"API behavior or contract notes\",\n memoryType: \"semantic\",\n defaultTags: [\"api\"],\n visibility: \"repo\",\n },\n workaround: {\n name: \"Workaround\",\n description: \"Temporary workaround for an issue\",\n memoryType: \"episodic\",\n defaultTags: [\"workaround\", \"temporary\"],\n prefix: \"Workaround:\",\n visibility: \"private\",\n },\n perf: {\n name: \"Performance\",\n description: \"Performance finding or optimization\",\n memoryType: \"semantic\",\n defaultTags: [\"performance\", \"optimization\"],\n prefix: \"Perf:\",\n visibility: \"repo\",\n },\n security: {\n name: \"Security\",\n description: \"Security consideration or finding\",\n memoryType: \"semantic\",\n defaultTags: [\"security\"],\n prefix: \"Security:\",\n visibility: \"repo\",\n },\n};\n\nexport function getTemplate(name: string): MemoryTemplate | undefined {\n return MEMORY_TEMPLATES[name.toLowerCase()];\n}\n\nexport function listTemplates(): MemoryTemplate[] {\n return Object.values(MEMORY_TEMPLATES);\n}\n\nexport function applyTemplate(\n template: MemoryTemplate,\n text: string,\n additionalTags: string[] = []\n): {\n text: string;\n memoryType: MemoryType;\n tags: string[];\n visibility: \"private\" | \"repo\" | \"auto\";\n} {\n const finalText = template.prefix && !text.toLowerCase().startsWith(template.prefix.toLowerCase())\n ? `${template.prefix} ${text}`\n : text;\n\n const tags = [...new Set([...template.defaultTags, ...additionalTags])];\n\n return {\n text: finalText,\n memoryType: template.memoryType,\n tags,\n visibility: template.visibility,\n };\n}\n\nexport function formatTemplateList(): string {\n const lines = [\"Available templates:\", \"\"];\n\n for (const [key, template] of Object.entries(MEMORY_TEMPLATES)) {\n lines.push(` ${key.padEnd(12)} - ${template.description}`);\n lines.push(` Type: ${template.memoryType}, Tags: ${template.defaultTags.join(\", \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport YAML from \"yaml\";\nimport type { AppConfig } from \"unforgit-shared\";\nimport { resolveLifecycleConfig } from \"unforgit-core\";\nimport { appConfigSchema } from \"./config-schemas.js\";\n\nconst DATA_DIR = \".unforgit\";\nconst CONFIG_FILE = \"unforgit.yaml\";\nconst DB_FILE = \"local.db\";\n\nfunction writeConfigYaml(configPath: string, value: Record<string, unknown>): void {\n const dir = path.dirname(configPath);\n fs.mkdirSync(dir, { recursive: true });\n\n const tmpPath = path.join(\n dir,\n `.${path.basename(configPath)}.${process.pid}.${randomUUID()}.tmp`,\n );\n const fd = fs.openSync(\n tmpPath,\n fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY,\n 0o600,\n );\n\n try {\n fs.writeFileSync(fd, YAML.stringify(value), \"utf-8\");\n fs.fsyncSync(fd);\n } catch (err) {\n try {\n fs.closeSync(fd);\n } catch {\n // Ignore close errors while preserving the original write error.\n }\n fs.rmSync(tmpPath, { force: true });\n throw err;\n }\n\n fs.closeSync(fd);\n fs.renameSync(tmpPath, configPath);\n fs.chmodSync(configPath, 0o600);\n}\n\nexport function detectGitInfo(cwd: string = process.cwd()): {\n orgId: string;\n repoId: string;\n} {\n try {\n const remoteUrl = execSync(\"git remote get-url origin\", {\n cwd,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n }).trim();\n\n // Handles both SSH (git@github.com:org/repo.git) and HTTPS (https://github.com/org/repo.git)\n const match =\n remoteUrl.match(/[:/]([^/]+)\\/([^/]+?)(?:\\.git)?$/) ?? undefined;\n\n if (match) {\n return { orgId: match[1], repoId: match[2] };\n }\n } catch {\n // Not a git repo or no remote configured\n }\n return { orgId: \"\", repoId: \"\" };\n}\n\nexport function getDataDir(cwd: string = process.cwd()): string {\n return path.join(cwd, DATA_DIR);\n}\n\nexport function getDbPath(cwd: string = process.cwd()): string {\n return path.join(getDataDir(cwd), DB_FILE);\n}\n\nexport function getConfigPath(cwd: string = process.cwd()): string {\n return path.join(getDataDir(cwd), CONFIG_FILE);\n}\n\nexport function isInitialized(cwd: string = process.cwd()): boolean {\n return fs.existsSync(getDataDir(cwd)) && fs.existsSync(getConfigPath(cwd));\n}\n\nexport function findRepoRoot(startDir: string = process.cwd()): string | null {\n let dir = path.resolve(startDir);\n const root = path.parse(dir).root;\n\n while (dir !== root) {\n if (isInitialized(dir)) return dir;\n dir = path.dirname(dir);\n }\n\n return null;\n}\n\nconst CURRENT_CONFIG_VERSION = 2;\n\nfunction migrateConfig(parsed: Record<string, unknown>, configPath: string): Record<string, unknown> {\n const version = (parsed.configVersion as number) ?? 0;\n\n if (version === CURRENT_CONFIG_VERSION) return parsed;\n\n if (version === 0) {\n parsed.configVersion = CURRENT_CONFIG_VERSION;\n writeConfigYaml(configPath, parsed);\n }\n\n if (version === 1) {\n parsed.configVersion = CURRENT_CONFIG_VERSION;\n writeConfigYaml(configPath, parsed);\n }\n\n return parsed;\n}\n\nfunction warnDeprecatedKeys(parsed: Record<string, unknown>): void {\n const deprecated: string[] = [];\n if ((parsed.remote as Record<string, unknown>)?.apiKey) {\n deprecated.push(\"remote.apiKey → use UNFORGIT_API_KEY env var instead\");\n }\n if (parsed.openaiApiKey) {\n deprecated.push(\"openaiApiKey → use OPENAI_API_KEY env var instead\");\n }\n if (deprecated.length > 0) {\n console.error(\n `[unforgit] Deprecated keys found in unforgit.yaml (ignored):\\n${deprecated.map((d) => ` - ${d}`).join(\"\\n\")}\\n` +\n `Remove them from your config. Secrets should be set via environment variables.\\n`,\n );\n }\n}\n\nexport function loadConfig(cwd: string = process.cwd()): AppConfig {\n const configPath = getConfigPath(cwd);\n if (!fs.existsSync(configPath)) {\n throw new Error(\n \"Unforgit not initialized. Run 'unforgit init' first.\",\n );\n }\n const raw = fs.readFileSync(configPath, \"utf-8\");\n const parsed = YAML.parse(raw) ?? {};\n\n const migrated = migrateConfig(parsed, configPath);\n\n warnDeprecatedKeys(migrated);\n\n const result = appConfigSchema.safeParse(migrated);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` - ${(i.path as (string | number)[]).join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(\n `Invalid unforgit.yaml configuration:\\n${issues}\\n\\nFix the config at ${configPath} or re-run 'unforgit init'.`,\n );\n }\n\n const defaults = defaultConfig();\n\n const { openaiApiKey: _oai, ...cleanMigrated } = migrated as Record<string, unknown> & { openaiApiKey?: unknown };\n if (cleanMigrated.remote && typeof cleanMigrated.remote === \"object\") {\n const { apiKey: _ak, ...cleanRemote } = cleanMigrated.remote as Record<string, unknown>;\n cleanMigrated.remote = cleanRemote;\n }\n\n return {\n ...defaults,\n ...cleanMigrated,\n ...result.data,\n remote: {\n ...defaults.remote,\n ...result.data.remote,\n },\n defaults: {\n ...defaults.defaults,\n ...result.data.defaults,\n },\n sync: {\n ...defaults.sync,\n ...(result.data.sync ?? {}),\n },\n embeddings: {\n ...defaults.embeddings,\n ...(result.data.embeddings ?? {}),\n },\n lifecycle: resolveLifecycleConfig(result.data.lifecycle),\n } as AppConfig;\n}\n\nexport function saveConfig(\n config: AppConfig,\n cwd: string = process.cwd(),\n): void {\n const configPath = getConfigPath(cwd);\n writeConfigYaml(configPath, config as unknown as Record<string, unknown>);\n}\n\nexport function defaultConfig(): AppConfig & { configVersion: number } {\n return {\n configVersion: CURRENT_CONFIG_VERSION,\n remote: {\n url: \"http://localhost:3737\",\n orgId: \"\",\n repoId: \"\",\n },\n defaults: {\n visibility: \"auto\",\n memoryType: \"episodic\",\n },\n sync: {\n enabled: true,\n intervalMs: 60000,\n debounceMs: 5000,\n autoResolveConflicts: \"last_write_wins\",\n },\n embeddings: {\n enabled: true,\n model: \"text-embedding-3-small\",\n autoGenerate: true,\n },\n lifecycle: resolveLifecycleConfig(),\n };\n}\n","import { z } from \"zod\";\n\nexport const syncConfigSchema = z.object({\n enabled: z.boolean(),\n intervalMs: z.number().positive(),\n debounceMs: z.number().nonnegative(),\n autoResolveConflicts: z.enum([\n \"last_write_wins\",\n \"local_wins\",\n \"remote_wins\",\n \"manual\",\n ]),\n});\n\nexport const embeddingConfigSchema = z.object({\n enabled: z.boolean(),\n model: z.string(),\n autoGenerate: z.boolean(),\n});\n\nexport const lifecycleTtlConfigSchema = z.object({\n episodic: z.number().int().positive().optional(),\n semantic: z.number().int().positive().optional(),\n procedural: z.number().int().positive().optional(),\n});\n\nexport const lifecycleUsageBoostSchema = z.object({\n enabled: z.boolean(),\n topKToRecord: z.number().int().positive(),\n minUsageCount: z.number().int().positive(),\n maxBoost: z.number().min(0).max(1),\n halfLifeDays: z.number().positive(),\n});\n\nexport const lifecycleMaintenanceSchema = z.object({\n staleEpisodicDays: z.number().int().positive(),\n consolidationThreshold: z.number().min(0).max(1),\n consolidationMinGroupSize: z.number().int().min(2),\n consolidationMaxGroups: z.number().int().positive(),\n promoteRecallCount: z.number().int().positive(),\n pinRecallCount: z.number().int().positive(),\n dryRunDefault: z.boolean(),\n autoRunOnStore: z.boolean(),\n autoRunOnRecall: z.boolean(),\n debounceMs: z.number().int().positive(),\n});\n\nexport const lifecycleConfigSchema = z.object({\n ttlSecondsByType: lifecycleTtlConfigSchema.optional(),\n usageBoost: lifecycleUsageBoostSchema.partial().optional(),\n maintenance: lifecycleMaintenanceSchema.partial().optional(),\n});\n\nconst remoteConfigSchema = z.object({\n url: z.string(),\n orgId: z.string(),\n repoId: z.string(),\n});\n\nexport const appConfigSchema = z.object({\n configVersion: z.number().optional(),\n remote: remoteConfigSchema,\n defaults: z.object({\n visibility: z.enum([\"private\", \"repo\", \"auto\"]),\n memoryType: z.enum([\"episodic\", \"semantic\", \"procedural\"]),\n }),\n sync: syncConfigSchema.optional(),\n embeddings: embeddingConfigSchema.optional(),\n lifecycle: lifecycleConfigSchema.optional(),\n remotes: z.record(z.string(), remoteConfigSchema).optional(),\n});\n\nconst VALID_MEMORY_TYPES = [\"episodic\", \"semantic\", \"procedural\"] as const;\n\nexport function validateMemoryType(value: string): value is (typeof VALID_MEMORY_TYPES)[number] {\n return (VALID_MEMORY_TYPES as readonly string[]).includes(value);\n}\n\nexport function parseConfidence(value: string): number {\n const n = parseFloat(value);\n if (Number.isNaN(n) || n < 0 || n > 1) {\n throw new Error(\"--confidence must be a number between 0 and 1\");\n }\n return n;\n}\n\nexport function parseThreshold(value: string): number {\n const n = parseFloat(value);\n if (Number.isNaN(n) || n < 0 || n > 1) {\n throw new Error(\"--threshold must be a number between 0 and 1\");\n }\n return n;\n}\n\nexport function parseTtl(value: string): number {\n const n = parseInt(value, 10);\n if (Number.isNaN(n) || n <= 0) {\n throw new Error(\"--ttl must be a positive integer (seconds)\");\n }\n return n;\n}\n\nexport function parsePositiveInt(value: string, name: string): number {\n const n = parseInt(value, 10);\n if (Number.isNaN(n) || n <= 0) {\n throw new Error(`--${name} must be a positive integer`);\n }\n return n;\n}\n","import type {\n CreateMemoryInput,\n MemoryLink,\n RecallQuery,\n RecallResult,\n} from \"unforgit-shared\";\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst MAX_RETRIES = 3;\nconst INITIAL_BACKOFF_MS = 1_000;\n\nfunction isTransientError(status: number): boolean {\n return status >= 500 || status === 429;\n}\n\nexport class RemoteClient {\n private apiKey?: string;\n private timeoutMs: number;\n\n constructor(\n private baseUrl: string,\n apiKey?: string,\n options?: { timeoutMs?: number },\n ) {\n this.apiKey = apiKey || process.env.UNFORGIT_API_KEY;\n this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n }\n\n private getHeaders(): Record<string, string> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (this.apiKey) {\n headers[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n private handleError(res: Response, operation: string, errorText: string): never {\n if (res.status === 401) {\n throw new Error(\n `Authentication failed for ${operation}: Invalid or missing API key. ` +\n `Set the UNFORGIT_API_KEY environment variable.`\n );\n }\n if (res.status === 404 && operation === \"resetAll\") {\n throw new Error(\n \"Remote resetAll failed (404): the configured server does not support \" +\n \"/v1/memories/reset. Rebuild or restart the remote API so it is running \" +\n \"a version that includes the reset endpoint.\"\n );\n }\n throw new Error(`Remote ${operation} failed (${res.status}): ${errorText}`);\n }\n\n private async fetchWithTimeout(\n url: string,\n init: RequestInit,\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n throw new Error(`Request timed out after ${this.timeoutMs}ms`);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init: RequestInit,\n operation: string,\n ): Promise<Response> {\n let lastError: Error | undefined;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const res = await this.fetchWithTimeout(url, init);\n\n if (res.ok || !isTransientError(res.status)) {\n return res;\n }\n\n lastError = new Error(\n `Remote ${operation} failed (${res.status}): ${await res.text()}`,\n );\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n\n const isFatalAbort =\n lastError.message.includes(\"timed out\") && attempt === MAX_RETRIES - 1;\n if (isFatalAbort) throw lastError;\n }\n\n if (attempt < MAX_RETRIES - 1) {\n const backoff = INITIAL_BACKOFF_MS * Math.pow(2, attempt);\n await new Promise((resolve) => setTimeout(resolve, backoff));\n }\n }\n\n throw lastError ?? new Error(`Remote ${operation} failed after ${MAX_RETRIES} retries`);\n }\n\n async store(input: CreateMemoryInput): Promise<{ id: string }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory`,\n { method: \"POST\", headers: this.getHeaders(), body: JSON.stringify(input) },\n \"store\",\n );\n if (!res.ok) {\n this.handleError(res, \"store\", await res.text());\n }\n return res.json() as Promise<{ id: string }>;\n }\n\n async recall(query: RecallQuery): Promise<{ results: RecallResult[] }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/recall`,\n { method: \"POST\", headers: this.getHeaders(), body: JSON.stringify(query) },\n \"recall\",\n );\n if (!res.ok) {\n this.handleError(res, \"recall\", await res.text());\n }\n return res.json() as Promise<{ results: RecallResult[] }>;\n }\n\n async deprecate(id: string, reason?: string): Promise<{ ok: boolean }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory/${id}/deprecate`,\n { method: \"POST\", headers: this.getHeaders(), body: JSON.stringify({ reason }) },\n \"deprecate\",\n );\n if (!res.ok) {\n this.handleError(res, \"deprecate\", await res.text());\n }\n return res.json() as Promise<{ ok: boolean }>;\n }\n\n async supersede(oldId: string, newId: string): Promise<{ ok: boolean }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory/${oldId}/supersede`,\n { method: \"POST\", headers: this.getHeaders(), body: JSON.stringify({ newId }) },\n \"supersede\",\n );\n if (!res.ok) {\n this.handleError(res, \"supersede\", await res.text());\n }\n return res.json() as Promise<{ ok: boolean }>;\n }\n\n async link(\n sourceId: string,\n targetId: string,\n linkType: string,\n metadata?: Record<string, unknown>,\n ): Promise<{ link: MemoryLink }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory/${sourceId}/link`,\n {\n method: \"POST\",\n headers: this.getHeaders(),\n body: JSON.stringify({ targetId, linkType, metadata }),\n },\n \"link\",\n );\n if (!res.ok) {\n this.handleError(res, \"link\", await res.text());\n }\n return res.json() as Promise<{ link: MemoryLink }>;\n }\n\n async unlink(\n sourceId: string,\n targetId: string,\n linkType: string,\n ): Promise<{ ok: boolean }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory/${sourceId}/link`,\n {\n method: \"DELETE\",\n headers: this.getHeaders(),\n body: JSON.stringify({ targetId, linkType }),\n },\n \"unlink\",\n );\n if (!res.ok) {\n this.handleError(res, \"unlink\", await res.text());\n }\n return res.json() as Promise<{ ok: boolean }>;\n }\n\n async getLinks(\n memoryId: string,\n linkType?: string,\n ): Promise<{ links: MemoryLink[] }> {\n const params = new URLSearchParams();\n if (linkType) params.set(\"linkType\", linkType);\n const qs = params.toString();\n const url = `${this.baseUrl}/v1/memory/${memoryId}/links${qs ? `?${qs}` : \"\"}`;\n\n const res = await this.fetchWithRetry(url, { headers: this.getHeaders() }, \"getLinks\");\n if (!res.ok) {\n this.handleError(res, \"getLinks\", await res.text());\n }\n return res.json() as Promise<{ links: MemoryLink[] }>;\n }\n\n async consolidate(body: Record<string, unknown>): Promise<{\n created: string[];\n superseded: string[];\n processedCount: number;\n }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/consolidate`,\n { method: \"POST\", headers: this.getHeaders(), body: JSON.stringify(body) },\n \"consolidate\",\n );\n if (!res.ok) {\n this.handleError(res, \"consolidate\", await res.text());\n }\n return res.json() as Promise<{\n created: string[];\n superseded: string[];\n processedCount: number;\n }>;\n }\n\n async delete(\n id: string,\n deletedBy?: string,\n hardDelete?: boolean,\n ): Promise<{ success: boolean; action: string }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory/${id}`,\n {\n method: \"DELETE\",\n headers: this.getHeaders(),\n body: JSON.stringify({ deletedBy, hardDelete }),\n },\n \"delete\",\n );\n if (!res.ok) {\n this.handleError(res, \"delete\", await res.text());\n }\n return res.json() as Promise<{ success: boolean; action: string }>;\n }\n\n async restore(id: string): Promise<{ success: boolean }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memory/${id}/restore`,\n { method: \"POST\", headers: this.getHeaders() },\n \"restore\",\n );\n if (!res.ok) {\n this.handleError(res, \"restore\", await res.text());\n }\n return res.json() as Promise<{ success: boolean }>;\n }\n\n async resetAll(orgId: string, repoId: string): Promise<{\n memoriesDeleted: number;\n linksDeleted: number;\n embeddingsDeleted: number;\n }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/memories/reset`,\n {\n method: \"POST\",\n headers: this.getHeaders(),\n body: JSON.stringify({ orgId, repoId }),\n },\n \"resetAll\",\n );\n if (!res.ok) {\n this.handleError(res, \"resetAll\", await res.text());\n }\n return res.json() as Promise<{\n memoriesDeleted: number;\n linksDeleted: number;\n embeddingsDeleted: number;\n }>;\n }\n\n async runLifecycle(body: {\n orgId: string;\n repoId: string;\n dryRun?: boolean;\n model?: string;\n preserveOriginals?: boolean;\n }): Promise<{\n dryRun: boolean;\n totalActiveMemories: number;\n expiredCandidates: Array<{\n id: string;\n ttlSeconds: number;\n reason: string;\n textPreview: string;\n }>;\n expiredCount: number;\n strengthenedCandidates: Array<{\n id: string;\n usageCount: number;\n lastUsed?: string;\n recommendedAction: \"promote\" | \"pin\";\n reason: string;\n textPreview: string;\n }>;\n consolidationCandidates: Array<{\n reason: string;\n averageScore: number;\n suggestedTags: string[];\n memories: Array<{ id: string; memoryType: string; text: string }>;\n }>;\n executedConsolidations: Array<{\n consolidatedId: string;\n sourceIds: string[];\n generatedText: string;\n suggestedTags: string[];\n memoryType: string;\n }>;\n warnings: string[];\n errors: string[];\n }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/lifecycle/run`,\n {\n method: \"POST\",\n headers: this.getHeaders(),\n body: JSON.stringify(body),\n },\n \"runLifecycle\",\n );\n if (!res.ok) {\n this.handleError(res, \"runLifecycle\", await res.text());\n }\n return res.json() as Promise<{\n dryRun: boolean;\n totalActiveMemories: number;\n expiredCandidates: Array<{\n id: string;\n ttlSeconds: number;\n reason: string;\n textPreview: string;\n }>;\n expiredCount: number;\n strengthenedCandidates: Array<{\n id: string;\n usageCount: number;\n lastUsed?: string;\n recommendedAction: \"promote\" | \"pin\";\n reason: string;\n textPreview: string;\n }>;\n consolidationCandidates: Array<{\n reason: string;\n averageScore: number;\n suggestedTags: string[];\n memories: Array<{ id: string; memoryType: string; text: string }>;\n }>;\n executedConsolidations: Array<{\n consolidatedId: string;\n sourceIds: string[];\n generatedText: string;\n suggestedTags: string[];\n memoryType: string;\n }>;\n warnings: string[];\n errors: string[];\n }>;\n }\n\n async createApiKey(name: string, orgId: string): Promise<{\n id: string;\n key: string;\n name: string;\n orgId: string;\n }> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/api-keys`,\n {\n method: \"POST\",\n headers: this.getHeaders(),\n body: JSON.stringify({ name, orgId }),\n },\n \"createApiKey\",\n );\n if (!res.ok) {\n this.handleError(res, \"createApiKey\", await res.text());\n }\n return res.json() as Promise<{ id: string; key: string; name: string; orgId: string }>;\n }\n\n async listApiKeys(orgId?: string): Promise<{\n keys: Array<{\n id: string;\n name: string;\n orgId: string;\n isActive: boolean;\n createdAt: string;\n lastUsedAt: string | null;\n }>;\n }> {\n const params = new URLSearchParams();\n if (orgId) params.set(\"orgId\", orgId);\n const qs = params.toString();\n const url = `${this.baseUrl}/v1/api-keys${qs ? `?${qs}` : \"\"}`;\n\n const res = await this.fetchWithRetry(url, { headers: this.getHeaders() }, \"listApiKeys\");\n if (!res.ok) {\n this.handleError(res, \"listApiKeys\", await res.text());\n }\n return res.json() as Promise<{\n keys: Array<{\n id: string;\n name: string;\n orgId: string;\n isActive: boolean;\n createdAt: string;\n lastUsedAt: string | null;\n }>;\n }>;\n }\n\n async revokeApiKey(id: string): Promise<void> {\n const res = await this.fetchWithRetry(\n `${this.baseUrl}/v1/api-keys/${id}`,\n { method: \"DELETE\", headers: this.getHeaders() },\n \"revokeApiKey\",\n );\n if (!res.ok) {\n if (res.status === 404) {\n throw new Error(`API key '${id}' not found.`);\n }\n this.handleError(res, \"revokeApiKey\", await res.text());\n }\n }\n}\n","import Database from \"better-sqlite3\";\nimport { v4 as uuid } from \"uuid\";\nimport path from \"node:path\";\nimport fs from \"node:fs\";\nimport type {\n Memory,\n MemoryLink,\n CreateMemoryInput,\n CreateLinkInput,\n LinkQuery,\n RecallQuery,\n RecallResult,\n ListQuery,\n StoreStats,\n ConsolidateMemoriesInput,\n ConsolidateMemoriesResult,\n ReconsolidateInput,\n FindSimilarQuery,\n Tombstone,\n DeleteMemoryInput,\n SyncState,\n SyncStatus,\n CurationSuggestion,\n CreateCurationSuggestionInput,\n ListCurationSuggestionsQuery,\n ReviewCurationSuggestionInput,\n} from \"unforgit-shared\";\nimport { computeCompositeScore, computeHybridScore } from \"unforgit-core\";\nimport {\n applyLifecycleDefaults,\n computeUsageBoost,\n} from \"unforgit-core\";\nimport {\n generateEmbedding,\n serializeEmbedding,\n deserializeEmbedding,\n cosineSimilarity,\n type EmbeddingConfig,\n} from \"unforgit-core\";\n\nconst SCHEMA_SQL = `\nCREATE TABLE IF NOT EXISTS memories (\n id TEXT PRIMARY KEY,\n org_id TEXT NOT NULL,\n repo_id TEXT NOT NULL,\n scope_type TEXT NOT NULL DEFAULT 'repo',\n memory_type TEXT NOT NULL CHECK(memory_type IN ('episodic','semantic','procedural')),\n visibility TEXT NOT NULL DEFAULT 'private' CHECK(visibility IN ('private','repo')),\n status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','deprecated','superseded','deleted')),\n text TEXT NOT NULL,\n summary TEXT,\n tags TEXT NOT NULL DEFAULT '[]',\n source_refs TEXT,\n confidence REAL,\n ttl_seconds INTEGER,\n supersedes_id TEXT,\n is_consolidation INTEGER NOT NULL DEFAULT 0,\n consolidation_version INTEGER,\n author_id TEXT,\n author_name TEXT,\n version INTEGER NOT NULL DEFAULT 1,\n deleted_at TEXT,\n deleted_by TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS tombstones (\n id TEXT PRIMARY KEY,\n memory_id TEXT NOT NULL UNIQUE,\n org_id TEXT NOT NULL,\n repo_id TEXT NOT NULL,\n deleted_at TEXT NOT NULL,\n deleted_by TEXT,\n synced_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_tombstones_sync ON tombstones(org_id, repo_id, synced_at);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(\n text, summary, content=memories, content_rowid=rowid\n);\n\nCREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN\n INSERT INTO memories_fts(rowid, text, summary)\n VALUES (new.rowid, new.text, new.summary);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN\n INSERT INTO memories_fts(memories_fts, rowid, text, summary)\n VALUES ('delete', old.rowid, old.text, old.summary);\nEND;\n\nCREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN\n INSERT INTO memories_fts(memories_fts, rowid, text, summary)\n VALUES ('delete', old.rowid, old.text, old.summary);\n INSERT INTO memories_fts(rowid, text, summary)\n VALUES (new.rowid, new.text, new.summary);\nEND;\n\nCREATE TABLE IF NOT EXISTS memory_links (\n id TEXT PRIMARY KEY,\n source_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,\n target_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,\n link_type TEXT NOT NULL CHECK(link_type IN ('related_to','derived_from','contradicts','depends_on')),\n metadata TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n UNIQUE(source_id, target_id, link_type)\n);\n\nCREATE TABLE IF NOT EXISTS sync_state (\n memory_id TEXT PRIMARY KEY,\n local_version INTEGER NOT NULL,\n remote_version INTEGER,\n last_pushed_at TEXT,\n last_pulled_at TEXT,\n sync_status TEXT NOT NULL DEFAULT 'pending_push' CHECK(sync_status IN ('synced','pending_push','pending_pull','conflict'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_sync_state_status ON sync_state(sync_status);\n\nCREATE TABLE IF NOT EXISTS synced_links (\n link_id TEXT PRIMARY KEY,\n synced_at TEXT NOT NULL\n);\n\nCREATE TABLE IF NOT EXISTS memory_embeddings (\n memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,\n embedding BLOB NOT NULL,\n model TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE TABLE IF NOT EXISTS memory_usage (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n memory_id TEXT NOT NULL,\n recalled_at TEXT NOT NULL DEFAULT (datetime('now')),\n query TEXT,\n session_id TEXT\n);\n\nCREATE INDEX IF NOT EXISTS idx_memory_usage_memory ON memory_usage(memory_id);\nCREATE INDEX IF NOT EXISTS idx_memory_usage_recalled ON memory_usage(recalled_at);\n\nCREATE TABLE IF NOT EXISTS curation_suggestions (\n id TEXT PRIMARY KEY,\n org_id TEXT NOT NULL,\n repo_id TEXT NOT NULL,\n type TEXT NOT NULL CHECK(type IN ('consolidate','deprecate','delete','add_tags','add_links','review','promote','generate_embedding')),\n priority TEXT NOT NULL CHECK(priority IN ('high','medium','low')),\n status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','approved','rejected','applied')),\n memory_ids TEXT NOT NULL DEFAULT '[]',\n reason TEXT NOT NULL,\n confidence REAL NOT NULL,\n payload TEXT,\n created_by TEXT,\n reviewed_by TEXT,\n review_note TEXT,\n reviewed_at TEXT,\n applied_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\nCREATE INDEX IF NOT EXISTS idx_curation_suggestions_repo_status ON curation_suggestions(org_id, repo_id, status, created_at);\n`;\n\nfunction rowToLink(row: Record<string, unknown>): MemoryLink {\n return {\n id: row.id as string,\n sourceId: row.source_id as string,\n targetId: row.target_id as string,\n linkType: row.link_type as MemoryLink[\"linkType\"],\n metadata: row.metadata\n ? JSON.parse(row.metadata as string)\n : undefined,\n createdAt: new Date(row.created_at as string),\n };\n}\n\nfunction rowToMemory(row: Record<string, unknown>): Memory {\n return {\n id: row.id as string,\n orgId: row.org_id as string,\n repoId: row.repo_id as string,\n scopeType: (row.scope_type as Memory[\"scopeType\"]) ?? \"repo\",\n memoryType: row.memory_type as Memory[\"memoryType\"],\n visibility: row.visibility as Memory[\"visibility\"],\n status: row.status as Memory[\"status\"],\n text: row.text as string,\n summary: (row.summary as string) ?? undefined,\n tags: JSON.parse((row.tags as string) ?? \"[]\"),\n sourceRefs: row.source_refs\n ? JSON.parse(row.source_refs as string)\n : undefined,\n confidence: (row.confidence as number) ?? undefined,\n ttlSeconds: (row.ttl_seconds as number) ?? undefined,\n supersedesId: (row.supersedes_id as string) ?? undefined,\n isConsolidation: row.is_consolidation === 1,\n consolidationVersion: (row.consolidation_version as number) ?? undefined,\n authorId: (row.author_id as string) ?? undefined,\n authorName: (row.author_name as string) ?? undefined,\n version: (row.version as number) ?? 1,\n deletedAt: row.deleted_at ? new Date(row.deleted_at as string) : undefined,\n deletedBy: (row.deleted_by as string) ?? undefined,\n createdAt: new Date(row.created_at as string),\n updatedAt: new Date(row.updated_at as string),\n };\n}\n\nfunction rowToCurationSuggestion(row: Record<string, unknown>): CurationSuggestion {\n return {\n id: row.id as string,\n orgId: row.org_id as string,\n repoId: row.repo_id as string,\n type: row.type as CurationSuggestion[\"type\"],\n priority: row.priority as CurationSuggestion[\"priority\"],\n status: row.status as CurationSuggestion[\"status\"],\n memoryIds: JSON.parse((row.memory_ids as string) ?? \"[]\"),\n reason: row.reason as string,\n confidence: row.confidence as number,\n payload: row.payload ? JSON.parse(row.payload as string) : undefined,\n createdBy: (row.created_by as string) ?? undefined,\n reviewedBy: (row.reviewed_by as string) ?? undefined,\n reviewNote: (row.review_note as string) ?? undefined,\n reviewedAt: row.reviewed_at ? new Date(row.reviewed_at as string) : undefined,\n appliedAt: row.applied_at ? new Date(row.applied_at as string) : undefined,\n createdAt: new Date(row.created_at as string),\n updatedAt: new Date(row.updated_at as string),\n };\n}\n\nfunction rowToTombstone(row: Record<string, unknown>): Tombstone {\n return {\n id: row.id as string,\n memoryId: row.memory_id as string,\n orgId: row.org_id as string,\n repoId: row.repo_id as string,\n deletedAt: new Date(row.deleted_at as string),\n deletedBy: (row.deleted_by as string) ?? undefined,\n syncedAt: row.synced_at ? new Date(row.synced_at as string) : undefined,\n };\n}\n\nfunction nonExpiredMemoryClause(alias?: string): string {\n const prefix = alias ? `${alias}.` : \"\";\n return `(${prefix}status != 'active' OR ${prefix}ttl_seconds IS NULL OR datetime(${prefix}created_at, '+' || ${prefix}ttl_seconds || ' seconds') >= datetime('now'))`;\n}\n\nexport class LocalStore {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n const dir = path.dirname(dbPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n this.db = new Database(dbPath);\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"foreign_keys = ON\");\n this.db.exec(SCHEMA_SQL);\n this.migrateSchema();\n }\n\n private migrateSchema(): void {\n const columns = this.db\n .prepare(\"PRAGMA table_info(memories)\")\n .all() as Array<{ name: string }>;\n const columnNames = columns.map((c) => c.name);\n\n if (!columnNames.includes(\"is_consolidation\")) {\n this.db.exec(\n \"ALTER TABLE memories ADD COLUMN is_consolidation INTEGER NOT NULL DEFAULT 0\",\n );\n }\n if (!columnNames.includes(\"consolidation_version\")) {\n this.db.exec(\n \"ALTER TABLE memories ADD COLUMN consolidation_version INTEGER\",\n );\n }\n if (!columnNames.includes(\"author_id\")) {\n this.db.exec(\"ALTER TABLE memories ADD COLUMN author_id TEXT\");\n }\n if (!columnNames.includes(\"author_name\")) {\n this.db.exec(\"ALTER TABLE memories ADD COLUMN author_name TEXT\");\n }\n if (!columnNames.includes(\"version\")) {\n this.db.exec(\"ALTER TABLE memories ADD COLUMN version INTEGER NOT NULL DEFAULT 1\");\n }\n if (!columnNames.includes(\"deleted_at\")) {\n this.db.exec(\"ALTER TABLE memories ADD COLUMN deleted_at TEXT\");\n }\n if (!columnNames.includes(\"deleted_by\")) {\n this.db.exec(\"ALTER TABLE memories ADD COLUMN deleted_by TEXT\");\n }\n\n const tables = this.db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='tombstones'\")\n .all() as Array<{ name: string }>;\n if (tables.length === 0) {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS tombstones (\n id TEXT PRIMARY KEY,\n memory_id TEXT NOT NULL UNIQUE,\n org_id TEXT NOT NULL,\n repo_id TEXT NOT NULL,\n deleted_at TEXT NOT NULL,\n deleted_by TEXT,\n synced_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n CREATE INDEX IF NOT EXISTS idx_tombstones_sync ON tombstones(org_id, repo_id, synced_at);\n `);\n }\n\n const syncTables = this.db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='sync_state'\")\n .all() as Array<{ name: string }>;\n if (syncTables.length === 0) {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS sync_state (\n memory_id TEXT PRIMARY KEY,\n local_version INTEGER NOT NULL,\n remote_version INTEGER,\n last_pushed_at TEXT,\n last_pulled_at TEXT,\n sync_status TEXT NOT NULL DEFAULT 'pending_push' CHECK(sync_status IN ('synced','pending_push','pending_pull','conflict'))\n );\n CREATE INDEX IF NOT EXISTS idx_sync_state_status ON sync_state(sync_status);\n `);\n }\n\n const embeddingTables = this.db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='memory_embeddings'\")\n .all() as Array<{ name: string }>;\n if (embeddingTables.length === 0) {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memory_embeddings (\n memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,\n embedding BLOB NOT NULL,\n model TEXT NOT NULL,\n created_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n `);\n }\n\n const usageTables = this.db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='memory_usage'\")\n .all() as Array<{ name: string }>;\n if (usageTables.length === 0) {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memory_usage (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n memory_id TEXT NOT NULL,\n recalled_at TEXT NOT NULL DEFAULT (datetime('now')),\n query TEXT,\n session_id TEXT\n );\n CREATE INDEX IF NOT EXISTS idx_memory_usage_memory ON memory_usage(memory_id);\n CREATE INDEX IF NOT EXISTS idx_memory_usage_recalled ON memory_usage(recalled_at);\n `);\n }\n\n const curationSuggestionTables = this.db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='curation_suggestions'\")\n .all() as Array<{ name: string }>;\n if (curationSuggestionTables.length === 0) {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS curation_suggestions (\n id TEXT PRIMARY KEY,\n org_id TEXT NOT NULL,\n repo_id TEXT NOT NULL,\n type TEXT NOT NULL CHECK(type IN ('consolidate','deprecate','delete','add_tags','add_links','review','promote','generate_embedding')),\n priority TEXT NOT NULL CHECK(priority IN ('high','medium','low')),\n status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','approved','rejected','applied')),\n memory_ids TEXT NOT NULL DEFAULT '[]',\n reason TEXT NOT NULL,\n confidence REAL NOT NULL,\n payload TEXT,\n created_by TEXT,\n reviewed_by TEXT,\n review_note TEXT,\n reviewed_at TEXT,\n applied_at TEXT,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n CREATE INDEX IF NOT EXISTS idx_curation_suggestions_repo_status ON curation_suggestions(org_id, repo_id, status, created_at);\n `);\n }\n }\n\n store(input: CreateMemoryInput): Memory {\n const resolvedInput = applyLifecycleDefaults(input);\n const id = uuid();\n const now = new Date().toISOString();\n const normalizedOrgId = resolvedInput.orgId.toLowerCase();\n const normalizedRepoId = resolvedInput.repoId.toLowerCase();\n const visibility =\n resolvedInput.visibility === \"auto\" || !resolvedInput.visibility\n ? \"private\"\n : resolvedInput.visibility;\n\n this.db\n .prepare(\n `INSERT INTO memories\n (id, org_id, repo_id, scope_type, memory_type, visibility, status, text, summary, tags, source_refs, confidence, ttl_seconds, author_id, author_name, created_at, updated_at)\n VALUES (?, ?, ?, 'repo', ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n normalizedOrgId,\n normalizedRepoId,\n resolvedInput.memoryType,\n visibility,\n resolvedInput.text,\n resolvedInput.summary ?? null,\n JSON.stringify(resolvedInput.tags ?? []),\n resolvedInput.sourceRefs ? JSON.stringify(resolvedInput.sourceRefs) : null,\n resolvedInput.confidence ?? null,\n resolvedInput.ttlSeconds ?? null,\n resolvedInput.authorId ?? null,\n resolvedInput.authorName ?? null,\n now,\n now,\n );\n\n this.setSyncState({\n memoryId: id,\n localVersion: 1,\n syncStatus: \"pending_push\",\n });\n\n return this.getById(id)!;\n }\n\n getById(id: string): Memory | undefined {\n const row = this.db\n .prepare(\"SELECT * FROM memories WHERE id = ?\")\n .get(id) as Record<string, unknown> | undefined;\n return row ? rowToMemory(row) : undefined;\n }\n\n recall(query: RecallQuery): RecallResult[] {\n const conditions: string[] = [\"m.org_id = ?\", \"m.repo_id = ?\"];\n const params: unknown[] = [query.orgId, query.repoId];\n\n if (!query.includeDeprecated) {\n conditions.push(\"m.status = 'active'\");\n }\n\n if (!query.includeExpired) {\n conditions.push(nonExpiredMemoryClause(\"m\"));\n }\n\n if (query.types && query.types.length > 0) {\n conditions.push(\n `m.memory_type IN (${query.types.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.types);\n }\n\n if (query.timeRange?.from) {\n conditions.push(\"m.created_at >= ?\");\n params.push(query.timeRange.from.toISOString());\n }\n if (query.timeRange?.to) {\n conditions.push(\"m.created_at <= ?\");\n params.push(query.timeRange.to.toISOString());\n }\n\n const whereClause = conditions.join(\" AND \");\n const k = query.k ?? 10;\n\n const rawQuery = query.query.replace(/[^\\w\\s]/g, \" \").trim();\n const words = rawQuery.split(/\\s+/).filter((w) => w.length > 0);\n \n // Use prefix matching without quotes for more flexible search\n // Also filter out very short words that add noise\n const searchableWords = words.filter((w) => w.length >= 2);\n const ftsQuery = searchableWords.length > 0 \n ? `(${searchableWords.map((w) => `${w}*`).join(\" OR \")})` \n : \"\";\n\n let sql: string;\n let finalParams: unknown[];\n\n if (ftsQuery) {\n sql = `\n SELECT m.*, fts.rank AS fts_rank\n FROM memories_fts fts\n JOIN memories m ON m.rowid = fts.rowid\n WHERE fts.memories_fts MATCH ?\n AND ${whereClause}\n ORDER BY m.is_consolidation DESC, fts.rank\n LIMIT ?\n `;\n finalParams = [ftsQuery, ...params, k * 2];\n } else {\n sql = `\n SELECT m.*, 0 AS fts_rank\n FROM memories m\n WHERE ${whereClause}\n ORDER BY m.is_consolidation DESC, m.created_at DESC\n LIMIT ?\n `;\n finalParams = [...params, k * 2];\n }\n\n let rows = this.db.prepare(sql).all(...finalParams) as Array<\n Record<string, unknown>\n >;\n\n // Fallback: if FTS returns no results, try LIKE search as last resort\n if (rows.length === 0 && searchableWords.length > 0) {\n const likeConditions = searchableWords\n .slice(0, 5) // limit to first 5 words\n .map(() => \"(m.text LIKE ? OR m.summary LIKE ?)\")\n .join(\" OR \");\n \n const likeParams: unknown[] = [];\n for (const word of searchableWords.slice(0, 5)) {\n likeParams.push(`%${word}%`, `%${word}%`);\n }\n\n const fallbackSql = `\n SELECT m.*, 0 AS fts_rank\n FROM memories m\n WHERE ${whereClause}\n AND (${likeConditions})\n ORDER BY m.is_consolidation DESC, m.created_at DESC\n LIMIT ?\n `;\n \n rows = this.db.prepare(fallbackSql).all(...params, ...likeParams, k * 2) as Array<\n Record<string, unknown>\n >;\n }\n\n const usageStats = this.getUsageStats(query.orgId, query.repoId);\n const usageMap = new Map(usageStats.map((stat) => [stat.memoryId, stat]));\n\n let results = rows.map((row) => {\n const memory = rowToMemory(row);\n const textScore = ftsQuery\n ? Math.min(1, Math.abs(row.fts_rank as number) / 10)\n : 0.5;\n\n const consolidationBoost = memory.isConsolidation ? 0.1 : 0;\n const usage = usageMap.get(memory.id);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n\n const result: RecallResult = {\n id: memory.id,\n memoryType: memory.memoryType,\n text: memory.text,\n summary: memory.summary,\n tags: memory.tags,\n sourceRefs: memory.sourceRefs,\n score: computeCompositeScore(\n textScore + consolidationBoost,\n memory.createdAt,\n memory.confidence,\n usageBoost,\n ),\n source: \"local\" as const,\n status: memory.status,\n supersedesId: memory.supersedesId,\n isConsolidation: memory.isConsolidation,\n consolidationVersion: memory.consolidationVersion,\n };\n\n if (query.includeConsolidatedSources && memory.isConsolidation) {\n const sources = this.getConsolidatedSources(memory.id);\n result.sourceMemories = sources.map((src) => ({\n id: src.id,\n memoryType: src.memoryType,\n text: src.text,\n summary: src.summary,\n tags: src.tags,\n sourceRefs: src.sourceRefs,\n score: 0,\n source: \"local\" as const,\n }));\n }\n\n return result;\n });\n\n if (query.tags && query.tags.length > 0) {\n results = results.filter((r) => {\n const memTags = r.tags;\n return query.tags!.some((t) => memTags.includes(t));\n });\n }\n\n return results\n .sort((a, b) => b.score - a.score)\n .slice(0, k);\n }\n\n list(query: ListQuery): Memory[] {\n const conditions: string[] = [\"org_id = ?\", \"repo_id = ?\"];\n const params: unknown[] = [query.orgId, query.repoId];\n\n if (!query.includeExpired) {\n conditions.push(nonExpiredMemoryClause());\n }\n\n if (query.types && query.types.length > 0) {\n conditions.push(\n `memory_type IN (${query.types.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.types);\n }\n\n if (query.status && query.status.length > 0) {\n conditions.push(\n `status IN (${query.status.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.status);\n }\n\n if (query.visibility && query.visibility.length > 0) {\n conditions.push(\n `visibility IN (${query.visibility.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.visibility);\n }\n\n if (query.search) {\n const rawSearch = query.search.replace(/[^\\w\\s]/g, \" \").trim();\n const searchWords = rawSearch.split(/\\s+/).filter((w) => w.length >= 2);\n const ftsSearch = searchWords.length > 0 ? `(${searchWords.map((w) => `${w}*`).join(\" OR \")})` : \"\";\n if (ftsSearch) {\n conditions.push(\n \"rowid IN (SELECT rowid FROM memories_fts WHERE memories_fts MATCH ?)\",\n );\n params.push(ftsSearch);\n }\n }\n\n const sortCol =\n query.sortBy === \"updatedAt\"\n ? \"updated_at\"\n : query.sortBy === \"confidence\"\n ? \"confidence\"\n : \"created_at\";\n const sortDir = query.sortOrder === \"asc\" ? \"ASC\" : \"DESC\";\n const limit = query.limit ?? 50;\n const offset = query.offset ?? 0;\n\n const sql = `\n SELECT * FROM memories\n WHERE ${conditions.join(\" AND \")}\n ORDER BY ${sortCol} ${sortDir}\n LIMIT ? OFFSET ?\n `;\n params.push(limit, offset);\n\n const rows = this.db.prepare(sql).all(...params) as Array<\n Record<string, unknown>\n >;\n return rows.map(rowToMemory);\n }\n\n count(query: ListQuery): number {\n const conditions: string[] = [\"org_id = ?\", \"repo_id = ?\"];\n const params: unknown[] = [query.orgId, query.repoId];\n\n if (!query.includeExpired) {\n conditions.push(nonExpiredMemoryClause());\n }\n\n if (query.types && query.types.length > 0) {\n conditions.push(\n `memory_type IN (${query.types.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.types);\n }\n\n if (query.status && query.status.length > 0) {\n conditions.push(\n `status IN (${query.status.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.status);\n }\n\n if (query.visibility && query.visibility.length > 0) {\n conditions.push(\n `visibility IN (${query.visibility.map(() => \"?\").join(\",\")})`,\n );\n params.push(...query.visibility);\n }\n\n if (query.search) {\n const rawSearch = query.search.replace(/[^\\w\\s]/g, \" \").trim();\n const searchWords = rawSearch.split(/\\s+/).filter((w) => w.length >= 2);\n const ftsSearch = searchWords.length > 0 ? `(${searchWords.map((w) => `${w}*`).join(\" OR \")})` : \"\";\n if (ftsSearch) {\n conditions.push(\n \"rowid IN (SELECT rowid FROM memories_fts WHERE memories_fts MATCH ?)\",\n );\n params.push(ftsSearch);\n }\n }\n\n const sql = `SELECT COUNT(*) as cnt FROM memories WHERE ${conditions.join(\" AND \")}`;\n const row = this.db.prepare(sql).get(...params) as { cnt: number };\n return row.cnt;\n }\n\n stats(orgId: string, repoId: string): StoreStats {\n const rows = this.db\n .prepare(\n `SELECT memory_type, status, visibility, COUNT(*) as cnt\n FROM memories WHERE org_id = ? AND repo_id = ?\n GROUP BY memory_type, status, visibility`,\n )\n .all(orgId, repoId) as Array<{\n memory_type: string;\n status: string;\n visibility: string;\n cnt: number;\n }>;\n\n const stats: StoreStats = {\n total: 0,\n byType: { episodic: 0, semantic: 0, procedural: 0 },\n byStatus: { active: 0, deprecated: 0, superseded: 0, deleted: 0 },\n byVisibility: { private: 0, repo: 0 },\n };\n\n for (const row of rows) {\n stats.total += row.cnt;\n if (row.memory_type in stats.byType) {\n stats.byType[row.memory_type as keyof typeof stats.byType] += row.cnt;\n }\n if (row.status in stats.byStatus) {\n stats.byStatus[row.status as keyof typeof stats.byStatus] += row.cnt;\n }\n if (row.visibility in stats.byVisibility) {\n stats.byVisibility[row.visibility] += row.cnt;\n }\n }\n\n return stats;\n }\n\n deprecate(id: string, reason?: string): boolean {\n const now = new Date().toISOString();\n const result = this.db\n .prepare(\n \"UPDATE memories SET status = 'deprecated', updated_at = ? WHERE id = ?\",\n )\n .run(now, id);\n\n if (reason && result.changes > 0) {\n const mem = this.getById(id);\n if (mem) {\n const refs = mem.sourceRefs ?? {};\n (refs as Record<string, unknown>).deprecation_reason = reason;\n this.db\n .prepare(\"UPDATE memories SET source_refs = ? WHERE id = ?\")\n .run(JSON.stringify(refs), id);\n }\n }\n\n return result.changes > 0;\n }\n\n supersede(oldId: string, newId: string): boolean {\n const now = new Date().toISOString();\n const result = this.db\n .prepare(\n \"UPDATE memories SET status = 'superseded', supersedes_id = ?, updated_at = ? WHERE id = ?\",\n )\n .run(newId, now, oldId);\n return result.changes > 0;\n }\n\n updateVisibility(id: string, visibility: \"private\" | \"repo\"): boolean {\n const now = new Date().toISOString();\n const result = this.db\n .prepare(\n \"UPDATE memories SET visibility = ?, updated_at = ? WHERE id = ?\",\n )\n .run(visibility, now, id);\n return result.changes > 0;\n }\n\n expireExpiredMemories(\n orgId?: string,\n repoId?: string,\n deletedBy = \"system:ttl-expiry\",\n ): number {\n const conditions = [\n \"status = 'active'\",\n \"ttl_seconds IS NOT NULL\",\n \"datetime(created_at, '+' || ttl_seconds || ' seconds') < datetime('now')\",\n ];\n const params: unknown[] = [];\n\n if (orgId) {\n conditions.push(\"org_id = ?\");\n params.push(orgId);\n }\n\n if (repoId) {\n conditions.push(\"repo_id = ?\");\n params.push(repoId);\n }\n\n const rows = this.db\n .prepare(\n `SELECT id FROM memories WHERE ${conditions.join(\" AND \")}`,\n )\n .all(...params) as Array<{ id: string }>;\n\n let expired = 0;\n for (const row of rows) {\n if (this.softDelete({ id: row.id, deletedBy })) {\n expired += 1;\n }\n }\n\n return expired;\n }\n\n purgeExpired(): number {\n return this.expireExpiredMemories();\n }\n\n link(input: CreateLinkInput): MemoryLink {\n const id = uuid();\n const now = new Date().toISOString();\n\n this.db\n .prepare(\n `INSERT INTO memory_links (id, source_id, target_id, link_type, metadata, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n input.sourceId,\n input.targetId,\n input.linkType,\n input.metadata ? JSON.stringify(input.metadata) : null,\n now,\n );\n\n return this.getLinkById(id)!;\n }\n\n unlink(sourceId: string, targetId: string, linkType: string): boolean {\n const result = this.db\n .prepare(\n \"DELETE FROM memory_links WHERE source_id = ? AND target_id = ? AND link_type = ?\",\n )\n .run(sourceId, targetId, linkType);\n return result.changes > 0;\n }\n\n getLinks(query: LinkQuery): MemoryLink[] {\n const conditions: string[] = [\n \"(source_id = ? OR target_id = ?)\",\n ];\n const params: unknown[] = [query.memoryId, query.memoryId];\n\n if (query.linkType) {\n conditions.push(\"link_type = ?\");\n params.push(query.linkType);\n }\n\n const sql = `SELECT * FROM memory_links WHERE ${conditions.join(\" AND \")} ORDER BY created_at DESC`;\n const rows = this.db.prepare(sql).all(...params) as Array<\n Record<string, unknown>\n >;\n return rows.map(rowToLink);\n }\n\n getLinkedMemories(memoryId: string, linkType?: string): Memory[] {\n const conditions: string[] = [\n \"(l.source_id = ? OR l.target_id = ?)\",\n ];\n const params: unknown[] = [memoryId, memoryId];\n\n if (linkType) {\n conditions.push(\"l.link_type = ?\");\n params.push(linkType);\n }\n\n const sql = `\n SELECT m.* FROM memories m\n JOIN memory_links l ON (\n (l.source_id = ? AND l.target_id = m.id) OR\n (l.target_id = ? AND l.source_id = m.id)\n )\n ${linkType ? \"WHERE l.link_type = ?\" : \"\"}\n ORDER BY m.created_at DESC\n `;\n const linkedParams = linkType\n ? [memoryId, memoryId, linkType]\n : [memoryId, memoryId];\n\n const rows = this.db.prepare(sql).all(...linkedParams) as Array<\n Record<string, unknown>\n >;\n return rows.map(rowToMemory);\n }\n\n private getLinkById(id: string): MemoryLink | undefined {\n const row = this.db\n .prepare(\"SELECT * FROM memory_links WHERE id = ?\")\n .get(id) as Record<string, unknown> | undefined;\n return row ? rowToLink(row) : undefined;\n }\n\n consolidateMemories(input: ConsolidateMemoriesInput): ConsolidateMemoriesResult {\n const { sourceIds, consolidatedText, memoryType, tags, preserveOriginals = true } = input;\n const orgId = input.orgId.toLowerCase();\n const repoId = input.repoId.toLowerCase();\n\n if (sourceIds.length < 2) {\n throw new Error(\"At least 2 source memories are required for consolidation\");\n }\n\n const sourceMemories = sourceIds\n .map((id) => this.getById(id))\n .filter((m): m is Memory => m !== undefined);\n\n if (sourceMemories.length !== sourceIds.length) {\n const foundIds = sourceMemories.map((m) => m.id);\n const missingIds = sourceIds.filter((id) => !foundIds.includes(id));\n throw new Error(`Source memories not found: ${missingIds.join(\", \")}`);\n }\n\n const inferredType = memoryType ?? this.inferMemoryType(sourceMemories);\n const mergedTags = tags ?? this.mergeTags(sourceMemories);\n const inheritedVisibility = sourceMemories.some((m) => m.visibility === \"repo\") ? \"repo\" : \"private\";\n\n const id = uuid();\n const now = new Date().toISOString();\n const version = 1;\n\n this.db\n .prepare(\n `INSERT INTO memories\n (id, org_id, repo_id, scope_type, memory_type, visibility, status, text, summary, tags, source_refs, confidence, is_consolidation, consolidation_version, created_at, updated_at)\n VALUES (?, ?, ?, 'repo', ?, ?, 'active', ?, ?, ?, ?, ?, 1, ?, ?, ?)`,\n )\n .run(\n id,\n orgId,\n repoId,\n inferredType,\n inheritedVisibility,\n consolidatedText,\n null,\n JSON.stringify(mergedTags),\n JSON.stringify({ consolidated_from: sourceIds }),\n null,\n version,\n now,\n now,\n );\n\n for (const sourceId of sourceIds) {\n this.link({\n sourceId: id,\n targetId: sourceId,\n linkType: \"derived_from\",\n metadata: { consolidation: true },\n });\n }\n\n if (preserveOriginals) {\n for (const sourceId of sourceIds) {\n this.supersede(sourceId, id);\n }\n }\n\n if (inheritedVisibility === \"repo\") {\n this.setSyncState({\n memoryId: id,\n localVersion: version,\n syncStatus: \"pending_push\",\n });\n }\n\n return {\n consolidatedId: id,\n version,\n sourcesPreserved: sourceIds.length,\n sourceIds,\n };\n }\n\n reconsolidate(input: ReconsolidateInput): ConsolidateMemoriesResult {\n const { existingConsolidationId, additionalSourceIds = [], newText, tags } = input;\n const orgId = input.orgId.toLowerCase();\n const repoId = input.repoId.toLowerCase();\n\n const existing = this.getById(existingConsolidationId);\n if (!existing) {\n throw new Error(`Consolidation not found: ${existingConsolidationId}`);\n }\n if (!existing.isConsolidation) {\n throw new Error(`Memory ${existingConsolidationId} is not a consolidation`);\n }\n\n const existingLinks = this.getLinks({ memoryId: existingConsolidationId, linkType: \"derived_from\" });\n const existingSourceIds = existingLinks\n .filter((l) => l.sourceId === existingConsolidationId)\n .map((l) => l.targetId);\n\n const allSourceIds = [...new Set([...existingSourceIds, ...additionalSourceIds])];\n\n for (const id of additionalSourceIds) {\n const mem = this.getById(id);\n if (!mem) {\n throw new Error(`Additional source memory not found: ${id}`);\n }\n }\n\n const newVersion = (existing.consolidationVersion ?? 1) + 1;\n const mergedTags = tags ?? existing.tags;\n const inheritedVisibility = existing.visibility;\n\n const id = uuid();\n const now = new Date().toISOString();\n\n this.db\n .prepare(\n `INSERT INTO memories\n (id, org_id, repo_id, scope_type, memory_type, visibility, status, text, summary, tags, source_refs, confidence, is_consolidation, consolidation_version, created_at, updated_at)\n VALUES (?, ?, ?, 'repo', ?, ?, 'active', ?, ?, ?, ?, ?, 1, ?, ?, ?)`,\n )\n .run(\n id,\n orgId,\n repoId,\n existing.memoryType,\n inheritedVisibility,\n newText,\n null,\n JSON.stringify(mergedTags),\n JSON.stringify({\n consolidated_from: allSourceIds,\n previous_consolidation: existingConsolidationId,\n }),\n null,\n newVersion,\n now,\n now,\n );\n\n this.link({\n sourceId: id,\n targetId: existingConsolidationId,\n linkType: \"derived_from\",\n metadata: { reconsolidation: true, previous_version: existing.consolidationVersion ?? 1 },\n });\n\n for (const sourceId of additionalSourceIds) {\n this.link({\n sourceId: id,\n targetId: sourceId,\n linkType: \"derived_from\",\n metadata: { consolidation: true },\n });\n this.supersede(sourceId, id);\n }\n\n this.supersede(existingConsolidationId, id);\n\n if (inheritedVisibility === \"repo\") {\n this.setSyncState({\n memoryId: id,\n localVersion: newVersion,\n syncStatus: \"pending_push\",\n });\n }\n\n return {\n consolidatedId: id,\n version: newVersion,\n sourcesPreserved: allSourceIds.length,\n sourceIds: allSourceIds,\n };\n }\n\n findSimilar(query: FindSimilarQuery): RecallResult[] {\n const { orgId, repoId, memoryId, threshold = 0.3, k = 10 } = query;\n\n const memory = this.getById(memoryId);\n if (!memory) {\n throw new Error(`Memory not found: ${memoryId}`);\n }\n\n const results = this.recall({\n orgId,\n repoId,\n query: memory.text,\n k: k + 1,\n });\n\n return results\n .filter((r) => r.id !== memoryId && r.score >= threshold)\n .slice(0, k);\n }\n\n getConsolidationHistory(memoryId: string): Memory[] {\n const memory = this.getById(memoryId);\n if (!memory) {\n return [];\n }\n\n const history: Memory[] = [];\n\n if (memory.isConsolidation) {\n const sourceLinks = this.getLinks({ memoryId, linkType: \"derived_from\" });\n for (const link of sourceLinks) {\n const targetId = link.sourceId === memoryId ? link.targetId : link.sourceId;\n const target = this.getById(targetId);\n if (target) {\n history.push(target);\n if (target.isConsolidation) {\n history.push(...this.getConsolidationHistory(targetId));\n }\n }\n }\n }\n\n return history;\n }\n\n getConsolidatedSources(consolidationId: string): Memory[] {\n const memory = this.getById(consolidationId);\n if (!memory || !memory.isConsolidation) {\n return [];\n }\n\n const sourceLinks = this.getLinks({ memoryId: consolidationId, linkType: \"derived_from\" });\n const sources: Memory[] = [];\n\n for (const link of sourceLinks) {\n if (link.sourceId === consolidationId) {\n const source = this.getById(link.targetId);\n if (source && !source.isConsolidation) {\n sources.push(source);\n }\n }\n }\n\n return sources;\n }\n\n private inferMemoryType(memories: Memory[]): Memory[\"memoryType\"] {\n const typeCounts = { episodic: 0, semantic: 0, procedural: 0 };\n for (const m of memories) {\n typeCounts[m.memoryType]++;\n }\n\n if (typeCounts.procedural > 0) return \"procedural\";\n if (typeCounts.semantic >= typeCounts.episodic) return \"semantic\";\n return \"episodic\";\n }\n\n private mergeTags(memories: Memory[]): string[] {\n const tagSet = new Set<string>();\n for (const m of memories) {\n for (const tag of m.tags) {\n tagSet.add(tag);\n }\n }\n return Array.from(tagSet);\n }\n\n softDelete(input: DeleteMemoryInput): boolean {\n const memory = this.getById(input.id);\n if (!memory) return false;\n\n const now = new Date().toISOString();\n const newVersion = (memory.version ?? 1) + 1;\n\n const result = this.db.transaction(() => {\n this.db\n .prepare(\n `UPDATE memories \n SET status = 'deleted', deleted_at = ?, deleted_by = ?, version = ?, updated_at = ?\n WHERE id = ?`,\n )\n .run(now, input.deletedBy ?? null, newVersion, now, input.id);\n\n this.db\n .prepare(\n `INSERT OR REPLACE INTO tombstones (id, memory_id, org_id, repo_id, deleted_at, deleted_by, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n uuid(),\n input.id,\n memory.orgId,\n memory.repoId,\n now,\n input.deletedBy ?? null,\n now,\n );\n\n return true;\n })();\n\n return result;\n }\n\n hardDelete(id: string): boolean {\n const result = this.db\n .prepare(\"DELETE FROM memories WHERE id = ?\")\n .run(id);\n return result.changes > 0;\n }\n\n restore(id: string): boolean {\n const now = new Date().toISOString();\n const result = this.db.transaction(() => {\n const updateResult = this.db\n .prepare(\n `UPDATE memories \n SET status = 'active', deleted_at = NULL, deleted_by = NULL, version = version + 1, updated_at = ?\n WHERE id = ? AND status = 'deleted'`,\n )\n .run(now, id);\n\n if (updateResult.changes > 0) {\n this.db\n .prepare(\"DELETE FROM tombstones WHERE memory_id = ?\")\n .run(id);\n }\n\n return updateResult.changes > 0;\n })();\n\n return result;\n }\n\n getTombstones(orgId: string, repoId: string, sinceSyncedAt?: Date): Tombstone[] {\n let sql = \"SELECT * FROM tombstones WHERE org_id = ? AND repo_id = ?\";\n const params: unknown[] = [orgId, repoId];\n\n if (sinceSyncedAt) {\n sql += \" AND (synced_at IS NULL OR synced_at > ?)\";\n params.push(sinceSyncedAt.toISOString());\n } else {\n sql += \" AND synced_at IS NULL\";\n }\n\n sql += \" ORDER BY deleted_at ASC\";\n\n const rows = this.db.prepare(sql).all(...params) as Array<Record<string, unknown>>;\n return rows.map(rowToTombstone);\n }\n\n getUnsyncedTombstones(orgId: string, repoId: string): Tombstone[] {\n const rows = this.db\n .prepare(\n \"SELECT * FROM tombstones WHERE org_id = ? AND repo_id = ? AND synced_at IS NULL ORDER BY deleted_at ASC\",\n )\n .all(orgId, repoId) as Array<Record<string, unknown>>;\n return rows.map(rowToTombstone);\n }\n\n markTombstoneSynced(memoryId: string): boolean {\n const now = new Date().toISOString();\n const result = this.db\n .prepare(\"UPDATE tombstones SET synced_at = ? WHERE memory_id = ?\")\n .run(now, memoryId);\n return result.changes > 0;\n }\n\n applyTombstone(tombstone: Tombstone): boolean {\n const memory = this.getById(tombstone.memoryId);\n if (!memory) {\n this.db\n .prepare(\n `INSERT OR REPLACE INTO tombstones (id, memory_id, org_id, repo_id, deleted_at, deleted_by, synced_at, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n tombstone.id,\n tombstone.memoryId,\n tombstone.orgId,\n tombstone.repoId,\n tombstone.deletedAt.toISOString(),\n tombstone.deletedBy ?? null,\n new Date().toISOString(),\n new Date().toISOString(),\n );\n return true;\n }\n\n return this.softDelete({\n id: tombstone.memoryId,\n deletedBy: tombstone.deletedBy,\n });\n }\n\n incrementVersion(id: string): number {\n const now = new Date().toISOString();\n this.db\n .prepare(\"UPDATE memories SET version = version + 1, updated_at = ? WHERE id = ?\")\n .run(now, id);\n const row = this.db\n .prepare(\"SELECT version FROM memories WHERE id = ?\")\n .get(id) as { version: number } | undefined;\n return row?.version ?? 1;\n }\n\n getModifiedSince(orgId: string, repoId: string, since: Date): Memory[] {\n const rows = this.db\n .prepare(\n `SELECT * FROM memories \n WHERE org_id = ? AND repo_id = ? AND updated_at > ?\n ORDER BY updated_at ASC`,\n )\n .all(orgId, repoId, since.toISOString()) as Array<Record<string, unknown>>;\n return rows.map(rowToMemory);\n }\n\n upsertFromRemote(memory: Memory): { action: \"created\" | \"updated\" | \"skipped\"; conflict: boolean } {\n const existing = this.getById(memory.id);\n const now = new Date().toISOString();\n const normalizedOrgId = memory.orgId.toLowerCase();\n const normalizedRepoId = memory.repoId.toLowerCase();\n\n if (!existing) {\n this.db\n .prepare(\n `INSERT INTO memories\n (id, org_id, repo_id, scope_type, memory_type, visibility, status, text, summary, tags, source_refs, confidence, ttl_seconds, supersedes_id, is_consolidation, consolidation_version, author_id, author_name, version, deleted_at, deleted_by, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n memory.id,\n normalizedOrgId,\n normalizedRepoId,\n memory.scopeType ?? \"repo\",\n memory.memoryType,\n memory.visibility,\n memory.status,\n memory.text,\n memory.summary ?? null,\n JSON.stringify(memory.tags ?? []),\n memory.sourceRefs ? JSON.stringify(memory.sourceRefs) : null,\n memory.confidence ?? null,\n memory.ttlSeconds ?? null,\n memory.supersedesId ?? null,\n memory.isConsolidation ? 1 : 0,\n memory.consolidationVersion ?? null,\n memory.authorId ?? null,\n memory.authorName ?? null,\n memory.version ?? 1,\n memory.deletedAt?.toISOString() ?? null,\n memory.deletedBy ?? null,\n memory.createdAt.toISOString(),\n now,\n );\n return { action: \"created\", conflict: false };\n }\n\n const remoteVersion = memory.version ?? 1;\n const localVersion = existing.version ?? 1;\n\n if (remoteVersion <= localVersion) {\n if (memory.updatedAt <= existing.updatedAt) {\n return { action: \"skipped\", conflict: false };\n }\n }\n\n const hasConflict = localVersion !== remoteVersion && existing.updatedAt > memory.updatedAt;\n\n this.db\n .prepare(\n `UPDATE memories SET\n memory_type = ?, visibility = ?, status = ?, text = ?, summary = ?, tags = ?,\n source_refs = ?, confidence = ?, ttl_seconds = ?, supersedes_id = ?,\n is_consolidation = ?, consolidation_version = ?, author_id = ?, author_name = ?,\n version = ?, deleted_at = ?, deleted_by = ?, updated_at = ?\n WHERE id = ?`,\n )\n .run(\n memory.memoryType,\n memory.visibility,\n memory.status,\n memory.text,\n memory.summary ?? null,\n JSON.stringify(memory.tags ?? []),\n memory.sourceRefs ? JSON.stringify(memory.sourceRefs) : null,\n memory.confidence ?? null,\n memory.ttlSeconds ?? null,\n memory.supersedesId ?? null,\n memory.isConsolidation ? 1 : 0,\n memory.consolidationVersion ?? null,\n memory.authorId ?? null,\n memory.authorName ?? null,\n Math.max(remoteVersion, localVersion) + 1,\n memory.deletedAt?.toISOString() ?? null,\n memory.deletedBy ?? null,\n now,\n memory.id,\n );\n\n return { action: \"updated\", conflict: hasConflict };\n }\n\n getSyncState(memoryId: string): SyncState | undefined {\n const row = this.db\n .prepare(\"SELECT * FROM sync_state WHERE memory_id = ?\")\n .get(memoryId) as Record<string, unknown> | undefined;\n return row ? this.rowToSyncState(row) : undefined;\n }\n\n getAllSyncStates(): SyncState[] {\n const rows = this.db\n .prepare(\"SELECT * FROM sync_state\")\n .all() as Array<Record<string, unknown>>;\n return rows.map((row) => this.rowToSyncState(row));\n }\n\n getSyncStatesByStatus(status: SyncStatus): SyncState[] {\n const rows = this.db\n .prepare(\"SELECT * FROM sync_state WHERE sync_status = ?\")\n .all(status) as Array<Record<string, unknown>>;\n return rows.map((row) => this.rowToSyncState(row));\n }\n\n getPendingPush(): Array<{ memory: Memory; syncState: SyncState }> {\n const rows = this.db\n .prepare(`\n SELECT m.*, s.local_version as sync_local_version, s.remote_version as sync_remote_version,\n s.last_pushed_at, s.last_pulled_at, s.sync_status\n FROM memories m\n JOIN sync_state s ON m.id = s.memory_id\n WHERE s.sync_status = 'pending_push'\n ORDER BY m.updated_at ASC\n `)\n .all() as Array<Record<string, unknown>>;\n\n return rows.map((row) => ({\n memory: rowToMemory(row),\n syncState: {\n memoryId: row.id as string,\n localVersion: row.sync_local_version as number,\n remoteVersion: row.sync_remote_version as number | undefined,\n lastPushedAt: row.last_pushed_at ? new Date(row.last_pushed_at as string) : undefined,\n lastPulledAt: row.last_pulled_at ? new Date(row.last_pulled_at as string) : undefined,\n syncStatus: row.sync_status as SyncStatus,\n },\n }));\n }\n\n getConflicts(): Array<{ memory: Memory; syncState: SyncState }> {\n const rows = this.db\n .prepare(`\n SELECT m.*, s.local_version as sync_local_version, s.remote_version as sync_remote_version,\n s.last_pushed_at, s.last_pulled_at, s.sync_status\n FROM memories m\n JOIN sync_state s ON m.id = s.memory_id\n WHERE s.sync_status = 'conflict'\n ORDER BY m.updated_at ASC\n `)\n .all() as Array<Record<string, unknown>>;\n\n return rows.map((row) => ({\n memory: rowToMemory(row),\n syncState: {\n memoryId: row.id as string,\n localVersion: row.sync_local_version as number,\n remoteVersion: row.sync_remote_version as number | undefined,\n lastPushedAt: row.last_pushed_at ? new Date(row.last_pushed_at as string) : undefined,\n lastPulledAt: row.last_pulled_at ? new Date(row.last_pulled_at as string) : undefined,\n syncStatus: row.sync_status as SyncStatus,\n },\n }));\n }\n\n setSyncState(state: SyncState): void {\n this.db\n .prepare(`\n INSERT OR REPLACE INTO sync_state (memory_id, local_version, remote_version, last_pushed_at, last_pulled_at, sync_status)\n VALUES (?, ?, ?, ?, ?, ?)\n `)\n .run(\n state.memoryId,\n state.localVersion,\n state.remoteVersion ?? null,\n state.lastPushedAt?.toISOString() ?? null,\n state.lastPulledAt?.toISOString() ?? null,\n state.syncStatus,\n );\n }\n\n markAsPushed(memoryId: string, remoteVersion: number): void {\n const now = new Date().toISOString();\n this.db\n .prepare(`\n UPDATE sync_state \n SET sync_status = 'synced', remote_version = ?, last_pushed_at = ?\n WHERE memory_id = ?\n `)\n .run(remoteVersion, now, memoryId);\n }\n\n markAsPulled(memoryId: string, localVersion: number): void {\n const now = new Date().toISOString();\n this.db\n .prepare(`\n UPDATE sync_state \n SET sync_status = 'synced', local_version = ?, last_pulled_at = ?\n WHERE memory_id = ?\n `)\n .run(localVersion, now, memoryId);\n }\n\n markAsConflict(memoryId: string, remoteVersion: number): void {\n this.db\n .prepare(`\n UPDATE sync_state \n SET sync_status = 'conflict', remote_version = ?\n WHERE memory_id = ?\n `)\n .run(remoteVersion, memoryId);\n }\n\n getUntrackedMemories(orgId: string, repoId: string): Memory[] {\n const rows = this.db\n .prepare(`\n SELECT m.* FROM memories m\n LEFT JOIN sync_state s ON m.id = s.memory_id\n WHERE m.org_id = ? AND m.repo_id = ? AND s.memory_id IS NULL\n ORDER BY m.created_at ASC\n `)\n .all(orgId, repoId) as Array<Record<string, unknown>>;\n return rows.map(rowToMemory);\n }\n\n initSyncStateForMemory(memoryId: string): void {\n const memory = this.getById(memoryId);\n if (!memory) return;\n\n const existing = this.getSyncState(memoryId);\n if (existing) return;\n\n this.setSyncState({\n memoryId,\n localVersion: memory.version,\n syncStatus: \"pending_push\",\n });\n }\n\n getSyncSummary(orgId: string, repoId: string): {\n synced: number;\n pendingPush: number;\n pendingPull: number;\n conflicts: number;\n } {\n const row = this.db\n .prepare(`\n SELECT\n SUM(CASE WHEN s.sync_status = 'synced' THEN 1 ELSE 0 END) as synced,\n SUM(CASE WHEN s.sync_status = 'pending_push' THEN 1 ELSE 0 END) as pending_push,\n SUM(CASE WHEN s.sync_status = 'pending_pull' THEN 1 ELSE 0 END) as pending_pull,\n SUM(CASE WHEN s.sync_status = 'conflict' THEN 1 ELSE 0 END) as conflicts\n FROM sync_state s\n JOIN memories m ON s.memory_id = m.id\n WHERE m.org_id = ? AND m.repo_id = ?\n `)\n .get(orgId, repoId) as Record<string, number>;\n\n return {\n synced: row.synced ?? 0,\n pendingPush: row.pending_push ?? 0,\n pendingPull: row.pending_pull ?? 0,\n conflicts: row.conflicts ?? 0,\n };\n }\n\n private rowToSyncState(row: Record<string, unknown>): SyncState {\n return {\n memoryId: row.memory_id as string,\n localVersion: row.local_version as number,\n remoteVersion: row.remote_version as number | undefined,\n lastPushedAt: row.last_pushed_at ? new Date(row.last_pushed_at as string) : undefined,\n lastPulledAt: row.last_pulled_at ? new Date(row.last_pulled_at as string) : undefined,\n syncStatus: row.sync_status as SyncStatus,\n };\n }\n\n getSupersededMemoriesToSync(orgId: string, repoId: string): Array<{ memory: Memory; newId: string }> {\n const rows = this.db\n .prepare(`\n SELECT m.*\n FROM memories m\n LEFT JOIN sync_state s ON s.memory_id = m.id\n WHERE m.org_id = ?\n AND m.repo_id = ?\n AND m.status = 'superseded'\n AND m.supersedes_id IS NOT NULL\n AND (\n s.memory_id IS NULL\n OR s.sync_status = 'pending_push'\n OR (s.sync_status = 'synced' AND (s.last_pushed_at IS NULL OR s.last_pushed_at < m.updated_at))\n )\n `)\n .all(orgId, repoId) as Array<Record<string, unknown>>;\n\n return rows.map((row) => ({\n memory: rowToMemory(row),\n newId: row.supersedes_id as string,\n }));\n }\n\n getLinksToSync(orgId: string, repoId: string): Array<{ link: MemoryLink; sourceMemoryId: string; targetMemoryId: string }> {\n const rows = this.db\n .prepare(`\n SELECT l.*, ms.id as source_mem_id, mt.id as target_mem_id\n FROM memory_links l\n JOIN memories ms ON ms.id = l.source_id\n JOIN memories mt ON mt.id = l.target_id\n WHERE ms.org_id = ?\n AND ms.repo_id = ?\n AND l.id NOT IN (SELECT link_id FROM synced_links)\n `)\n .all(orgId, repoId) as Array<Record<string, unknown>>;\n\n return rows.map((row) => ({\n link: rowToLink(row),\n sourceMemoryId: row.source_mem_id as string,\n targetMemoryId: row.target_mem_id as string,\n }));\n }\n\n markLinkSynced(linkId: string): void {\n const now = new Date().toISOString();\n this.db\n .prepare(`INSERT OR IGNORE INTO synced_links (link_id, synced_at) VALUES (?, ?)`)\n .run(linkId, now);\n }\n\n markStatusSynced(memoryId: string): void {\n const now = new Date().toISOString();\n this.db\n .prepare(`UPDATE sync_state SET last_pushed_at = ? WHERE memory_id = ?`)\n .run(now, memoryId);\n }\n\n unconsolidate(consolidationId: string): {\n restoredIds: string[];\n consolidationDeleted: boolean;\n linksRemoved: number;\n } {\n const memory = this.getById(consolidationId);\n if (!memory) {\n throw new Error(`Memory not found: ${consolidationId}`);\n }\n if (!memory.isConsolidation) {\n throw new Error(`Memory ${consolidationId} is not a consolidation`);\n }\n\n const sourceLinks = this.getLinks({ memoryId: consolidationId, linkType: \"derived_from\" });\n const sourceIds = sourceLinks\n .filter((l) => l.sourceId === consolidationId)\n .map((l) => l.targetId);\n\n const now = new Date().toISOString();\n const restoredIds: string[] = [];\n let linksRemoved = 0;\n\n this.db.transaction(() => {\n for (const sourceId of sourceIds) {\n const source = this.getById(sourceId);\n if (source && source.status === \"superseded\" && source.supersedesId === consolidationId) {\n this.db\n .prepare(\n `UPDATE memories\n SET status = 'active', supersedes_id = NULL, version = version + 1, updated_at = ?\n WHERE id = ?`,\n )\n .run(now, sourceId);\n restoredIds.push(sourceId);\n\n this.setSyncState({\n memoryId: sourceId,\n localVersion: (source.version ?? 1) + 1,\n syncStatus: \"pending_push\",\n });\n }\n }\n\n // Remove derived_from links from the consolidation to source memories\n const deleteLinksResult = this.db\n .prepare(\n `DELETE FROM memory_links \n WHERE source_id = ? AND link_type = 'derived_from'`,\n )\n .run(consolidationId);\n linksRemoved = deleteLinksResult.changes;\n\n // Also remove any links where the consolidation is the target\n const deleteTargetLinksResult = this.db\n .prepare(\n `DELETE FROM memory_links \n WHERE target_id = ?`,\n )\n .run(consolidationId);\n linksRemoved += deleteTargetLinksResult.changes;\n\n // Remove from synced_links table if exists\n this.db\n .prepare(\n `DELETE FROM synced_links \n WHERE link_id IN (\n SELECT id FROM memory_links WHERE source_id = ? OR target_id = ?\n )`,\n )\n .run(consolidationId, consolidationId);\n\n this.softDelete({\n id: consolidationId,\n deletedBy: \"unconsolidate\",\n });\n })();\n\n return {\n restoredIds,\n consolidationDeleted: true,\n linksRemoved,\n };\n }\n\n cleanupOrphanLinks(): number {\n const result = this.db\n .prepare(\n `DELETE FROM memory_links\n WHERE id IN (\n SELECT ml.id FROM memory_links ml\n LEFT JOIN memories ms ON ms.id = ml.source_id\n LEFT JOIN memories mt ON mt.id = ml.target_id\n WHERE ms.id IS NULL \n OR mt.id IS NULL\n OR ms.status = 'deleted'\n OR mt.status = 'deleted'\n )`,\n )\n .run();\n\n this.db\n .prepare(\n `DELETE FROM synced_links\n WHERE link_id NOT IN (SELECT id FROM memory_links)`,\n )\n .run();\n\n return result.changes;\n }\n\n async storeEmbedding(\n memoryId: string,\n embedding: number[],\n model: string\n ): Promise<void> {\n const now = new Date().toISOString();\n const blob = serializeEmbedding(embedding);\n\n this.db\n .prepare(\n `INSERT OR REPLACE INTO memory_embeddings (memory_id, embedding, model, created_at)\n VALUES (?, ?, ?, ?)`\n )\n .run(memoryId, blob, model, now);\n }\n\n async generateAndStoreEmbedding(\n memoryId: string,\n text: string,\n config?: EmbeddingConfig\n ): Promise<void> {\n try {\n const result = await generateEmbedding(text, config);\n await this.storeEmbedding(memoryId, result.embedding, result.model);\n } catch (error) {\n console.error(`Failed to generate embedding for ${memoryId}:`, error);\n }\n }\n\n getEmbedding(memoryId: string): number[] | undefined {\n const row = this.db\n .prepare(\"SELECT embedding FROM memory_embeddings WHERE memory_id = ?\")\n .get(memoryId) as { embedding: Buffer } | undefined;\n\n if (!row) return undefined;\n return deserializeEmbedding(row.embedding);\n }\n\n hasEmbedding(memoryId: string): boolean {\n const row = this.db\n .prepare(\"SELECT 1 FROM memory_embeddings WHERE memory_id = ?\")\n .get(memoryId);\n return !!row;\n }\n\n getAllEmbeddings(\n orgId: string,\n repoId: string\n ): Array<{ memoryId: string; embedding: number[] }> {\n const rows = this.db\n .prepare(\n `SELECT e.memory_id, e.embedding FROM memory_embeddings e\n JOIN memories m ON e.memory_id = m.id\n WHERE m.org_id = ? AND m.repo_id = ? AND m.status = 'active'`\n )\n .all(orgId, repoId) as Array<{ memory_id: string; embedding: Buffer }>;\n\n return rows.map((row) => ({\n memoryId: row.memory_id,\n embedding: deserializeEmbedding(row.embedding),\n }));\n }\n\n getMemoriesWithoutEmbeddings(orgId: string, repoId: string): Memory[] {\n const rows = this.db\n .prepare(\n `SELECT m.* FROM memories m\n LEFT JOIN memory_embeddings e ON m.id = e.memory_id\n WHERE m.org_id = ? AND m.repo_id = ? AND m.status = 'active' AND e.memory_id IS NULL`\n )\n .all(orgId, repoId) as Array<Record<string, unknown>>;\n\n return rows.map(rowToMemory);\n }\n\n async recallWithEmbeddings(\n query: RecallQuery,\n queryEmbedding?: number[]\n ): Promise<RecallResult[]> {\n const ftsResults = this.recall(query);\n\n if (!queryEmbedding) {\n return ftsResults;\n }\n\n const allEmbeddings = this.getAllEmbeddings(query.orgId, query.repoId);\n\n if (allEmbeddings.length === 0) {\n return ftsResults;\n }\n\n const embeddingScores = new Map<string, number>();\n for (const { memoryId, embedding } of allEmbeddings) {\n const similarity = cosineSimilarity(queryEmbedding, embedding);\n embeddingScores.set(memoryId, Math.max(0, similarity));\n }\n\n const ftsIds = new Set(ftsResults.map((r) => r.id));\n const k = query.k ?? 10;\n const usageStats = this.getUsageStats(query.orgId, query.repoId);\n const usageMap = new Map(usageStats.map((stat) => [stat.memoryId, stat]));\n\n const sortedByEmbedding = Array.from(embeddingScores.entries())\n .filter(([id]) => !ftsIds.has(id))\n .sort((a, b) => b[1] - a[1])\n .slice(0, k);\n\n const additionalMemories: RecallResult[] = [];\n for (const [memoryId, similarity] of sortedByEmbedding) {\n if (similarity < 0.3) continue;\n const memory = this.getById(memoryId);\n if (\n !memory ||\n memory.status !== \"active\" ||\n (!query.includeExpired && memory.ttlSeconds && memory.createdAt.getTime() + memory.ttlSeconds * 1000 <= Date.now())\n ) {\n continue;\n }\n\n const usage = usageMap.get(memory.id);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n\n additionalMemories.push({\n id: memory.id,\n memoryType: memory.memoryType,\n text: memory.text,\n summary: memory.summary,\n tags: memory.tags,\n sourceRefs: memory.sourceRefs,\n score: computeHybridScore(0, similarity, memory.createdAt, memory.confidence, usageBoost),\n source: \"local\",\n status: memory.status,\n supersedesId: memory.supersedesId,\n isConsolidation: memory.isConsolidation,\n consolidationVersion: memory.consolidationVersion,\n });\n }\n\n const hybridResults = ftsResults.map((r) => {\n const embScore = embeddingScores.get(r.id) ?? 0;\n const memory = this.getById(r.id);\n if (!memory) return r;\n const usage = usageMap.get(r.id);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n\n return {\n ...r,\n score: computeHybridScore(r.score, embScore, memory.createdAt, memory.confidence, usageBoost),\n };\n });\n\n const combined = [...hybridResults, ...additionalMemories];\n return combined.sort((a, b) => b.score - a.score).slice(0, k);\n }\n\n recordUsage(memoryId: string, query?: string, sessionId?: string): void {\n this.db\n .prepare(\n `INSERT INTO memory_usage (memory_id, query, session_id) VALUES (?, ?, ?)`\n )\n .run(memoryId, query ?? null, sessionId ?? null);\n }\n\n recordUsageBatch(memoryIds: string[], query?: string, sessionId?: string): void {\n const stmt = this.db.prepare(\n `INSERT INTO memory_usage (memory_id, query, session_id) VALUES (?, ?, ?)`\n );\n const insertMany = this.db.transaction((ids: string[]) => {\n for (const id of ids) {\n stmt.run(id, query ?? null, sessionId ?? null);\n }\n });\n insertMany(memoryIds);\n }\n\n getUsageCount(memoryId: string): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM memory_usage WHERE memory_id = ?\")\n .get(memoryId) as { cnt: number };\n return row.cnt;\n }\n\n getUsageStats(\n orgId: string,\n repoId: string\n ): Array<{ memoryId: string; count: number; lastUsed: Date }> {\n const rows = this.db\n .prepare(\n `SELECT u.memory_id, COUNT(*) as cnt, MAX(u.recalled_at) as last_used\n FROM memory_usage u\n JOIN memories m ON u.memory_id = m.id\n WHERE m.org_id = ? AND m.repo_id = ?\n GROUP BY u.memory_id\n ORDER BY cnt DESC`\n )\n .all(orgId, repoId) as Array<{\n memory_id: string;\n cnt: number;\n last_used: string;\n }>;\n\n return rows.map((row) => ({\n memoryId: row.memory_id,\n count: row.cnt,\n lastUsed: new Date(row.last_used),\n }));\n }\n\n getTopUsedMemories(\n orgId: string,\n repoId: string,\n limit = 10\n ): Array<{ memory: Memory; usageCount: number }> {\n const rows = this.db\n .prepare(\n `SELECT m.*, COUNT(u.id) as usage_count\n FROM memories m\n LEFT JOIN memory_usage u ON m.id = u.memory_id\n WHERE m.org_id = ? AND m.repo_id = ? AND m.status = 'active'\n GROUP BY m.id\n ORDER BY usage_count DESC\n LIMIT ?`\n )\n .all(orgId, repoId, limit) as Array<Record<string, unknown>>;\n\n return rows.map((row) => ({\n memory: rowToMemory(row),\n usageCount: row.usage_count as number,\n }));\n }\n\n getUnusedMemories(\n orgId: string,\n repoId: string,\n daysSinceCreation = 30\n ): Memory[] {\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - daysSinceCreation);\n\n const rows = this.db\n .prepare(\n `SELECT m.* FROM memories m\n LEFT JOIN memory_usage u ON m.id = u.memory_id\n WHERE m.org_id = ? \n AND m.repo_id = ? \n AND m.status = 'active'\n AND m.created_at < ?\n AND u.id IS NULL`\n )\n .all(orgId, repoId, cutoff.toISOString()) as Array<Record<string, unknown>>;\n\n return rows.map(rowToMemory);\n }\n\n getEmbeddingStats(orgId: string, repoId: string): {\n total: number;\n withEmbedding: number;\n withoutEmbedding: number;\n } {\n const row = this.db\n .prepare(\n `SELECT \n COUNT(m.id) as total,\n COUNT(e.memory_id) as with_embedding\n FROM memories m\n LEFT JOIN memory_embeddings e ON m.id = e.memory_id\n WHERE m.org_id = ? AND m.repo_id = ? AND m.status = 'active'`\n )\n .get(orgId, repoId) as { total: number; with_embedding: number };\n\n return {\n total: row.total,\n withEmbedding: row.with_embedding,\n withoutEmbedding: row.total - row.with_embedding,\n };\n }\n\n createCurationSuggestion(input: CreateCurationSuggestionInput): CurationSuggestion {\n const id = uuid();\n const now = new Date().toISOString();\n const normalizedOrgId = input.orgId.toLowerCase();\n const normalizedRepoId = input.repoId.toLowerCase();\n\n this.db\n .prepare(\n `INSERT INTO curation_suggestions\n (id, org_id, repo_id, type, priority, status, memory_ids, reason, confidence, payload, created_by, created_at, updated_at)\n VALUES (?, ?, ?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n normalizedOrgId,\n normalizedRepoId,\n input.type,\n input.priority,\n JSON.stringify(input.memoryIds),\n input.reason,\n input.confidence,\n input.payload ? JSON.stringify(input.payload) : null,\n input.createdBy ?? null,\n now,\n now,\n );\n\n return this.getCurationSuggestionById(id)!;\n }\n\n listCurationSuggestions(query: ListCurationSuggestionsQuery): CurationSuggestion[] {\n const clauses = [\"org_id = ?\", \"repo_id = ?\"];\n const params: unknown[] = [query.orgId.toLowerCase(), query.repoId.toLowerCase()];\n\n if (query.status && query.status.length > 0) {\n clauses.push(`status IN (${query.status.map(() => \"?\").join(\",\")})`);\n params.push(...query.status);\n }\n\n if (query.types && query.types.length > 0) {\n clauses.push(`type IN (${query.types.map(() => \"?\").join(\",\")})`);\n params.push(...query.types);\n }\n\n const limit = Math.min(query.limit ?? 100, 500);\n const offset = query.offset ?? 0;\n params.push(limit, offset);\n\n const rows = this.db\n .prepare(\n `SELECT * FROM curation_suggestions\n WHERE ${clauses.join(\" AND \")}\n ORDER BY created_at DESC\n LIMIT ? OFFSET ?`,\n )\n .all(...params) as Array<Record<string, unknown>>;\n\n return rows.map(rowToCurationSuggestion);\n }\n\n reviewCurationSuggestion(input: ReviewCurationSuggestionInput): CurationSuggestion {\n const existing = this.getCurationSuggestionById(input.id);\n if (!existing) {\n throw new Error(`Curation suggestion not found: ${input.id}`);\n }\n\n const now = new Date().toISOString();\n this.db\n .prepare(\n `UPDATE curation_suggestions\n SET status = ?, reviewed_by = ?, review_note = ?, reviewed_at = ?,\n applied_at = CASE WHEN ? = 'applied' THEN ? ELSE applied_at END,\n updated_at = ?\n WHERE id = ?`,\n )\n .run(\n input.status,\n input.reviewedBy ?? null,\n input.reviewNote ?? null,\n now,\n input.status,\n now,\n now,\n input.id,\n );\n\n return this.getCurationSuggestionById(input.id)!;\n }\n\n private getCurationSuggestionById(id: string): CurationSuggestion | undefined {\n const row = this.db\n .prepare(\"SELECT * FROM curation_suggestions WHERE id = ?\")\n .get(id) as Record<string, unknown> | undefined;\n return row ? rowToCurationSuggestion(row) : undefined;\n }\n\n resetAll(): { memoriesDeleted: number; linksDeleted: number; embeddingsDeleted: number } {\n const result = this.db.transaction(() => {\n const embeddingsDeleted = this.db.prepare(\"DELETE FROM memory_embeddings\").run().changes;\n const linksDeleted = this.db.prepare(\"DELETE FROM memory_links\").run().changes;\n this.db.prepare(\"DELETE FROM synced_links\").run();\n this.db.prepare(\"DELETE FROM sync_state\").run();\n this.db.prepare(\"DELETE FROM tombstones\").run();\n this.db.prepare(\"DELETE FROM memory_usage\").run();\n const memoriesDeleted = this.db.prepare(\"DELETE FROM memories\").run().changes;\n this.db.exec(\"INSERT INTO memories_fts(memories_fts) VALUES('rebuild')\");\n return { memoriesDeleted, linksDeleted, embeddingsDeleted };\n })();\n\n return result;\n }\n\n clearEmbeddings(): number {\n return this.db.prepare(\"DELETE FROM memory_embeddings\").run().changes;\n }\n\n close(): void {\n this.db.close();\n }\n}\n","\n/* !!! This is code generated by Prisma. Do not edit directly. !!! */\n/* eslint-disable */\n// biome-ignore-all lint: generated file\n// @ts-nocheck \n/*\n * This file should be your main import to use Prisma. Through it you get access to all the models, enums, and input types.\n * If you're looking for something you can import in the client-side of your application, please refer to the `browser.ts` file instead.\n *\n * 🟢 You can import this file directly.\n */\n\nimport * as process from 'node:process'\nimport * as path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nglobalThis['__dirname'] = path.dirname(fileURLToPath(import.meta.url))\n\nimport * as runtime from \"@prisma/client/runtime/client\"\nimport * as $Enums from \"./enums\"\nimport * as $Class from \"./internal/class\"\nimport * as Prisma from \"./internal/prismaNamespace\"\n\nexport * as $Enums from './enums'\nexport * from \"./enums\"\n/**\n * ## Prisma Client\n * \n * Type-safe database client for TypeScript\n * @example\n * ```\n * const prisma = new PrismaClient({\n * adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })\n * })\n * // Fetch zero or more Memories\n * const memories = await prisma.memory.findMany()\n * ```\n * \n * Read more in our [docs](https://pris.ly/d/client).\n */\nexport const PrismaClient = $Class.getPrismaClientClass()\nexport type PrismaClient<LogOpts extends Prisma.LogLevel = never, OmitOpts extends Prisma.PrismaClientOptions[\"omit\"] = Prisma.PrismaClientOptions[\"omit\"], ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = $Class.PrismaClient<LogOpts, OmitOpts, ExtArgs>\nexport { Prisma }\n\n/**\n * Model Memory\n * \n */\nexport type Memory = Prisma.MemoryModel\n/**\n * Model MemoryEmbedding\n * \n */\nexport type MemoryEmbedding = Prisma.MemoryEmbeddingModel\n/**\n * Model MemoryUsage\n * \n */\nexport type MemoryUsage = Prisma.MemoryUsageModel\n/**\n * Model MemoryLink\n * \n */\nexport type MemoryLink = Prisma.MemoryLinkModel\n/**\n * Model Tombstone\n * \n */\nexport type Tombstone = Prisma.TombstoneModel\n/**\n * Model ApiKey\n * \n */\nexport type ApiKey = Prisma.ApiKeyModel\n/**\n * Model ApiKeyLog\n * \n */\nexport type ApiKeyLog = Prisma.ApiKeyLogModel\n/**\n * Model User\n * \n */\nexport type User = Prisma.UserModel\n/**\n * Model UserRepoAccess\n * \n */\nexport type UserRepoAccess = Prisma.UserRepoAccessModel\n","\n/* !!! This is code generated by Prisma. Do not edit directly. !!! */\n/* eslint-disable */\n// biome-ignore-all lint: generated file\n// @ts-nocheck \n/*\n * WARNING: This is an internal file that is subject to change!\n *\n * 🛑 Under no circumstances should you import this file directly! 🛑\n *\n * Please import the `PrismaClient` class from the `client.ts` file instead.\n */\n\nimport * as runtime from \"@prisma/client/runtime/client\"\nimport type * as Prisma from \"./prismaNamespace\"\n\n\nconst config: runtime.GetPrismaClientConfig = {\n \"previewFeatures\": [],\n \"clientVersion\": \"7.8.0\",\n \"engineVersion\": \"3c6e192761c0362d496ed980de936e2f3cebcd3a\",\n \"activeProvider\": \"postgresql\",\n \"inlineSchema\": \"datasource db {\\n provider = \\\"postgresql\\\"\\n}\\n\\ngenerator client {\\n provider = \\\"prisma-client\\\"\\n output = \\\"../packages/db/src/generated/prisma\\\"\\n}\\n\\nmodel Memory {\\n id String @id @default(uuid()) @db.Uuid\\n orgId String @map(\\\"org_id\\\")\\n repoId String @map(\\\"repo_id\\\")\\n scopeType String @default(\\\"repo\\\") @map(\\\"scope_type\\\")\\n memoryType String @map(\\\"memory_type\\\")\\n visibility String @default(\\\"repo\\\")\\n status String @default(\\\"active\\\")\\n text String\\n summary String?\\n tags String[]\\n sourceRefs Json? @map(\\\"source_refs\\\")\\n confidence Float?\\n ttlSeconds Int? @map(\\\"ttl_seconds\\\")\\n supersedesId String? @map(\\\"supersedes_id\\\") @db.Uuid\\n version Int @default(1)\\n deletedAt DateTime? @map(\\\"deleted_at\\\")\\n deletedBy String? @map(\\\"deleted_by\\\")\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n updatedAt DateTime @updatedAt @map(\\\"updated_at\\\")\\n\\n supersedes Memory? @relation(\\\"Supersedes\\\", fields: [supersedesId], references: [id])\\n supersededBy Memory[] @relation(\\\"Supersedes\\\")\\n\\n sourceLinks MemoryLink[] @relation(\\\"SourceLinks\\\")\\n targetLinks MemoryLink[] @relation(\\\"TargetLinks\\\")\\n embedding MemoryEmbedding?\\n usages MemoryUsage[]\\n\\n @@index([orgId, repoId, memoryType, status])\\n @@index([orgId, repoId, updatedAt])\\n @@index([deletedAt])\\n @@map(\\\"memories\\\")\\n}\\n\\nmodel MemoryEmbedding {\\n memoryId String @id @map(\\\"memory_id\\\") @db.Uuid\\n embedding Bytes\\n model String\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n\\n memory Memory @relation(fields: [memoryId], references: [id], onDelete: Cascade)\\n\\n @@map(\\\"memory_embeddings\\\")\\n}\\n\\nmodel MemoryUsage {\\n id Int @id @default(autoincrement())\\n memoryId String @map(\\\"memory_id\\\") @db.Uuid\\n recalledAt DateTime @default(now()) @map(\\\"recalled_at\\\")\\n query String?\\n sessionId String? @map(\\\"session_id\\\")\\n\\n memory Memory @relation(fields: [memoryId], references: [id], onDelete: Cascade)\\n\\n @@index([memoryId])\\n @@index([recalledAt])\\n @@map(\\\"memory_usage\\\")\\n}\\n\\nmodel MemoryLink {\\n id String @id @default(uuid()) @db.Uuid\\n sourceId String @map(\\\"source_id\\\") @db.Uuid\\n targetId String @map(\\\"target_id\\\") @db.Uuid\\n linkType String @map(\\\"link_type\\\")\\n metadata Json?\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n\\n source Memory @relation(\\\"SourceLinks\\\", fields: [sourceId], references: [id], onDelete: Cascade)\\n target Memory @relation(\\\"TargetLinks\\\", fields: [targetId], references: [id], onDelete: Cascade)\\n\\n @@unique([sourceId, targetId, linkType])\\n @@map(\\\"memory_links\\\")\\n}\\n\\nmodel Tombstone {\\n id String @id @default(uuid()) @db.Uuid\\n memoryId String @map(\\\"memory_id\\\") @db.Uuid\\n orgId String @map(\\\"org_id\\\")\\n repoId String @map(\\\"repo_id\\\")\\n deletedAt DateTime @map(\\\"deleted_at\\\")\\n deletedBy String? @map(\\\"deleted_by\\\")\\n syncedAt DateTime? @map(\\\"synced_at\\\")\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n\\n @@unique([memoryId])\\n @@index([orgId, repoId, syncedAt])\\n @@map(\\\"tombstones\\\")\\n}\\n\\nmodel ApiKey {\\n id String @id @default(uuid()) @db.Uuid\\n key String @unique\\n name String\\n label String?\\n orgId String @map(\\\"org_id\\\")\\n repoId String? @map(\\\"repo_id\\\")\\n userId String? @map(\\\"user_id\\\") @db.Uuid\\n createdBy String? @map(\\\"created_by\\\") @db.Uuid\\n isActive Boolean @default(true) @map(\\\"is_active\\\")\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n lastUsedAt DateTime? @map(\\\"last_used_at\\\")\\n\\n user User? @relation(fields: [userId], references: [id])\\n logs ApiKeyLog[]\\n\\n @@index([key])\\n @@index([orgId])\\n @@index([userId])\\n @@map(\\\"api_keys\\\")\\n}\\n\\nmodel ApiKeyLog {\\n id String @id @default(uuid()) @db.Uuid\\n apiKeyId String @map(\\\"api_key_id\\\") @db.Uuid\\n operation String\\n memoryId String? @map(\\\"memory_id\\\") @db.Uuid\\n orgId String @map(\\\"org_id\\\")\\n repoId String @map(\\\"repo_id\\\")\\n query String?\\n metadata Json?\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n\\n apiKey ApiKey @relation(fields: [apiKeyId], references: [id], onDelete: Cascade)\\n\\n @@index([apiKeyId])\\n @@index([createdAt])\\n @@index([memoryId])\\n @@index([orgId, repoId])\\n @@map(\\\"api_key_logs\\\")\\n}\\n\\nmodel User {\\n id String @id @default(uuid()) @db.Uuid\\n githubId Int @unique @map(\\\"github_id\\\")\\n githubLogin String @map(\\\"github_login\\\")\\n name String?\\n email String?\\n avatarUrl String? @map(\\\"avatar_url\\\")\\n isAdmin Boolean @default(false) @map(\\\"is_admin\\\")\\n createdAt DateTime @default(now()) @map(\\\"created_at\\\")\\n updatedAt DateTime @updatedAt @map(\\\"updated_at\\\")\\n\\n apiKeys ApiKey[]\\n repoAccess UserRepoAccess[]\\n\\n @@map(\\\"users\\\")\\n}\\n\\nmodel UserRepoAccess {\\n id String @id @default(uuid()) @db.Uuid\\n userId String @map(\\\"user_id\\\") @db.Uuid\\n orgId String @map(\\\"org_id\\\")\\n repoId String @map(\\\"repo_id\\\")\\n permission String\\n grantedAt DateTime @default(now()) @map(\\\"granted_at\\\")\\n grantedBy String? @map(\\\"granted_by\\\") @db.Uuid\\n\\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\\n\\n @@unique([userId, orgId, repoId])\\n @@index([orgId, repoId])\\n @@map(\\\"user_repo_access\\\")\\n}\\n\",\n \"runtimeDataModel\": {\n \"models\": {},\n \"enums\": {},\n \"types\": {}\n },\n \"parameterizationSchema\": {\n \"strings\": [],\n \"graph\": \"\"\n }\n}\n\nconfig.runtimeDataModel = JSON.parse(\"{\\\"models\\\":{\\\"Memory\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"orgId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"org_id\\\"},{\\\"name\\\":\\\"repoId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"repo_id\\\"},{\\\"name\\\":\\\"scopeType\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"scope_type\\\"},{\\\"name\\\":\\\"memoryType\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"memory_type\\\"},{\\\"name\\\":\\\"visibility\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"status\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"text\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"summary\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"tags\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"sourceRefs\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Json\\\",\\\"dbName\\\":\\\"source_refs\\\"},{\\\"name\\\":\\\"confidence\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Float\\\"},{\\\"name\\\":\\\"ttlSeconds\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Int\\\",\\\"dbName\\\":\\\"ttl_seconds\\\"},{\\\"name\\\":\\\"supersedesId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"supersedes_id\\\"},{\\\"name\\\":\\\"version\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Int\\\"},{\\\"name\\\":\\\"deletedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"deleted_at\\\"},{\\\"name\\\":\\\"deletedBy\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"deleted_by\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"},{\\\"name\\\":\\\"updatedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"updated_at\\\"},{\\\"name\\\":\\\"supersedes\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"Memory\\\",\\\"relationName\\\":\\\"Supersedes\\\"},{\\\"name\\\":\\\"supersededBy\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"Memory\\\",\\\"relationName\\\":\\\"Supersedes\\\"},{\\\"name\\\":\\\"sourceLinks\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"MemoryLink\\\",\\\"relationName\\\":\\\"SourceLinks\\\"},{\\\"name\\\":\\\"targetLinks\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"MemoryLink\\\",\\\"relationName\\\":\\\"TargetLinks\\\"},{\\\"name\\\":\\\"embedding\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"MemoryEmbedding\\\",\\\"relationName\\\":\\\"MemoryToMemoryEmbedding\\\"},{\\\"name\\\":\\\"usages\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"MemoryUsage\\\",\\\"relationName\\\":\\\"MemoryToMemoryUsage\\\"}],\\\"dbName\\\":\\\"memories\\\"},\\\"MemoryEmbedding\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"memoryId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"memory_id\\\"},{\\\"name\\\":\\\"embedding\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Bytes\\\"},{\\\"name\\\":\\\"model\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"},{\\\"name\\\":\\\"memory\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"Memory\\\",\\\"relationName\\\":\\\"MemoryToMemoryEmbedding\\\"}],\\\"dbName\\\":\\\"memory_embeddings\\\"},\\\"MemoryUsage\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Int\\\"},{\\\"name\\\":\\\"memoryId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"memory_id\\\"},{\\\"name\\\":\\\"recalledAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"recalled_at\\\"},{\\\"name\\\":\\\"query\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"sessionId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"session_id\\\"},{\\\"name\\\":\\\"memory\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"Memory\\\",\\\"relationName\\\":\\\"MemoryToMemoryUsage\\\"}],\\\"dbName\\\":\\\"memory_usage\\\"},\\\"MemoryLink\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"sourceId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"source_id\\\"},{\\\"name\\\":\\\"targetId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"target_id\\\"},{\\\"name\\\":\\\"linkType\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"link_type\\\"},{\\\"name\\\":\\\"metadata\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Json\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"},{\\\"name\\\":\\\"source\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"Memory\\\",\\\"relationName\\\":\\\"SourceLinks\\\"},{\\\"name\\\":\\\"target\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"Memory\\\",\\\"relationName\\\":\\\"TargetLinks\\\"}],\\\"dbName\\\":\\\"memory_links\\\"},\\\"Tombstone\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"memoryId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"memory_id\\\"},{\\\"name\\\":\\\"orgId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"org_id\\\"},{\\\"name\\\":\\\"repoId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"repo_id\\\"},{\\\"name\\\":\\\"deletedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"deleted_at\\\"},{\\\"name\\\":\\\"deletedBy\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"deleted_by\\\"},{\\\"name\\\":\\\"syncedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"synced_at\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"}],\\\"dbName\\\":\\\"tombstones\\\"},\\\"ApiKey\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"key\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"name\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"label\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"orgId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"org_id\\\"},{\\\"name\\\":\\\"repoId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"repo_id\\\"},{\\\"name\\\":\\\"userId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"user_id\\\"},{\\\"name\\\":\\\"createdBy\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"created_by\\\"},{\\\"name\\\":\\\"isActive\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Boolean\\\",\\\"dbName\\\":\\\"is_active\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"},{\\\"name\\\":\\\"lastUsedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"last_used_at\\\"},{\\\"name\\\":\\\"user\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"User\\\",\\\"relationName\\\":\\\"ApiKeyToUser\\\"},{\\\"name\\\":\\\"logs\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"ApiKeyLog\\\",\\\"relationName\\\":\\\"ApiKeyToApiKeyLog\\\"}],\\\"dbName\\\":\\\"api_keys\\\"},\\\"ApiKeyLog\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"apiKeyId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"api_key_id\\\"},{\\\"name\\\":\\\"operation\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"memoryId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"memory_id\\\"},{\\\"name\\\":\\\"orgId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"org_id\\\"},{\\\"name\\\":\\\"repoId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"repo_id\\\"},{\\\"name\\\":\\\"query\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"metadata\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Json\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"},{\\\"name\\\":\\\"apiKey\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"ApiKey\\\",\\\"relationName\\\":\\\"ApiKeyToApiKeyLog\\\"}],\\\"dbName\\\":\\\"api_key_logs\\\"},\\\"User\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"githubId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Int\\\",\\\"dbName\\\":\\\"github_id\\\"},{\\\"name\\\":\\\"githubLogin\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"github_login\\\"},{\\\"name\\\":\\\"name\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"email\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"avatarUrl\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"avatar_url\\\"},{\\\"name\\\":\\\"isAdmin\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"Boolean\\\",\\\"dbName\\\":\\\"is_admin\\\"},{\\\"name\\\":\\\"createdAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"created_at\\\"},{\\\"name\\\":\\\"updatedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"updated_at\\\"},{\\\"name\\\":\\\"apiKeys\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"ApiKey\\\",\\\"relationName\\\":\\\"ApiKeyToUser\\\"},{\\\"name\\\":\\\"repoAccess\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"UserRepoAccess\\\",\\\"relationName\\\":\\\"UserToUserRepoAccess\\\"}],\\\"dbName\\\":\\\"users\\\"},\\\"UserRepoAccess\\\":{\\\"fields\\\":[{\\\"name\\\":\\\"id\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"userId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"user_id\\\"},{\\\"name\\\":\\\"orgId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"org_id\\\"},{\\\"name\\\":\\\"repoId\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"repo_id\\\"},{\\\"name\\\":\\\"permission\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\"},{\\\"name\\\":\\\"grantedAt\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"DateTime\\\",\\\"dbName\\\":\\\"granted_at\\\"},{\\\"name\\\":\\\"grantedBy\\\",\\\"kind\\\":\\\"scalar\\\",\\\"type\\\":\\\"String\\\",\\\"dbName\\\":\\\"granted_by\\\"},{\\\"name\\\":\\\"user\\\",\\\"kind\\\":\\\"object\\\",\\\"type\\\":\\\"User\\\",\\\"relationName\\\":\\\"UserToUserRepoAccess\\\"}],\\\"dbName\\\":\\\"user_repo_access\\\"}},\\\"enums\\\":{},\\\"types\\\":{}}\")\nconfig.parameterizationSchema = {\n strings: JSON.parse(\"[\\\"where\\\",\\\"supersedes\\\",\\\"orderBy\\\",\\\"cursor\\\",\\\"supersededBy\\\",\\\"source\\\",\\\"target\\\",\\\"sourceLinks\\\",\\\"targetLinks\\\",\\\"memory\\\",\\\"embedding\\\",\\\"usages\\\",\\\"_count\\\",\\\"Memory.findUnique\\\",\\\"Memory.findUniqueOrThrow\\\",\\\"Memory.findFirst\\\",\\\"Memory.findFirstOrThrow\\\",\\\"Memory.findMany\\\",\\\"data\\\",\\\"Memory.createOne\\\",\\\"Memory.createMany\\\",\\\"Memory.createManyAndReturn\\\",\\\"Memory.updateOne\\\",\\\"Memory.updateMany\\\",\\\"Memory.updateManyAndReturn\\\",\\\"create\\\",\\\"update\\\",\\\"Memory.upsertOne\\\",\\\"Memory.deleteOne\\\",\\\"Memory.deleteMany\\\",\\\"having\\\",\\\"_avg\\\",\\\"_sum\\\",\\\"_min\\\",\\\"_max\\\",\\\"Memory.groupBy\\\",\\\"Memory.aggregate\\\",\\\"MemoryEmbedding.findUnique\\\",\\\"MemoryEmbedding.findUniqueOrThrow\\\",\\\"MemoryEmbedding.findFirst\\\",\\\"MemoryEmbedding.findFirstOrThrow\\\",\\\"MemoryEmbedding.findMany\\\",\\\"MemoryEmbedding.createOne\\\",\\\"MemoryEmbedding.createMany\\\",\\\"MemoryEmbedding.createManyAndReturn\\\",\\\"MemoryEmbedding.updateOne\\\",\\\"MemoryEmbedding.updateMany\\\",\\\"MemoryEmbedding.updateManyAndReturn\\\",\\\"MemoryEmbedding.upsertOne\\\",\\\"MemoryEmbedding.deleteOne\\\",\\\"MemoryEmbedding.deleteMany\\\",\\\"MemoryEmbedding.groupBy\\\",\\\"MemoryEmbedding.aggregate\\\",\\\"MemoryUsage.findUnique\\\",\\\"MemoryUsage.findUniqueOrThrow\\\",\\\"MemoryUsage.findFirst\\\",\\\"MemoryUsage.findFirstOrThrow\\\",\\\"MemoryUsage.findMany\\\",\\\"MemoryUsage.createOne\\\",\\\"MemoryUsage.createMany\\\",\\\"MemoryUsage.createManyAndReturn\\\",\\\"MemoryUsage.updateOne\\\",\\\"MemoryUsage.updateMany\\\",\\\"MemoryUsage.updateManyAndReturn\\\",\\\"MemoryUsage.upsertOne\\\",\\\"MemoryUsage.deleteOne\\\",\\\"MemoryUsage.deleteMany\\\",\\\"MemoryUsage.groupBy\\\",\\\"MemoryUsage.aggregate\\\",\\\"MemoryLink.findUnique\\\",\\\"MemoryLink.findUniqueOrThrow\\\",\\\"MemoryLink.findFirst\\\",\\\"MemoryLink.findFirstOrThrow\\\",\\\"MemoryLink.findMany\\\",\\\"MemoryLink.createOne\\\",\\\"MemoryLink.createMany\\\",\\\"MemoryLink.createManyAndReturn\\\",\\\"MemoryLink.updateOne\\\",\\\"MemoryLink.updateMany\\\",\\\"MemoryLink.updateManyAndReturn\\\",\\\"MemoryLink.upsertOne\\\",\\\"MemoryLink.deleteOne\\\",\\\"MemoryLink.deleteMany\\\",\\\"MemoryLink.groupBy\\\",\\\"MemoryLink.aggregate\\\",\\\"Tombstone.findUnique\\\",\\\"Tombstone.findUniqueOrThrow\\\",\\\"Tombstone.findFirst\\\",\\\"Tombstone.findFirstOrThrow\\\",\\\"Tombstone.findMany\\\",\\\"Tombstone.createOne\\\",\\\"Tombstone.createMany\\\",\\\"Tombstone.createManyAndReturn\\\",\\\"Tombstone.updateOne\\\",\\\"Tombstone.updateMany\\\",\\\"Tombstone.updateManyAndReturn\\\",\\\"Tombstone.upsertOne\\\",\\\"Tombstone.deleteOne\\\",\\\"Tombstone.deleteMany\\\",\\\"Tombstone.groupBy\\\",\\\"Tombstone.aggregate\\\",\\\"apiKeys\\\",\\\"user\\\",\\\"repoAccess\\\",\\\"apiKey\\\",\\\"logs\\\",\\\"ApiKey.findUnique\\\",\\\"ApiKey.findUniqueOrThrow\\\",\\\"ApiKey.findFirst\\\",\\\"ApiKey.findFirstOrThrow\\\",\\\"ApiKey.findMany\\\",\\\"ApiKey.createOne\\\",\\\"ApiKey.createMany\\\",\\\"ApiKey.createManyAndReturn\\\",\\\"ApiKey.updateOne\\\",\\\"ApiKey.updateMany\\\",\\\"ApiKey.updateManyAndReturn\\\",\\\"ApiKey.upsertOne\\\",\\\"ApiKey.deleteOne\\\",\\\"ApiKey.deleteMany\\\",\\\"ApiKey.groupBy\\\",\\\"ApiKey.aggregate\\\",\\\"ApiKeyLog.findUnique\\\",\\\"ApiKeyLog.findUniqueOrThrow\\\",\\\"ApiKeyLog.findFirst\\\",\\\"ApiKeyLog.findFirstOrThrow\\\",\\\"ApiKeyLog.findMany\\\",\\\"ApiKeyLog.createOne\\\",\\\"ApiKeyLog.createMany\\\",\\\"ApiKeyLog.createManyAndReturn\\\",\\\"ApiKeyLog.updateOne\\\",\\\"ApiKeyLog.updateMany\\\",\\\"ApiKeyLog.updateManyAndReturn\\\",\\\"ApiKeyLog.upsertOne\\\",\\\"ApiKeyLog.deleteOne\\\",\\\"ApiKeyLog.deleteMany\\\",\\\"ApiKeyLog.groupBy\\\",\\\"ApiKeyLog.aggregate\\\",\\\"User.findUnique\\\",\\\"User.findUniqueOrThrow\\\",\\\"User.findFirst\\\",\\\"User.findFirstOrThrow\\\",\\\"User.findMany\\\",\\\"User.createOne\\\",\\\"User.createMany\\\",\\\"User.createManyAndReturn\\\",\\\"User.updateOne\\\",\\\"User.updateMany\\\",\\\"User.updateManyAndReturn\\\",\\\"User.upsertOne\\\",\\\"User.deleteOne\\\",\\\"User.deleteMany\\\",\\\"User.groupBy\\\",\\\"User.aggregate\\\",\\\"UserRepoAccess.findUnique\\\",\\\"UserRepoAccess.findUniqueOrThrow\\\",\\\"UserRepoAccess.findFirst\\\",\\\"UserRepoAccess.findFirstOrThrow\\\",\\\"UserRepoAccess.findMany\\\",\\\"UserRepoAccess.createOne\\\",\\\"UserRepoAccess.createMany\\\",\\\"UserRepoAccess.createManyAndReturn\\\",\\\"UserRepoAccess.updateOne\\\",\\\"UserRepoAccess.updateMany\\\",\\\"UserRepoAccess.updateManyAndReturn\\\",\\\"UserRepoAccess.upsertOne\\\",\\\"UserRepoAccess.deleteOne\\\",\\\"UserRepoAccess.deleteMany\\\",\\\"UserRepoAccess.groupBy\\\",\\\"UserRepoAccess.aggregate\\\",\\\"AND\\\",\\\"OR\\\",\\\"NOT\\\",\\\"id\\\",\\\"userId\\\",\\\"orgId\\\",\\\"repoId\\\",\\\"permission\\\",\\\"grantedAt\\\",\\\"grantedBy\\\",\\\"equals\\\",\\\"in\\\",\\\"notIn\\\",\\\"lt\\\",\\\"lte\\\",\\\"gt\\\",\\\"gte\\\",\\\"not\\\",\\\"contains\\\",\\\"startsWith\\\",\\\"endsWith\\\",\\\"githubId\\\",\\\"githubLogin\\\",\\\"name\\\",\\\"email\\\",\\\"avatarUrl\\\",\\\"isAdmin\\\",\\\"createdAt\\\",\\\"updatedAt\\\",\\\"every\\\",\\\"some\\\",\\\"none\\\",\\\"apiKeyId\\\",\\\"operation\\\",\\\"memoryId\\\",\\\"query\\\",\\\"metadata\\\",\\\"string_contains\\\",\\\"string_starts_with\\\",\\\"string_ends_with\\\",\\\"array_starts_with\\\",\\\"array_ends_with\\\",\\\"array_contains\\\",\\\"key\\\",\\\"label\\\",\\\"createdBy\\\",\\\"isActive\\\",\\\"lastUsedAt\\\",\\\"userId_orgId_repoId\\\",\\\"deletedAt\\\",\\\"deletedBy\\\",\\\"syncedAt\\\",\\\"sourceId\\\",\\\"targetId\\\",\\\"linkType\\\",\\\"recalledAt\\\",\\\"sessionId\\\",\\\"model\\\",\\\"scopeType\\\",\\\"memoryType\\\",\\\"visibility\\\",\\\"status\\\",\\\"text\\\",\\\"summary\\\",\\\"tags\\\",\\\"sourceRefs\\\",\\\"confidence\\\",\\\"ttlSeconds\\\",\\\"supersedesId\\\",\\\"version\\\",\\\"has\\\",\\\"hasEvery\\\",\\\"hasSome\\\",\\\"sourceId_targetId_linkType\\\",\\\"is\\\",\\\"isNot\\\",\\\"connectOrCreate\\\",\\\"upsert\\\",\\\"createMany\\\",\\\"set\\\",\\\"disconnect\\\",\\\"delete\\\",\\\"connect\\\",\\\"updateMany\\\",\\\"deleteMany\\\",\\\"increment\\\",\\\"decrement\\\",\\\"multiply\\\",\\\"divide\\\",\\\"push\\\"]\"),\n graph: \"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-QEAIeYBAQD5AQAh5wEBAPkBACHoAQEA-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-gEAIc4BAACWAgAg3gEBAPgBACHfAQEA-AEAIeABAQD5AQAhAwAAAAcAIAIAAG0AMB4AAG4AIAMAAAAHACACAAAIADADAAAJACALqgEAAKwCADCrAQAAdAAQrAEAAKwCADCtAQEAAAABrwEBAI8CACGwAQEAjwIAIcUBQACSAgAhzAEBAAAAAdsBQACSAgAh3AEBAJACACHdAUAApwIAIQEAAABxACABAAAAcQAgC6oBAACsAgAwqwEAAHQAEKwBAACsAgAwrQEBAJ0CACGvAQEAjwIAIbABAQCPAgAhxQFAAJICACHMAQEAnQIAIdsBQACSAgAh3AEBAJACACHdAUAApwIAIQLcAQAAyAIAIN0BAADIAgAgAwAAAHQAIAIAAHUAMAMAAHEAIAMAAAB0ACACAAB1ADADAABxACADAAAAdAAgAgAAdQAwAwAAcQAgCK0BAQAAAAGvAQEAAAABsAEBAAAAAcUBQAAAAAHMAQEAAAAB2wFAAAAAAdwBAQAAAAHdAUAAAAABARIAAHkAIAitAQEAAAABrwEBAAAAAbABAQAAAAHFAUAAAAABzAEBAAAAAdsBQAAAAAHcAQEAAAAB3QFAAAAAAQESAAB7ADABEgAAewAwCK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhzAEBAMwCACHbAUAAzQIAIdwBAQDOAgAh3QFAAPACACECAAAAcQAgEgAAfgAgCK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhzAEBAMwCACHbAUAAzQIAIdwBAQDOAgAh3QFAAPACACECAAAAdAAgEgAAgAEAIAIAAAB0ACASAACAAQAgAwAAAHEAIBkAAHkAIBoAAH4AIAEAAABxACABAAAAdAAgBQwAAJIDACAhAACUAwAgIgAAkwMAINwBAADIAgAg3QEAAMgCACALqgEAAKsCADCrAQAAhwEAEKwBAACrAgAwrQEBAPgBACGvAQEA-QEAIbABAQD5AQAhxQFAAPoBACHMAQEA-AEAIdsBQAD6AQAh3AEBAIcCACHdAUAAmQIAIQMAAAB0ACACAACGAQAwHgAAhwEAIAMAAAB0ACACAAB1ADADAABxACAQZgAAqAIAIGkAAKkCACCqAQAApgIAMKsBAACOAQAQrAEAAKYCADCtAQEAAAABrgEBAJ4CACGvAQEAjwIAIbABAQCQAgAhwQEBAI8CACHFAUAAkgIAIdUBAQAAAAHWAQEAkAIAIdcBAQCeAgAh2AEgAJECACHZAUAApwIAIQEAAACKAQAgDmUAAJMCACBnAACUAgAgqgEAAI4CADCrAQAAjAEAEKwBAACOAgAwrQEBAJ0CACG_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-AEAIa8BAQD5AQAhsAEBAPkBACHFAUAA-gEAIcoBAQD4AQAhywEBAPkBACHMAQEA-wEAIc0BAQCHAgAhzgEAAJYCACADAAAAlwEAIAIAAMUBADAeAADGAQAgAwAAAJcBACACAACYAQAwAwAAmQEAIA5lAACTAgAgZwAAlAIAIKoBAACOAgAwqwEAAIwBABCsAQAAjgIAMK0BAQAAAAG_AQIAAAABwAEBAI8CACHBAQEAkAIAIcIBAQCQAgAhwwEBAJACACHEASAAkQIAIcUBQACSAgAhxgFAAJICACEBAAAAyQEAIAEAAADJAQAgBWUAAIMDACBnAACEAwAgwQEAAMgCACDCAQAAyAIAIMMBAADIAgAgAwAAAIwBACACAADMAQAwAwAAyQEAIAMAAACMAQAgAgAAzAEAMAMAAMkBACADAAAAjAEAIAIAAMwBADADAADJAQAgC2UAAIEDACBnAACCAwAgrQEBAAAAAb8BAgAAAAHAAQEAAAABwQEBAAAAAcIBAQAAAAHDAQEAAAABxAEgAAAAAcUBQAAAAAHGAUAAAAABARIAANABACAJrQEBAAAAAb8BAgAAAAHAAQEAAAABwQEBAAAAAcIBAQAAAAHDAQEAAAABxAEgAAAAAcUBQAAAAAHGAUAAAAABARIAANIBADABEgAA0gEAMAtlAADYAgAgZwAA2QIAIK0BAQDMAgAhvwECANYCACHAAQEAzAIAIcEBAQDOAgAhwgEBAM4CACHDAQEAzgIAIcQBIADXAgAhxQFAAM0CACHGAUAAzQIAIQIAAADJAQAgEgAA1QEAIAmtAQEAzAIAIb8BAgDWAgAhwAEBAMwCACHBAQEAzgIAIcIBAQDOAgAhwwEBAM4CACHEASAA1wIAIcUBQADNAgAhxgFAAM0CACECAAAAjAEAIBIAANcBACACAAAAjAEAIBIAANcBACADAAAAyQEAIBkAANABACAaAADVAQAgAQAAAMkBACABAAAAjAEAIAgMAADRAgAgHwAA0gIAICAAANUCACAhAADUAgAgIgAA0wIAIMEBAADIAgAgwgEAAMgCACDDAQAAyAIAIAyqAQAAhQIAMKsBAADeAQAQrAEAAIUCADCtAQEA-AEAIb8BAgCGAgAhwAEBAPkBACHBAQEAhwIAIcIBAQCHAgAhwwEBAIcCACHEASAAiAIAIcUBQAD6AQAhxgFAAPoBACEDAAAAjAEAIAIAAN0BADAeAADeAQAgAwAAAIwBACACAADMAQAwAwAAyQEAIAEAAACTAQAgAQAAAJMBACADAAAAkQEAIAIAAJIBADADAACTAQAgAwAAAJEBACACAACSAQAwAwAAkwEAIAMAAACRAQAgAgAAkgEAMAMAAJMBACAIZgAA0AIAIK0BAQAAAAGuAQEAAAABrwEBAAAAAbABAQAAAAGxAQEAAAABsgFAAAAAAbMBAQAAAAEBEgAA5gEAIAetAQEAAAABrgEBAAAAAa8BAQAAAAGwAQEAAAABsQEBAAAAAbIBQAAAAAGzAQEAAAABARIAAOgBADABEgAA6AEAMAhmAADPAgAgrQEBAMwCACGuAQEAzAIAIa8BAQDMAgAhsAEBAMwCACGxAQEAzAIAIbIBQADNAgAhswEBAM4CACECAAAAkwEAIBIAAOsBACAHrQEBAMwCACGuAQEAzAIAIa8BAQDMAgAhsAEBAMwCACGxAQEAzAIAIbIBQADNAgAhswEBAM4CACECAAAAkQEAIBIAAO0BACACAAAAkQEAIBIAAO0BACADAAAAkwEAIBkAAOYBACAaAADrAQAgAQAAAJMBACABAAAAkQEAIAQMAADJAgAgIQAAywIAICIAAMoCACCzAQAAyAIAIAqqAQAA9wEAMKsBAAD0AQAQrAEAAPcBADCtAQEA-AEAIa4BAQD4AQAhrwEBAPkBACGwAQEA-QEAIbEBAQD5AQAhsgFAAPoBACGzAQEA-wEAIQMAAACRAQAgAgAA8wEAMB4AAPQBACADAAAAkQEAIAIAAJIBADADAACTAQAgCqoBAAD3AQAwqwEAAPQBABCsAQAA9wEAMK0BAQD4AQAhrgEBAPgBACGvAQEA-QEAIbABAQD5AQAhsQEBAPkBACGyAUAA-gEAIbMBAQD7AQAhCwwAAIACACAhAACDAgAgIgAAgwIAILQBAQAAAAG1AQEAAAAEtgEBAAAABLcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEAhAIAIQ4MAACAAgAgIQAAgwIAICIAAIMCACC0AQEAAAABtQEBAAAABLYBAQAAAAS3AQEAAAABuAEBAAAAAbkBAQAAAAG6AQEAAAABuwEBAIICACG8AQEAAAABvQEBAAAAAb4BAQAAAAELDAAAgAIAICEAAIECACAiAACBAgAgtAFAAAAAAbUBQAAAAAS2AUAAAAAEtwFAAAAAAbgBQAAAAAG5AUAAAAABugFAAAAAAbsBQAD_AQAhCwwAAP0BACAhAAD-AQAgIgAA_gEAILQBAQAAAAG1AQEAAAAFtgEBAAAABbcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEA_AEAIQsMAAD9AQAgIQAA_gEAICIAAP4BACC0AQEAAAABtQEBAAAABbYBAQAAAAW3AQEAAAABuAEBAAAAAbkBAQAAAAG6AQEAAAABuwEBAPwBACEItAECAAAAAbUBAgAAAAW2AQIAAAAFtwECAAAAAbgBAgAAAAG5AQIAAAABugECAAAAAbsBAgD9AQAhC7QBAQAAAAG1AQEAAAAFtgEBAAAABbcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEA_gEAIbwBAQAAAAG9AQEAAAABvgEBAAAAAQsMAACAAgAgIQAAgQIAICIAAIECACC0AUAAAAABtQFAAAAABLYBQAAAAAS3AUAAAAABuAFAAAAAAbkBQAAAAAG6AUAAAAABuwFAAP8BACEItAECAAAAAbUBAgAAAAS2AQIAAAAEtwECAAAAAbgBAgAAAAG5AQIAAAABugECAAAAAbsBAgCAAgAhCLQBQAAAAAG1AUAAAAAEtgFAAAAABLcBQAAAAAG4AUAAAAABuQFAAAAAAboBQAAAAAG7AUAAgQIAIQ4MAACAAgAgIQAAgwIAICIAAIMCACC0AQEAAAABtQEBAAAABLYBAQAAAAS3AQEAAAABuAEBAAAAAbkBAQAAAAG6AQEAAAABuwEBAIICACG8AQEAAAABvQEBAAAAAb4BAQAAAAELtAEBAAAAAbUBAQAAAAS2AQEAAAAEtwEBAAAAAbgBAQAAAAG5AQEAAAABugEBAAAAAbsBAQCDAgAhvAEBAAAAAb0BAQAAAAG-AQEAAAABCwwAAIACACAhAACDAgAgIgAAgwIAILQBAQAAAAG1AQEAAAAEtgEBAAAABLcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEAhAIAIQyqAQAAhQIAMKsBAADeAQAQrAEAAIUCADCtAQEA-AEAIb8BAgCGAgAhwAEBAPkBACHBAQEAhwIAIcIBAQCHAgAhwwEBAIcCACHEASAAiAIAIcUBQAD6AQAhxgFAAPoBACENDAAAgAIAIB8AAI0CACAgAACAAgAgIQAAgAIAICIAAIACACC0AQIAAAABtQECAAAABLYBAgAAAAS3AQIAAAABuAECAAAAAbkBAgAAAAG6AQIAAAABuwECAIwCACEODAAA_QEAICEAAP4BACAiAAD-AQAgtAEBAAAAAbUBAQAAAAW2AQEAAAAFtwEBAAAAAbgBAQAAAAG5AQEAAAABugEBAAAAAbsBAQCLAgAhvAEBAAAAAb0BAQAAAAG-AQEAAAABBQwAAIACACAhAACKAgAgIgAAigIAILQBIAAAAAG7ASAAiQIAIQUMAACAAgAgIQAAigIAICIAAIoCACC0ASAAAAABuwEgAIkCACECtAEgAAAAAbsBIACKAgAhDgwAAP0BACAhAAD-AQAgIgAA_gEAILQBAQAAAAG1AQEAAAAFtgEBAAAABbcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEAiwIAIbwBAQAAAAG9AQEAAAABvgEBAAAAAQ0MAACAAgAgHwAAjQIAICAAAIACACAhAACAAgAgIgAAgAIAILQBAgAAAAG1AQIAAAAEtgECAAAABLcBAgAAAAG4AQIAAAABuQECAAAAAboBAgAAAAG7AQIAjAIAIQi0AQgAAAABtQEIAAAABLYBCAAAAAS3AQgAAAABuAEIAAAAAbkBCAAAAAG6AQgAAAABuwEIAI0CACEOZQAAkwIAIGcAAJQCACCqAQAAjgIAMKsBAACMAQAQrAEAAI4CADCtAQEAnQIAIb8BAgCqAgAhwAEBAI8CACHBAQEAkAIAIcIBAQCQAgAhwwEBAJACACHEASAAkQIAIcUBQACSAgAhxgFAAJICACELtAEBAAAAAbUBAQAAAAS2AQEAAAAEtwEBAAAAAbgBAQAAAAG5AQEAAAABugEBAAAAAbsBAQCDAgAhvAEBAAAAAb0BAQAAAAG-AQEAAAABC7QBAQAAAAG1AQEAAAAFtgEBAAAABbcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEA_gEAIbwBAQAAAAG9AQEAAAABvgEBAAAAAQK0ASAAAAABuwEgAIoCACEItAFAAAAAAbUBQAAAAAS2AUAAAAAEtwFAAAAAAbgBQAAAAAG5AUAAAAABugFAAAAAAbsBQACBAgAhA8cBAACOAQAgyAEAAI4BACDJAQAAjgEAIAPHAQAAkQEAIMgBAACRAQAgyQEAAJEBACAMqgEAAJUCADCrAQAAxgEAEKwBAACVAgAwrQEBAPgBACGvAQEA-QEAIbABAQD5AQAhxQFAAPoBACHKAQEA-AEAIcsBAQD5AQAhzAEBAPsBACHNAQEAhwIAIc4BAACWAgAgDwwAAP0BACAhAACXAgAgIgAAlwIAILQBgAAAAAG3AYAAAAABuAGAAAAAAbkBgAAAAAG6AYAAAAABuwGAAAAAAc8BAQAAAAHQAQEAAAAB0QEBAAAAAdIBgAAAAAHTAYAAAAAB1AGAAAAAAQy0AYAAAAABtwGAAAAAAbgBgAAAAAG5AYAAAAABugGAAAAAAbsBgAAAAAHPAQEAAAAB0AEBAAAAAdEBAQAAAAHSAYAAAAAB0wGAAAAAAdQBgAAAAAEOqgEAAJgCADCrAQAAsAEAEKwBAACYAgAwrQEBAPgBACGuAQEA-wEAIa8BAQD5AQAhsAEBAIcCACHBAQEA-QEAIcUBQAD6AQAh1QEBAPkBACHWAQEAhwIAIdcBAQD7AQAh2AEgAIgCACHZAUAAmQIAIQsMAAD9AQAgIQAAmwIAICIAAJsCACC0AUAAAAABtQFAAAAABbYBQAAAAAW3AUAAAAABuAFAAAAAAbkBQAAAAAG6AUAAAAABuwFAAJoCACELDAAA_QEAICEAAJsCACAiAACbAgAgtAFAAAAAAbUBQAAAAAW2AUAAAAAFtwFAAAAAAbgBQAAAAAG5AUAAAAABugFAAAAAAbsBQACaAgAhCLQBQAAAAAG1AUAAAAAFtgFAAAAABbcBQAAAAAG4AUAAAAABuQFAAAAAAboBQAAAAAG7AUAAmwIAIQ1oAACgAgAgqgEAAJwCADCrAQAAlwEAEKwBAACcAgAwrQEBAJ0CACGvAQEAjwIAIbABAQCPAgAhxQFAAJICACHKAQEAnQIAIcsBAQCPAgAhzAEBAJ4CACHNAQEAkAIAIc4BAACfAgAgCLQBAQAAAAG1AQEAAAAEtgEBAAAABLcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEAogIAIQi0AQEAAAABtQEBAAAABbYBAQAAAAW3AQEAAAABuAEBAAAAAbkBAQAAAAG6AQEAAAABuwEBAKECACEMtAGAAAAAAbcBgAAAAAG4AYAAAAABuQGAAAAAAboBgAAAAAG7AYAAAAABzwEBAAAAAdABAQAAAAHRAQEAAAAB0gGAAAAAAdMBgAAAAAHUAYAAAAABEmYAAKgCACBpAACpAgAgqgEAAKYCADCrAQAAjgEAEKwBAACmAgAwrQEBAJ0CACGuAQEAngIAIa8BAQCPAgAhsAEBAJACACHBAQEAjwIAIcUBQACSAgAh1QEBAI8CACHWAQEAkAIAIdcBAQCeAgAh2AEgAJECACHZAUAApwIAIfQBAACOAQAg9QEAAI4BACAItAEBAAAAAbUBAQAAAAW2AQEAAAAFtwEBAAAAAbgBAQAAAAG5AQEAAAABugEBAAAAAbsBAQChAgAhCLQBAQAAAAG1AQEAAAAEtgEBAAAABLcBAQAAAAG4AQEAAAABuQEBAAAAAboBAQAAAAG7AQEAogIAIQOuAQEAAAABrwEBAAAAAbABAQAAAAELZgAApQIAIKoBAACkAgAwqwEAAJEBABCsAQAApAIAMK0BAQCdAgAhrgEBAJ0CACGvAQEAjwIAIbABAQCPAgAhsQEBAI8CACGyAUAAkgIAIbMBAQCeAgAhEGUAAJMCACBnAACUAgAgqgEAAI4CADCrAQAAjAEAEKwBAACOAgAwrQEBAJ0CACG_AQIAqgIAIcABAQCPAgAhwQEBAJACACHCAQEAkAIAIcMBAQCQAgAhxAEgAJECACHFAUAAkgIAIcYBQACSAgAh9AEAAIwBACD1AQAAjAEAIBBmAACoAgAgaQAAqQIAIKoBAACmAgAwqwEAAI4BABCsAQAApgIAMK0BAQCdAgAhrgEBAJ4CACGvAQEAjwIAIbABAQCQAgAhwQEBAI8CACHFAUAAkgIAIdUBAQCPAgAh1gEBAJACACHXAQEAngIAIdgBIACRAgAh2QFAAKcCACEItAFAAAAAAbUBQAAAAAW2AUAAAAAFtwFAAAAAAbgBQAAAAAG5AUAAAAABugFAAAAAAbsBQACbAgAhEGUAAJMCACBnAACUAgAgqgEAAI4CADCrAQAAjAEAEKwBAACOAgAwrQEBAJ0CACG_AQIAqgIAIcABAQCPAgAhwQEBAJACACHCAQEAkAIAIcMBAQCQAgAhxAEgAJECACHFAUAAkgIAIcYBQACSAgAh9AEAAIwBACD1AQAAjAEAIAPHAQAAlwEAIMgBAACXAQAgyQEAAJcBACAItAECAAAAAbUBAgAAAAS2AQIAAAAEtwECAAAAAbgBAgAAAAG5AQIAAAABugECAAAAAbsBAgCAAgAhC6oBAACrAgAwqwEAAIcBABCsAQAAqwIAMK0BAQD4AQAhrwEBAPkBACGwAQEA-QEAIcUBQAD6AQAhzAEBAPgBACHbAUAA-gEAIdwBAQCHAgAh3QFAAJkCACELqgEAAKwCADCrAQAAdAAQrAEAAKwCADCtAQEAnQIAIa8BAQCPAgAhsAEBAI8CACHFAUAAkgIAIcwBAQCdAgAh2wFAAJICACHcAQEAkAIAId0BQACnAgAhCaoBAACtAgAwqwEAAG4AEKwBAACtAgAwrQEBAPgBACHFAUAA-gEAIc4BAACWAgAg3gEBAPgBACHfAQEA-AEAIeABAQD5AQAhCKoBAACuAgAwqwEAAFgAEKwBAACuAgAwrQECAIYCACHMAQEA-AEAIc0BAQCHAgAh4QFAAPoBACHiAQEAhwIAIQcKAAGwAgAhqgEAAK8CADCrAQAAQgAQrAEAAK8CADDFAUAA-gEAIcwBAQD4AQAh4wEBAPkBACEHDAAAgAIAICEAALICACAiAACyAgAgtAEAAQAAAbUBAAEAAAS2AQABAAAEuwEAAbECACEHDAAAgAIAICEAALICACAiAACyAgAgtAEAAQAAAbUBAAEAAAS2AQABAAAEuwEAAbECACEEtAEAAQAAAbUBAAEAAAS2AQABAAAEuwEAAbICACEICQAAtQIAIAoAAbQCACGqAQAAswIAMKsBAAAMABCsAQAAswIAMMUBQACSAgAhzAEBAJ0CACHjAQEAjwIAIQS0AQABAAABtQEAAQAABLYBAAEAAAS7AQABsgIAIR4BAADDAgAgBAAAxAIAIAcAAMUCACAIAADFAgAgCgAAxgIAIAsAAMcCACCqAQAAwAIAMKsBAAADABCsAQAAwAIAMK0BAQCdAgAhrwEBAI8CACGwAQEAjwIAIcUBQACSAgAhxgFAAJICACHbAUAApwIAIdwBAQCQAgAh5AEBAI8CACHlAQEAjwIAIeYBAQCPAgAh5wEBAI8CACHoAQEAjwIAIekBAQCQAgAh6gEAALcCACDrAQAAnwIAIOwBCADBAgAh7QECAMICACHuAQEAngIAIe8BAgCqAgAh9AEAAAMAIPUBAAADACAWqgEAALYCADCrAQAAKgAQrAEAALYCADCtAQEA-AEAIa8BAQD5AQAhsAEBAPkBACHFAUAA-gEAIcYBQAD6AQAh2wFAAJkCACHcAQEAhwIAIeQBAQD5AQAh5QEBAPkBACHmAQEA-QEAIecBAQD5AQAh6AEBAPkBACHpAQEAhwIAIeoBAAC3AgAg6wEAAJYCACDsAQgAuAIAIe0BAgC5AgAh7gEBAPsBACHvAQIAhgIAIQS0AQEAAAAF8AEBAAAAAfEBAQAAAATyAQEAAAAEDQwAAP0BACAfAAC7AgAgIAAAuwIAICEAALsCACAiAAC7AgAgtAEIAAAAAbUBCAAAAAW2AQgAAAAFtwEIAAAAAbgBCAAAAAG5AQgAAAABugEIAAAAAbsBCAC8AgAhDQwAAP0BACAfAAC7AgAgIAAA_QEAICEAAP0BACAiAAD9AQAgtAECAAAAAbUBAgAAAAW2AQIAAAAFtwECAAAAAbgBAgAAAAG5AQIAAAABugECAAAAAbsBAgC6AgAhDQwAAP0BACAfAAC7AgAgIAAA_QEAICEAAP0BACAiAAD9AQAgtAECAAAAAbUBAgAAAAW2AQIAAAAFtwECAAAAAbgBAgAAAAG5AQIAAAABugECAAAAAbsBAgC6AgAhCLQBCAAAAAG1AQgAAAAFtgEIAAAABbcBCAAAAAG4AQgAAAABuQEIAAAAAboBCAAAAAG7AQgAuwIAIQ0MAAD9AQAgHwAAuwIAICAAALsCACAhAAC7AgAgIgAAuwIAILQBCAAAAAG1AQgAAAAFtgEIAAAABbcBCAAAAAG4AQgAAAABuQEIAAAAAboBCAAAAAG7AQgAvAIAIQkJAAC1AgAgqgEAAL0CADCrAQAADgAQrAEAAL0CADCtAQIAqgIAIcwBAQCdAgAhzQEBAJACACHhAUAAkgIAIeIBAQCQAgAhA94BAQAAAAHfAQEAAAAB4AEBAAAAAQsFAAC1AgAgBgAAtQIAIKoBAAC_AgAwqwEAAAcAEKwBAAC_AgAwrQEBAJ0CACHFAUAAkgIAIc4BAACfAgAg3gEBAJ0CACHfAQEAnQIAIeABAQCPAgAhHAEAAMMCACAEAADEAgAgBwAAxQIAIAgAAMUCACAKAADGAgAgCwAAxwIAIKoBAADAAgAwqwEAAAMAEKwBAADAAgAwrQEBAJ0CACGvAQEAjwIAIbABAQCPAgAhxQFAAJICACHGAUAAkgIAIdsBQACnAgAh3AEBAJACACHkAQEAjwIAIeUBAQCPAgAh5gEBAI8CACHnAQEAjwIAIegBAQCPAgAh6QEBAJACACHqAQAAtwIAIOsBAACfAgAg7AEIAMECACHtAQIAwgIAIe4BAQCeAgAh7wECAKoCACEItAEIAAAAAbUBCAAAAAW2AQgAAAAFtwEIAAAAAbgBCAAAAAG5AQgAAAABugEIAAAAAbsBCAC7AgAhCLQBAgAAAAG1AQIAAAAFtgECAAAABbcBAgAAAAG4AQIAAAABuQECAAAAAboBAgAAAAG7AQIA_QEAIR4BAADDAgAgBAAAxAIAIAcAAMUCACAIAADFAgAgCgAAxgIAIAsAAMcCACCqAQAAwAIAMKsBAAADABCsAQAAwAIAMK0BAQCdAgAhrwEBAI8CACGwAQEAjwIAIcUBQACSAgAhxgFAAJICACHbAUAApwIAIdwBAQCQAgAh5AEBAI8CACHlAQEAjwIAIeYBAQCPAgAh5wEBAI8CACHoAQEAjwIAIekBAQCQAgAh6gEAALcCACDrAQAAnwIAIOwBCADBAgAh7QECAMICACHuAQEAngIAIe8BAgCqAgAh9AEAAAMAIPUBAAADACADxwEAAAMAIMgBAAADACDJAQAAAwAgA8cBAAAHACDIAQAABwAgyQEAAAcAIAoJAAC1AgAgCgABtAIAIaoBAACzAgAwqwEAAAwAEKwBAACzAgAwxQFAAJICACHMAQEAnQIAIeMBAQCPAgAh9AEAAAwAIPUBAAAMACADxwEAAA4AIMgBAAAOACDJAQAADgAgAAAAAAH5AQEAAAABAfkBQAAAAAEB-QEBAAAAAQUZAACfBAAgGgAAogQAIPYBAACgBAAg9wEAAKEEACD8AQAAyQEAIAMZAACfBAAg9gEAAKAEACD8AQAAyQEAIAAAAAAABfkBAgAAAAH_AQIAAAABgAICAAAAAYECAgAAAAGCAgIAAAABAfkBIAAAAAELGQAA5gIAMBoAAOsCADD2AQAA5wIAMPcBAADoAgAw-AEAAOkCACD5AQAA6gIAMPoBAADqAgAw-wEAAOoCADD8AQAA6gIAMP0BAADsAgAw_gEAAO0CADALGQAA2gIAMBoAAN8CADD2AQAA2wIAMPcBAADcAgAw-AEAAN0CACD5AQAA3gIAMPoBAADeAgAw-wEAAN4CADD8AQAA3gIAMP0BAADgAgAw_gEAAOECADAGrQEBAAAAAa8BAQAAAAGwAQEAAAABsQEBAAAAAbIBQAAAAAGzAQEAAAABAgAAAJMBACAZAADlAgAgAwAAAJMBACAZAADlAgAgGgAA5AIAIAESAACeBAAwDGYAAKUCACCqAQAApAIAMKsBAACRAQAQrAEAAKQCADCtAQEAAAABrgEBAJ0CACGvAQEAjwIAIbABAQCPAgAhsQEBAI8CACGyAUAAkgIAIbMBAQCeAgAh2gEAAKMCACACAAAAkwEAIBIAAOQCACACAAAA4gIAIBIAAOMCACAKqgEAAOECADCrAQAA4gIAEKwBAADhAgAwrQEBAJ0CACGuAQEAnQIAIa8BAQCPAgAhsAEBAI8CACGxAQEAjwIAIbIBQACSAgAhswEBAJ4CACEKqgEAAOECADCrAQAA4gIAEKwBAADhAgAwrQEBAJ0CACGuAQEAnQIAIa8BAQCPAgAhsAEBAI8CACGxAQEAjwIAIbIBQACSAgAhswEBAJ4CACEGrQEBAMwCACGvAQEAzAIAIbABAQDMAgAhsQEBAMwCACGyAUAAzQIAIbMBAQDOAgAhBq0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIbEBAQDMAgAhsgFAAM0CACGzAQEAzgIAIQatAQEAAAABrwEBAAAAAbABAQAAAAGxAQEAAAABsgFAAAAAAbMBAQAAAAELaQAAgAMAIK0BAQAAAAGvAQEAAAABsAEBAAAAAcEBAQAAAAHFAUAAAAAB1QEBAAAAAdYBAQAAAAHXAQEAAAAB2AEgAAAAAdkBQAAAAAECAAAAigEAIBkAAP8CACADAAAAigEAIBkAAP8CACAaAADxAgAgARIAAJ0EADAQZgAAqAIAIGkAAKkCACCqAQAApgIAMKsBAACOAQAQrAEAAKYCADCtAQEAAAABrgEBAJ4CACGvAQEAjwIAIbABAQCQAgAhwQEBAI8CACHFAUAAkgIAIdUBAQAAAAHWAQEAkAIAIdcBAQCeAgAh2AEgAJECACHZAUAApwIAIQIAAACKAQAgEgAA8QIAIAIAAADuAgAgEgAA7wIAIA6qAQAA7QIAMKsBAADuAgAQrAEAAO0CADCtAQEAnQIAIa4BAQCeAgAhrwEBAI8CACGwAQEAkAIAIcEBAQCPAgAhxQFAAJICACHVAQEAjwIAIdYBAQCQAgAh1wEBAJ4CACHYASAAkQIAIdkBQACnAgAhDqoBAADtAgAwqwEAAO4CABCsAQAA7QIAMK0BAQCdAgAhrgEBAJ4CACGvAQEAjwIAIbABAQCQAgAhwQEBAI8CACHFAUAAkgIAIdUBAQCPAgAh1gEBAJACACHXAQEAngIAIdgBIACRAgAh2QFAAKcCACEKrQEBAMwCACGvAQEAzAIAIbABAQDOAgAhwQEBAMwCACHFAUAAzQIAIdUBAQDMAgAh1gEBAM4CACHXAQEAzgIAIdgBIADXAgAh2QFAAPACACEB-QFAAAAAAQtpAADyAgAgrQEBAMwCACGvAQEAzAIAIbABAQDOAgAhwQEBAMwCACHFAUAAzQIAIdUBAQDMAgAh1gEBAM4CACHXAQEAzgIAIdgBIADXAgAh2QFAAPACACELGQAA8wIAMBoAAPgCADD2AQAA9AIAMPcBAAD1AgAw-AEAAPYCACD5AQAA9wIAMPoBAAD3AgAw-wEAAPcCADD8AQAA9wIAMP0BAAD5AgAw_gEAAPoCADAIrQEBAAAAAa8BAQAAAAGwAQEAAAABxQFAAAAAAcsBAQAAAAHMAQEAAAABzQEBAAAAAc4BgAAAAAECAAAAmQEAIBkAAP4CACADAAAAmQEAIBkAAP4CACAaAAD9AgAgARIAAJwEADANaAAAoAIAIKoBAACcAgAwqwEAAJcBABCsAQAAnAIAMK0BAQAAAAGvAQEAjwIAIbABAQCPAgAhxQFAAJICACHKAQEAnQIAIcsBAQCPAgAhzAEBAJ4CACHNAQEAkAIAIc4BAACfAgAgAgAAAJkBACASAAD9AgAgAgAAAPsCACASAAD8AgAgDKoBAAD6AgAwqwEAAPsCABCsAQAA-gIAMK0BAQCdAgAhrwEBAI8CACGwAQEAjwIAIcUBQACSAgAhygEBAJ0CACHLAQEAjwIAIcwBAQCeAgAhzQEBAJACACHOAQAAnwIAIAyqAQAA-gIAMKsBAAD7AgAQrAEAAPoCADCtAQEAnQIAIa8BAQCPAgAhsAEBAI8CACHFAUAAkgIAIcoBAQCdAgAhywEBAI8CACHMAQEAngIAIc0BAQCQAgAhzgEAAJ8CACAIrQEBAMwCACGvAQEAzAIAIbABAQDMAgAhxQFAAM0CACHLAQEAzAIAIcwBAQDOAgAhzQEBAM4CACHOAYAAAAABCK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhywEBAMwCACHMAQEAzgIAIc0BAQDOAgAhzgGAAAAAAQitAQEAAAABrwEBAAAAAbABAQAAAAHFAUAAAAABywEBAAAAAcwBAQAAAAHNAQEAAAABzgGAAAAAAQtpAACAAwAgrQEBAAAAAa8BAQAAAAGwAQEAAAABwQEBAAAAAcUBQAAAAAHVAQEAAAAB1gEBAAAAAdcBAQAAAAHYASAAAAAB2QFAAAAAAQQZAADzAgAw9gEAAPQCADD4AQAA9gIAIPwBAAD3AgAwBBkAAOYCADD2AQAA5wIAMPgBAADpAgAg_AEAAOoCADAEGQAA2gIAMPYBAADbAgAw-AEAAN0CACD8AQAA3gIAMAAAAAAABRkAAJcEACAaAACaBAAg9gEAAJgEACD3AQAAmQQAIPwBAACKAQAgAxkAAJcEACD2AQAAmAQAIPwBAACKAQAgAAAABxkAAJIEACAaAACVBAAg9gEAAJMEACD3AQAAlAQAIPoBAACMAQAg-wEAAIwBACD8AQAAyQEAIAMZAACSBAAg9gEAAJMEACD8AQAAyQEAIAdmAACQAwAgaQAAkQMAIK4BAADIAgAgsAEAAMgCACDWAQAAyAIAINcBAADIAgAg2QEAAMgCACAFZQAAgwMAIGcAAIQDACDBAQAAyAIAIMIBAADIAgAgwwEAAMgCACAAAAAAAAAABRkAAIoEACAaAACQBAAg9gEAAIsEACD3AQAAjwQAIPwBAAABACAFGQAAiAQAIBoAAI0EACD2AQAAiQQAIPcBAACMBAAg_AEAAAEAIAMZAACKBAAg9gEAAIsEACD8AQAAAQAgAxkAAIgEACD2AQAAiQQAIPwBAAABACAAAAAAAAUZAACDBAAgGgAAhgQAIPYBAACEBAAg9wEAAIUEACD8AQAAAQAgAxkAAIMEACD2AQAAhAQAIPwBAAABACAAAAAB-QEAAQAAAQUZAAD-AwAgGgAAgQQAIPYBAAD_AwAg9wEAAIAEACD8AQAAAQAgAxkAAP4DACD2AQAA_wMAIPwBAAABACANAQAAqQMAIAQAAPEDACAHAADyAwAgCAAA8gMAIAoAAPMDACALAAD0AwAg2wEAAMgCACDcAQAAyAIAIOkBAADIAgAg6wEAAMgCACDsAQAAyAIAIO0BAADIAgAg7gEAAMgCACAAAAAAAAL5AQEAAAAEgwIBAAAABQX5AQgAAAAB_wEIAAAAAYACCAAAAAGBAggAAAABggIIAAAAAQX5AQIAAAAB_wECAAAAAYACAgAAAAGBAgIAAAABggICAAAAAQcZAAD1AwAgGgAA_AMAIPYBAAD2AwAg9wEAAPsDACD6AQAAAwAg-wEAAAMAIPwBAAABACALGQAA3gMAMBoAAOMDADD2AQAA3wMAMPcBAADgAwAw-AEAAOEDACD5AQAA4gMAMPoBAADiAwAw-wEAAOIDADD8AQAA4gMAMP0BAADkAwAw_gEAAOUDADALGQAA1QMAMBoAANkDADD2AQAA1gMAMPcBAADXAwAw-AEAANgDACD5AQAAzQMAMPoBAADNAwAw-wEAAM0DADD8AQAAzQMAMP0BAADaAwAw_gEAANADADALGQAAyQMAMBoAAM4DADD2AQAAygMAMPcBAADLAwAw-AEAAMwDACD5AQAAzQMAMPoBAADNAwAw-wEAAM0DADD8AQAAzQMAMP0BAADPAwAw_gEAANADADAHGQAAxAMAIBoAAMcDACD2AQAAxQMAIPcBAADGAwAg-gEAAAwAIPsBAAAMACD8AQAALQAgCxkAALgDADAaAAC9AwAw9gEAALkDADD3AQAAugMAMPgBAAC7AwAg-QEAALwDADD6AQAAvAMAMPsBAAC8AwAw_AEAALwDADD9AQAAvgMAMP4BAAC_AwAwBK0BAgAAAAHNAQEAAAAB4QFAAAAAAeIBAQAAAAECAAAAEAAgGQAAwwMAIAMAAAAQACAZAADDAwAgGgAAwgMAIAESAAD6AwAwCQkAALUCACCqAQAAvQIAMKsBAAAOABCsAQAAvQIAMK0BAgAAAAHMAQEAnQIAIc0BAQCQAgAh4QFAAJICACHiAQEAkAIAIQIAAAAQACASAADCAwAgAgAAAMADACASAADBAwAgCKoBAAC_AwAwqwEAAMADABCsAQAAvwMAMK0BAgCqAgAhzAEBAJ0CACHNAQEAkAIAIeEBQACSAgAh4gEBAJACACEIqgEAAL8DADCrAQAAwAMAEKwBAAC_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_AEAAM0DADAEGQAAyQMAMPYBAADKAwAw-AEAAMwDACD8AQAAzQMAMAMZAADEAwAg9gEAAMUDACD8AQAALQAgBBkAALgDADD2AQAAuQMAMPgBAAC7AwAg_AEAALwDADADGQAA9QMAIPYBAAD2AwAg_AEAAAEAIAAAAQkAAKkDACAAGAEAAPADACAHAADsAwAgCAAA7QMAIAoAAO4DACALAADvAwAgrQEBAAAAAa8BAQAAAAGwAQEAAAABxQFAAAAAAcYBQAAAAAHbAUAAAAAB3AEBAAAAAeQBAQAAAAHlAQEAAAAB5gEBAAAAAecBAQAAAAHoAQEAAAAB6QEBAAAAAeoBAADqAwAg6wGAAAAAAewBCAAAAAHtAQIAAAAB7gEBAAAAAe8BAgAAAAECAAAAAQAgGQAA9QMAIBKtAQEAAAABrwEBAAAAAbABAQAAAAHFAUAAAAABxgFAAAAAAdsBQAAAAAHcAQEAAAAB5AEBAAAAAeUBAQAAAAHmAQEAAAAB5wEBAAAAAegBAQAAAAHpAQEAAAAB6gEAAOoDACDrAYAAAAAB7AEIAAAAAe0BAgAAAAHvAQIAAAABBa0BAQAAAAHFAUAAAAABzgGAAAAAAd8BAQAAAAHgAQEAAAABBa0BAQAAAAHFAUAAAAABzgGAAAAAAd4BAQAAAAHgAQEAAAABBK0BAgAAAAHNAQEAAAAB4QFAAAAAAeIBAQAAAAEDAAAAAwAgGQAA9QMAIBoAAP0DACAaAAAAAwAgAQAAsgMAIAcAALQDACAIAAC1AwAgCgAAtgMAIAsAALcDACASAAD9AwAgrQEBAMwCACGvAQEAzAIAIbABAQDMAgAhxQFAAM0CACHGAUAAzQIAIdsBQADwAgAh3AEBAM4CACHkAQEAzAIAIeUBAQDMAgAh5gEBAMwCACHnAQEAzAIAIegBAQDMAgAh6QEBAM4CACHqAQAArwMAIOsBgAAAAAHsAQgAsAMAIe0BAgCxAwAh7gEBAM4CACHvAQIA1gIAIRgBAACyAwAgBwAAtAMAIAgAALUDACAKAAC2AwAgCwAAtwMAIK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhxgFAAM0CACHbAUAA8AIAIdwBAQDOAgAh5AEBAMwCACHlAQEAzAIAIeYBAQDMAgAh5wEBAMwCACHoAQEAzAIAIekBAQDOAgAh6gEAAK8DACDrAYAAAAAB7AEIALADACHtAQIAsQMAIe4BAQDOAgAh7wECANYCACEYAQAA8AMAIAQAAOsDACAHAADsAwAgCAAA7QMAIAsAAO8DACCtAQEAAAABrwEBAAAAAbABAQAAAAHFAUAAAAABxgFAAAAAAdsBQAAAAAHcAQEAAAAB5AEBAAAAAeUBAQAAAAHmAQEAAAAB5wEBAAAAAegBAQAAAAHpAQEAAAAB6gEAAOoDACDrAYAAAAAB7AEIAAAAAe0BAgAAAAHuAQEAAAAB7wECAAAAAQIAAAABACAZAAD-AwAgAwAAAAMAIBkAAP4DACAaAACCBAAgGgAAAAMAIAEAALIDACAEAACzAwAgBwAAtAMAIAgAALUDACALAAC3AwAgEgAAggQAIK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhxgFAAM0CACHbAUAA8AIAIdwBAQDOAgAh5AEBAMwCACHlAQEAzAIAIeYBAQDMAgAh5wEBAMwCACHoAQEAzAIAIekBAQDOAgAh6gEAAK8DACDrAYAAAAAB7AEIALADACHtAQIAsQMAIe4BAQDOAgAh7wECANYCACEYAQAAsgMAIAQAALMDACAHAAC0AwAgCAAAtQMAIAsAALcDACCtAQEAzAIAIa8BAQDMAgAhsAEBAMwCACHFAUAAzQIAIcYBQADNAgAh2wFAAPACACHcAQEAzgIAIeQBAQDMAgAh5QEBAMwCACHmAQEAzAIAIecBAQDMAgAh6AEBAMwCACHpAQEAzgIAIeoBAACvAwAg6wGAAAAAAewBCACwAwAh7QECALEDACHuAQEAzgIAIe8BAgDWAgAhGAEAAPADACAEAADrAwAgBwAA7AMAIAgAAO0DACAKAADuAwAgrQEBAAAAAa8BAQAAAAGwAQEAAAABxQFAAAAAAcYBQAAAAAHbAUAAAAAB3AEBAAAAAeQBAQAAAAHlAQEAAAAB5gEBAAAAAecBAQAAAAHoAQEAAAAB6QEBAAAAAeoBAADqAwAg6wGAAAAAAewBCAAAAAHtAQIAAAAB7gEBAAAAAe8BAgAAAAECAAAAAQAgGQAAgwQAIAMAAAADACAZAACDBAAgGgAAhwQAIBoAAAADACABAACyAwAgBAAAswMAIAcAALQDACAIAAC1AwAgCgAAtgMAIBIAAIcEACCtAQEAzAIAIa8BAQDMAgAhsAEBAMwCACHFAUAAzQIAIcYBQADNAgAh2wFAAPACACHcAQEAzgIAIeQBAQDMAgAh5QEBAMwCACHmAQEAzAIAIecBAQDMAgAh6AEBAMwCACHpAQEAzgIAIeoBAACvAwAg6wGAAAAAAewBCACwAwAh7QECALEDACHuAQEAzgIAIe8BAgDWAgAhGAEAALIDACAEAACzAwAgBwAAtAMAIAgAALUDACAKAAC2AwAgrQEBAMwCACGvAQEAzAIAIbABAQDMAgAhxQFAAM0CACHGAUAAzQIAIdsBQADwAgAh3AEBAM4CACHkAQEAzAIAIeUBAQDMAgAh5gEBAMwCACHnAQEAzAIAIegBAQDMAgAh6QEBAM4CACHqAQAArwMAIOsBgAAAAAHsAQgAsAMAIe0BAgCxAwAh7gEBAM4CACHvAQIA1gIAIRgBAADwAwAgBAAA6wMAIAcAAOwDACAKAADuAwAgCwAA7wMAIK0BAQAAAAGvAQEAAAABsAEBAAAAAcUBQAAAAAHGAUAAAAAB2wFAAAAAAdwBAQAAAAHkAQEAAAAB5QEBAAAAAeYBAQAAAAHnAQEAAAAB6AEBAAAAAekBAQAAAAHqAQAA6gMAIOsBgAAAAAHsAQgAAAAB7QECAAAAAe4BAQAAAAHvAQIAAAABAgAAAAEAIBkAAIgEACAYAQAA8AMAIAQAAOsDACAIAADtAwAgCgAA7gMAIAsAAO8DACCtAQEAAAABrwEBAAAAAbABAQAAAAHFAUAAAAABxgFAAAAAAdsBQAAAAAHcAQEAAAAB5AEBAAAAAeUBAQAAAAHmAQEAAAAB5wEBAAAAAegBAQAAAAHpAQEAAAAB6gEAAOoDACDrAYAAAAAB7AEIAAAAAe0BAgAAAAHuAQEAAAAB7wECAAAAAQIAAAABACAZAACKBAAgAwAAAAMAIBkAAIgEACAaAACOBAAgGgAAAAMAIAEAALIDACAEAACzAwAgBwAAtAMAIAoAALYDACALAAC3AwAgEgAAjgQAIK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhxgFAAM0CACHbAUAA8AIAIdwBAQDOAgAh5AEBAMwCACHlAQEAzAIAIeYBAQDMAgAh5wEBAMwCACHoAQEAzAIAIekBAQDOAgAh6gEAAK8DACDrAYAAAAAB7AEIALADACHtAQIAsQMAIe4BAQDOAgAh7wECANYCACEYAQAAsgMAIAQAALMDACAHAAC0AwAgCgAAtgMAIAsAALcDACCtAQEAzAIAIa8BAQDMAgAhsAEBAMwCACHFAUAAzQIAIcYBQADNAgAh2wFAAPACACHcAQEAzgIAIeQBAQDMAgAh5QEBAMwCACHmAQEAzAIAIecBAQDMAgAh6AEBAMwCACHpAQEAzgIAIeoBAACvAwAg6wGAAAAAAewBCACwAwAh7QECALEDACHuAQEAzgIAIe8BAgDWAgAhAwAAAAMAIBkAAIoEACAaAACRBAAgGgAAAAMAIAEAALIDACAEAACzAwAgCAAAtQMAIAoAALYDACALAAC3AwAgEgAAkQQAIK0BAQDMAgAhrwEBAMwCACGwAQEAzAIAIcUBQADNAgAhxgFAAM0CACHbAUAA8AIAIdwBAQDOAgAh5AEBAMwCACHlAQEAzAIAIeYBAQDMAgAh5wEBAMwCACHoAQEAzAIAIekBAQDOAgAh6gEAAK8DACDrAYAAAAAB7AEIALADACHtAQIAsQMAIe4BAQDOAgAh7wECANYCACEYAQAAsgMAIAQAALMDACAIAAC1AwAgCgAAtgMAIAsAALcDACCtAQEAzAIAIa8BAQDMAgAhsAEBAMwCACHFAUAAzQIAIcYBQADNAgAh2wFAAPACACHcAQEAzgIAIeQBAQDMAgAh5QEBAMwCACHmAQEAzAIAIecBAQDMAgAh6AEBAMwCACHpAQEAzgIAIeoBAACvAwAg6wGAAAAAAewBCACwAwAh7QECALEDACHuAQEAzgIAIe8BAgDWAgAhCmcAAIIDACCtAQEAAAABvwECAAAAAcABAQAAAAHBAQEAAAABwgEBAAAAAcMBAQAAAAHEASAAAAABxQFAAAAAAcYBQAAAAAECAAAAyQEAIBkAAJIEACADAAAAjAEAIBkAAJIEACAaAACWBAAgDAAAAIwBACASAACWBAAgZwAA2QIAIK0BAQDMAgAhvwECANYCACHAAQEAzAIAIcEBAQDOAgAhwgEBAM4CACHDAQEAzgIAIcQBIADXAgAhxQFAAM0CACHGAUAAzQIAIQpnAADZAgAgrQEBAMwCACG_AQIA1gIAIcABAQDMAgAhwQEBAM4CACHCAQEAzgIAIcMBAQDOAgAhxAEgANcCACHFAUAAzQIAIcYBQADNAgAhDGYAAI4DACCtAQEAAAABrgEBAAAAAa8BAQAAAAGwAQEAAAABwQEBAAAAAcUBQAAAAAHVAQEAAAAB1gEBAAAAAdcBAQAAAAHYASAAAAAB2QFAAAAAAQIAAACKAQAgGQAAlwQAIAMAAACOAQAgGQAAlwQAIBoAAJsEACAOAAAAjgEAIBIAAJsEACBmAACNAwAgrQEBAMwCACGuAQEAzgIAIa8BAQDMAgAhsAEBAM4CACHBAQEAzAIAIcUBQADNAgAh1QEBAMwCACHWAQEAzgIAIdcBAQDOAgAh2AEgANcCACHZAUAA8AIAIQxmAACNAwAgrQEBAMwCACGuAQEAzgIAIa8BAQDMAgAhsAEBAM4CACHBAQEAzAIAIcUBQADNAgAh1QEBAMwCACHWAQEAzgIAIdcBAQDOAgAh2AEgANcCACHZAUAA8AIAIQitAQEAAAABrwEBAAAAAbABAQAAAAHFAUAAAAABywEBAAAAAcwBAQAAAAHNAQEAAAABzgGAAAAAAQqtAQEAAAABrwEBAAAAAbABAQAAAAHBAQEAAAABxQFAAAAAAdUBAQAAAAHWAQEAAAAB1wEBAAAAAdgBIAAAAAHZAUAAAAABBq0BAQAAAAGvAQEAAAABsAEBAAAAAbEBAQAAAAGyAUAAAAABswEBAAAAAQplAACBAwAgrQEBAAAAAb8BAgAAAAHAAQEAAAABwQEBAAAAAcIBAQAAAAHDAQEAAAABxAEgAAAAAcUBQAAAAAHGAUAAAAABAgAAAMkBACAZAACfBAAgAwAAAIwBACAZAACfBAAgGgAAowQAIAwAAACMAQAgEgAAowQAIGUAANgCACCtAQEAzAIAIb8BAgDWAgAhwAEBAMwCACHBAQEAzgIAIcIBAQDOAgAhwwEBAM4CACHEASAA1wIAIcUBQADNAgAhxgFAAM0CACEKZQAA2AIAIK0BAQDMAgAhvwECANYCACHAAQEAzAIAIcEBAQDOAgAhwgEBAM4CACHDAQEAzgIAIcQBIADXAgAhxQFAAM0CACHGAUAAzQIAIQcBBAEEBgEHCgIICwIKDQMLEQQMAAUCBQABBgABAQkAAQEJAAEEBBIABxMACBQACxUAAAEBHwEBASUBBQwACh8ACyAADCEADSIADgAAAAAABQwACh8ACyAADCEADSIADgEJAAEBCQABAwwAEyEAFCIAFQAAAAMMABMhABQiABUBCQABAQkAAQUMABofABsgABwhAB0iAB4AAAAAAAUMABofABsgABwhAB0iAB4CBQABBgABAgUAAQYAAQMMACMhACQiACUAAAADDAAjIQAkIgAlAAAAAwwAKyEALCIALQAAAAMMACshACwiAC0DDAA0Zo0BMGmaATMDDAAyZZABL2eUATEBZgAwAmWVAQBnlgEAAWgALwFpmwEAAWalATABZqsBMAMMADghADkiADoAAAADDAA4IQA5IgA6AWgALwFoAC8DDAA_IQBAIgBBAAAAAwwAPyEAQCIAQQAABQwARh8ARyAASCEASSIASgAAAAAABQwARh8ARyAASCEASSIASgFmADABZgAwAwwATyEAUCIAUQAAAAMMAE8hAFAiAFENAgEOFgEPFwEQGAERGQETGwEUHQYVHgcWIQEXIwYYJAgbJgEcJwEdKAYjKwkkLA8lLgMmLwMnMQMoMgMpMwMqNQMrNwYsOBAtOgMuPAYvPREwPgMxPwMyQAYzQxI0RBY1RQQ2RgQ3RwQ4SAQ5SQQ6SwQ7TQY8Thc9UAQ-UgY_UxhAVARBVQRCVgZDWRlEWh9FWwJGXAJHXQJIXgJJXwJKYQJLYwZMZCBNZgJOaAZPaSFQagJRawJSbAZTbyJUcCZVcidWcydXdidYdydZeCdaeidbfAZcfShdfydegQEGX4IBKWCDASdhhAEnYoUBBmOIASpkiQEuaosBL2ucAS9snQEvbZ4BL26fAS9voQEvcKMBBnGkATVypwEvc6kBBnSqATZ1rAEvdq0BL3euAQZ4sQE3ebIBO3qzATN7tAEzfLUBM322ATN-twEzf7kBM4ABuwEGgQG8ATyCAb4BM4MBwAEGhAHBAT2FAcIBM4YBwwEzhwHEAQaIAccBPokByAFCigHKATCLAcsBMIwBzQEwjQHOATCOAc8BMI8B0QEwkAHTAQaRAdQBQ5IB1gEwkwHYAQaUAdkBRJUB2gEwlgHbATCXAdwBBpgB3wFFmQHgAUuaAeEBMZsB4gExnAHjATGdAeQBMZ4B5QExnwHnATGgAekBBqEB6gFMogHsATGjAe4BBqQB7wFNpQHwATGmAfEBMacB8gEGqAH1AU6pAfYBUg\"\n}\n\nasync function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {\n const { Buffer } = await import('node:buffer')\n const wasmArray = Buffer.from(wasmBase64, 'base64')\n return new WebAssembly.Module(wasmArray)\n}\n\nconfig.compilerWasm = {\n getRuntime: async () => await import(\"@prisma/client/runtime/query_compiler_fast_bg.postgresql.mjs\"),\n\n getQueryCompilerWasmModule: async () => {\n const { wasm } = await import(\"@prisma/client/runtime/query_compiler_fast_bg.postgresql.wasm-base64.mjs\")\n return await decodeBase64AsWasm(wasm)\n },\n\n importName: \"./query_compiler_fast_bg.js\"\n}\n\n\n\nexport type LogOptions<ClientOptions extends Prisma.PrismaClientOptions> =\n 'log' extends keyof ClientOptions ? ClientOptions['log'] extends Array<Prisma.LogLevel | Prisma.LogDefinition> ? Prisma.GetEvents<ClientOptions['log']> : never : never\n\nexport interface PrismaClientConstructor {\n /**\n * ## Prisma Client\n * \n * Type-safe database client for TypeScript\n * @example\n * ```\n * const prisma = new PrismaClient({\n * adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })\n * })\n * // Fetch zero or more Memories\n * const memories = await prisma.memory.findMany()\n * ```\n * \n * Read more in our [docs](https://pris.ly/d/client).\n */\n\n new <\n Options extends Prisma.PrismaClientOptions = Prisma.PrismaClientOptions,\n LogOpts extends LogOptions<Options> = LogOptions<Options>,\n OmitOpts extends Prisma.PrismaClientOptions['omit'] = Options extends { omit: infer U } ? U : Prisma.PrismaClientOptions['omit'],\n ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs\n >(options: Prisma.Subset<Options, Prisma.PrismaClientOptions> ): PrismaClient<LogOpts, OmitOpts, ExtArgs>\n}\n\n/**\n * ## Prisma Client\n * \n * Type-safe database client for TypeScript\n * @example\n * ```\n * const prisma = new PrismaClient({\n * adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL })\n * })\n * // Fetch zero or more Memories\n * const memories = await prisma.memory.findMany()\n * ```\n * \n * Read more in our [docs](https://pris.ly/d/client).\n */\n\nexport interface PrismaClient<\n in LogOpts extends Prisma.LogLevel = never,\n in out OmitOpts extends Prisma.PrismaClientOptions['omit'] = undefined,\n in out ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs\n> {\n [K: symbol]: { types: Prisma.TypeMap<ExtArgs>['other'] }\n\n $on<V extends LogOpts>(eventType: V, callback: (event: V extends 'query' ? Prisma.QueryEvent : Prisma.LogEvent) => void): PrismaClient;\n\n /**\n * Connect with the database\n */\n $connect(): runtime.Types.Utils.JsPromise<void>;\n\n /**\n * Disconnect from the database\n */\n $disconnect(): runtime.Types.Utils.JsPromise<void>;\n\n/**\n * Executes a prepared raw query and returns the number of affected rows.\n * @example\n * ```\n * const result = await prisma.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};`\n * ```\n *\n * Read more in our [docs](https://pris.ly/d/raw-queries).\n */\n $executeRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise<number>;\n\n /**\n * Executes a raw query and returns the number of affected rows.\n * Susceptible to SQL injections, see documentation.\n * @example\n * ```\n * const result = await prisma.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com')\n * ```\n *\n * Read more in our [docs](https://pris.ly/d/raw-queries).\n */\n $executeRawUnsafe<T = unknown>(query: string, ...values: any[]): Prisma.PrismaPromise<number>;\n\n /**\n * Performs a prepared raw query and returns the `SELECT` data.\n * @example\n * ```\n * const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};`\n * ```\n *\n * Read more in our [docs](https://pris.ly/d/raw-queries).\n */\n $queryRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise<T>;\n\n /**\n * Performs a raw query and returns the `SELECT` data.\n * Susceptible to SQL injections, see documentation.\n * @example\n * ```\n * const result = await prisma.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com')\n * ```\n *\n * Read more in our [docs](https://pris.ly/d/raw-queries).\n */\n $queryRawUnsafe<T = unknown>(query: string, ...values: any[]): Prisma.PrismaPromise<T>;\n\n\n /**\n * Allows the running of a sequence of read/write operations that are guaranteed to either succeed or fail as a whole.\n * @example\n * ```\n * const [george, bob, alice] = await prisma.$transaction([\n * prisma.user.create({ data: { name: 'George' } }),\n * prisma.user.create({ data: { name: 'Bob' } }),\n * prisma.user.create({ data: { name: 'Alice' } }),\n * ])\n * ```\n * \n * Read more in our [docs](https://www.prisma.io/docs/orm/prisma-client/queries/transactions).\n */\n $transaction<P extends Prisma.PrismaPromise<any>[]>(arg: [...P], options?: { maxWait?: number, timeout?: number, isolationLevel?: Prisma.TransactionIsolationLevel }): runtime.Types.Utils.JsPromise<runtime.Types.Utils.UnwrapTuple<P>>\n\n $transaction<R>(fn: (prisma: Omit<PrismaClient, runtime.ITXClientDenyList>) => runtime.Types.Utils.JsPromise<R>, options?: { maxWait?: number, timeout?: number, isolationLevel?: Prisma.TransactionIsolationLevel }): runtime.Types.Utils.JsPromise<R>\n\n $extends: runtime.Types.Extensions.ExtendsHook<\"extends\", Prisma.TypeMapCb<OmitOpts>, ExtArgs, runtime.Types.Utils.Call<Prisma.TypeMapCb<OmitOpts>, {\n extArgs: ExtArgs\n }>>\n\n /**\n * `prisma.memory`: Exposes CRUD operations for the **Memory** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more Memories\n * const memories = await prisma.memory.findMany()\n * ```\n */\n get memory(): Prisma.MemoryDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.memoryEmbedding`: Exposes CRUD operations for the **MemoryEmbedding** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more MemoryEmbeddings\n * const memoryEmbeddings = await prisma.memoryEmbedding.findMany()\n * ```\n */\n get memoryEmbedding(): Prisma.MemoryEmbeddingDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.memoryUsage`: Exposes CRUD operations for the **MemoryUsage** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more MemoryUsages\n * const memoryUsages = await prisma.memoryUsage.findMany()\n * ```\n */\n get memoryUsage(): Prisma.MemoryUsageDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.memoryLink`: Exposes CRUD operations for the **MemoryLink** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more MemoryLinks\n * const memoryLinks = await prisma.memoryLink.findMany()\n * ```\n */\n get memoryLink(): Prisma.MemoryLinkDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.tombstone`: Exposes CRUD operations for the **Tombstone** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more Tombstones\n * const tombstones = await prisma.tombstone.findMany()\n * ```\n */\n get tombstone(): Prisma.TombstoneDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.apiKey`: Exposes CRUD operations for the **ApiKey** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more ApiKeys\n * const apiKeys = await prisma.apiKey.findMany()\n * ```\n */\n get apiKey(): Prisma.ApiKeyDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.apiKeyLog`: Exposes CRUD operations for the **ApiKeyLog** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more ApiKeyLogs\n * const apiKeyLogs = await prisma.apiKeyLog.findMany()\n * ```\n */\n get apiKeyLog(): Prisma.ApiKeyLogDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.user`: Exposes CRUD operations for the **User** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more Users\n * const users = await prisma.user.findMany()\n * ```\n */\n get user(): Prisma.UserDelegate<ExtArgs, { omit: OmitOpts }>;\n\n /**\n * `prisma.userRepoAccess`: Exposes CRUD operations for the **UserRepoAccess** model.\n * Example usage:\n * ```ts\n * // Fetch zero or more UserRepoAccesses\n * const userRepoAccesses = await prisma.userRepoAccess.findMany()\n * ```\n */\n get userRepoAccess(): Prisma.UserRepoAccessDelegate<ExtArgs, { omit: OmitOpts }>;\n}\n\nexport function getPrismaClientClass(): PrismaClientConstructor {\n return runtime.getPrismaClient(config) as unknown as PrismaClientConstructor\n}\n","\n/* !!! This is code generated by Prisma. Do not edit directly. !!! */\n/* eslint-disable */\n// biome-ignore-all lint: generated file\n// @ts-nocheck \n/*\n * WARNING: This is an internal file that is subject to change!\n *\n * 🛑 Under no circumstances should you import this file directly! 🛑\n *\n * All exports from this file are wrapped under a `Prisma` namespace object in the client.ts file.\n * While this enables partial backward compatibility, it is not part of the stable public API.\n *\n * If you are looking for your Models, Enums, and Input Types, please import them from the respective\n * model files in the `model` directory!\n */\n\nimport * as runtime from \"@prisma/client/runtime/client\"\nimport type * as Prisma from \"../models\"\nimport { type PrismaClient } from \"./class\"\n\nexport type * from '../models'\n\nexport type DMMF = typeof runtime.DMMF\n\nexport type PrismaPromise<T> = runtime.Types.Public.PrismaPromise<T>\n\n/**\n * Prisma Errors\n */\n\nexport const PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError\nexport type PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError\n\nexport const PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError\nexport type PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError\n\nexport const PrismaClientRustPanicError = runtime.PrismaClientRustPanicError\nexport type PrismaClientRustPanicError = runtime.PrismaClientRustPanicError\n\nexport const PrismaClientInitializationError = runtime.PrismaClientInitializationError\nexport type PrismaClientInitializationError = runtime.PrismaClientInitializationError\n\nexport const PrismaClientValidationError = runtime.PrismaClientValidationError\nexport type PrismaClientValidationError = runtime.PrismaClientValidationError\n\n/**\n * Re-export of sql-template-tag\n */\nexport const sql = runtime.sqltag\nexport const empty = runtime.empty\nexport const join = runtime.join\nexport const raw = runtime.raw\nexport const Sql = runtime.Sql\nexport type Sql = runtime.Sql\n\n\n\n/**\n * Decimal.js\n */\nexport const Decimal = runtime.Decimal\nexport type Decimal = runtime.Decimal\n\nexport type DecimalJsLike = runtime.DecimalJsLike\n\n/**\n* Extensions\n*/\nexport type Extension = runtime.Types.Extensions.UserArgs\nexport const getExtensionContext = runtime.Extensions.getExtensionContext\nexport type Args<T, F extends runtime.Operation> = runtime.Types.Public.Args<T, F>\nexport type Payload<T, F extends runtime.Operation = never> = runtime.Types.Public.Payload<T, F>\nexport type Result<T, A, F extends runtime.Operation> = runtime.Types.Public.Result<T, A, F>\nexport type Exact<A, W> = runtime.Types.Public.Exact<A, W>\n\nexport type PrismaVersion = {\n client: string\n engine: string\n}\n\n/**\n * Prisma Client JS version: 7.8.0\n * Query Engine version: 3c6e192761c0362d496ed980de936e2f3cebcd3a\n */\nexport const prismaVersion: PrismaVersion = {\n client: \"7.8.0\",\n engine: \"3c6e192761c0362d496ed980de936e2f3cebcd3a\"\n}\n\n/**\n * Utility Types\n */\n\nexport type Bytes = runtime.Bytes\nexport type JsonObject = runtime.JsonObject\nexport type JsonArray = runtime.JsonArray\nexport type JsonValue = runtime.JsonValue\nexport type InputJsonObject = runtime.InputJsonObject\nexport type InputJsonArray = runtime.InputJsonArray\nexport type InputJsonValue = runtime.InputJsonValue\n\n\nexport const NullTypes = {\n DbNull: runtime.NullTypes.DbNull as (new (secret: never) => typeof runtime.DbNull),\n JsonNull: runtime.NullTypes.JsonNull as (new (secret: never) => typeof runtime.JsonNull),\n AnyNull: runtime.NullTypes.AnyNull as (new (secret: never) => typeof runtime.AnyNull),\n}\n/**\n * Helper for filtering JSON entries that have `null` on the database (empty on the db)\n *\n * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field\n */\nexport const DbNull = runtime.DbNull\n\n/**\n * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)\n *\n * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field\n */\nexport const JsonNull = runtime.JsonNull\n\n/**\n * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`\n *\n * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field\n */\nexport const AnyNull = runtime.AnyNull\n\n\ntype SelectAndInclude = {\n select: any\n include: any\n}\n\ntype SelectAndOmit = {\n select: any\n omit: any\n}\n\n/**\n * From T, pick a set of properties whose keys are in the union K\n */\ntype Prisma__Pick<T, K extends keyof T> = {\n [P in K]: T[P];\n};\n\nexport type Enumerable<T> = T | Array<T>;\n\n/**\n * Subset\n * @desc From `T` pick properties that exist in `U`. Simple version of Intersection\n */\nexport type Subset<T, U> = {\n [key in keyof T]: key extends keyof U ? T[key] : never;\n};\n\n/**\n * SelectSubset\n * @desc From `T` pick properties that exist in `U`. Simple version of Intersection.\n * Additionally, it validates, if both select and include are present. If the case, it errors.\n */\nexport type SelectSubset<T, U> = {\n [key in keyof T]: key extends keyof U ? T[key] : never\n} &\n (T extends SelectAndInclude\n ? 'Please either choose `select` or `include`.'\n : T extends SelectAndOmit\n ? 'Please either choose `select` or `omit`.'\n : {})\n\n/**\n * Subset + Intersection\n * @desc From `T` pick properties that exist in `U` and intersect `K`\n */\nexport type SubsetIntersection<T, U, K> = {\n [key in keyof T]: key extends keyof U ? T[key] : never\n} &\n K\n\ntype Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };\n\n/**\n * XOR is needed to have a real mutually exclusive union type\n * https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types\n */\nexport type XOR<T, U> =\n T extends object ?\n U extends object ?\n (Without<T, U> & U) | (Without<U, T> & T)\n : U : T\n\n\n/**\n * Is T a Record?\n */\ntype IsObject<T extends any> = T extends Array<any>\n? False\n: T extends Date\n? False\n: T extends Uint8Array\n? False\n: T extends BigInt\n? False\n: T extends object\n? True\n: False\n\n\n/**\n * If it's T[], return T\n */\nexport type UnEnumerate<T extends unknown> = T extends Array<infer U> ? U : T\n\n/**\n * From ts-toolbelt\n */\n\ntype __Either<O extends object, K extends Key> = Omit<O, K> &\n {\n // Merge all but K\n [P in K]: Prisma__Pick<O, P & keyof O> // With K possibilities\n }[K]\n\ntype EitherStrict<O extends object, K extends Key> = Strict<__Either<O, K>>\n\ntype EitherLoose<O extends object, K extends Key> = ComputeRaw<__Either<O, K>>\n\ntype _Either<\n O extends object,\n K extends Key,\n strict extends Boolean\n> = {\n 1: EitherStrict<O, K>\n 0: EitherLoose<O, K>\n}[strict]\n\nexport type Either<\n O extends object,\n K extends Key,\n strict extends Boolean = 1\n> = O extends unknown ? _Either<O, K, strict> : never\n\nexport type Union = any\n\nexport type PatchUndefined<O extends object, O1 extends object> = {\n [K in keyof O]: O[K] extends undefined ? At<O1, K> : O[K]\n} & {}\n\n/** Helper Types for \"Merge\" **/\nexport type IntersectOf<U extends Union> = (\n U extends unknown ? (k: U) => void : never\n) extends (k: infer I) => void\n ? I\n : never\n\nexport type Overwrite<O extends object, O1 extends object> = {\n [K in keyof O]: K extends keyof O1 ? O1[K] : O[K];\n} & {};\n\ntype _Merge<U extends object> = IntersectOf<Overwrite<U, {\n [K in keyof U]-?: At<U, K>;\n}>>;\n\ntype Key = string | number | symbol;\ntype AtStrict<O extends object, K extends Key> = O[K & keyof O];\ntype AtLoose<O extends object, K extends Key> = O extends unknown ? AtStrict<O, K> : never;\nexport type At<O extends object, K extends Key, strict extends Boolean = 1> = {\n 1: AtStrict<O, K>;\n 0: AtLoose<O, K>;\n}[strict];\n\nexport type ComputeRaw<A extends any> = A extends Function ? A : {\n [K in keyof A]: A[K];\n} & {};\n\nexport type OptionalFlat<O> = {\n [K in keyof O]?: O[K];\n} & {};\n\ntype _Record<K extends keyof any, T> = {\n [P in K]: T;\n};\n\n// cause typescript not to expand types and preserve names\ntype NoExpand<T> = T extends unknown ? T : never;\n\n// this type assumes the passed object is entirely optional\nexport type AtLeast<O extends object, K extends string> = NoExpand<\n O extends unknown\n ? | (K extends keyof O ? { [P in K]: O[P] } & O : O)\n | {[P in keyof O as P extends K ? P : never]-?: O[P]} & O\n : never>;\n\ntype _Strict<U, _U = U> = U extends unknown ? U & OptionalFlat<_Record<Exclude<Keys<_U>, keyof U>, never>> : never;\n\nexport type Strict<U extends object> = ComputeRaw<_Strict<U>>;\n/** End Helper Types for \"Merge\" **/\n\nexport type Merge<U extends object> = ComputeRaw<_Merge<Strict<U>>>;\n\nexport type Boolean = True | False\n\nexport type True = 1\n\nexport type False = 0\n\nexport type Not<B extends Boolean> = {\n 0: 1\n 1: 0\n}[B]\n\nexport type Extends<A1 extends any, A2 extends any> = [A1] extends [never]\n ? 0 // anything `never` is false\n : A1 extends A2\n ? 1\n : 0\n\nexport type Has<U extends Union, U1 extends Union> = Not<\n Extends<Exclude<U1, U>, U1>\n>\n\nexport type Or<B1 extends Boolean, B2 extends Boolean> = {\n 0: {\n 0: 0\n 1: 1\n }\n 1: {\n 0: 1\n 1: 1\n }\n}[B1][B2]\n\nexport type Keys<U extends Union> = U extends unknown ? keyof U : never\n\nexport type GetScalarType<T, O> = O extends object ? {\n [P in keyof T]: P extends keyof O\n ? O[P]\n : never\n} : never\n\ntype FieldPaths<\n T,\n U = Omit<T, '_avg' | '_sum' | '_count' | '_min' | '_max'>\n> = IsObject<T> extends True ? U : T\n\nexport type GetHavingFields<T> = {\n [K in keyof T]: Or<\n Or<Extends<'OR', K>, Extends<'AND', K>>,\n Extends<'NOT', K>\n > extends True\n ? // infer is only needed to not hit TS limit\n // based on the brilliant idea of Pierre-Antoine Mills\n // https://github.com/microsoft/TypeScript/issues/30188#issuecomment-478938437\n T[K] extends infer TK\n ? GetHavingFields<UnEnumerate<TK> extends object ? Merge<UnEnumerate<TK>> : never>\n : never\n : {} extends FieldPaths<T[K]>\n ? never\n : K\n}[keyof T]\n\n/**\n * Convert tuple to union\n */\ntype _TupleToUnion<T> = T extends (infer E)[] ? E : never\ntype TupleToUnion<K extends readonly any[]> = _TupleToUnion<K>\nexport type MaybeTupleToUnion<T> = T extends any[] ? TupleToUnion<T> : T\n\n/**\n * Like `Pick`, but additionally can also accept an array of keys\n */\nexport type PickEnumerable<T, K extends Enumerable<keyof T> | keyof T> = Prisma__Pick<T, MaybeTupleToUnion<K>>\n\n/**\n * Exclude all keys with underscores\n */\nexport type ExcludeUnderscoreKeys<T extends string> = T extends `_${string}` ? never : T\n\n\nexport type FieldRef<Model, FieldType> = runtime.FieldRef<Model, FieldType>\n\ntype FieldRefInputType<Model, FieldType> = Model extends never ? never : FieldRef<Model, FieldType>\n\n\nexport const ModelName = {\n Memory: 'Memory',\n MemoryEmbedding: 'MemoryEmbedding',\n MemoryUsage: 'MemoryUsage',\n MemoryLink: 'MemoryLink',\n Tombstone: 'Tombstone',\n ApiKey: 'ApiKey',\n ApiKeyLog: 'ApiKeyLog',\n User: 'User',\n UserRepoAccess: 'UserRepoAccess'\n} as const\n\nexport type ModelName = (typeof ModelName)[keyof typeof ModelName]\n\n\n\nexport interface TypeMapCb<GlobalOmitOptions = {}> extends runtime.Types.Utils.Fn<{extArgs: runtime.Types.Extensions.InternalArgs }, runtime.Types.Utils.Record<string, any>> {\n returns: TypeMap<this['params']['extArgs'], GlobalOmitOptions>\n}\n\nexport type TypeMap<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs, GlobalOmitOptions = {}> = {\n globalOmitOptions: {\n omit: GlobalOmitOptions\n }\n meta: {\n modelProps: \"memory\" | \"memoryEmbedding\" | \"memoryUsage\" | \"memoryLink\" | \"tombstone\" | \"apiKey\" | \"apiKeyLog\" | \"user\" | \"userRepoAccess\"\n txIsolationLevel: TransactionIsolationLevel\n }\n model: {\n Memory: {\n payload: Prisma.$MemoryPayload<ExtArgs>\n fields: Prisma.MemoryFieldRefs\n operations: {\n findUnique: {\n args: Prisma.MemoryFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.MemoryFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>\n }\n findFirst: {\n args: Prisma.MemoryFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.MemoryFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>\n }\n findMany: {\n args: Prisma.MemoryFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>[]\n }\n create: {\n args: Prisma.MemoryCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>\n }\n createMany: {\n args: Prisma.MemoryCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.MemoryCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>[]\n }\n delete: {\n args: Prisma.MemoryDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>\n }\n update: {\n args: Prisma.MemoryUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>\n }\n deleteMany: {\n args: Prisma.MemoryDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.MemoryUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.MemoryUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>[]\n }\n upsert: {\n args: Prisma.MemoryUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryPayload>\n }\n aggregate: {\n args: Prisma.MemoryAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateMemory>\n }\n groupBy: {\n args: Prisma.MemoryGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryGroupByOutputType>[]\n }\n count: {\n args: Prisma.MemoryCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryCountAggregateOutputType> | number\n }\n }\n }\n MemoryEmbedding: {\n payload: Prisma.$MemoryEmbeddingPayload<ExtArgs>\n fields: Prisma.MemoryEmbeddingFieldRefs\n operations: {\n findUnique: {\n args: Prisma.MemoryEmbeddingFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.MemoryEmbeddingFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>\n }\n findFirst: {\n args: Prisma.MemoryEmbeddingFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.MemoryEmbeddingFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>\n }\n findMany: {\n args: Prisma.MemoryEmbeddingFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>[]\n }\n create: {\n args: Prisma.MemoryEmbeddingCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>\n }\n createMany: {\n args: Prisma.MemoryEmbeddingCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.MemoryEmbeddingCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>[]\n }\n delete: {\n args: Prisma.MemoryEmbeddingDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>\n }\n update: {\n args: Prisma.MemoryEmbeddingUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>\n }\n deleteMany: {\n args: Prisma.MemoryEmbeddingDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.MemoryEmbeddingUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.MemoryEmbeddingUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>[]\n }\n upsert: {\n args: Prisma.MemoryEmbeddingUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryEmbeddingPayload>\n }\n aggregate: {\n args: Prisma.MemoryEmbeddingAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateMemoryEmbedding>\n }\n groupBy: {\n args: Prisma.MemoryEmbeddingGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryEmbeddingGroupByOutputType>[]\n }\n count: {\n args: Prisma.MemoryEmbeddingCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryEmbeddingCountAggregateOutputType> | number\n }\n }\n }\n MemoryUsage: {\n payload: Prisma.$MemoryUsagePayload<ExtArgs>\n fields: Prisma.MemoryUsageFieldRefs\n operations: {\n findUnique: {\n args: Prisma.MemoryUsageFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.MemoryUsageFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>\n }\n findFirst: {\n args: Prisma.MemoryUsageFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.MemoryUsageFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>\n }\n findMany: {\n args: Prisma.MemoryUsageFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>[]\n }\n create: {\n args: Prisma.MemoryUsageCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>\n }\n createMany: {\n args: Prisma.MemoryUsageCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.MemoryUsageCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>[]\n }\n delete: {\n args: Prisma.MemoryUsageDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>\n }\n update: {\n args: Prisma.MemoryUsageUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>\n }\n deleteMany: {\n args: Prisma.MemoryUsageDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.MemoryUsageUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.MemoryUsageUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>[]\n }\n upsert: {\n args: Prisma.MemoryUsageUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryUsagePayload>\n }\n aggregate: {\n args: Prisma.MemoryUsageAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateMemoryUsage>\n }\n groupBy: {\n args: Prisma.MemoryUsageGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryUsageGroupByOutputType>[]\n }\n count: {\n args: Prisma.MemoryUsageCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryUsageCountAggregateOutputType> | number\n }\n }\n }\n MemoryLink: {\n payload: Prisma.$MemoryLinkPayload<ExtArgs>\n fields: Prisma.MemoryLinkFieldRefs\n operations: {\n findUnique: {\n args: Prisma.MemoryLinkFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.MemoryLinkFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>\n }\n findFirst: {\n args: Prisma.MemoryLinkFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.MemoryLinkFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>\n }\n findMany: {\n args: Prisma.MemoryLinkFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>[]\n }\n create: {\n args: Prisma.MemoryLinkCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>\n }\n createMany: {\n args: Prisma.MemoryLinkCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.MemoryLinkCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>[]\n }\n delete: {\n args: Prisma.MemoryLinkDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>\n }\n update: {\n args: Prisma.MemoryLinkUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>\n }\n deleteMany: {\n args: Prisma.MemoryLinkDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.MemoryLinkUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.MemoryLinkUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>[]\n }\n upsert: {\n args: Prisma.MemoryLinkUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$MemoryLinkPayload>\n }\n aggregate: {\n args: Prisma.MemoryLinkAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateMemoryLink>\n }\n groupBy: {\n args: Prisma.MemoryLinkGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryLinkGroupByOutputType>[]\n }\n count: {\n args: Prisma.MemoryLinkCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.MemoryLinkCountAggregateOutputType> | number\n }\n }\n }\n Tombstone: {\n payload: Prisma.$TombstonePayload<ExtArgs>\n fields: Prisma.TombstoneFieldRefs\n operations: {\n findUnique: {\n args: Prisma.TombstoneFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.TombstoneFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>\n }\n findFirst: {\n args: Prisma.TombstoneFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.TombstoneFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>\n }\n findMany: {\n args: Prisma.TombstoneFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>[]\n }\n create: {\n args: Prisma.TombstoneCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>\n }\n createMany: {\n args: Prisma.TombstoneCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.TombstoneCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>[]\n }\n delete: {\n args: Prisma.TombstoneDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>\n }\n update: {\n args: Prisma.TombstoneUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>\n }\n deleteMany: {\n args: Prisma.TombstoneDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.TombstoneUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.TombstoneUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>[]\n }\n upsert: {\n args: Prisma.TombstoneUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$TombstonePayload>\n }\n aggregate: {\n args: Prisma.TombstoneAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateTombstone>\n }\n groupBy: {\n args: Prisma.TombstoneGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.TombstoneGroupByOutputType>[]\n }\n count: {\n args: Prisma.TombstoneCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.TombstoneCountAggregateOutputType> | number\n }\n }\n }\n ApiKey: {\n payload: Prisma.$ApiKeyPayload<ExtArgs>\n fields: Prisma.ApiKeyFieldRefs\n operations: {\n findUnique: {\n args: Prisma.ApiKeyFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.ApiKeyFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>\n }\n findFirst: {\n args: Prisma.ApiKeyFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.ApiKeyFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>\n }\n findMany: {\n args: Prisma.ApiKeyFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>[]\n }\n create: {\n args: Prisma.ApiKeyCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>\n }\n createMany: {\n args: Prisma.ApiKeyCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.ApiKeyCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>[]\n }\n delete: {\n args: Prisma.ApiKeyDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>\n }\n update: {\n args: Prisma.ApiKeyUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>\n }\n deleteMany: {\n args: Prisma.ApiKeyDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.ApiKeyUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.ApiKeyUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>[]\n }\n upsert: {\n args: Prisma.ApiKeyUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyPayload>\n }\n aggregate: {\n args: Prisma.ApiKeyAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateApiKey>\n }\n groupBy: {\n args: Prisma.ApiKeyGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.ApiKeyGroupByOutputType>[]\n }\n count: {\n args: Prisma.ApiKeyCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.ApiKeyCountAggregateOutputType> | number\n }\n }\n }\n ApiKeyLog: {\n payload: Prisma.$ApiKeyLogPayload<ExtArgs>\n fields: Prisma.ApiKeyLogFieldRefs\n operations: {\n findUnique: {\n args: Prisma.ApiKeyLogFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.ApiKeyLogFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>\n }\n findFirst: {\n args: Prisma.ApiKeyLogFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.ApiKeyLogFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>\n }\n findMany: {\n args: Prisma.ApiKeyLogFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>[]\n }\n create: {\n args: Prisma.ApiKeyLogCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>\n }\n createMany: {\n args: Prisma.ApiKeyLogCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.ApiKeyLogCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>[]\n }\n delete: {\n args: Prisma.ApiKeyLogDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>\n }\n update: {\n args: Prisma.ApiKeyLogUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>\n }\n deleteMany: {\n args: Prisma.ApiKeyLogDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.ApiKeyLogUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.ApiKeyLogUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>[]\n }\n upsert: {\n args: Prisma.ApiKeyLogUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$ApiKeyLogPayload>\n }\n aggregate: {\n args: Prisma.ApiKeyLogAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateApiKeyLog>\n }\n groupBy: {\n args: Prisma.ApiKeyLogGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.ApiKeyLogGroupByOutputType>[]\n }\n count: {\n args: Prisma.ApiKeyLogCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.ApiKeyLogCountAggregateOutputType> | number\n }\n }\n }\n User: {\n payload: Prisma.$UserPayload<ExtArgs>\n fields: Prisma.UserFieldRefs\n operations: {\n findUnique: {\n args: Prisma.UserFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.UserFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>\n }\n findFirst: {\n args: Prisma.UserFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.UserFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>\n }\n findMany: {\n args: Prisma.UserFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>[]\n }\n create: {\n args: Prisma.UserCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>\n }\n createMany: {\n args: Prisma.UserCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.UserCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>[]\n }\n delete: {\n args: Prisma.UserDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>\n }\n update: {\n args: Prisma.UserUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>\n }\n deleteMany: {\n args: Prisma.UserDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.UserUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.UserUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>[]\n }\n upsert: {\n args: Prisma.UserUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserPayload>\n }\n aggregate: {\n args: Prisma.UserAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateUser>\n }\n groupBy: {\n args: Prisma.UserGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.UserGroupByOutputType>[]\n }\n count: {\n args: Prisma.UserCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.UserCountAggregateOutputType> | number\n }\n }\n }\n UserRepoAccess: {\n payload: Prisma.$UserRepoAccessPayload<ExtArgs>\n fields: Prisma.UserRepoAccessFieldRefs\n operations: {\n findUnique: {\n args: Prisma.UserRepoAccessFindUniqueArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload> | null\n }\n findUniqueOrThrow: {\n args: Prisma.UserRepoAccessFindUniqueOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>\n }\n findFirst: {\n args: Prisma.UserRepoAccessFindFirstArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload> | null\n }\n findFirstOrThrow: {\n args: Prisma.UserRepoAccessFindFirstOrThrowArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>\n }\n findMany: {\n args: Prisma.UserRepoAccessFindManyArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>[]\n }\n create: {\n args: Prisma.UserRepoAccessCreateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>\n }\n createMany: {\n args: Prisma.UserRepoAccessCreateManyArgs<ExtArgs>\n result: BatchPayload\n }\n createManyAndReturn: {\n args: Prisma.UserRepoAccessCreateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>[]\n }\n delete: {\n args: Prisma.UserRepoAccessDeleteArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>\n }\n update: {\n args: Prisma.UserRepoAccessUpdateArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>\n }\n deleteMany: {\n args: Prisma.UserRepoAccessDeleteManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateMany: {\n args: Prisma.UserRepoAccessUpdateManyArgs<ExtArgs>\n result: BatchPayload\n }\n updateManyAndReturn: {\n args: Prisma.UserRepoAccessUpdateManyAndReturnArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>[]\n }\n upsert: {\n args: Prisma.UserRepoAccessUpsertArgs<ExtArgs>\n result: runtime.Types.Utils.PayloadToResult<Prisma.$UserRepoAccessPayload>\n }\n aggregate: {\n args: Prisma.UserRepoAccessAggregateArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.AggregateUserRepoAccess>\n }\n groupBy: {\n args: Prisma.UserRepoAccessGroupByArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.UserRepoAccessGroupByOutputType>[]\n }\n count: {\n args: Prisma.UserRepoAccessCountArgs<ExtArgs>\n result: runtime.Types.Utils.Optional<Prisma.UserRepoAccessCountAggregateOutputType> | number\n }\n }\n }\n }\n} & {\n other: {\n payload: any\n operations: {\n $executeRaw: {\n args: [query: TemplateStringsArray | Sql, ...values: any[]],\n result: any\n }\n $executeRawUnsafe: {\n args: [query: string, ...values: any[]],\n result: any\n }\n $queryRaw: {\n args: [query: TemplateStringsArray | Sql, ...values: any[]],\n result: any\n }\n $queryRawUnsafe: {\n args: [query: string, ...values: any[]],\n result: any\n }\n }\n }\n}\n\n/**\n * Enums\n */\n\nexport const TransactionIsolationLevel = runtime.makeStrictEnum({\n ReadUncommitted: 'ReadUncommitted',\n ReadCommitted: 'ReadCommitted',\n RepeatableRead: 'RepeatableRead',\n Serializable: 'Serializable'\n} as const)\n\nexport type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof typeof TransactionIsolationLevel]\n\n\nexport const MemoryScalarFieldEnum = {\n id: 'id',\n orgId: 'orgId',\n repoId: 'repoId',\n scopeType: 'scopeType',\n memoryType: 'memoryType',\n visibility: 'visibility',\n status: 'status',\n text: 'text',\n summary: 'summary',\n tags: 'tags',\n sourceRefs: 'sourceRefs',\n confidence: 'confidence',\n ttlSeconds: 'ttlSeconds',\n supersedesId: 'supersedesId',\n version: 'version',\n deletedAt: 'deletedAt',\n deletedBy: 'deletedBy',\n createdAt: 'createdAt',\n updatedAt: 'updatedAt'\n} as const\n\nexport type MemoryScalarFieldEnum = (typeof MemoryScalarFieldEnum)[keyof typeof MemoryScalarFieldEnum]\n\n\nexport const MemoryEmbeddingScalarFieldEnum = {\n memoryId: 'memoryId',\n embedding: 'embedding',\n model: 'model',\n createdAt: 'createdAt'\n} as const\n\nexport type MemoryEmbeddingScalarFieldEnum = (typeof MemoryEmbeddingScalarFieldEnum)[keyof typeof MemoryEmbeddingScalarFieldEnum]\n\n\nexport const MemoryUsageScalarFieldEnum = {\n id: 'id',\n memoryId: 'memoryId',\n recalledAt: 'recalledAt',\n query: 'query',\n sessionId: 'sessionId'\n} as const\n\nexport type MemoryUsageScalarFieldEnum = (typeof MemoryUsageScalarFieldEnum)[keyof typeof MemoryUsageScalarFieldEnum]\n\n\nexport const MemoryLinkScalarFieldEnum = {\n id: 'id',\n sourceId: 'sourceId',\n targetId: 'targetId',\n linkType: 'linkType',\n metadata: 'metadata',\n createdAt: 'createdAt'\n} as const\n\nexport type MemoryLinkScalarFieldEnum = (typeof MemoryLinkScalarFieldEnum)[keyof typeof MemoryLinkScalarFieldEnum]\n\n\nexport const TombstoneScalarFieldEnum = {\n id: 'id',\n memoryId: 'memoryId',\n orgId: 'orgId',\n repoId: 'repoId',\n deletedAt: 'deletedAt',\n deletedBy: 'deletedBy',\n syncedAt: 'syncedAt',\n createdAt: 'createdAt'\n} as const\n\nexport type TombstoneScalarFieldEnum = (typeof TombstoneScalarFieldEnum)[keyof typeof TombstoneScalarFieldEnum]\n\n\nexport const ApiKeyScalarFieldEnum = {\n id: 'id',\n key: 'key',\n name: 'name',\n label: 'label',\n orgId: 'orgId',\n repoId: 'repoId',\n userId: 'userId',\n createdBy: 'createdBy',\n isActive: 'isActive',\n createdAt: 'createdAt',\n lastUsedAt: 'lastUsedAt'\n} as const\n\nexport type ApiKeyScalarFieldEnum = (typeof ApiKeyScalarFieldEnum)[keyof typeof ApiKeyScalarFieldEnum]\n\n\nexport const ApiKeyLogScalarFieldEnum = {\n id: 'id',\n apiKeyId: 'apiKeyId',\n operation: 'operation',\n memoryId: 'memoryId',\n orgId: 'orgId',\n repoId: 'repoId',\n query: 'query',\n metadata: 'metadata',\n createdAt: 'createdAt'\n} as const\n\nexport type ApiKeyLogScalarFieldEnum = (typeof ApiKeyLogScalarFieldEnum)[keyof typeof ApiKeyLogScalarFieldEnum]\n\n\nexport const UserScalarFieldEnum = {\n id: 'id',\n githubId: 'githubId',\n githubLogin: 'githubLogin',\n name: 'name',\n email: 'email',\n avatarUrl: 'avatarUrl',\n isAdmin: 'isAdmin',\n createdAt: 'createdAt',\n updatedAt: 'updatedAt'\n} as const\n\nexport type UserScalarFieldEnum = (typeof UserScalarFieldEnum)[keyof typeof UserScalarFieldEnum]\n\n\nexport const UserRepoAccessScalarFieldEnum = {\n id: 'id',\n userId: 'userId',\n orgId: 'orgId',\n repoId: 'repoId',\n permission: 'permission',\n grantedAt: 'grantedAt',\n grantedBy: 'grantedBy'\n} as const\n\nexport type UserRepoAccessScalarFieldEnum = (typeof UserRepoAccessScalarFieldEnum)[keyof typeof UserRepoAccessScalarFieldEnum]\n\n\nexport const SortOrder = {\n asc: 'asc',\n desc: 'desc'\n} as const\n\nexport type SortOrder = (typeof SortOrder)[keyof typeof SortOrder]\n\n\nexport const NullableJsonNullValueInput = {\n DbNull: DbNull,\n JsonNull: JsonNull\n} as const\n\nexport type NullableJsonNullValueInput = (typeof NullableJsonNullValueInput)[keyof typeof NullableJsonNullValueInput]\n\n\nexport const QueryMode = {\n default: 'default',\n insensitive: 'insensitive'\n} as const\n\nexport type QueryMode = (typeof QueryMode)[keyof typeof QueryMode]\n\n\nexport const JsonNullValueFilter = {\n DbNull: DbNull,\n JsonNull: JsonNull,\n AnyNull: AnyNull\n} as const\n\nexport type JsonNullValueFilter = (typeof JsonNullValueFilter)[keyof typeof JsonNullValueFilter]\n\n\nexport const NullsOrder = {\n first: 'first',\n last: 'last'\n} as const\n\nexport type NullsOrder = (typeof NullsOrder)[keyof typeof NullsOrder]\n\n\n\n/**\n * Field references\n */\n\n\n/**\n * Reference to a field of type 'String'\n */\nexport type StringFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'String'>\n \n\n\n/**\n * Reference to a field of type 'String[]'\n */\nexport type ListStringFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'String[]'>\n \n\n\n/**\n * Reference to a field of type 'Json'\n */\nexport type JsonFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Json'>\n \n\n\n/**\n * Reference to a field of type 'QueryMode'\n */\nexport type EnumQueryModeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'QueryMode'>\n \n\n\n/**\n * Reference to a field of type 'Float'\n */\nexport type FloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float'>\n \n\n\n/**\n * Reference to a field of type 'Float[]'\n */\nexport type ListFloatFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Float[]'>\n \n\n\n/**\n * Reference to a field of type 'Int'\n */\nexport type IntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Int'>\n \n\n\n/**\n * Reference to a field of type 'Int[]'\n */\nexport type ListIntFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Int[]'>\n \n\n\n/**\n * Reference to a field of type 'DateTime'\n */\nexport type DateTimeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'DateTime'>\n \n\n\n/**\n * Reference to a field of type 'DateTime[]'\n */\nexport type ListDateTimeFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'DateTime[]'>\n \n\n\n/**\n * Reference to a field of type 'Bytes'\n */\nexport type BytesFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Bytes'>\n \n\n\n/**\n * Reference to a field of type 'Bytes[]'\n */\nexport type ListBytesFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Bytes[]'>\n \n\n\n/**\n * Reference to a field of type 'Boolean'\n */\nexport type BooleanFieldRefInput<$PrismaModel> = FieldRefInputType<$PrismaModel, 'Boolean'>\n \n\n/**\n * Batch Payload for updateMany & deleteMany & createMany\n */\nexport type BatchPayload = {\n count: number\n}\n\nexport const defineExtension = runtime.Extensions.defineExtension as unknown as runtime.Types.Extensions.ExtendsHook<\"define\", TypeMapCb, runtime.Types.Extensions.DefaultArgs>\nexport type DefaultPrismaClient = PrismaClient\nexport type ErrorFormat = 'pretty' | 'colorless' | 'minimal'\nexport type PrismaClientOptions = ({\n /**\n * Instance of a Driver Adapter, e.g., like one provided by `@prisma/adapter-pg`.\n */\n adapter: runtime.SqlDriverAdapterFactory\n accelerateUrl?: never\n} | {\n /**\n * Prisma Accelerate URL allowing the client to connect through Accelerate instead of a direct database.\n */\n accelerateUrl: string\n adapter?: never\n}) & {\n /**\n * @default \"colorless\"\n */\n errorFormat?: ErrorFormat\n /**\n * @example\n * ```\n * // Shorthand for `emit: 'stdout'`\n * log: ['query', 'info', 'warn', 'error']\n * \n * // Emit as events only\n * log: [\n * { emit: 'event', level: 'query' },\n * { emit: 'event', level: 'info' },\n * { emit: 'event', level: 'warn' }\n * { emit: 'event', level: 'error' }\n * ]\n * \n * / Emit as events and log to stdout\n * og: [\n * { emit: 'stdout', level: 'query' },\n * { emit: 'stdout', level: 'info' },\n * { emit: 'stdout', level: 'warn' }\n * { emit: 'stdout', level: 'error' }\n * \n * ```\n * Read more in our [docs](https://pris.ly/d/logging).\n */\n log?: (LogLevel | LogDefinition)[]\n /**\n * The default values for transactionOptions\n * maxWait ?= 2000\n * timeout ?= 5000\n */\n transactionOptions?: {\n maxWait?: number\n timeout?: number\n isolationLevel?: TransactionIsolationLevel\n }\n /**\n * Global configuration for omitting model fields by default.\n * \n * @example\n * ```\n * const prisma = new PrismaClient({\n * omit: {\n * user: {\n * password: true\n * }\n * }\n * })\n * ```\n */\n omit?: GlobalOmitConfig\n /**\n * SQL commenter plugins that add metadata to SQL queries as comments.\n * Comments follow the sqlcommenter format: https://google.github.io/sqlcommenter/\n * \n * @example\n * ```\n * const prisma = new PrismaClient({\n * adapter,\n * comments: [\n * traceContext(),\n * queryInsights(),\n * ],\n * })\n * ```\n */\n comments?: runtime.SqlCommenterPlugin[]\n /**\n * Optional maximum size for the query plan cache. If not provided, a default size will be used.\n * A value of `0` can be used to disable the cache entirely. A higher cache size can improve\n * performance for applications that execute a large number of unique queries, while a smaller\n * cache size can reduce memory usage.\n * \n * @example\n * ```\n * const prisma = new PrismaClient({\n * adapter,\n * queryPlanCacheMaxSize: 100,\n * })\n * ```\n */\n queryPlanCacheMaxSize?: number\n}\nexport type GlobalOmitConfig = {\n memory?: Prisma.MemoryOmit\n memoryEmbedding?: Prisma.MemoryEmbeddingOmit\n memoryUsage?: Prisma.MemoryUsageOmit\n memoryLink?: Prisma.MemoryLinkOmit\n tombstone?: Prisma.TombstoneOmit\n apiKey?: Prisma.ApiKeyOmit\n apiKeyLog?: Prisma.ApiKeyLogOmit\n user?: Prisma.UserOmit\n userRepoAccess?: Prisma.UserRepoAccessOmit\n}\n\n/* Types for Logging */\nexport type LogLevel = 'info' | 'query' | 'warn' | 'error'\nexport type LogDefinition = {\n level: LogLevel\n emit: 'stdout' | 'event'\n}\n\nexport type CheckIsLogLevel<T> = T extends LogLevel ? T : never;\n\nexport type GetLogType<T> = CheckIsLogLevel<\n T extends LogDefinition ? T['level'] : T\n>;\n\nexport type GetEvents<T extends any[]> = T extends Array<LogLevel | LogDefinition>\n ? GetLogType<T[number]>\n : never;\n\nexport type QueryEvent = {\n timestamp: Date\n query: string\n params: string\n duration: number\n target: string\n}\n\nexport type LogEvent = {\n timestamp: Date\n message: string\n target: string\n}\n/* End Types for Logging */\n\n\nexport type PrismaAction =\n | 'findUnique'\n | 'findUniqueOrThrow'\n | 'findMany'\n | 'findFirst'\n | 'findFirstOrThrow'\n | 'create'\n | 'createMany'\n | 'createManyAndReturn'\n | 'update'\n | 'updateMany'\n | 'updateManyAndReturn'\n | 'upsert'\n | 'delete'\n | 'deleteMany'\n | 'executeRaw'\n | 'queryRaw'\n | 'aggregate'\n | 'count'\n | 'runCommandRaw'\n | 'findRaw'\n | 'groupBy'\n\n/**\n * `PrismaClient` proxy available in interactive transactions.\n */\nexport type TransactionClient = Omit<DefaultPrismaClient, runtime.ITXClientDenyList>\n\n","import { PrismaClient } from \"./generated/prisma/client.js\";\nimport { PrismaPg } from \"@prisma/adapter-pg\";\nimport type {\n Memory,\n MemoryLink,\n MemoryType,\n CreateMemoryInput,\n CreateLinkInput,\n LinkQuery,\n RecallQuery,\n RecallResult,\n ListQuery,\n StoreStats,\n Tombstone,\n DeleteMemoryInput,\n FindSimilarQuery,\n ConsolidateMemoriesInput,\n ConsolidateMemoriesResult,\n} from \"unforgit-shared\";\nimport { computeCompositeScore, computeHybridScore } from \"unforgit-core\";\nimport {\n applyLifecycleDefaults,\n computeUsageBoost,\n isMemoryExpired,\n} from \"unforgit-core\";\nimport {\n generateEmbedding,\n embeddingToPgVector,\n serializeEmbedding,\n deserializeEmbedding,\n isOpenAIConfigured,\n type EmbeddingConfig,\n} from \"unforgit-core\";\n\nfunction prismaRowToMemory(row: Record<string, unknown>): Memory {\n return {\n id: row.id as string,\n orgId: row.orgId as string,\n repoId: row.repoId as string,\n scopeType: (row.scopeType as Memory[\"scopeType\"]) ?? \"repo\",\n memoryType: row.memoryType as Memory[\"memoryType\"],\n visibility: row.visibility as Memory[\"visibility\"],\n status: row.status as Memory[\"status\"],\n text: row.text as string,\n summary: (row.summary as string) ?? undefined,\n tags: (row.tags as string[]) ?? [],\n sourceRefs: row.sourceRefs as Record<string, unknown> | undefined,\n confidence: (row.confidence as number) ?? undefined,\n ttlSeconds: (row.ttlSeconds as number) ?? undefined,\n supersedesId: (row.supersedesId as string) ?? undefined,\n version: (row.version as number) ?? 1,\n deletedAt: row.deletedAt ? new Date(row.deletedAt as string) : undefined,\n deletedBy: (row.deletedBy as string) ?? undefined,\n createdAt: new Date(row.createdAt as string),\n updatedAt: new Date(row.updatedAt as string),\n };\n}\n\nfunction prismaRowToTombstone(row: Record<string, unknown>): Tombstone {\n return {\n id: row.id as string,\n memoryId: row.memoryId as string,\n orgId: row.orgId as string,\n repoId: row.repoId as string,\n deletedAt: new Date(row.deletedAt as string),\n deletedBy: (row.deletedBy as string) ?? undefined,\n syncedAt: row.syncedAt ? new Date(row.syncedAt as string) : undefined,\n };\n}\n\nfunction filterExpiredMemories<T extends Pick<Memory, \"createdAt\" | \"ttlSeconds\" | \"status\">>(\n memories: T[],\n includeExpired?: boolean,\n): T[] {\n if (includeExpired) {\n return memories;\n }\n\n return memories.filter((memory) => !isMemoryExpired(memory));\n}\n\nfunction isMissingTableError(error: unknown, tableName: string): boolean {\n if (!error || typeof error !== \"object\") {\n return false;\n }\n\n const code = \"code\" in error ? error.code : undefined;\n const message = \"message\" in error ? String(error.message) : \"\";\n const unqualifiedTableName = tableName.split(\".\").at(-1) ?? tableName;\n\n return code === \"P2021\" && (\n message.includes(`\\`${tableName}\\``) ||\n message.includes(`\\`${unqualifiedTableName}\\``)\n );\n}\n\nexport function safeLogIdentifier(value: string): string {\n const bounded = value.length > 64 ? `${value.slice(0, 64)}...` : value;\n return bounded.replace(/[\\r\\n\\t]/g, \"?\");\n}\n\nexport interface RemoteStoreOptions {\n autoEmbeddingEnabled?: boolean;\n}\n\nexport class RemoteStore {\n private prisma: PrismaClient;\n private autoEmbeddingEnabled: boolean;\n\n constructor(connectionString: string, options: RemoteStoreOptions = {}) {\n const adapter = new PrismaPg({ connectionString });\n this.prisma = new PrismaClient({ adapter });\n this.autoEmbeddingEnabled = options.autoEmbeddingEnabled ??\n process.env.AUTO_EMBEDDING_ENABLED === \"true\";\n }\n\n async store(input: CreateMemoryInput): Promise<Memory> {\n const resolvedInput = applyLifecycleDefaults(input);\n const visibility =\n resolvedInput.visibility === \"auto\" || !resolvedInput.visibility\n ? \"repo\"\n : resolvedInput.visibility;\n\n const normalizedOrgId = resolvedInput.orgId.toLowerCase();\n const normalizedRepoId = resolvedInput.repoId.toLowerCase();\n\n const data: Record<string, unknown> = {\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n memoryType: resolvedInput.memoryType,\n visibility,\n text: resolvedInput.text,\n summary: resolvedInput.summary,\n tags: resolvedInput.tags ?? [],\n sourceRefs: (resolvedInput.sourceRefs as Record<string, string>) ?? undefined,\n confidence: resolvedInput.confidence,\n ttlSeconds: resolvedInput.ttlSeconds,\n };\n\n let memory: Memory;\n\n if (resolvedInput.id) {\n const row = await this.prisma.memory.upsert({\n where: { id: resolvedInput.id },\n create: {\n id: resolvedInput.id,\n ...data,\n } as Parameters<typeof this.prisma.memory.create>[0][\"data\"],\n update: {\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n memoryType: resolvedInput.memoryType,\n visibility,\n text: resolvedInput.text,\n summary: resolvedInput.summary,\n tags: resolvedInput.tags ?? [],\n sourceRefs: (resolvedInput.sourceRefs as Record<string, string>) ?? undefined,\n confidence: resolvedInput.confidence,\n ttlSeconds: resolvedInput.ttlSeconds,\n },\n });\n\n memory = prismaRowToMemory(row as unknown as Record<string, unknown>);\n } else {\n const row = await this.prisma.memory.create({\n data: data as Parameters<typeof this.prisma.memory.create>[0][\"data\"],\n });\n\n memory = prismaRowToMemory(row as unknown as Record<string, unknown>);\n }\n\n if (this.autoEmbeddingEnabled && isOpenAIConfigured()) {\n this.generateAndStoreEmbedding(memory.id, memory.text).catch((err) => {\n console.error(`Auto-embedding failed for ${memory.id}:`, err);\n });\n }\n\n return memory;\n }\n\n async getById(id: string): Promise<Memory | undefined> {\n const row = await this.prisma.memory.findUnique({ where: { id } });\n return row\n ? prismaRowToMemory(row as unknown as Record<string, unknown>)\n : undefined;\n }\n\n async recall(query: RecallQuery): Promise<RecallResult[]> {\n const k = query.k ?? 10;\n\n const where: Record<string, unknown> = {\n orgId: query.orgId,\n repoId: query.repoId,\n };\n\n if (!query.includeDeprecated) {\n where.status = \"active\";\n }\n\n if (query.types && query.types.length > 0) {\n where.memoryType = { in: query.types };\n }\n\n if (query.tags && query.tags.length > 0) {\n where.tags = { hasSome: query.tags };\n }\n\n if (query.timeRange) {\n const createdAt: Record<string, Date> = {};\n if (query.timeRange.from) createdAt.gte = query.timeRange.from;\n if (query.timeRange.to) createdAt.lte = query.timeRange.to;\n if (Object.keys(createdAt).length > 0) where.createdAt = createdAt;\n }\n\n const usageStats = await this.getUsageStats(query.orgId, query.repoId);\n const usageMap = new Map(usageStats.map((stat) => [stat.memoryId, stat]));\n\n const sanitizedQuery = query.query.replace(/[^\\w\\s]/g, \" \").trim();\n\n if (sanitizedQuery) {\n const ftsResults = await this.prisma.$queryRawUnsafe<\n Array<Record<string, unknown>>\n >(\n `SELECT m.*,\n ts_rank(to_tsvector('english', m.text || ' ' || coalesce(m.summary, '')),\n plainto_tsquery('english', $1)) AS fts_rank\n FROM memories m\n WHERE to_tsvector('english', m.text || ' ' || coalesce(m.summary, ''))\n @@ plainto_tsquery('english', $1)\n AND m.org_id = $2\n AND m.repo_id = $3\n AND m.status = $4\n AND (\n m.status != 'active'\n OR m.ttl_seconds IS NULL\n OR m.created_at + (m.ttl_seconds * INTERVAL '1 second') >= NOW()\n )\n ORDER BY fts_rank DESC\n LIMIT $5`,\n sanitizedQuery,\n query.orgId,\n query.repoId,\n query.includeDeprecated ? \"active\" : \"active\",\n k * 2,\n );\n\n return ftsResults.map((row) => {\n const textScore = Math.min(\n 1,\n (row.fts_rank as number) * 2,\n );\n const usage = usageMap.get(row.id as string);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n return {\n id: row.id as string,\n memoryType: row.memory_type as Memory[\"memoryType\"],\n text: row.text as string,\n summary: (row.summary as string) ?? undefined,\n tags: (row.tags as string[]) ?? [],\n sourceRefs: row.source_refs as Record<string, unknown> | undefined,\n score: computeCompositeScore(\n textScore,\n new Date(row.created_at as string),\n row.confidence as number | undefined,\n usageBoost,\n ),\n source: \"remote\" as const,\n status: row.status as Memory[\"status\"],\n supersedesId: (row.supersedes_id as string) ?? undefined,\n };\n });\n }\n\n const rows = await this.prisma.memory.findMany({\n where,\n orderBy: { createdAt: \"desc\" },\n });\n\n return filterExpiredMemories(\n rows.map((row) =>\n prismaRowToMemory(row as unknown as Record<string, unknown>),\n ),\n query.includeExpired,\n )\n .slice(0, k)\n .map((memory) => {\n const usage = usageMap.get(memory.id);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n\n return {\n id: memory.id,\n memoryType: memory.memoryType,\n text: memory.text,\n summary: memory.summary,\n tags: memory.tags,\n sourceRefs: memory.sourceRefs,\n score: computeCompositeScore(\n 0.5,\n memory.createdAt,\n memory.confidence ?? undefined,\n usageBoost,\n ),\n source: \"remote\" as const,\n status: memory.status,\n supersedesId: memory.supersedesId ?? undefined,\n };\n });\n }\n\n async list(query: ListQuery): Promise<Memory[]> {\n const where: Record<string, unknown> = {\n orgId: query.orgId,\n repoId: query.repoId,\n };\n\n if (query.types && query.types.length > 0) {\n where.memoryType = { in: query.types };\n }\n if (query.status && query.status.length > 0) {\n where.status = { in: query.status };\n }\n if (query.visibility && query.visibility.length > 0) {\n where.visibility = { in: query.visibility };\n }\n if (query.tags && query.tags.length > 0) {\n where.tags = { hasSome: query.tags };\n }\n if (query.search) {\n where.text = { contains: query.search, mode: \"insensitive\" };\n }\n\n const sortField =\n query.sortBy === \"updatedAt\"\n ? \"updatedAt\"\n : query.sortBy === \"confidence\"\n ? \"confidence\"\n : \"createdAt\";\n\n const rows = await this.prisma.memory.findMany({\n where,\n orderBy: { [sortField]: query.sortOrder ?? \"desc\" },\n });\n\n const filtered = filterExpiredMemories(\n rows.map((r) =>\n prismaRowToMemory(r as unknown as Record<string, unknown>),\n ),\n query.includeExpired,\n );\n const offset = query.offset ?? 0;\n const limit = query.limit ?? 50;\n return filtered.slice(offset, offset + limit);\n }\n\n async count(query: ListQuery): Promise<number> {\n const where: Record<string, unknown> = {\n orgId: query.orgId,\n repoId: query.repoId,\n };\n\n if (query.types && query.types.length > 0) {\n where.memoryType = { in: query.types };\n }\n if (query.status && query.status.length > 0) {\n where.status = { in: query.status };\n }\n if (query.visibility && query.visibility.length > 0) {\n where.visibility = { in: query.visibility };\n }\n if (query.tags && query.tags.length > 0) {\n where.tags = { hasSome: query.tags };\n }\n if (query.search) {\n where.text = { contains: query.search, mode: \"insensitive\" };\n }\n\n const rows = await this.prisma.memory.findMany({\n where,\n select: {\n id: true,\n status: true,\n ttlSeconds: true,\n createdAt: true,\n },\n });\n\n return filterExpiredMemories(\n rows.map((row) => ({\n id: row.id,\n status: row.status as Memory[\"status\"],\n ttlSeconds: row.ttlSeconds ?? undefined,\n createdAt: row.createdAt,\n })),\n query.includeExpired,\n ).length;\n }\n\n async stats(orgId: string, repoId: string): Promise<StoreStats> {\n const rows = await this.prisma.$queryRawUnsafe<\n Array<{\n memory_type: string;\n status: string;\n visibility: string;\n cnt: bigint;\n }>\n >(\n `SELECT memory_type, status, visibility, COUNT(*) as cnt\n FROM memories WHERE org_id = $1 AND repo_id = $2\n GROUP BY memory_type, status, visibility`,\n orgId,\n repoId,\n );\n\n const stats: StoreStats = {\n total: 0,\n byType: { episodic: 0, semantic: 0, procedural: 0 },\n byStatus: { active: 0, deprecated: 0, superseded: 0, deleted: 0 },\n byVisibility: { private: 0, repo: 0 },\n };\n\n for (const row of rows) {\n const count = Number(row.cnt);\n stats.total += count;\n if (row.memory_type in stats.byType) {\n stats.byType[row.memory_type as keyof typeof stats.byType] += count;\n }\n if (row.status in stats.byStatus) {\n stats.byStatus[row.status as keyof typeof stats.byStatus] += count;\n }\n if (row.visibility in stats.byVisibility) {\n stats.byVisibility[row.visibility] += count;\n }\n }\n\n return stats;\n }\n\n async deprecate(id: string, reason?: string): Promise<boolean> {\n try {\n const existing = await this.prisma.memory.findUnique({ where: { id } });\n if (!existing) return false;\n\n const sourceRefs = (existing.sourceRefs as Record<string, unknown>) ?? {};\n if (reason) sourceRefs.deprecation_reason = reason;\n\n await this.prisma.memory.update({\n where: { id },\n data: {\n status: \"deprecated\",\n sourceRefs: Object.keys(sourceRefs).length > 0 ? (sourceRefs as Record<string, string>) : undefined,\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async supersede(oldId: string, newId: string): Promise<boolean> {\n try {\n await this.prisma.memory.update({\n where: { id: oldId },\n data: {\n status: \"superseded\",\n supersedesId: newId,\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async pin(id: string): Promise<boolean> {\n try {\n const existing = await this.prisma.memory.findUnique({ where: { id } });\n if (!existing) return false;\n\n const tags = existing.tags.includes(\"pinned\")\n ? existing.tags\n : [...existing.tags, \"pinned\"];\n\n await this.prisma.memory.update({\n where: { id },\n data: { tags },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async expireExpiredMemories(\n orgId?: string,\n repoId?: string,\n deletedBy = \"system:ttl-expiry\",\n ): Promise<number> {\n const where: Record<string, unknown> = {\n status: \"active\",\n };\n\n if (orgId) {\n where.orgId = orgId;\n }\n\n if (repoId) {\n where.repoId = repoId;\n }\n\n const rows = await this.prisma.memory.findMany({\n where,\n select: {\n id: true,\n status: true,\n ttlSeconds: true,\n createdAt: true,\n },\n });\n\n let expired = 0;\n for (const row of rows) {\n if (\n !isMemoryExpired({\n status: row.status as Memory[\"status\"],\n ttlSeconds: row.ttlSeconds ?? undefined,\n createdAt: row.createdAt,\n })\n ) {\n continue;\n }\n\n if (await this.softDelete({ id: row.id, deletedBy })) {\n expired += 1;\n }\n }\n\n return expired;\n }\n\n async link(input: CreateLinkInput): Promise<MemoryLink> {\n const row = await this.prisma.memoryLink.upsert({\n where: {\n sourceId_targetId_linkType: {\n sourceId: input.sourceId,\n targetId: input.targetId,\n linkType: input.linkType,\n },\n },\n create: {\n sourceId: input.sourceId,\n targetId: input.targetId,\n linkType: input.linkType,\n metadata: input.metadata as Record<string, string> | undefined,\n },\n update: {\n metadata: input.metadata as Record<string, string> | undefined,\n },\n });\n\n return {\n id: row.id,\n sourceId: row.sourceId,\n targetId: row.targetId,\n linkType: row.linkType as MemoryLink[\"linkType\"],\n metadata: row.metadata as Record<string, unknown> | undefined,\n createdAt: row.createdAt,\n };\n }\n\n async unlink(\n sourceId: string,\n targetId: string,\n linkType: string,\n ): Promise<boolean> {\n try {\n await this.prisma.memoryLink.delete({\n where: {\n sourceId_targetId_linkType: { sourceId, targetId, linkType },\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async getLinks(query: LinkQuery): Promise<MemoryLink[]> {\n const where: Record<string, unknown> = {\n OR: [\n { sourceId: query.memoryId },\n { targetId: query.memoryId },\n ],\n };\n\n if (query.linkType) {\n where.linkType = query.linkType;\n }\n\n const rows = await this.prisma.memoryLink.findMany({\n where,\n orderBy: { createdAt: \"desc\" },\n });\n\n return rows.map((row) => ({\n id: row.id,\n sourceId: row.sourceId,\n targetId: row.targetId,\n linkType: row.linkType as MemoryLink[\"linkType\"],\n metadata: row.metadata as Record<string, unknown> | undefined,\n createdAt: row.createdAt,\n }));\n }\n\n async getAllLinks(orgId: string, repoId: string): Promise<MemoryLink[]> {\n const rows = await this.prisma.memoryLink.findMany({\n where: {\n source: { orgId, repoId },\n },\n orderBy: { createdAt: \"desc\" },\n });\n\n return rows.map((row) => ({\n id: row.id,\n sourceId: row.sourceId,\n targetId: row.targetId,\n linkType: row.linkType as MemoryLink[\"linkType\"],\n metadata: row.metadata as Record<string, unknown> | undefined,\n createdAt: row.createdAt,\n }));\n }\n\n async getLinkedMemories(\n memoryId: string,\n linkType?: string,\n ): Promise<Memory[]> {\n const linkWhere: Record<string, unknown> = {\n OR: [{ sourceId: memoryId }, { targetId: memoryId }],\n };\n if (linkType) linkWhere.linkType = linkType;\n\n const links = await this.prisma.memoryLink.findMany({\n where: linkWhere,\n include: { source: true, target: true },\n });\n\n const seen = new Set<string>();\n const memories: Memory[] = [];\n\n for (const link of links) {\n const other =\n link.sourceId === memoryId ? link.target : link.source;\n if (!seen.has(other.id)) {\n seen.add(other.id);\n memories.push(\n prismaRowToMemory(other as unknown as Record<string, unknown>),\n );\n }\n }\n\n return memories;\n }\n\n async softDelete(input: DeleteMemoryInput): Promise<boolean> {\n try {\n const existing = await this.prisma.memory.findUnique({ where: { id: input.id } });\n if (!existing) return false;\n\n const newVersion = (existing.version ?? 1) + 1;\n\n await this.prisma.$transaction([\n this.prisma.memory.update({\n where: { id: input.id },\n data: {\n status: \"deleted\",\n deletedAt: new Date(),\n deletedBy: input.deletedBy,\n version: newVersion,\n },\n }),\n this.prisma.tombstone.upsert({\n where: { memoryId: input.id },\n create: {\n memoryId: input.id,\n orgId: existing.orgId,\n repoId: existing.repoId,\n deletedAt: new Date(),\n deletedBy: input.deletedBy,\n },\n update: {\n deletedAt: new Date(),\n deletedBy: input.deletedBy,\n syncedAt: null,\n },\n }),\n ]);\n\n return true;\n } catch {\n return false;\n }\n }\n\n async hardDelete(id: string): Promise<boolean> {\n try {\n await this.prisma.memory.delete({ where: { id } });\n return true;\n } catch {\n return false;\n }\n }\n\n async restore(id: string): Promise<boolean> {\n try {\n const result = await this.prisma.$transaction([\n this.prisma.memory.update({\n where: { id, status: \"deleted\" },\n data: {\n status: \"active\",\n deletedAt: null,\n deletedBy: null,\n version: { increment: 1 },\n },\n }),\n this.prisma.tombstone.delete({\n where: { memoryId: id },\n }),\n ]);\n return result[0] !== null;\n } catch {\n return false;\n }\n }\n\n async getTombstones(orgId: string, repoId: string, sinceSyncedAt?: Date): Promise<Tombstone[]> {\n const where: Record<string, unknown> = { orgId, repoId };\n\n if (sinceSyncedAt) {\n where.OR = [\n { syncedAt: null },\n { syncedAt: { gt: sinceSyncedAt } },\n ];\n } else {\n where.syncedAt = null;\n }\n\n const rows = await this.prisma.tombstone.findMany({\n where,\n orderBy: { deletedAt: \"asc\" },\n });\n\n return rows.map((r) => prismaRowToTombstone(r as unknown as Record<string, unknown>));\n }\n\n async getUnsyncedTombstones(orgId: string, repoId: string): Promise<Tombstone[]> {\n const rows = await this.prisma.tombstone.findMany({\n where: { orgId, repoId, syncedAt: null },\n orderBy: { deletedAt: \"asc\" },\n });\n\n return rows.map((r) => prismaRowToTombstone(r as unknown as Record<string, unknown>));\n }\n\n async markTombstoneSynced(memoryId: string): Promise<boolean> {\n try {\n await this.prisma.tombstone.update({\n where: { memoryId },\n data: { syncedAt: new Date() },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async applyTombstone(tombstone: Tombstone): Promise<boolean> {\n try {\n const existing = await this.prisma.memory.findUnique({ where: { id: tombstone.memoryId } });\n\n if (!existing) {\n await this.prisma.tombstone.upsert({\n where: { memoryId: tombstone.memoryId },\n create: {\n memoryId: tombstone.memoryId,\n orgId: tombstone.orgId,\n repoId: tombstone.repoId,\n deletedAt: tombstone.deletedAt,\n deletedBy: tombstone.deletedBy,\n syncedAt: new Date(),\n },\n update: {\n deletedAt: tombstone.deletedAt,\n deletedBy: tombstone.deletedBy,\n syncedAt: new Date(),\n },\n });\n return true;\n }\n\n return this.softDelete({\n id: tombstone.memoryId,\n deletedBy: tombstone.deletedBy,\n });\n } catch {\n return false;\n }\n }\n\n async getModifiedSince(orgId: string, repoId: string, since: Date): Promise<Memory[]> {\n const rows = await this.prisma.memory.findMany({\n where: {\n orgId,\n repoId,\n updatedAt: { gt: since },\n },\n orderBy: { updatedAt: \"asc\" },\n });\n\n return rows.map((r) => prismaRowToMemory(r as unknown as Record<string, unknown>));\n }\n\n async upsertFromLocal(memory: Memory): Promise<{ action: \"created\" | \"updated\" | \"skipped\"; conflict: boolean }> {\n const existing = await this.prisma.memory.findUnique({ where: { id: memory.id } });\n\n const normalizedOrgId = memory.orgId.toLowerCase();\n const normalizedRepoId = memory.repoId.toLowerCase();\n\n if (!existing) {\n await this.prisma.memory.create({\n data: {\n id: memory.id,\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n scopeType: memory.scopeType ?? \"repo\",\n memoryType: memory.memoryType,\n visibility: memory.visibility,\n status: memory.status,\n text: memory.text,\n summary: memory.summary,\n tags: memory.tags ?? [],\n sourceRefs: memory.sourceRefs as Record<string, string> | undefined,\n confidence: memory.confidence,\n ttlSeconds: memory.ttlSeconds,\n supersedesId: memory.supersedesId,\n version: memory.version ?? 1,\n deletedAt: memory.deletedAt,\n deletedBy: memory.deletedBy,\n createdAt: memory.createdAt,\n },\n });\n return { action: \"created\", conflict: false };\n }\n\n const remoteVersion = existing.version ?? 1;\n const localVersion = memory.version ?? 1;\n\n if (localVersion <= remoteVersion) {\n if (memory.updatedAt <= existing.updatedAt) {\n return { action: \"skipped\", conflict: false };\n }\n }\n\n const hasConflict = localVersion !== remoteVersion && existing.updatedAt > memory.updatedAt;\n\n await this.prisma.memory.update({\n where: { id: memory.id },\n data: {\n memoryType: memory.memoryType,\n visibility: memory.visibility,\n status: memory.status,\n text: memory.text,\n summary: memory.summary,\n tags: memory.tags ?? [],\n sourceRefs: memory.sourceRefs as Record<string, string> | undefined,\n confidence: memory.confidence,\n ttlSeconds: memory.ttlSeconds,\n supersedesId: memory.supersedesId,\n version: Math.max(remoteVersion, localVersion) + 1,\n deletedAt: memory.deletedAt,\n deletedBy: memory.deletedBy,\n },\n });\n\n return { action: \"updated\", conflict: hasConflict };\n }\n\n async disconnect(): Promise<void> {\n await this.prisma.$disconnect();\n }\n\n async validateApiKey(key: string): Promise<{ id: string; orgId: string; name: string } | null> {\n const apiKey = await this.prisma.apiKey.findUnique({\n where: { key },\n });\n\n if (!apiKey || !apiKey.isActive) {\n return null;\n }\n\n await this.prisma.apiKey.update({\n where: { id: apiKey.id },\n data: { lastUsedAt: new Date() },\n });\n\n return {\n id: apiKey.id,\n orgId: apiKey.orgId,\n name: apiKey.name,\n };\n }\n\n async createApiKey(name: string, orgId: string, label?: string): Promise<{ id: string; key: string; name: string; orgId: string; label: string | null }> {\n const key = `hk_${crypto.randomUUID().replace(/-/g, \"\")}`;\n const normalizedOrgId = orgId.toLowerCase();\n\n const apiKey = await this.prisma.apiKey.create({\n data: {\n key,\n name,\n orgId: normalizedOrgId,\n label: label ?? null,\n },\n });\n\n return {\n id: apiKey.id,\n key: apiKey.key,\n name: apiKey.name,\n orgId: apiKey.orgId,\n label: apiKey.label,\n };\n }\n\n async listApiKeys(orgId?: string): Promise<Array<{ id: string; key: string; name: string; label: string | null; orgId: string; isActive: boolean; createdAt: Date; lastUsedAt: Date | null }>> {\n const where = orgId ? { orgId } : {};\n\n const keys = await this.prisma.apiKey.findMany({\n where,\n orderBy: { createdAt: \"desc\" },\n select: {\n id: true,\n key: true,\n name: true,\n label: true,\n orgId: true,\n isActive: true,\n createdAt: true,\n lastUsedAt: true,\n },\n });\n\n return keys;\n }\n\n async revokeApiKey(id: string): Promise<boolean> {\n try {\n await this.prisma.apiKey.update({\n where: { id },\n data: { isActive: false },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async toggleApiKey(id: string): Promise<{ isActive: boolean } | null> {\n try {\n const existing = await this.prisma.apiKey.findUnique({ where: { id } });\n if (!existing) return null;\n\n const updated = await this.prisma.apiKey.update({\n where: { id },\n data: { isActive: !existing.isActive },\n });\n\n return { isActive: updated.isActive };\n } catch {\n return null;\n }\n }\n\n async updateApiKeyLabel(id: string, label: string): Promise<{ label: string | null } | null> {\n try {\n const updated = await this.prisma.apiKey.update({\n where: { id },\n data: { label: label.trim() || null },\n });\n\n return { label: updated.label };\n } catch {\n return null;\n }\n }\n\n async deleteApiKey(id: string): Promise<boolean> {\n try {\n await this.prisma.apiKey.delete({ where: { id } });\n return true;\n } catch {\n return false;\n }\n }\n\n async storeEmbedding(\n memoryId: string,\n embedding: number[],\n model: string\n ): Promise<void> {\n const embeddingBytes = Buffer.from(serializeEmbedding(embedding));\n const vectorStr = embeddingToPgVector(embedding);\n\n await this.prisma.$executeRaw`\n INSERT INTO memory_embeddings (memory_id, embedding, embedding_vector, model, created_at)\n VALUES (${memoryId}::uuid, ${embeddingBytes}, ${vectorStr}::vector, ${model}, NOW())\n ON CONFLICT (memory_id) DO UPDATE SET\n embedding = ${embeddingBytes},\n embedding_vector = ${vectorStr}::vector,\n model = ${model},\n created_at = NOW()\n `;\n }\n\n async generateAndStoreEmbedding(\n memoryId: string,\n text: string,\n config?: EmbeddingConfig\n ): Promise<void> {\n try {\n const result = await generateEmbedding(text, config);\n await this.storeEmbedding(memoryId, result.embedding, result.model);\n } catch {\n console.error(\"Failed to generate embedding for memory\");\n }\n }\n\n async getEmbedding(memoryId: string): Promise<number[] | undefined> {\n const result = await this.prisma.memoryEmbedding.findUnique({\n where: { memoryId },\n select: { embedding: true },\n });\n\n if (!result) return undefined;\n return deserializeEmbedding(Buffer.from(result.embedding));\n }\n\n async hasEmbedding(memoryId: string): Promise<boolean> {\n const count = await this.prisma.memoryEmbedding.count({\n where: { memoryId },\n });\n return count > 0;\n }\n\n async recallWithEmbeddings(\n query: RecallQuery,\n queryEmbedding?: number[]\n ): Promise<RecallResult[]> {\n const ftsResults = await this.recall(query);\n\n if (!queryEmbedding) {\n return ftsResults;\n }\n\n const vectorStr = embeddingToPgVector(queryEmbedding);\n const k = query.k ?? 10;\n const usageStats = await this.getUsageStats(query.orgId, query.repoId);\n const usageMap = new Map(usageStats.map((stat) => [stat.memoryId, stat]));\n\n const embeddingResults = await this.prisma.$queryRaw<\n Array<{\n memory_id: string;\n similarity: number;\n }>\n >`\n SELECT \n e.memory_id,\n 1 - (e.embedding_vector <=> ${vectorStr}::vector) as similarity\n FROM memory_embeddings e\n JOIN memories m ON e.memory_id = m.id\n WHERE m.org_id = ${query.orgId}\n AND m.repo_id = ${query.repoId}\n AND m.status = 'active'\n AND (\n m.ttl_seconds IS NULL\n OR m.created_at + (m.ttl_seconds * INTERVAL '1 second') >= NOW()\n )\n ORDER BY e.embedding_vector <=> ${vectorStr}::vector\n LIMIT ${k * 2}\n `;\n\n const embeddingScores = new Map<string, number>();\n for (const row of embeddingResults) {\n embeddingScores.set(row.memory_id, Math.max(0, row.similarity));\n }\n\n const ftsIds = new Set(ftsResults.map((r) => r.id));\n const additionalMemories: RecallResult[] = [];\n\n for (const row of embeddingResults) {\n if (ftsIds.has(row.memory_id) || row.similarity < 0.3) continue;\n\n const memory = await this.getById(row.memory_id);\n if (!memory || memory.status !== \"active\" || (!query.includeExpired && isMemoryExpired(memory))) {\n continue;\n }\n\n const usage = usageMap.get(memory.id);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n\n additionalMemories.push({\n id: memory.id,\n memoryType: memory.memoryType,\n text: memory.text,\n summary: memory.summary,\n tags: memory.tags,\n sourceRefs: memory.sourceRefs,\n score: computeHybridScore(0, row.similarity, memory.createdAt, memory.confidence, usageBoost),\n source: \"remote\",\n status: memory.status,\n supersedesId: memory.supersedesId,\n });\n }\n\n const hybridResults = ftsResults.map((r) => {\n const embScore = embeddingScores.get(r.id) ?? 0;\n const usage = usageMap.get(r.id);\n const usageBoost = computeUsageBoost(\n usage?.count ?? 0,\n usage?.lastUsed,\n );\n return {\n ...r,\n score: embScore > 0\n ? computeHybridScore(r.score * 0.6, embScore, new Date(), undefined, usageBoost)\n : r.score,\n };\n });\n\n const combined = [...hybridResults, ...additionalMemories];\n return combined.sort((a, b) => b.score - a.score).slice(0, k);\n }\n\n async getMemoriesWithoutEmbeddings(\n orgId: string,\n repoId: string\n ): Promise<Memory[]> {\n const memories = await this.prisma.$queryRaw<Array<Record<string, unknown>>>`\n SELECT m.* FROM memories m\n LEFT JOIN memory_embeddings e ON m.id = e.memory_id\n WHERE m.org_id = ${orgId}\n AND m.repo_id = ${repoId}\n AND m.status = 'active'\n AND e.memory_id IS NULL\n `;\n\n return memories.map(prismaRowToMemory);\n }\n\n async recordUsage(\n memoryId: string,\n query?: string,\n sessionId?: string\n ): Promise<void> {\n await this.prisma.memoryUsage.create({\n data: {\n memoryId,\n query,\n sessionId,\n },\n });\n }\n\n async recordUsageBatch(\n memoryIds: string[],\n query?: string,\n sessionId?: string\n ): Promise<void> {\n await this.prisma.memoryUsage.createMany({\n data: memoryIds.map((memoryId) => ({\n memoryId,\n query,\n sessionId,\n })),\n });\n }\n\n async getUsageStats(\n orgId: string,\n repoId: string\n ): Promise<Array<{ memoryId: string; count: number; lastUsed: Date }>> {\n const stats = await this.prisma.$queryRaw<\n Array<{ memory_id: string; count: bigint; last_used: Date }>\n >`\n SELECT \n u.memory_id,\n COUNT(*) as count,\n MAX(u.recalled_at) as last_used\n FROM memory_usage u\n JOIN memories m ON u.memory_id = m.id\n WHERE m.org_id = ${orgId} AND m.repo_id = ${repoId}\n GROUP BY u.memory_id\n ORDER BY count DESC\n `;\n\n return stats.map((row) => ({\n memoryId: row.memory_id,\n count: Number(row.count),\n lastUsed: row.last_used,\n }));\n }\n\n async getEmbeddingStats(\n orgId: string,\n repoId: string\n ): Promise<{ total: number; withEmbedding: number; withoutEmbedding: number }> {\n const result = await this.prisma.$queryRaw<\n Array<{ total: bigint; with_embedding: bigint }>\n >`\n SELECT \n COUNT(m.id) as total,\n COUNT(e.memory_id) as with_embedding\n FROM memories m\n LEFT JOIN memory_embeddings e ON m.id = e.memory_id\n WHERE m.org_id = ${orgId} AND m.repo_id = ${repoId} AND m.status = 'active'\n `;\n\n const row = result[0];\n const total = Number(row?.total ?? 0);\n const withEmbedding = Number(row?.with_embedding ?? 0);\n\n return {\n total,\n withEmbedding,\n withoutEmbedding: total - withEmbedding,\n };\n }\n\n async findSimilar(query: FindSimilarQuery): Promise<RecallResult[]> {\n const { orgId, repoId, memoryId, threshold = 0.3, k = 10 } = query;\n\n const memory = await this.getById(memoryId);\n if (!memory) {\n throw new Error(`Memory not found: ${memoryId}`);\n }\n\n const embedding = await this.getEmbedding(memoryId);\n\n if (embedding) {\n const vectorStr = embeddingToPgVector(embedding);\n\n const results = await this.prisma.$queryRaw<\n Array<{\n id: string;\n memory_type: string;\n text: string;\n summary: string | null;\n tags: string[];\n source_refs: Record<string, unknown> | null;\n confidence: number | null;\n status: string;\n supersedes_id: string | null;\n created_at: Date;\n similarity: number;\n }>\n >`\n SELECT \n m.id,\n m.memory_type,\n m.text,\n m.summary,\n m.tags,\n m.source_refs,\n m.confidence,\n m.status,\n m.supersedes_id,\n m.created_at,\n 1 - (e.embedding_vector <=> ${vectorStr}::vector) as similarity\n FROM memories m\n JOIN memory_embeddings e ON m.id = e.memory_id\n WHERE m.org_id = ${orgId}\n AND m.repo_id = ${repoId}\n AND m.status = 'active'\n AND m.id != ${memoryId}\n ORDER BY e.embedding_vector <=> ${vectorStr}::vector\n LIMIT ${k + 1}\n `;\n\n return results\n .filter((r) => r.similarity >= threshold)\n .slice(0, k)\n .map((r) => ({\n id: r.id,\n memoryType: r.memory_type as Memory[\"memoryType\"],\n text: r.text,\n summary: r.summary ?? undefined,\n tags: r.tags ?? [],\n sourceRefs: r.source_refs ?? undefined,\n score: r.similarity,\n source: \"remote\" as const,\n status: r.status as Memory[\"status\"],\n supersedesId: r.supersedes_id ?? undefined,\n }));\n }\n\n const results = await this.recall({\n orgId,\n repoId,\n query: memory.text,\n k: k + 1,\n });\n\n return results\n .filter((r) => r.id !== memoryId && r.score >= threshold)\n .slice(0, k);\n }\n\n async consolidateMemories(\n input: ConsolidateMemoriesInput\n ): Promise<ConsolidateMemoriesResult> {\n const {\n orgId,\n repoId,\n sourceIds,\n consolidatedText,\n memoryType,\n tags,\n preserveOriginals = true,\n } = input;\n\n if (sourceIds.length < 2) {\n throw new Error(\"At least 2 source memories are required for consolidation\");\n }\n\n const sourceMemories: Memory[] = [];\n for (const id of sourceIds) {\n const memory = await this.getById(id);\n if (memory) {\n sourceMemories.push(memory);\n }\n }\n\n if (sourceMemories.length !== sourceIds.length) {\n const foundIds = sourceMemories.map((m) => m.id);\n const missingIds = sourceIds.filter((id) => !foundIds.includes(id));\n throw new Error(`Source memories not found: ${missingIds.join(\", \")}`);\n }\n\n const inferredType = memoryType ?? this.inferMemoryType(sourceMemories);\n const mergedTags = tags ?? this.mergeTags(sourceMemories);\n const inheritedVisibility = sourceMemories.some((m) => m.visibility === \"repo\")\n ? \"repo\"\n : \"private\";\n\n const sourceRefs: Record<string, unknown> = {\n consolidated_from: sourceIds,\n consolidation_version: 1,\n };\n\n const consolidated = await this.store({\n orgId,\n repoId,\n memoryType: inferredType,\n visibility: inheritedVisibility,\n text: consolidatedText,\n tags: mergedTags,\n sourceRefs,\n confidence: 0.8,\n });\n\n for (const sourceId of sourceIds) {\n try {\n await this.link({\n sourceId: consolidated.id,\n targetId: sourceId,\n linkType: \"derived_from\",\n });\n\n if (!preserveOriginals) {\n await this.supersede(sourceId, consolidated.id);\n }\n } catch {\n // Best effort linking\n }\n }\n\n return {\n consolidatedId: consolidated.id,\n version: 1,\n sourcesPreserved: preserveOriginals ? sourceIds.length : 0,\n sourceIds,\n };\n }\n\n private inferMemoryType(memories: Memory[]): MemoryType {\n const typeCount: Record<string, number> = {};\n for (const m of memories) {\n typeCount[m.memoryType] = (typeCount[m.memoryType] || 0) + 1;\n }\n\n const sorted = Object.entries(typeCount).sort((a, b) => b[1] - a[1]);\n if (sorted[0]) {\n return sorted[0][0] as MemoryType;\n }\n\n return \"semantic\";\n }\n\n private mergeTags(memories: Memory[]): string[] {\n const allTags = new Set<string>();\n for (const m of memories) {\n for (const tag of m.tags) {\n allTags.add(tag);\n }\n }\n return Array.from(allTags);\n }\n\n async getTopUsedMemories(\n orgId: string,\n repoId: string,\n limit = 10\n ): Promise<Array<{ memory: Memory; usageCount: number }>> {\n const stats = await this.getUsageStats(orgId, repoId);\n const topStats = stats.slice(0, limit);\n\n const results: Array<{ memory: Memory; usageCount: number }> = [];\n for (const stat of topStats) {\n const memory = await this.getById(stat.memoryId);\n if (memory) {\n results.push({ memory, usageCount: stat.count });\n }\n }\n\n return results;\n }\n\n async resetAll(\n orgId: string,\n repoId: string,\n ): Promise<{ memoriesDeleted: number; linksDeleted: number; embeddingsDeleted: number }> {\n const memories = await this.prisma.memory.findMany({\n where: { orgId, repoId },\n select: { id: true },\n });\n const memoryIds = memories.map((m) => m.id);\n\n if (memoryIds.length === 0) {\n return { memoriesDeleted: 0, linksDeleted: 0, embeddingsDeleted: 0 };\n }\n\n let embeddingsDeleted = 0;\n try {\n const result = await this.prisma.memoryEmbedding.deleteMany({\n where: { memoryId: { in: memoryIds } },\n });\n embeddingsDeleted = result.count;\n } catch (error) {\n if (!isMissingTableError(error, \"public.memory_embeddings\")) {\n throw error;\n }\n }\n\n try {\n await this.prisma.memoryUsage.deleteMany({\n where: { memoryId: { in: memoryIds } },\n });\n } catch (error) {\n if (!isMissingTableError(error, \"public.memory_usage\")) {\n throw error;\n }\n }\n\n const [linksResult, , memoriesResult] = await this.prisma.$transaction([\n this.prisma.memoryLink.deleteMany({\n where: { OR: [{ sourceId: { in: memoryIds } }, { targetId: { in: memoryIds } }] },\n }),\n this.prisma.tombstone.deleteMany({ where: { orgId, repoId } }),\n this.prisma.memory.deleteMany({ where: { orgId, repoId } }),\n ]);\n\n return {\n memoriesDeleted: memoriesResult.count,\n linksDeleted: linksResult.count,\n embeddingsDeleted,\n };\n }\n\n async upsertUser(input: {\n githubId: number;\n githubLogin: string;\n name?: string | null;\n email?: string | null;\n avatarUrl?: string | null;\n }): Promise<{\n id: string;\n githubId: number;\n githubLogin: string;\n name: string | null;\n email: string | null;\n avatarUrl: string | null;\n isAdmin: boolean;\n createdAt: Date;\n updatedAt: Date;\n }> {\n const adminGithubIds = this.getAdminGithubIds();\n const isAdminFromEnv = adminGithubIds.includes(input.githubId);\n\n const user = await this.prisma.user.upsert({\n where: { githubId: input.githubId },\n create: {\n githubId: input.githubId,\n githubLogin: input.githubLogin,\n name: input.name ?? null,\n email: input.email ?? null,\n avatarUrl: input.avatarUrl ?? null,\n isAdmin: isAdminFromEnv,\n },\n update: {\n githubLogin: input.githubLogin,\n name: input.name ?? null,\n email: input.email ?? null,\n avatarUrl: input.avatarUrl ?? null,\n isAdmin: isAdminFromEnv,\n },\n });\n\n return user;\n }\n\n private getAdminGithubIds(): number[] {\n const adminIdsEnv = process.env.ADMIN_GITHUB_IDS || \"\";\n return adminIdsEnv\n .split(\",\")\n .map((id) => parseInt(id.trim(), 10))\n .filter((id) => !isNaN(id));\n }\n\n async getUserById(id: string): Promise<{\n id: string;\n githubId: number;\n githubLogin: string;\n name: string | null;\n email: string | null;\n avatarUrl: string | null;\n isAdmin: boolean;\n createdAt: Date;\n updatedAt: Date;\n } | null> {\n return this.prisma.user.findUnique({ where: { id } });\n }\n\n async getUserByGithubId(githubId: number): Promise<{\n id: string;\n githubId: number;\n githubLogin: string;\n name: string | null;\n email: string | null;\n avatarUrl: string | null;\n isAdmin: boolean;\n createdAt: Date;\n updatedAt: Date;\n } | null> {\n return this.prisma.user.findUnique({ where: { githubId } });\n }\n\n async listUsers(): Promise<Array<{\n id: string;\n githubId: number;\n githubLogin: string;\n name: string | null;\n email: string | null;\n avatarUrl: string | null;\n isAdmin: boolean;\n createdAt: Date;\n updatedAt: Date;\n }>> {\n return this.prisma.user.findMany({\n orderBy: { createdAt: \"desc\" },\n });\n }\n\n async setUserAdmin(id: string, isAdmin: boolean): Promise<boolean> {\n try {\n await this.prisma.user.update({\n where: { id },\n data: { isAdmin },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async deleteUser(id: string): Promise<boolean> {\n try {\n await this.prisma.user.delete({ where: { id } });\n return true;\n } catch {\n return false;\n }\n }\n\n async upsertRepoAccess(input: {\n userId: string;\n orgId: string;\n repoId: string;\n permission: string;\n grantedBy?: string;\n }): Promise<{\n id: string;\n userId: string;\n orgId: string;\n repoId: string;\n permission: string;\n grantedAt: Date;\n grantedBy: string | null;\n }> {\n const normalizedOrgId = input.orgId.toLowerCase();\n const normalizedRepoId = input.repoId.toLowerCase();\n\n return this.prisma.userRepoAccess.upsert({\n where: {\n userId_orgId_repoId: {\n userId: input.userId,\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n },\n },\n create: {\n userId: input.userId,\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n permission: input.permission,\n grantedBy: input.grantedBy ?? null,\n },\n update: {\n permission: input.permission,\n grantedBy: input.grantedBy ?? null,\n },\n });\n }\n\n async getUserRepoAccess(userId: string): Promise<Array<{\n id: string;\n userId: string;\n orgId: string;\n repoId: string;\n permission: string;\n grantedAt: Date;\n grantedBy: string | null;\n }>> {\n return this.prisma.userRepoAccess.findMany({\n where: { userId },\n orderBy: [{ orgId: \"asc\" }, { repoId: \"asc\" }],\n });\n }\n\n async getRepoUsers(orgId: string, repoId: string): Promise<Array<{\n id: string;\n userId: string;\n orgId: string;\n repoId: string;\n permission: string;\n grantedAt: Date;\n grantedBy: string | null;\n user: {\n id: string;\n githubLogin: string;\n name: string | null;\n avatarUrl: string | null;\n };\n }>> {\n return this.prisma.userRepoAccess.findMany({\n where: { orgId, repoId },\n include: {\n user: {\n select: {\n id: true,\n githubLogin: true,\n name: true,\n avatarUrl: true,\n },\n },\n },\n orderBy: { grantedAt: \"desc\" },\n });\n }\n\n async revokeRepoAccess(userId: string, orgId: string, repoId: string): Promise<boolean> {\n try {\n await this.prisma.userRepoAccess.delete({\n where: {\n userId_orgId_repoId: { userId, orgId, repoId },\n },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n async getAllRepos(): Promise<Array<{\n orgId: string;\n repoId: string;\n keyCount: number;\n memoryCount: number;\n }>> {\n const memoryCounts = await this.prisma.memory.groupBy({\n by: [\"orgId\", \"repoId\"],\n _count: { id: true },\n where: { status: \"active\" },\n });\n\n const keyCounts = await this.prisma.apiKey.groupBy({\n by: [\"orgId\"],\n _count: { id: true },\n where: { isActive: true },\n });\n\n const memoryMap = new Map<string, number>();\n for (const m of memoryCounts) {\n memoryMap.set(`${m.orgId}/${m.repoId}`, m._count.id);\n }\n\n const keyMap = new Map<string, number>();\n for (const k of keyCounts) {\n keyMap.set(k.orgId, k._count.id);\n }\n\n const uniqueRepos = new Set<string>();\n const repos: Array<{ orgId: string; repoId: string; keyCount: number; memoryCount: number }> = [];\n\n for (const m of memoryCounts) {\n const key = `${m.orgId}/${m.repoId}`;\n if (!uniqueRepos.has(key)) {\n uniqueRepos.add(key);\n repos.push({\n orgId: m.orgId,\n repoId: m.repoId,\n keyCount: keyMap.get(m.orgId) ?? 0,\n memoryCount: m._count.id,\n });\n }\n }\n\n return repos;\n }\n\n async createApiKeyForUser(\n name: string,\n orgId: string,\n repoId: string | null,\n userId: string,\n createdBy: string,\n label?: string\n ): Promise<{ id: string; key: string; name: string; label: string | null; orgId: string; repoId: string | null; userId: string }> {\n const key = `hk_${crypto.randomUUID().replace(/-/g, \"\")}`;\n const normalizedOrgId = orgId.toLowerCase();\n const normalizedRepoId = repoId?.toLowerCase() ?? null;\n\n const apiKey = await this.prisma.apiKey.create({\n data: {\n key,\n name,\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n userId,\n createdBy,\n label: label ?? null,\n },\n });\n\n return {\n id: apiKey.id,\n key: apiKey.key,\n name: apiKey.name,\n label: apiKey.label,\n orgId: apiKey.orgId,\n repoId: apiKey.repoId,\n userId: apiKey.userId!,\n };\n }\n\n async getUserApiKeys(userId: string): Promise<Array<{\n id: string;\n key: string;\n name: string;\n label: string | null;\n orgId: string;\n repoId: string | null;\n isActive: boolean;\n createdAt: Date;\n lastUsedAt: Date | null;\n }>> {\n return this.prisma.apiKey.findMany({\n where: { userId },\n orderBy: { createdAt: \"desc\" },\n });\n }\n\n async listApiKeysWithUsers(): Promise<Array<{\n id: string;\n key: string;\n name: string;\n label: string | null;\n orgId: string;\n repoId: string | null;\n userId: string | null;\n isActive: boolean;\n createdAt: Date;\n lastUsedAt: Date | null;\n user: { id: string; githubLogin: string; name: string | null } | null;\n }>> {\n return this.prisma.apiKey.findMany({\n orderBy: { createdAt: \"desc\" },\n include: {\n user: {\n select: {\n id: true,\n githubLogin: true,\n name: true,\n },\n },\n },\n });\n }\n\n async dailyCounts(\n orgId: string,\n repoId: string,\n days: number,\n sinceDate?: Date\n ): Promise<Array<{ date: string; count: number }>> {\n const startDate = sinceDate ?? new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n\n const rows = await this.prisma.$queryRaw<Array<{ date: string; count: bigint }>>`\n SELECT DATE(created_at) as date, COUNT(*) as count\n FROM memories\n WHERE org_id = ${orgId}\n AND repo_id = ${repoId}\n AND created_at >= ${startDate}\n GROUP BY DATE(created_at)\n ORDER BY date ASC\n `;\n\n return rows.map((r) => ({\n date: r.date,\n count: Number(r.count),\n }));\n }\n\n async hourlyCounts(\n orgId: string,\n repoId: string\n ): Promise<Array<{ hour: number; count: number }>> {\n const rows = await this.prisma.$queryRaw<Array<{ hour: number; count: bigint }>>`\n SELECT EXTRACT(HOUR FROM created_at)::int as hour, COUNT(*) as count\n FROM memories\n WHERE org_id = ${orgId}\n AND repo_id = ${repoId}\n AND created_at >= NOW() - INTERVAL '24 hours'\n GROUP BY EXTRACT(HOUR FROM created_at)\n ORDER BY hour ASC\n `;\n\n return rows.map((r) => ({\n hour: r.hour,\n count: Number(r.count),\n }));\n }\n\n async weeklyTrend(\n orgId: string,\n repoId: string,\n weeks: number\n ): Promise<Array<{ week: string; count: number }>> {\n const startDate = new Date(Date.now() - weeks * 7 * 24 * 60 * 60 * 1000);\n\n const rows = await this.prisma.$queryRaw<Array<{ week: string; count: bigint }>>`\n SELECT TO_CHAR(DATE_TRUNC('week', created_at), 'YYYY-WW') as week, COUNT(*) as count\n FROM memories\n WHERE org_id = ${orgId}\n AND repo_id = ${repoId}\n AND created_at >= ${startDate}\n GROUP BY DATE_TRUNC('week', created_at)\n ORDER BY week ASC\n `;\n\n return rows.map((r) => ({\n week: r.week,\n count: Number(r.count),\n }));\n }\n\n async topTags(\n orgId: string,\n repoId: string,\n limit: number,\n sinceDate?: Date\n ): Promise<Array<{ tag: string; count: number }>> {\n let rows: Array<{ tag: string; count: bigint }>;\n\n if (sinceDate) {\n rows = await this.prisma.$queryRaw<Array<{ tag: string; count: bigint }>>`\n SELECT unnest(tags) as tag, COUNT(*) as count\n FROM memories\n WHERE org_id = ${orgId}\n AND repo_id = ${repoId}\n AND status = 'active'\n AND created_at >= ${sinceDate}\n GROUP BY tag\n ORDER BY count DESC\n LIMIT ${limit}\n `;\n } else {\n rows = await this.prisma.$queryRaw<Array<{ tag: string; count: bigint }>>`\n SELECT unnest(tags) as tag, COUNT(*) as count\n FROM memories\n WHERE org_id = ${orgId}\n AND repo_id = ${repoId}\n AND status = 'active'\n GROUP BY tag\n ORDER BY count DESC\n LIMIT ${limit}\n `;\n }\n\n return rows.map((r) => ({\n tag: r.tag,\n count: Number(r.count),\n }));\n }\n\n async createApiKeyLog(input: {\n apiKeyId: string;\n operation: string;\n orgId: string;\n repoId: string;\n memoryId?: string;\n query?: string;\n metadata?: Record<string, unknown>;\n }): Promise<{\n id: string;\n apiKeyId: string;\n operation: string;\n orgId: string;\n repoId: string;\n memoryId: string | null;\n query: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: Date;\n }> {\n const normalizedOrgId = input.orgId.toLowerCase();\n const normalizedRepoId = input.repoId.toLowerCase();\n\n const log = await this.prisma.apiKeyLog.create({\n data: {\n apiKeyId: input.apiKeyId,\n operation: input.operation,\n orgId: normalizedOrgId,\n repoId: normalizedRepoId,\n memoryId: input.memoryId ?? null,\n query: input.query ?? null,\n metadata: input.metadata as Record<string, string> | undefined,\n },\n });\n\n return {\n id: log.id,\n apiKeyId: log.apiKeyId,\n operation: log.operation,\n orgId: log.orgId,\n repoId: log.repoId,\n memoryId: log.memoryId,\n query: log.query,\n metadata: log.metadata as Record<string, unknown> | null,\n createdAt: log.createdAt,\n };\n }\n\n async getApiKeyLogs(filters: {\n apiKeyId?: string;\n apiKeyIds?: string[];\n orgId?: string;\n repoId?: string;\n operation?: string;\n since?: Date;\n until?: Date;\n limit?: number;\n offset?: number;\n }): Promise<Array<{\n id: string;\n apiKeyId: string;\n operation: string;\n orgId: string;\n repoId: string;\n memoryId: string | null;\n query: string | null;\n metadata: Record<string, unknown> | null;\n createdAt: Date;\n apiKey: {\n id: string;\n name: string;\n label: string | null;\n user: { id: string; githubLogin: string; name: string | null } | null;\n };\n }>> {\n const where: Record<string, unknown> = {};\n\n if (filters.apiKeyId) {\n where.apiKeyId = filters.apiKeyId;\n }\n if (filters.apiKeyIds && filters.apiKeyIds.length > 0) {\n where.apiKeyId = { in: filters.apiKeyIds };\n }\n if (filters.orgId) {\n where.orgId = filters.orgId;\n }\n if (filters.repoId) {\n where.repoId = filters.repoId;\n }\n if (filters.operation) {\n where.operation = filters.operation;\n }\n if (filters.since || filters.until) {\n const createdAt: Record<string, Date> = {};\n if (filters.since) createdAt.gte = filters.since;\n if (filters.until) createdAt.lte = filters.until;\n where.createdAt = createdAt;\n }\n\n const logs = await this.prisma.apiKeyLog.findMany({\n where,\n orderBy: { createdAt: \"desc\" },\n take: filters.limit ?? 100,\n skip: filters.offset ?? 0,\n include: {\n apiKey: {\n select: {\n id: true,\n name: true,\n label: true,\n user: {\n select: {\n id: true,\n githubLogin: true,\n name: true,\n },\n },\n },\n },\n },\n });\n\n return logs.map((log) => ({\n id: log.id,\n apiKeyId: log.apiKeyId,\n operation: log.operation,\n orgId: log.orgId,\n repoId: log.repoId,\n memoryId: log.memoryId,\n query: log.query,\n metadata: log.metadata as Record<string, unknown> | null,\n createdAt: log.createdAt,\n apiKey: log.apiKey,\n }));\n }\n\n async countApiKeyLogs(filters: {\n apiKeyId?: string;\n apiKeyIds?: string[];\n orgId?: string;\n repoId?: string;\n operation?: string;\n since?: Date;\n until?: Date;\n }): Promise<number> {\n const where: Record<string, unknown> = {};\n\n if (filters.apiKeyId) {\n where.apiKeyId = filters.apiKeyId;\n }\n if (filters.apiKeyIds && filters.apiKeyIds.length > 0) {\n where.apiKeyId = { in: filters.apiKeyIds };\n }\n if (filters.orgId) {\n where.orgId = filters.orgId;\n }\n if (filters.repoId) {\n where.repoId = filters.repoId;\n }\n if (filters.operation) {\n where.operation = filters.operation;\n }\n if (filters.since || filters.until) {\n const createdAt: Record<string, Date> = {};\n if (filters.since) createdAt.gte = filters.since;\n if (filters.until) createdAt.lte = filters.until;\n where.createdAt = createdAt;\n }\n\n return this.prisma.apiKeyLog.count({ where });\n }\n}\n"],"mappings":"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","names":["OpenAI","config","config","OpenAI","candidates","preview","config","config","path","fs","path","runtime","path","fs","id","config","Buffer","NullTypes"]}
|