import type { AgentConfig, MastraDBMessage, MessageList } from '@mastra/core/agent';
import type { Processor, ProcessInputStepArgs, ProcessOutputResultArgs } from '@mastra/core/processors';
import type { RequestContext } from '@mastra/core/request-context';
import type { MemoryStorage, ObservationalMemoryRecord } from '@mastra/core/storage';
import { TokenCounter } from './token-counter.js';
import type { ObservationConfig, ReflectionConfig, ThresholdRange, ModelSettings, ProviderOptions } from './types.js';
/**
 * Debug event emitted when observation-related events occur.
 * Useful for understanding what the Observer is doing.
 */
export interface ObservationDebugEvent {
    type: 'observation_triggered' | 'observation_complete' | 'reflection_triggered' | 'reflection_complete' | 'tokens_accumulated' | 'step_progress';
    timestamp: Date;
    threadId: string;
    resourceId: string;
    /** Messages that were sent to the Observer */
    messages?: Array<{
        role: string;
        content: string;
    }>;
    /** Token counts */
    pendingTokens?: number;
    sessionTokens?: number;
    totalPendingTokens?: number;
    threshold?: number;
    /** Input token count (for reflection events) */
    inputTokens?: number;
    /** Number of active observations (for reflection events) */
    activeObservationsLength?: number;
    /** Output token count after reflection */
    outputTokens?: number;
    /** The observations that were generated */
    observations?: string;
    /** Previous observations (before this event) */
    previousObservations?: string;
    /** Observer's raw output */
    rawObserverOutput?: string;
    /** LLM usage from Observer/Reflector calls */
    usage?: {
        inputTokens?: number;
        outputTokens?: number;
        totalTokens?: number;
    };
    /** Step progress fields (for step_progress events) */
    stepNumber?: number;
    finishReason?: string;
    thresholdPercent?: number;
    willSave?: boolean;
    willObserve?: boolean;
}
/**
 * Configuration for ObservationalMemory
 */
export interface ObservationalMemoryConfig {
    /**
     * Storage adapter for persisting observations.
     * Must be a MemoryStorage instance (from MastraStorage.stores.memory).
     */
    storage: MemoryStorage;
    /**
     * Model for both Observer and Reflector agents.
     * Sets the model for both agents at once. Cannot be used together with
     * `observation.model` or `reflection.model` — an error will be thrown.
     *
     * @default 'google/gemini-2.5-flash'
     */
    model?: AgentConfig['model'];
    /**
     * Observation step configuration.
     */
    observation?: ObservationConfig;
    /**
     * Reflection step configuration.
     */
    reflection?: ReflectionConfig;
    /**
     * Memory scope for observations.
     * - 'resource': Observations span all threads for a resource (cross-thread memory)
     * - 'thread': Observations are per-thread (default)
     */
    scope?: 'resource' | 'thread';
    /**
     * Debug callback for observation events.
     * Called whenever observation-related events occur.
     * Useful for debugging and understanding the observation flow.
     */
    onDebugEvent?: (event: ObservationDebugEvent) => void;
    obscureThreadIds?: boolean;
    /**
     * Share the token budget between messages and observations.
     * When true, the total budget = observation.messageTokens + reflection.observationTokens.
     * - Messages can use more space when observations are small
     * - Observations can use more space when messages are small
     *
     * This helps maximize context usage by allowing flexible allocation.
     *
     * @default false
     */
    shareTokenBudget?: boolean;
}
/**
 * Internal resolved config with all defaults applied.
 * Thresholds are stored as ThresholdRange internally for dynamic calculation,
 * even when user provides a simple number (converted based on shareTokenBudget).
 */
