@anuma/sdk 10.0.4 → 10.1.1

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.
@@ -3954,6 +3954,159 @@ declare function makeSyntheticStoredMessage(opts: CreateMessageOptions): StoredM
3954
3954
  */
3955
3955
  declare function makeSyntheticStoredConversation(opts?: CreateConversationOptions, defaultTitle?: string): StoredConversation;
3956
3956
 
3957
+ /**
3958
+ * Types for the conversation-memory storage module.
3959
+ *
3960
+ * A conversation-memory row links a conversation to a vault memory it drew on,
3961
+ * so the conversation Memories panel survives reload. Only the memory id and
3962
+ * recall score are stored; content lives in the encrypted memory_vault.
3963
+ */
3964
+ /** Plain object representation of a conversation-memory record. */
3965
+ interface StoredConversationMemory {
3966
+ /** WatermelonDB internal ID */
3967
+ uniqueId: string;
3968
+ /** The conversation this memory was drawn on in */
3969
+ conversationId: string;
3970
+ /** The memory_vault record id this row points at */
3971
+ memoryId: string;
3972
+ /** Recall relevance score (~0–1) at the time it was recorded */
3973
+ score: number;
3974
+ createdAt: Date;
3975
+ }
3976
+ /** One memory drawn on during a turn, passed to addConversationMemoriesOp. */
3977
+ interface ConversationMemoryInput {
3978
+ memoryId: string;
3979
+ score: number;
3980
+ }
3981
+
3982
+ /**
3983
+ * Minimal interface for an observable (reactive) query result.
3984
+ *
3985
+ * Shaped to be compatible with RxJS-style `Observable` (which is what
3986
+ * WatermelonDB returns) and with a simple polling fallback, so non-reactive
3987
+ * backends can implement it without depending on rxjs.
3988
+ */
3989
+ interface ChatStorageObservable<T> {
3990
+ subscribe(observer: {
3991
+ next: (value: T) => void;
3992
+ error?: (err: unknown) => void;
3993
+ complete?: () => void;
3994
+ }): {
3995
+ unsubscribe: () => void;
3996
+ };
3997
+ }
3998
+ /**
3999
+ * Common filter options for conversation queries. Kept deliberately narrow —
4000
+ * most call sites only need these.
4001
+ */
4002
+ interface ConversationQueryOptions {
4003
+ /** If set, only return conversations in this project. `null` = no project. */
4004
+ projectId?: string | null;
4005
+ }
4006
+ /**
4007
+ * Backend-agnostic interface for chat/conversation storage.
4008
+ *
4009
+ * The method set mirrors the operations we actually use across the SDK:
4010
+ * `*Op` functions in `src/lib/db/chat/operations.ts` plus the `observe*`
4011
+ * patterns used by react hooks. Targeted updates (e.g., `updateMessageError`)
4012
+ * are exposed as separate methods rather than a generic `update()` because
4013
+ * several of them have special semantics (encryption bypass for embeddings,
4014
+ * unique constraints on feedback, etc).
4015
+ */
4016
+ interface ChatStorageAdapter {
4017
+ getConversation(conversationId: string): Promise<StoredConversation | null>;
4018
+ getConversations(options?: ConversationQueryOptions): Promise<StoredConversation[]>;
4019
+ createConversation(options?: CreateConversationOptions): Promise<StoredConversation>;
4020
+ updateConversationTitle(conversationId: string, title: string): Promise<boolean>;
4021
+ updateConversationProject(conversationId: string, projectId: string | null): Promise<boolean>;
4022
+ /** Pin or unpin a conversation. Pinning stamps `pinnedAt`; list queries are
4023
+ * NOT reordered — consumers sort pinned chats first using `pinnedAt`. */
4024
+ updateConversationPinned(conversationId: string, pinned: boolean): Promise<boolean>;
4025
+ /** Soft delete. Implementations are responsible for cascading to messages/media. */
4026
+ deleteConversation(conversationId: string): Promise<boolean>;
4027
+ observeConversations(options?: ConversationQueryOptions): ChatStorageObservable<StoredConversation[]>;
4028
+ getMessages(conversationId: string): Promise<StoredMessage[]>;
4029
+ /**
4030
+ * Paginated display read: newest `limit` messages (optionally below
4031
+ * `beforeMessageId`), ascending, with embeddings skipped. See
4032
+ * `getMessagesPageOp`.
4033
+ *
4034
+ * Optional so this is an additive, non-breaking interface change (same
4035
+ * rationale as {@link updateMessageFileIds}). The default
4036
+ * {@link WatermelonChatStorageAdapter} provides it.
4037
+ */
4038
+ getMessagesPage?(conversationId: string, options: GetMessagesPageOptions): Promise<StoredMessage[]>;
4039
+ /**
4040
+ * Whole-thread branch-tree skeleton (no decrypt). See
4041
+ * `getMessageSkeletonsOp`. Optional for the same additive-change rationale.
4042
+ */
4043
+ getMessageSkeletons?(conversationId: string): Promise<MessageSkeleton[]>;
4044
+ /** Total message count for a conversation. Optional (additive change). */
4045
+ getMessageCount?(conversationId: string): Promise<number>;
4046
+ createMessage(options: CreateMessageOptions): Promise<StoredMessage>;
4047
+ updateMessageEmbedding(uniqueId: string, vector: number[], embeddingModel: string): Promise<StoredMessage | null>;
4048
+ updateMessageChunks(uniqueId: string, chunks: MessageChunk[], embeddingModel: string): Promise<StoredMessage | null>;
4049
+ updateMessageError(uniqueId: string, error: string): Promise<StoredMessage | null>;
4050
+ updateMessageFeedback(uniqueId: string, feedback: MessageFeedback): Promise<StoredMessage | null>;
4051
+ /**
4052
+ * Replace a message's attached media ids (`fileIds`). Used to attach a
4053
+ * generated artifact (e.g. a rendered document PDF) to the assistant message
4054
+ * that produced it, after streaming. Pass the FULL desired list.
4055
+ *
4056
+ * Optional so this is an additive, non-breaking interface change: only hosts
4057
+ * wiring document/artifact generation need it, and existing custom adapters
4058
+ * keep compiling without implementing it. The default
4059
+ * {@link WatermelonChatStorageAdapter} provides it.
4060
+ */
4061
+ updateMessageFileIds?(uniqueId: string, fileIds: string[]): Promise<StoredMessage | null>;
4062
+ /** Clears all messages in a conversation (used for the "clear chat" action). */
4063
+ clearMessages(conversationId: string): Promise<void>;
4064
+ observeMessages(conversationId: string): ChatStorageObservable<StoredMessage[]>;
4065
+ getAllFiles(): Promise<StoredFileWithContext[]>;
4066
+ /**
4067
+ * Run a set of mutations inside a single write transaction. Any mutation
4068
+ * calls made on the adapter inside the callback are grouped into one atomic
4069
+ * write on backends that support it.
4070
+ *
4071
+ * On backends without transaction support, this may fall back to sequential
4072
+ * writes. Implementations must document the guarantee they provide.
4073
+ */
4074
+ write<T>(fn: (adapter: ChatStorageAdapter) => Promise<T>): Promise<T>;
4075
+ }
4076
+
4077
+ interface ChatChunkSearchOptions {
4078
+ limit?: number;
4079
+ minSimilarity?: number;
4080
+ conversationId?: string;
4081
+ excludeConversationId?: string;
4082
+ embeddingModel?: string;
4083
+ chunkCache?: ChunkVectorCache;
4084
+ onStats?: (stats: ChunkSearchStats) => void;
4085
+ }
4086
+ /** Everything `useChatStorage` reads and writes for chats, so a hook can run on local or server storage. */
4087
+ interface ChatBackend extends ChatStorageAdapter {
4088
+ createConversation(options?: CreateConversationOptions, defaultTitle?: string): Promise<StoredConversation>;
4089
+ getAllFiles(options?: Parameters<typeof getAllFilesOp>[1]): Promise<StoredFileWithContext[]>;
4090
+ getMessagesPage(conversationId: string, options: GetMessagesPageOptions): Promise<StoredMessage[]>;
4091
+ getMessageSkeletons(conversationId: string): Promise<MessageSkeleton[]>;
4092
+ /** Reads messages by id in the order asked, leaving out ids that are not stored. */
4093
+ getMessagesByIds(uniqueIds: readonly string[]): Promise<StoredMessage[]>;
4094
+ getMessageCount(conversationId: string): Promise<number>;
4095
+ getToolCallEventIds(conversationId: string): Promise<Set<string>>;
4096
+ upsertMessage(options: CreateMessageOptions & {
4097
+ uniqueId: string;
4098
+ }): Promise<StoredMessage>;
4099
+ searchChunks(queryVector: number[], options?: ChatChunkSearchOptions): Promise<ChunkSearchResult[]>;
4100
+ getSummary(conversationId: string): Promise<StoredConversationSummary | null>;
4101
+ upsertSummary(conversationId: string, summary: string, summarizedUpTo: string, tokenCount: number): Promise<StoredConversationSummary>;
4102
+ deleteSummary(conversationId: string): Promise<void>;
4103
+ deleteMessage(uniqueId: string): Promise<string | null>;
4104
+ getMemoryLinks(conversationId: string): Promise<StoredConversationMemory[]>;
4105
+ /** Records the memories a turn drew on in recall order, moving already-linked ones to this turn with their new score. */
4106
+ addMemoryLinks(conversationId: string, items: ConversationMemoryInput[]): Promise<void>;
4107
+ clearMemoryLinks(conversationId: string): Promise<void>;
4108
+ }
4109
+
3957
4110
  /** Recent window — observations inside this count as "active". */
