/**
 * Local Memory Store - SQLite-backed persistence for qmemory.
 *
 * Ported from Python qmemory's memory_store.py + db.py.
 * Uses better-sqlite3 for synchronous, fast, single-file persistence.
 *
 * Storage location:
 *   ~/.qlogicagent/profiles/<owner_user_id>/memory/memories.db
 *
 * Schema:
 *   - memories: core fact storage with optional embedding blob
 *   - memories_fts: FTS5 full-text index for keyword search
 *   - profiles: user profile KV (future)
 */
export { resolveMemoryDbPath } from "./memory-db-path.js";
export interface MemoryRecord {
    id: string;
    text: string;
    userId: string;
    category: string;
    importance: number;
    confidence: number;
    source: string;
    sessionId: string;
    eventDate: string;
    tags: string[];
    embedding: Float32Array | null;
    createdAt: number;
    updatedAt: number;
    accessCount: number;
    lastAccessedAt: number;
    isArchived: boolean;
    /** Lightweight attachment refs (populated by the provider for atlas/detail). */
    attachments?: MemoryAttachmentRef[];
}
/** Lightweight attachment reference carried on records / atlas wire (no bytes, no extractedText). */
export interface MemoryAttachmentRef {
    id: string;
    kind: string;
    filename: string;
    mimeType: string;
    size: number;
    url: string;
}
/** Full attachment index row (DB-backed; file bytes live on disk under the attachments dir). */
export interface MemoryAttachmentRow {
    id: string;
    memoryId: string;
    userId: string;
    kind: string;
    filename: string;
    mimeType: string;
    size: number;
    relPath: string;
    extractedText: string;
    createdAt: number;
}
export interface MemoryAttachmentInsert {
    id: string;
    userId: string;
    kind: string;
    filename: string;
    mimeType: string;
    size: number;
    relPath: string;
    extractedText?: string;
    memoryId?: string;
}
export interface MemoryInsertInput {
    text: string;
    userId: string;
    category?: string;
    importance?: number;
    confidence?: number;
    source?: string;
    sessionId?: string;
    eventDate?: string;
    tags?: string[];
    embedding?: Float32Array;
}
export interface MemoryUpdateInput {
    text?: string;
    category?: string;
    importance?: number;
    source?: string;
    eventDate?: string;
    tags?: string[];
    embedding?: Float32Array | null;
}
export interface MemorySearchHit {
    id: string;
    text: string;
    score: number;
    category: string;
    importance: number;
    metadata: Record<string, unknown>;
}
export interface MemoryAtlasBucket {
    id: string;
    startAt: number;
    endAt: number;
    count: number;
    avgImportance: number;
    avgConfidence: number;
    topCategory: string;
}
export interface MemoryAtlasCluster {
    id: string;
    label: string;
    kind: "source" | "category" | "tag";
    count: number;
    startAt: number;
    endAt: number;
    avgImportance: number;
    avgConfidence: number;
    topCategory: string;
}
export interface MemoryAtlasWindowCursor {
    startAt: number;
    endAt: number;
    centerAt: number;
    pageSize: number;
    hasBefore: boolean;
    hasAfter: boolean;
}
export interface MemoryAtlasResult {
    totalCount: number;
    records: MemoryRecord[];
    buckets: MemoryAtlasBucket[];
    clusters: MemoryAtlasCluster[];
    windowCursor: MemoryAtlasWindowCursor | null;
    timeRange: {
        startAt: number;
        endAt: number;
    } | null;
}
export type MemorySourceKind = "manual" | "explicit" | "document" | "image" | "video" | "auto" | "turn" | "dream" | "agent";
export type MemoryClaimStatus = "active" | "superseded" | "conflicted" | "archived" | "pending_confirmation";
export type MemoryProposalStatus = "pending" | "accepted" | "merged" | "conflicted" | "rejected";
export interface MemoryObservationInput {
    userId: string;
    text: string;
    source: string;
    sourcePriority: number;
    sessionId?: string;
    evidenceType?: string;
    payload?: Record<string, unknown>;
}
export interface MemoryObservationRecord extends Required<Omit<MemoryObservationInput, "payload" | "sessionId" | "evidenceType">> {
    id: string;
    sessionId: string;
    evidenceType: string;
    payload: Record<string, unknown>;
    createdAt: number;
}
export interface MemoryProposalInput {
    userId: string;
    observationIds: string[];
    text: string;
    category: string;
    importance: number;
    confidence: number;
    source: string;
    sourcePriority: number;
    entity: string;
    predicate: string;
    value: Record<string, unknown>;
    validTime?: string;
    tags?: string[];
    status?: MemoryProposalStatus;
    relatedClaimIds?: string[];
}
export interface MemoryProposalRecord extends Omit<MemoryProposalInput, "value" | "validTime" | "tags" | "status" | "relatedClaimIds"> {
    id: string;
    value: Record<string, unknown>;
    validTime: string;
    tags: string[];
    status: MemoryProposalStatus;
    relatedClaimIds: string[];
    createdAt: number;
    updatedAt: number;
}
export interface MemoryClaimInput {
    userId: string;
    memoryId?: string;
    entity: string;
    predicate: string;
    value: Record<string, unknown>;
    text: string;
    category: string;
    importance: number;
    confidence: number;
    source: string;
    sourcePriority: number;
    status: MemoryClaimStatus;
    validTime?: string;
    evidenceIds: string[];
    supersedesClaimId?: string;
    conflictGroupId?: string;
}
export interface MemoryClaimRecord extends Omit<MemoryClaimInput, "memoryId" | "value" | "validTime" | "supersedesClaimId" | "conflictGroupId"> {
    id: string;
    memoryId: string;
    value: Record<string, unknown>;
    validTime: string;
    supersedesClaimId: string;
    conflictGroupId: string;
    createdAt: number;
    updatedAt: number;
}
export interface MemoryConflictRecord {
    id: string;
    userId: string;
    claimAId: string;
    claimBId: string;
    reason: string;
    status: "open" | "resolved" | "dismissed";
    createdAt: number;
    updatedAt: number;
}
export interface SqliteDatabase {
    exec(sql: string): void;
    prepare(sql: string): SqliteStatement;
    pragma(pragma: string): unknown;
    close(): void;
}
export interface SqliteStatement {
    run(...params: unknown[]): {
        changes: number;
        lastInsertRowid: number | bigint;
    };
    get(...params: unknown[]): unknown;
    all(...params: unknown[]): unknown[];
}
export declare class LocalMemoryStore {
    private db;
    constructor(db: SqliteDatabase);
    private initSchema;
    /**
     * Insert a new memory record. Returns the generated ID.
     */
    insert(input: MemoryInsertInput): string;
    /**
     * Full-text search using FTS5. Returns ranked results.
     */
    searchFts(query: string, userId: string, limit?: number): MemorySearchHit[];
    /**
     * Vector similarity search using pre-computed embeddings.
     * Performs brute-force cosine similarity (efficient for <100k records per user).
     */
    searchVector(queryEmbedding: Float32Array, userId: string, limit?: number, minScore?: number): MemorySearchHit[];
    /**
     * Hybrid search: FTS5 + vector similarity, de-duplicated and merged.
     */
    searchHybrid(query: string, queryEmbedding: Float32Array | null, userId: string, limit?: number): MemorySearchHit[];
    /**
     * Get all memories for a user (paginated).
     */
    listByUser(userId: string, page?: number, pageSize?: number, activeOnly?: boolean): MemoryRecord[];
    /**
     * Return a windowed atlas payload for large-history visualization.
     *
     * `records` are only the interactive window. `buckets` and `clusters` summarize
     * the whole history so the UI can render distant history as star dust /
     * aggregate galaxies without loading every memory as an interactive object.
     */
    getAtlas(userId: string, options?: {
        pageSize?: number;
        windowStartAt?: number;
        windowEndAt?: number;
        windowCenterAt?: number;
        bucketCount?: number;
        clusterLimit?: number;
        activeOnly?: boolean;
    }): MemoryAtlasResult;
    private getAtlasBuckets;
    private getAtlasClusters;
    /**
     * Get a single memory by ID.
     */
    getById(id: string): MemoryRecord | null;
    /**
     * Update memory text and bump updatedAt.
     */
    updateText(id: string, text: string, embedding?: Float32Array): boolean;
    /**
     * Update editable memory fields and bump updatedAt.
     */
    update(id: string, input: MemoryUpdateInput): boolean;
    /**
     * Delete a memory by ID.
     */
    delete(id: string): boolean;
    /**
     * Archive a memory (soft-delete: set is_archived=1).
     * Used by dedup gate when a similar but newer memory supersedes an older one.
     */
    archive(id: string): boolean;
    /**
     * Temporal expiry: archive event/plan memories whose event_date has passed
     * beyond a grace period (e.g., "meeting tomorrow" 3 days after it happened).
     */
    decayTemporalExpiry(userId: string, graceDays?: number): number;
    /**
     * Staleness decay: reduce importance of memories not accessed in a long time.
     * Memories accessed recently retain their importance; stale ones degrade.
     */
    decayStaleness(userId: string, staleDays?: number, decayFactor?: number): number;
    /**
     * Noise archival: archive low-importance memories that never got accessed.
     * Memories written by the agent but never recalled are likely noise.
     */
    decayNoiseArchival(userId: string, minAgeDays?: number, maxImportance?: number): number;
    /**
     * Run all decay strategies. Returns total affected count.
     */
    runFullDecay(userId: string, options?: {
        temporalGraceDays?: number;
        staleDays?: number;
        staleDecayFactor?: number;
        noiseMinAgeDays?: number;
        noiseMaxImportance?: number;
    }): {
        temporal: number;
        stale: number;
        noise: number;
        total: number;
    };
    /**
     * Apply feedback signal to a memory, adjusting importance accordingly.
     *
     * Signals:
     *   - "useful" boosts importance by +0.15 (capped at 1.0)
     *   - "irrelevant" reduces importance by -0.2
     *   - "outdated" archives immediately
     *   - "wrong" deletes immediately
     */
    applyFeedback(memoryId: string, signal: "useful" | "irrelevant" | "outdated" | "wrong"): boolean;
    /**
     * Get a profile value for a user.
     */
    getProfile(userId: string, key: string): string | null;
    /**
     * Set a profile value (upsert).
     */
    setProfile(userId: string, key: string, value: string): void;
    /**
     * Get all profile entries for a user.
     */
    getAllProfiles(userId: string): Record<string, string>;
    /**
     * Delete a profile entry.
     */
    deleteProfile(userId: string, key: string): boolean;
    private profileTableCreated;
    private ensureProfileTable;
    /**
     * Retrieve memories within a time range, grouped by day.
     * Used for "what happened last week" type queries and dream synthesis.
     */
    getTemporalSlice(userId: string, startMs: number, endMs: number, options?: {
        category?: string;
        limit?: number;
    }): Array<{
        date: string;
        memories: Array<{
            id: string;
            text: string;
            category: string;
            importance: number;
        }>;
    }>;
    /**
     * Get memory activity summary over recent N days.
     * Returns daily counts and high-importance entries used by temporal synthesis.
     */
    getActivitySummary(userId: string, days?: number): {
        dailyCounts: Array<{
            date: string;
            count: number;
        }>;
        highlights: Array<{
            id: string;
            text: string;
            category: string;
            importance: number;
            date: string;
        }>;
    };
    /**
     * Find memories related to a specific event date (卤tolerance).
     * Used for temporal context retrieval, such as finding memories around a requested date.
     */
    findByEventDate(userId: string, targetDate: string, toleranceDays?: number): MemorySearchHit[];
    /**
     * Record an access (for importance/relevance boosting).
     */
    recordAccess(id: string): void;
    /**
     * Get total memory count for a user.
     */
    count(userId: string, activeOnly?: boolean): number;
    /**
     * Delete all memories for a user.
     */
    resetUser(userId: string): number;
    /**
     * Run SQLite VACUUM to reclaim space after deletions/archival.
     * Should be called periodically (e.g. after decay cycles).
     */
    vacuum(): void;
    /**
     * Get database size info for capacity monitoring.
     */
    getStorageStats(): {
        pageCount: number;
        pageSize: number;
        totalBytes: number;
        freePages: number;
    };
    /**
     * Export archived memories as JSONL (for cold storage / backup).
     * Deletes exported records from the database to reclaim space.
     */
    exportAndPurgeArchived(userId: string, maxExport?: number): Array<{
        id: string;
        text: string;
        category: string;
        importance: number;
        createdAt: number;
        archivedAt: number;
        tags: string[];
    }>;
    /**
     * Enforce capacity limit: if active memories exceed maxCount,
     * archive the oldest lowest-importance ones.
     */
    enforceCapacityLimit(userId: string, maxCount?: number): number;
    insertObservation(input: MemoryObservationInput): string;
    insertProposal(input: MemoryProposalInput): string;
    updateProposalStatus(id: string, status: MemoryProposalStatus, relatedClaimIds?: string[]): boolean;
    insertClaim(input: MemoryClaimInput): string;
    listClaims(userId: string, statuses?: MemoryClaimStatus[]): MemoryClaimRecord[];
    findClaimsByFact(userId: string, entity: string, predicate: string, validTime?: string): MemoryClaimRecord[];
    mergeClaimEvidence(id: string, evidenceIds: string[], confidence: number, importance: number): boolean;
    updateClaimsByMemoryId(memoryId: string, status: MemoryClaimStatus): number;
    insertConflict(input: {
        userId: string;
        claimAId: string;
        claimBId: string;
        reason: string;
    }): string;
    listConflicts(userId: string): MemoryConflictRecord[];
    getClaimById(id: string): MemoryClaimRecord | undefined;
    setClaimStatus(id: string, status: MemoryClaimStatus): boolean;
    /** Mark a conflict resolved (the resolver has already updated the claims). */
    setConflictStatus(id: string, status: "open" | "resolved" | "dismissed"): boolean;
    /** Open conflicts only (the ones needing resolution). */
    listOpenConflicts(userId: string): MemoryConflictRecord[];
    /**
     * Promote pending_confirmation claims that have accumulated enough independent
     * evidence to become active. Returns the number promoted.
     */
    promotePendingClaims(userId: string, minEvidence: number): number;
    insertAttachment(input: MemoryAttachmentInsert): void;
    getAttachmentById(id: string): MemoryAttachmentRow | null;
    listAttachmentsByMemoryId(memoryId: string): MemoryAttachmentRow[];
    /** Batch-load attachments for many memories (for atlas windows). */
    listAttachmentsByMemoryIds(memoryIds: string[]): Map<string, MemoryAttachmentRow[]>;
    /** Link orphan/owned attachments to a committed memory. Returns linked count. */
    linkAttachments(memoryId: string, attachmentIds: string[], userId: string): number;
    setAttachmentExtractedText(id: string, text: string): boolean;
    /** Delete attachment index rows for a memory; returns their rel paths for file cleanup. */
    deleteAttachmentsByMemoryId(memoryId: string): string[];
    /** Orphan attachments (uploaded but never saved to a memory) older than cutoff. */
    listOrphanAttachments(cutoff: number): MemoryAttachmentRow[];
    deleteAttachmentById(id: string): void;
    close(): void;
}