interface ResolvedObservationConfig {
    model: AgentConfig['model'];
    /** Internal threshold - always stored as ThresholdRange for dynamic calculation */
    messageTokens: number | ThresholdRange;
    /** Whether shared token budget is enabled */
    shareTokenBudget: boolean;
    /** Model settings - merged with user config and defaults */
    modelSettings: ModelSettings;
    providerOptions: ProviderOptions;
    maxTokensPerBatch: number;
    /** Token interval for async background observation buffering (resolved from config) */
    bufferEvery?: number;
    /** Ratio of buffered observations to activate (0-1 float) */
    asyncActivation?: number;
    /** Token threshold above which synchronous observation is forced */
    blockAfter?: number;
}
interface ResolvedReflectionConfig {
    model: AgentConfig['model'];
    /** Internal threshold - always stored as ThresholdRange for dynamic calculation */
    observationTokens: number | ThresholdRange;
    /** Whether shared token budget is enabled */
    shareTokenBudget: boolean;
    /** Model settings - merged with user config and defaults */
    modelSettings: ModelSettings;
    providerOptions: ProviderOptions;
    /** Ratio (0-1) controlling when async reflection buffering starts */
    asyncActivation?: number;
}
/**
 * Default configuration values matching the spec
 */
export declare const OBSERVATIONAL_MEMORY_DEFAULTS: {
    readonly observation: {
        readonly model: "google/gemini-2.5-flash";
        readonly messageTokens: 30000;
        readonly modelSettings: {
            readonly temperature: 0.3;
            readonly maxOutputTokens: 100000;
        };
        readonly providerOptions: {
            readonly google: {
                readonly thinkingConfig: {
                    readonly thinkingBudget: 215;
                };
            };
        };
        readonly maxTokensPerBatch: 10000;
        readonly bufferEvery: number | undefined;
        readonly asyncActivation: number | undefined;
    };
    readonly reflection: {
        readonly model: "google/gemini-2.5-flash";
        readonly observationTokens: 40000;
        readonly modelSettings: {
            readonly temperature: 0;
            readonly maxOutputTokens: 100000;
        };
        readonly providerOptions: {
            readonly google: {
                readonly thinkingConfig: {
                    readonly thinkingBudget: 1024;
                };
            };
        };
        readonly asyncActivation: number | undefined;
    };
};
/**
 * ObservationalMemory - A three-agent memory system for long conversations.
 *
 * This processor:
 * 1. On input: Injects observations into context, filters out observed messages
 * 2. On output: Tracks new messages, triggers Observer/Reflector when thresholds hit
 *
 * The Actor (main agent) sees:
 * - Observations (compressed history)
 * - Suggested continuation message
 * - Recent unobserved messages
 *
 * @example
 * ```ts
 * import { ObservationalMemory } from '@mastra/memory/processors';
 *
 * // Minimal configuration
 * const om = new ObservationalMemory({ storage });
 *
 * // Full configuration
 * const om = new ObservationalMemory({
 *   storage,
 *   model: 'google/gemini-2.5-flash', // shared model for both agents
 *   shareTokenBudget: true,
 *   observation: {
 *     messageTokens: 30_000,
 *     modelSettings: { temperature: 0.3 },
 *   },
 *   reflection: {
 *     observationTokens: 40_000,
 *   },
 * });
 *
 * const agent = new Agent({
 *   inputProcessors: [om],
 *   outputProcessors: [om],
 * });
 * ```
 */