3958
4111
  declare const TREND_RECENT_WINDOW_DAYS = 30;
3959
4112
  /** Beyond this since last observation → stale. */
@@ -4221,8 +4374,10 @@ interface RecallContext {
4221
4374
  factSource?: RecallFactSource;
4222
4375
  /** Required when `types` includes 'fact'. */
4223
4376
  vaultCtx?: VaultMemoryOperationsContext;
4224
- /** Required when `types` includes 'chunk'. */
4377
+ /** Required when `types` includes 'chunk', unless `chats` is given. */
4225
4378
  storageCtx?: StorageOperationsContext;
4379
+ /** Chat chunk search; takes precedence over `storageCtx`. */
4380
+ chats?: Pick<ChatBackend, "searchChunks">;
4226
4381
  /** Embedding API options. */
4227
4382
  embeddingOptions: EmbeddingOptions;
4228
4383
  /** Vault embedding LRU cache. */
@@ -7248,6 +7403,32 @@ interface SearchSource {
7248
7403
  snippet?: string;
7249
7404
  date?: string;
7250
7405
  }
7406
+ /** Options for paginated message reads ({@link getMessagesPageOp}). */
7407
+ interface GetMessagesPageOptions {
7408
+ /**
7409
+ * Upper-bound cursor. Without `boundaryExcludeUniqueIds` it is EXCLUSIVE:
7410
+ * only messages with `messageId < beforeMessageId` are returned. Omit to
7411
+ * fetch the newest page (the conversation tail).
7412
+ */
7413
+ beforeMessageId?: number;
7414
+ /**
7415
+ * uniqueIds of the rows the caller already holds AT the `beforeMessageId`
7416
+ * boundary. `message_id` is not guaranteed unique in legacy data (ids were
7417
+ * assigned count-based, so a mid-thread delete let the next create reuse a
7418
+ * freed id) — with an exclusive cursor, an unseen row sharing the boundary
7419
+ * id would be silently skipped by every page. When this is provided, the
7420
+ * boundary id is fetched INCLUSIVELY and these known rows are filtered
7421
+ * out, so a duplicated boundary row is returned exactly once.
7422
+ */
7423
+ boundaryExcludeUniqueIds?: string[];
7424
+ /**
7425
+ * Maximum rows to return — the NEWEST `limit` rows of the matching range.
7426
+ * Must be a positive integer: non-positive or non-finite values yield an
7427
+ * EMPTY page (never an unbounded read — SQLite treats `LIMIT -1` as "no
7428
+ * limit"), and fractional values are floored.
7429
+ */
7430
+ limit: number;
7431
+ }
7251
7432
  /** Options for keyset-paginated conversation-list reads ({@link getConversationsPageOp}). */
7252
7433
  interface GetConversationsPageOptions {
7253
7434
  /**
@@ -7274,6 +7455,27 @@ interface GetConversationsPageOptions {
7274
7455
  */
7275
7456
  limit?: number;
7276
7457
  }
7458
+ /**
7459
+ * Lightweight, mostly-undecrypted projection of a message row. Contains just
7460
+ * enough for consumers to build the conversation's branch tree (parent/child
7461
+ * structure) without paying the decrypt + embedding-parse cost of a full
7462
+ * {@link StoredMessage} read.
7463
+ *
7464
+ * `content` is populated (decrypted) ONLY for user-role rows whose parent is
7465
+ * also a user-role row — the regeneration artifacts that branch logic must
7466
+ * classify by content prefix. All other rows leave `content` undefined.
7467
+ */
7468
+ interface MessageSkeleton {
7469
+ uniqueId: string;
7470
+ messageId: number;
7471
+ conversationId: string;
7472
+ role: ChatRole;
7473
+ createdAt: Date;
7474
+ parentMessageId?: string;
7475
+ model?: string;
7476
+ /** See interface docs — only set for user rows with a user-role parent. */
7477
+ content?: string;
7478
+ }
7277
7479
  interface StoredMessage {
7278
7480
  uniqueId: string;
7279
7481
  messageId: number;
@@ -7588,6 +7790,7 @@ declare function summaryToSystemMessage(summary: string): LlmapiMessage;
7588
7790
  /** Options for `maybeSummarizeHistory` */
7589
7791
  interface MaybeSummarizeHistoryOptions {
7590
7792
  database: Database;
7793
+ summaries?: Pick<ChatBackend, "getSummary" | "upsertSummary">;
7591
7794
  conversationId: string;
7592
7795
  messages: StoredMessage[];
7593
7796
  summarizeHistory: boolean;
@@ -7620,7 +7823,7 @@ declare function maybeSummarizeHistory(options: MaybeSummarizeHistoryOptions): P
7620
7823
  * Delete the conversation summary cache. Logs a warning on failure
7621
7824
  * rather than throwing, since this is a cascade cleanup operation.
7622
7825
  */
7623
- declare function cleanupConversationSummary(database: Database, conversationId: string): Promise<void>;
7826
+ declare function cleanupConversationSummary(storage: Database | Pick<ChatBackend, "deleteSummary">, conversationId: string): Promise<void>;
7624
7827
 
7625
7828
  interface WeatherClassification {
7626
7829
  /** Whether the prompt likely asks for weather data. */
@@ -7825,12 +8028,12 @@ declare function clearLazyTitleCache(): void;
7825
8028
  declare function decryptConversationTitle(encryptedTitle: string, address: string): Promise<string>;
7826
8029
 
7827
8030
  /** Context needed for summary operations */
7828
- interface SummaryOperationsContext {
8031
+ interface SummaryOperationsContext extends Pick<StorageOperationsContext, "walletAddress" | "signMessage" | "embeddedWalletSigner"> {
7829
8032
  database: Database;
7830
8033
  summariesCollection: Collection<ConversationSummary>;
7831
8034
  }
7832
8035
  /** Create a summary operations context from a database instance */
7833
- declare function createSummaryContext(database: Database): SummaryOperationsContext;
8036
+ declare function createSummaryContext(database: Database, encryption?: Pick<SummaryOperationsContext, "walletAddress" | "signMessage" | "embeddedWalletSigner">): SummaryOperationsContext;
7834
8037
  /**
7835
8038
  * Get the cached summary for a conversation.
7836
8039
  * Returns null if no summary exists yet.
@@ -10442,7 +10645,7 @@ declare function chunkAndEmbedAllMessages(ctx: StorageOperationsContext, options
10442
10645
  * The tool allows the LLM to search through past conversation messages
10443
10646
  * using semantic similarity. Messages must have embeddings stored to be searchable.
10444
10647
  *
10445
- * @param storageCtx - Storage operations context for database access
10648
+ * @param storage - Chat storage: a WatermelonDB operations context or a chat backend
10446
10649
  * @param embeddingOptions - Options for embedding generation
10447
10650
  * @param searchOptions - Default search options (can be overridden per-call)
10448
10651
  * @returns A ToolConfig that can be passed to chat completion tools
@@ -10462,7 +10665,7 @@ declare function chunkAndEmbedAllMessages(ctx: StorageOperationsContext, options
10462
10665
  * });
10463
10666
  * ```
10464
10667
  */
10465
- declare function createMemoryEngineTool(storageCtx: StorageOperationsContext, embeddingOptions: EmbeddingOptions, searchOptions?: Partial<MemoryEngineSearchOptions>, callbacks?: {
10668
+ declare function createMemoryEngineTool(storage: StorageOperationsContext | Pick<ChatBackend, "searchChunks" | "getMessages">, embeddingOptions: EmbeddingOptions, searchOptions?: Partial<MemoryEngineSearchOptions>, callbacks?: {
10466
10669
  /** Called after retrieval with the conversation IDs that were actually returned to the LLM. */
10467
10670
  onRetrieve?: (conversationIds: string[]) => void;
10468
10671
  }): ToolConfig;
@@ -3954,6 +3954,159 @@ declare function makeSyntheticStoredMessage(opts: CreateMessageOptions): StoredM
3954
3954
  */
3955
3955
  declare function makeSyntheticStoredConversation(opts?: CreateConversationOptions, defaultTitle?: string): StoredConversation;
3956
3956
 
3957
+ /**
3958
+ * Types for the conversation-memory storage module.
3959
+ *
3960
+ * A conversation-memory row links a conversation to a vault memory it drew on,
3961
+ * so the conversation Memories panel survives reload. Only the memory id and
3962
+ * recall score are stored; content lives in the encrypted memory_vault.
3963
+ */
3964
+ /** Plain object representation of a conversation-memory record. */
3965
+ interface StoredConversationMemory {
3966
+ /** WatermelonDB internal ID */
3967
+ uniqueId: string;
3968
+ /** The conversation this memory was drawn on in */
3969
+ conversationId: string;
3970
+ /** The memory_vault record id this row points at */
3971
+ memoryId: string;
3972
+ /** Recall relevance score (~0–1) at the time it was recorded */
3973
+ score: number;
3974
+ createdAt: Date;
3975
+ }
3976
+ /** One memory drawn on during a turn, passed to addConversationMemoriesOp. */
3977
+ interface ConversationMemoryInput {
3978
+ memoryId: string;
3979
+ score: number;
3980
+ }
3981
+
3982
+ /**
3983
+ * Minimal interface for an observable (reactive) query result.
3984
+ *
3985
+ * Shaped to be compatible with RxJS-style `Observable` (which is what
3986
+ * WatermelonDB returns) and with a simple polling fallback, so non-reactive
3987
+ * backends can implement it without depending on rxjs.
3988
+ */
3989
+ interface ChatStorageObservable<T> {
3990
+ subscribe(observer: {
3991
+ next: (value: T) => void;
3992
+ error?: (err: unknown) => void;
3993
+ complete?: () => void;
3994
+ }): {
3995
+ unsubscribe: () => void;
3996
+ };
3997
+ }
3998
+ /**
3999
+ * Common filter options for conversation queries. Kept deliberately narrow —
4000
+ * most call sites only need these.
4001
+ */
4002
+ interface ConversationQueryOptions {
4003
+ /** If set, only return conversations in this project. `null` = no project. */
4004
+ projectId?: string | null;
4005
+ }
4006
+ /**
4007
+ * Backend-agnostic interface for chat/conversation storage.
4008
+ *
4009
+ * The method set mirrors the operations we actually use across the SDK:
4010
+ * `*Op` functions in `src/lib/db/chat/operations.ts` plus the `observe*`
4011
+ * patterns used by react hooks. Targeted updates (e.g., `updateMessageError`)
4012
+ * are exposed as separate methods rather than a generic `update()` because
4013
+ * several of them have special semantics (encryption bypass for embeddings,
4014
+ * unique constraints on feedback, etc).
4015
+ */
4016
+ interface ChatStorageAdapter {
4017
+ getConversation(conversationId: string): Promise<StoredConversation | null>;
4018
+ getConversations(options?: ConversationQueryOptions): Promise<StoredConversation[]>;
4019
+ createConversation(options?: CreateConversationOptions): Promise<StoredConversation>;
4020
+ updateConversationTitle(conversationId: string, title: string): Promise<boolean>;
4021
+ updateConversationProject(conversationId: string, projectId: string | null): Promise<boolean>;
4022
+ /** Pin or unpin a conversation. Pinning stamps `pinnedAt`; list queries are
4023
+ * NOT reordered — consumers sort pinned chats first using `pinnedAt`. */
4024
+ updateConversationPinned(conversationId: string, pinned: boolean): Promise<boolean>;
4025
+ /** Soft delete. Implementations are responsible for cascading to messages/media. */
4026
+ deleteConversation(conversationId: string): Promise<boolean>;
4027
+ observeConversations(options?: ConversationQueryOptions): ChatStorageObservable<StoredConversation[]>;
4028
+ getMessages(conversationId: string): Promise<StoredMessage[]>;
4029
+ /**
4030
+ * Paginated display read: newest `limit` messages (optionally below
4031
+ * `beforeMessageId`), ascending, with embeddings skipped. See
4032
+ * `getMessagesPageOp`.
4033
+ *
4034
+ * Optional so this is an additive, non-breaking interface change (same
4035
+ * rationale as {@link updateMessageFileIds}). The default
4036
+ * {@link WatermelonChatStorageAdapter} provides it.
4037
+ */
4038
+ getMessagesPage?(conversationId: string, options: GetMessagesPageOptions): Promise<StoredMessage[]>;
4039
+ /**
4040
+ * Whole-thread branch-tree skeleton (no decrypt). See
4041
+ * `getMessageSkeletonsOp`. Optional for the same additive-change rationale.
4042
+ */
4043
+ getMessageSkeletons?(conversationId: string): Promise<MessageSkeleton[]>;
4044
+ /** Total message count for a conversation. Optional (additive change). */
4045
+ getMessageCount?(conversationId: string): Promise<number>;
4046
+ createMessage(options: CreateMessageOptions): Promise<StoredMessage>;
4047
+ updateMessageEmbedding(uniqueId: string, vector: number[], embeddingModel: string): Promise<StoredMessage | null>;
4048
+ updateMessageChunks(uniqueId: string, chunks: MessageChunk[], embeddingModel: string): Promise<StoredMessage | null>;
4049
+ updateMessageError(uniqueId: string, error: string): Promise<StoredMessage | null>;
4050
+ updateMessageFeedback(uniqueId: string, feedback: MessageFeedback): Promise<StoredMessage | null>;
4051
+ /**
4052
+ * Replace a message's attached media ids (`fileIds`). Used to attach a
4053
+ * generated artifact (e.g. a rendered document PDF) to the assistant message
4054
+ * that produced it, after streaming. Pass the FULL desired list.
4055
+ *
4056
+ * Optional so this is an additive, non-breaking interface change: only hosts
4057
+ * wiring document/artifact generation need it, and existing custom adapters
4058
+ * keep compiling without implementing it. The default
4059
+ * {@link WatermelonChatStorageAdapter} provides it.
4060
+ */
4061
+ updateMessageFileIds?(uniqueId: string, fileIds: string[]): Promise<StoredMessage | null>;
4062
+ /** Clears all messages in a conversation (used for the "clear chat" action). */
4063
+ clearMessages(conversationId: string): Promise<void>;
4064
+ observeMessages(conversationId: string): ChatStorageObservable<StoredMessage[]>;
4065
+ getAllFiles(): Promise<StoredFileWithContext[]>;
4066
+ /**
4067
+ * Run a set of mutations inside a single write transaction. Any mutation
4068
+ * calls made on the adapter inside the callback are grouped into one atomic
4069
+ * write on backends that support it.
4070
+ *
4071
+ * On backends without transaction support, this may fall back to sequential
4072
+ * writes. Implementations must document the guarantee they provide.
4073
+ */
4074
+ write<T>(fn: (adapter: ChatStorageAdapter) => Promise<T>): Promise<T>;
4075
+ }
4076
+
4077
+ interface ChatChunkSearchOptions {
4078
+ limit?: number;
4079
+ minSimilarity?: number;
4080
+ conversationId?: string;
4081
+ excludeConversationId?: string;
4082
+ embeddingModel?: string;
4083
+ chunkCache?: ChunkVectorCache;
4084
+ onStats?: (stats: ChunkSearchStats) => void;
4085
+ }
4086
+ /** Everything `useChatStorage` reads and writes for chats, so a hook can run on local or server storage. */
4087
+ interface ChatBackend extends ChatStorageAdapter {
4088
+ createConversation(options?: CreateConversationOptions, defaultTitle?: string): Promise<StoredConversation>;
4089
+ getAllFiles(options?: Parameters<typeof getAllFilesOp>[1]): Promise<StoredFileWithContext[]>;
4090
+ getMessagesPage(conversationId: string, options: GetMessagesPageOptions): Promise<StoredMessage[]>;
4091
+ getMessageSkeletons(conversationId: string): Promise<MessageSkeleton[]>;
4092
+ /** Reads messages by id in the order asked, leaving out ids that are not stored. */
4093
+ getMessagesByIds(uniqueIds: readonly string[]): Promise<StoredMessage[]>;
4094
+ getMessageCount(conversationId: string): Promise<number>;
4095
+ getToolCallEventIds(conversationId: string): Promise<Set<string>>;
4096
+ upsertMessage(options: CreateMessageOptions & {
4097
+ uniqueId: string;
4098
+ }): Promise<StoredMessage>;
4099
+ searchChunks(queryVector: number[], options?: ChatChunkSearchOptions): Promise<ChunkSearchResult[]>;
4100
+ getSummary(conversationId: string): Promise<StoredConversationSummary | null>;
4101
+ upsertSummary(conversationId: string, summary: string, summarizedUpTo: string, tokenCount: number): Promise<StoredConversationSummary>;
4102
+ deleteSummary(conversationId: string): Promise<void>;
4103
+ deleteMessage(uniqueId: string): Promise<string | null>;
4104
+ getMemoryLinks(conversationId: string): Promise<StoredConversationMemory[]>;
4105
+ /** Records the memories a turn drew on in recall order, moving already-linked ones to this turn with their new score. */
4106
+ addMemoryLinks(conversationId: string, items: ConversationMemoryInput[]): Promise<void>;
4107
+ clearMemoryLinks(conversationId: string): Promise<void>;
4108
+ }
4109
+
3957
4110
  /** Recent window — observations inside this count as "active". */
3958
4111
  declare const TREND_RECENT_WINDOW_DAYS = 30;
3959
4112
  /** Beyond this since last observation → stale. */
@@ -4221,8 +4374,10 @@ interface RecallContext {
4221
4374
  factSource?: RecallFactSource;
4222
4375
  /** Required when `types` includes 'fact'. */
4223
4376
  vaultCtx?: VaultMemoryOperationsContext;
4224
- /** Required when `types` includes 'chunk'. */
4377
+ /** Required when `types` includes 'chunk', unless `chats` is given. */
4225
4378
  storageCtx?: StorageOperationsContext;
4379
+ /** Chat chunk search; takes precedence over `storageCtx`. */
4380
+ chats?: Pick<ChatBackend, "searchChunks">;
4226
4381
  /** Embedding API options. */
4227
4382
  embeddingOptions: EmbeddingOptions;
4228
4383
  /** Vault embedding LRU cache. */
@@ -7248,6 +7403,32 @@ interface SearchSource {
7248
7403
  snippet?: string;
7249
7404
  date?: string;
7250
7405
  }
7406
+ /** Options for paginated message reads ({@link getMessagesPageOp}). */
7407
+ interface GetMessagesPageOptions {
7408
+ /**
7409
+ * Upper-bound cursor. Without `boundaryExcludeUniqueIds` it is EXCLUSIVE:
7410
+ * only messages with `messageId < beforeMessageId` are returned. Omit to
7411
+ * fetch the newest page (the conversation tail).
7412
+ */
7413
+ beforeMessageId?: number;
7414
+ /**
7415
+ * uniqueIds of the rows the caller already holds AT the `beforeMessageId`
7416
+ * boundary. `message_id` is not guaranteed unique in legacy data (ids were
7417
+ * assigned count-based, so a mid-thread delete let the next create reuse a
7418
+ * freed id) — with an exclusive cursor, an unseen row sharing the boundary
7419
+ * id would be silently skipped by every page. When this is provided, the
7420
+ * boundary id is fetched INCLUSIVELY and these known rows are filtered
7421
+ * out, so a duplicated boundary row is returned exactly once.
7422
+ */
7423
+ boundaryExcludeUniqueIds?: string[];
7424
+ /**
7425
+ * Maximum rows to return — the NEWEST `limit` rows of the matching range.
7426
+ * Must be a positive integer: non-positive or non-finite values yield an
7427
+ * EMPTY page (never an unbounded read — SQLite treats `LIMIT -1` as "no
7428
+ * limit"), and fractional values are floored.
7429
+ */
7430
+ limit: number;
7431
+ }
7251
7432
  /** Options for keyset-paginated conversation-list reads ({@link getConversationsPageOp}). */
7252
7433
  interface GetConversationsPageOptions {
7253
7434
  /**
@@ -7274,6 +7455,27 @@ interface GetConversationsPageOptions {
7274
7455
  */
7275
7456
  limit?: number;
7276
7457
  }
7458
+ /**
7459
+ * Lightweight, mostly-undecrypted projection of a message row. Contains just
7460
+ * enough for consumers to build the conversation's branch tree (parent/child
7461
+ * structure) without paying the decrypt + embedding-parse cost of a full
7462
+ * {@link StoredMessage} read.
7463
+ *
7464
+ * `content` is populated (decrypted) ONLY for user-role rows whose parent is
7465
+ * also a user-role row — the regeneration artifacts that branch logic must
7466
+ * classify by content prefix. All other rows leave `content` undefined.
7467
+ */
7468
+ interface MessageSkeleton {
7469
+ uniqueId: string;
7470
+ messageId: number;
7471
+ conversationId: string;
7472
+ role: ChatRole;
7473
+ createdAt: Date;
7474
+ parentMessageId?: string;
7475
+ model?: string;
7476
+ /** See interface docs — only set for user rows with a user-role parent. */
7477
+ content?: string;
7478
+ }
7277
7479
  interface StoredMessage {
7278
7480
  uniqueId: string;
7279
7481
  messageId: number;
@@ -7588,6 +7790,7 @@ declare function summaryToSystemMessage(summary: string): LlmapiMessage;
7588
7790
  /** Options for `maybeSummarizeHistory` */
7589
7791
  interface MaybeSummarizeHistoryOptions {
7590
7792
  database: Database;
7793
+ summaries?: Pick<ChatBackend, "getSummary" | "upsertSummary">;
7591
7794
  conversationId: string;
7592
7795
  messages: StoredMessage[];
7593
7796
  summarizeHistory: boolean;
@@ -7620,7 +7823,7 @@ declare function maybeSummarizeHistory(options: MaybeSummarizeHistoryOptions): P
7620
7823
  * Delete the conversation summary cache. Logs a warning on failure
7621
7824
  * rather than throwing, since this is a cascade cleanup operation.
7622
7825
  */
7623
- declare function cleanupConversationSummary(database: Database, conversationId: string): Promise<void>;
7826
+ declare function cleanupConversationSummary(storage: Database | Pick<ChatBackend, "deleteSummary">, conversationId: string): Promise<void>;
7624
7827
 
7625
7828
  interface WeatherClassification {
7626
7829
  /** Whether the prompt likely asks for weather data. */
@@ -7825,12 +8028,12 @@ declare function clearLazyTitleCache(): void;
7825
8028
  declare function decryptConversationTitle(encryptedTitle: string, address: string): Promise<string>;
7826
8029
 
7827
8030
  /** Context needed for summary operations */
7828
- interface SummaryOperationsContext {
8031
+ interface SummaryOperationsContext extends Pick<StorageOperationsContext, "walletAddress" | "signMessage" | "embeddedWalletSigner"> {
7829
8032
  database: Database;
7830
8033
  summariesCollection: Collection<ConversationSummary>;
7831
8034
  }
7832
8035
  /** Create a summary operations context from a database instance */
7833
- declare function createSummaryContext(database: Database): SummaryOperationsContext;
8036
+ declare function createSummaryContext(database: Database, encryption?: Pick<SummaryOperationsContext, "walletAddress" | "signMessage" | "embeddedWalletSigner">): SummaryOperationsContext;
7834
8037
  /**
7835
8038
  * Get the cached summary for a conversation.
7836
8039
  * Returns null if no summary exists yet.
@@ -10442,7 +10645,7 @@ declare function chunkAndEmbedAllMessages(ctx: StorageOperationsContext, options
10442
10645
  * The tool allows the LLM to search through past conversation messages
10443
10646
  * using semantic similarity. Messages must have embeddings stored to be searchable.
10444
10647
  *
10445
- * @param storageCtx - Storage operations context for database access
10648
+ * @param storage - Chat storage: a WatermelonDB operations context or a chat backend
10446
10649
  * @param embeddingOptions - Options for embedding generation
10447
10650
  * @param searchOptions - Default search options (can be overridden per-call)
10448
10651
  * @returns A ToolConfig that can be passed to chat completion tools
@@ -10462,7 +10665,7 @@ declare function chunkAndEmbedAllMessages(ctx: StorageOperationsContext, options
10462
10665
  * });
10463
10666
  * ```
10464
10667
  */
10465
- declare function createMemoryEngineTool(storageCtx: StorageOperationsContext, embeddingOptions: EmbeddingOptions, searchOptions?: Partial<MemoryEngineSearchOptions>, callbacks?: {
10668
+ declare function createMemoryEngineTool(storage: StorageOperationsContext | Pick<ChatBackend, "searchChunks" | "getMessages">, embeddingOptions: EmbeddingOptions, searchOptions?: Partial<MemoryEngineSearchOptions>, callbacks?: {
10466
10669
  /** Called after retrieval with the conversation IDs that were actually returned to the LLM. */
10467
10670
  onRetrieve?: (conversationIds: string[]) => void;
10468
10671
  }): ToolConfig;