export declare class ObservationalMemory implements Processor<'observational-memory'> {
    readonly id: "observational-memory";
    readonly name = "Observational Memory";
    private storage;
    private tokenCounter;
    private scope;
    private observationConfig;
    private reflectionConfig;
    private onDebugEvent?;
    /** Internal Observer agent - created lazily */
    private observerAgent?;
    /** Internal Reflector agent - created lazily */
    private reflectorAgent?;
    private shouldObscureThreadIds;
    private hasher;
    private threadIdCache;
    /**
     * Track message IDs observed during this instance's lifetime.
     * Prevents re-observing messages when per-thread lastObservedAt cursors
     * haven't fully advanced past messages observed in a prior cycle.
     */
    private observedMessageIds;
    /** Internal MessageHistory for message persistence */
    private messageHistory;
    /**
     * In-memory mutex for serializing observation/reflection cycles per resource/thread.
     * Prevents race conditions where two concurrent cycles could both read isObserving=false
     * before either sets it to true, leading to lost work.
     *
     * Key format: "resource:{resourceId}" or "thread:{threadId}"
     * Value: Promise that resolves when the lock is released
     *
     * NOTE: This mutex only works within a single Node.js process. For distributed
     * deployments, external locking (Redis, database locks) would be needed, or
     * accept eventual consistency (acceptable for v1).
     */
    private locks;
    /**
     * Track in-flight async buffering operations per resource/thread.
     * Key format: "obs:{lockKey}" or "refl:{lockKey}"
     * Value: Promise that resolves when buffering completes
     */
    private asyncBufferingOps;
    /**
     * Track the last token boundary at which we started buffering.
     * Used to determine when we've crossed a new `bufferEvery` interval.
     * Key format: "obs:{lockKey}" or "refl:{lockKey}"
     */
    private lastBufferedBoundary;
    /**
     * Tracks cycleId for in-flight buffered reflections.
     * Since reflection buffering doesn't use chunks (it's a single string),
     * we store the cycleId in-memory so we can match it at activation time.
     * Key format: "refl:{lockKey}"
     */
    private reflectionBufferCycleIds;
    /**
     * Check if async buffering is enabled for observations.
     */
    private isAsyncObservationEnabled;
    /**
     * Check if async buffering is enabled for reflections.
     * Reflection buffering is enabled when asyncActivation is set (triggers at threshold * asyncActivation).
     */
    private isAsyncReflectionEnabled;
    /**
     * Get the buffer interval boundary key for observations.
     */
    private getObservationBufferKey;
    /**
     * Get the buffer interval boundary key for reflections.
     */
    private getReflectionBufferKey;
    /**
     * Safely get bufferedObservationChunks as an array.
     * Handles cases where it might be a JSON string or undefined.
     */
    private getBufferedChunks;
    /**
     * Check if we've crossed a new bufferEvery interval boundary.
     * Returns true if async buffering should be triggered.
     */
    private shouldTriggerAsyncObservation;
    /**
     * Check if async reflection buffering should be triggered.
     * Triggers once when observation tokens reach `threshold * asyncActivation`.
     * Only allows one buffered reflection at a time.
     */
    private shouldTriggerAsyncReflection;
    /**
     * Check if an async buffering operation is already in progress.
     */
    private isAsyncBufferingInProgress;
    /**
     * Acquire a lock for the given key, execute the callback, then release.
     * If a lock is already held, waits for it to be released before acquiring.
     */
    private withLock;
    /**
     * Get the lock key for the current scope
     */
    private getLockKey;
    constructor(config: ObservationalMemoryConfig);
    /**
     * Get the current configuration for this OM instance.
     * Used by the server to expose config to the UI when OM is added via processors.
     */
    get config(): {
        scope: 'resource' | 'thread';
        observation: {
            messageTokens: number | ThresholdRange;
        };
        reflection: {
            observationTokens: number | ThresholdRange;
        };
    };
    /**
     * Get the full config including resolved model names.
     * This is async because it needs to resolve the model configs.
     */
    getResolvedConfig(requestContext?: RequestContext): Promise<{
        scope: 'resource' | 'thread';
        observation: {
            messageTokens: number | ThresholdRange;
            model: string;
        };
        reflection: {
            observationTokens: number | ThresholdRange;
            model: string;
        };
    }>;
    /**
     * Emit a debug event if the callback is configured
     */
    private emitDebugEvent;
    /**
     * Validate buffer configuration on first use.
     * Ensures bufferEvery is less than the threshold and asyncActivation is valid.
     */
    private validateBufferConfig;
    /**
     * Resolve bufferEvery: if it's a fraction (0 < value < 1), multiply by messageTokens threshold.
     * Otherwise return the absolute token count.
     */
    private resolveBufferEvery;
    /**
     * Resolve blockAfter config value.
     * If 0 < blockAfter < 1, treat as a fraction of extra headroom above messageTokens.
     * e.g. blockAfter: 0.25 with messageTokens: 20_000 → 25_000
     */
    private resolveBlockAfter;
    /**
     * Get the maximum value from a threshold (simple number or range)
     */
    private getMaxThreshold;
    /**
     * Calculate dynamic threshold based on observation space.
     * When shareTokenBudget is enabled, the message threshold can expand
     * into unused observation space, up to the total context budget.
     *
     * Total budget = messageTokens + observationTokens
     * Effective threshold = totalBudget - currentObservationTokens
     *
     * Example with 30k:40k thresholds (70k total):
     * - 0 observations → messages can use ~70k
     * - 10k observations → messages can use ~60k
     * - 40k observations → messages back to ~30k
     */
    private calculateDynamicThreshold;
    /**
     * Get or create the Observer agent
     */
    private getObserverAgent;
    /**
     * Get or create the Reflector agent
     */
    private getReflectorAgent;
    /**
     * Get thread/resource IDs for storage lookup
     */
    private getStorageIds;
    /**
     * Get or create the observational memory record
     */
    private getOrCreateRecord;
    /**
     * Check if we need to trigger reflection.
     */
    private shouldReflect;
    /**
     * Get current config snapshot for observation markers.
     */
    private getObservationMarkerConfig;
    /**
     * Create a start marker for when observation begins.
     */
    private createObservationStartMarker;
    /**
     * Create an end marker for when observation completes successfully.
     */
    private createObservationEndMarker;
    /**
     * Create a failed marker for when observation fails.
     */
    private createObservationFailedMarker;
    /**
     * Create a start marker for when async buffering begins.
     */
    private createBufferingStartMarker;
    /**
     * Create an end marker for when async buffering completes successfully.
     */
    private createBufferingEndMarker;
    /**
     * Create a failed marker for when async buffering fails.
     */
    private createBufferingFailedMarker;
    /**
     * Create an activation marker for when buffered observations are activated.
     */
    private createActivationMarker;
    /**
     * Find the last completed observation boundary in a message's parts.
     * A completed observation is a start marker followed by an end marker.
     *
     * Returns the index of the END marker (which is the observation boundary),
     * or -1 if no completed observation is found.
     */
    private findLastCompletedObservationBoundary;
    /**
     * Check if a message has an in-progress observation (start without end).
     */
    private hasInProgressObservation;
    /**
     * Seal messages to prevent new parts from being merged into them.
     * This is used when starting buffering to capture the current content state.
     *
     * Sealing works by:
     * 1. Setting `message.content.metadata.mastra.sealed = true` (message-level flag)
     * 2. Adding `metadata.mastra.sealedAt` to the last part (boundary marker)
     *
     * When MessageList.add() receives a message with the same ID as a sealed message,
     * it creates a new message with only the parts beyond the seal boundary.
     *
     * The messages are mutated in place - since they're references to the same objects
     * in the MessageList, the seal will be recognized immediately.
     *
     * @param messages - Messages to seal (mutated in place)
     */
    private sealMessagesForBuffering;
    /**
     * Insert an observation marker into a message.
     * The marker is appended directly to the message's parts array (mutating in place).
     * Also persists the change to storage so markers survive page refresh.
     *
     * For end/failed markers, the message is also "sealed" to prevent future content
     * from being merged into it. This ensures observation markers are preserved.
     */
    /**
     * Insert an observation marker into a message.
     * For start markers, this pushes the part directly.
     * For end/failed markers, this should be called AFTER writer.custom() has added the part,
     * so we just find the part and add sealing metadata.
     */
    /**
     * Get unobserved parts from a message.
     * If the message has a completed observation (start + end), only return parts after the end.
     * If observation is in progress (start without end), include parts before the start.
     * Otherwise, return all parts.
     */
    private getUnobservedParts;
    /**
     * Check if a message has any unobserved parts.
     */
    private hasUnobservedParts;
    /**
     * Create a virtual message containing only the unobserved parts.
     * This is used for token counting and observation.
     */
    private createUnobservedMessage;
    /**
     * Get unobserved messages with part-level filtering.
     *
     * This method uses data-om-observation-end markers to filter at the part level:
     * 1. For messages WITH a completed observation: only return parts AFTER the end marker
     * 2. For messages WITHOUT completed observation: check timestamp against lastObservedAt
     *
     * This handles the case where a single message accumulates many parts
     * (like tool calls) during an agentic loop - we only observe the new parts.
     */
    private getUnobservedMessages;
    /**
     * Wrapper for observer/reflector agent.generate() calls that checks for abort.
     * agent.generate() returns an empty result on abort instead of throwing,
     * so we must check the signal before and after the call.
     * Retries are handled by Mastra's built-in p-retry at the model execution layer.
     */
    private withAbortCheck;
    /**
     * Call the Observer agent to extract observations.
     */
    private callObserver;
    /**
     * Call the Observer agent for multiple threads in a single batched request.
     * This is more efficient than calling the Observer for each thread individually.
     * Returns per-thread results with observations, currentTask, and suggestedContinuation,
     * plus the total usage for the batch.
     */
    private callMultiThreadObserver;
    /**
     * Call the Reflector agent to condense observations.
     * Includes compression validation and retry logic.
     */
    private callReflector;
    /**
     * Format observations for injection into context.
     * Applies token optimization before presenting to the Actor.
     *
     * In resource scope mode, filters continuity messages to only show
     * the message for the current thread.
     */
    /**
     * Format observations for injection into the Actor's context.
     * @param observations - The observations to inject
     * @param suggestedResponse - Thread-specific suggested response (from thread metadata)
     * @param unobservedContextBlocks - Formatted <unobserved-context> blocks from other threads
     */
    private formatObservationsForContext;
    /**
     * Get threadId and resourceId from either RequestContext or MessageList
     */
    private getThreadContext;
    /**
     * Load historical unobserved messages into the message list (step 0 only).
     * In resource scope, loads only current thread's messages.
     * In thread scope, loads all unobserved messages for the thread.
     */
    private loadHistoricalMessagesIfNeeded;
    /**
     * Calculate all threshold-related values for observation decision making.
     */
    private calculateObservationThresholds;
    /**
     * Emit debug event and stream progress part for UI feedback.
     */
    private emitStepProgress;
    /**
     * Handle observation when threshold is reached.
     * Tries async activation first if enabled, then falls back to sync observation.
     * Returns whether observation succeeded.
     */
    private handleThresholdReached;
    /**
     * Remove observed messages from message list after successful observation.
     * Accepts optional observedMessageIds for activation-based cleanup (when no markers are present).
     */
    private cleanupAfterObservation;
    /**
     * Handle per-step save when threshold is not reached.
     * Persists messages incrementally to prevent data loss on interruption.
     */
    private handlePerStepSave;
    /**
     * Inject observations as system message and add continuation reminder.
     */
    private injectObservationsIntoContext;
    /**
     * Filter out already-observed messages from message list (step 0 only).
     * Historical messages loaded from DB may contain observation markers from previous sessions.
     */
    private filterAlreadyObservedMessages;
    /**
     * Process input at each step - check threshold, observe if needed, save, inject observations.
     * This is the ONLY processor method - all OM logic happens here.
     *
     * Flow:
     * 1. Load historical messages (step 0 only)
     * 2. Check if observation threshold is reached
     * 3. If threshold reached: observe, save messages with markers
     * 4. Inject observations into context
     * 5. Filter out already-observed messages
     */
    processInputStep(args: ProcessInputStepArgs): Promise<MessageList | MastraDBMessage[]>;
    /**
     * Save any unsaved messages at the end of the agent turn.
     *
     * This is the "final save" that catches messages that processInputStep didn't save
     * (e.g., when the observation threshold was never reached, or on single-step execution).
     * Without this, messages would be lost because MessageHistory is disabled when OM is active.
     */
    processOutputResult(args: ProcessOutputResultArgs): Promise<MessageList | MastraDBMessage[]>;
    /**
     * Save messages to storage, regenerating IDs for any messages that were
     * previously saved with observation markers (sealed).
     *
     * After saving, tracks which messages now have observation markers
     * so their IDs won't be reused in future save cycles.
     */
    private saveMessagesWithSealedIdTracking;
    /**
     * Load messages from storage that haven't been observed yet.
     * Uses cursor-based query with lastObservedAt timestamp for efficiency.
     *
     * In resource scope mode, loads messages for the entire resource (all threads).
     * In thread scope mode, loads messages for just the current thread.
     */
    private loadUnobservedMessages;
    /**
     * Load unobserved messages from other threads (not the current thread) for a resource.
     * Called fresh each step so it reflects the latest lastObservedAt cursors
     * after observations complete.
     */
    private loadOtherThreadsContext;
    /**
     * Format unobserved messages from other threads as <unobserved-context> blocks.
     * These are injected into the Actor's context so it has awareness of activity
     * in other threads for the same resource.
     */
    private formatUnobservedContextBlocks;
    private representThreadIDInContext;
    /**
     * Strip any thread tags that the Observer might have added.
     * Thread attribution is handled externally by the system, not by the Observer.
     * This is a defense-in-depth measure.
     */
    private stripThreadTags;
    /**
     * Get the maximum createdAt timestamp from a list of messages.
     * Used to set lastObservedAt to the most recent message timestamp instead of current time.
     * This ensures historical data (like LongMemEval fixtures) works correctly.
     */
    private getMaxMessageTimestamp;
    /**
     * Wrap observations in a thread attribution tag.
     * Used in resource scope to track which thread observations came from.
     */
    private wrapWithThreadTag;
    /**
     * Append or merge new thread sections.
     * If the new section has the same thread ID and date as an existing section,
     * merge the observations into that section to reduce token usage.
     * Otherwise, append as a new section.
     */
    private replaceOrAppendThreadSection;
    /**
     * Sort threads by their oldest unobserved message.
     * Returns thread IDs in order from oldest to most recent.
     * This ensures no thread's messages get "stuck" unobserved.
     */
    private sortThreadsByOldestMessage;
    /**
     * Do synchronous observation (fallback when no buffering)
     */
    private doSynchronousObservation;
    /**
     * Start an async background observation that stores results to bufferedObservations.
     * This is a fire-and-forget operation that runs in the background.
     * The results will be swapped to active when the main threshold is reached.
     *
     * If another buffering operation is already in progress for this scope, this will
     * wait for it to complete before starting a new one (mutex behavior).
     *
     * @param record - Current OM record
     * @param threadId - Thread ID
     * @param unobservedMessages - All unobserved messages (will be filtered for already-buffered)
     * @param lockKey - Lock key for this scope
     * @param writer - Optional stream writer for emitting buffering markers
     */
    private startAsyncBufferedObservation;
    /**
     * Internal method that waits for existing buffering operation and then runs new buffering.
     * This implements the mutex-wait behavior.
     */
    private runAsyncBufferedObservation;
    /**
     * Perform async buffered observation - observes messages and stores to bufferedObservations.
     * Does NOT update activeObservations or trigger reflection.
     *
     * The observer sees: active observations + existing buffered observations + message history
     * (excluding already-buffered messages).
     */
    private doAsyncBufferedObservation;
    /**
     * Combine active and buffered observations for the buffering observer context.
     * The buffering observer needs to see both so it doesn't duplicate content.
     */
    private combineObservationsForBuffering;
    /**
     * Try to activate buffered observations when threshold is reached.
     * Returns true if activation succeeded, false if no buffered content or activation failed.
     *
     * @param record - Current OM record
     * @param lockKey - Lock key for this scope
     * @param writer - Optional writer for emitting UI markers
     */
    private tryActivateBufferedObservations;
    /**
     * Start an async background reflection that stores results to bufferedReflection.
     * This is a fire-and-forget operation that runs in the background.
     * The results will be swapped to active when the main reflection threshold is reached.
     *
     * @param record - Current OM record
     * @param observationTokens - Current observation token count
     * @param lockKey - Lock key for this scope
     */
    private startAsyncBufferedReflection;
    /**
     * Perform async buffered reflection - reflects observations and stores to bufferedReflection.
     * Does NOT create a new generation or update activeObservations.
     */
    private doAsyncBufferedReflection;
    /**
     * Try to activate buffered reflection when threshold is reached.
     * Returns true if activation succeeded, false if no buffered content or activation failed.
     *
     * @param record - Current OM record
     * @param lockKey - Lock key for this scope
     */
    private tryActivateBufferedReflection;
    /**
     * Resource-scoped observation: observe ALL threads with unobserved messages.
     * Threads are observed in oldest-first order to ensure no thread's messages
     * get "stuck" unobserved forever.
     *
     * Key differences from thread-scoped observation:
     * 1. Loads messages from ALL threads for the resource
     * 2. Observes threads one-by-one in oldest-first order
     * 3. Only updates lastObservedAt AFTER all threads are observed
     * 4. Only triggers reflection AFTER all threads are observed
     */
    private doResourceScopedObservation;
    /**
     * Check if async reflection should be triggered or activated.
     * Only handles the async path — will never do synchronous (blocking) reflection.
     * Safe to call after buffered observation activation.
     */
    private maybeAsyncReflect;
    /**
     * Check if reflection needed and trigger if so.
     * Supports both synchronous reflection and async buffered reflection.
     * When async buffering is enabled via `bufferEvery`, reflection is triggered
     * in the background at intervals, and activated when the threshold is reached.
     */
    private maybeReflect;
    /**
     * Manually trigger observation.
     */
    observe(threadId: string, resourceId?: string, _prompt?: string): Promise<void>;
    /**
     * Manually trigger reflection with optional guidance prompt.
     *
     * @example
     * ```ts
     * // Trigger reflection with specific focus
     * await om.reflect(threadId, resourceId,
     *   "focus on the authentication implementation, only keep minimal details about UI styling"
     * );
     * ```
     */
    reflect(threadId: string, resourceId?: string, prompt?: string): Promise<void>;
    /**
     * Get current observations for a thread/resource
     */
    getObservations(threadId: string, resourceId?: string): Promise<string | undefined>;
    /**
     * Get current record for a thread/resource
     */
    getRecord(threadId: string, resourceId?: string): Promise<ObservationalMemoryRecord | null>;
    /**
     * Get observation history (previous generations)
     */
    getHistory(threadId: string, resourceId?: string, limit?: number): Promise<ObservationalMemoryRecord[]>;
    /**
     * Clear all memory for a specific thread/resource
     */
    clear(threadId: string, resourceId?: string): Promise<void>;
    /**
     * Get the underlying storage adapter
     */
    getStorage(): MemoryStorage;
    /**
     * Get the token counter
     */
    getTokenCounter(): TokenCounter;
    /**
     * Get current observation configuration
     */
    getObservationConfig(): ResolvedObservationConfig;
    /**
     * Get current reflection configuration
     */
    getReflectionConfig(): ResolvedReflectionConfig;
}
export {};
//# sourceMappingURL=observational-memory.d.ts.map