@anuma/sdk 3.2.0 → 3.3.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.
@@ -9,145 +9,438 @@ import * as _nozbe_watermelondb_Schema from '@nozbe/watermelondb/Schema';
9
9
  import { Class } from '@nozbe/watermelondb/types';
10
10
  import { DatabaseAdapter } from '@nozbe/watermelondb/adapters/type';
11
11
 
12
- /**
13
- * ExtraFields contains additional metadata
14
- */
15
- type LlmapiChatCompletionExtraFields = {
12
+ type AuthToken = string | undefined;
13
+ interface Auth {
16
14
  /**
17
- * Latency is the request latency in milliseconds
15
+ * Which part of the request do we use to send the auth?
16
+ *
17
+ * @default 'header'
18
18
  */
19
- latency?: number;
19
+ in?: 'header' | 'query' | 'cookie';
20
20
  /**
21
- * ModelRequested is the model that was requested
21
+ * Header or query parameter name.
22
+ *
23
+ * @default 'Authorization'
22
24
  */
23
- model_requested?: string;
25
+ name?: string;
26
+ scheme?: 'basic' | 'bearer';
27
+ type: 'apiKey' | 'http';
28
+ }
29
+
30
+ interface SerializerOptions<T> {
24
31
  /**
25
- * Provider is the LLM provider used (e.g., "openai", "anthropic")
32
+ * @default true
26
33
  */
27
- provider?: string;
34
+ explode: boolean;
35
+ style: T;
36
+ }
37
+ type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
38
+ type ObjectStyle = 'form' | 'deepObject';
39
+
40
+ type QuerySerializer = (query: Record<string, unknown>) => string;
41
+ type BodySerializer = (body: unknown) => unknown;
42
+ type QuerySerializerOptionsObject = {
43
+ allowReserved?: boolean;
44
+ array?: Partial<SerializerOptions<ArrayStyle>>;
45
+ object?: Partial<SerializerOptions<ObjectStyle>>;
46
+ };
47
+ type QuerySerializerOptions = QuerySerializerOptionsObject & {
28
48
  /**
29
- * RequestType is always "chat_completion"
49
+ * Per-parameter serialization overrides. When provided, these settings
50
+ * override the global array/object settings for specific parameter names.
30
51
  */
31
- request_type?: string;
52
+ parameters?: Record<string, QuerySerializerOptionsObject>;
32
53
  };
33
- type LlmapiChatCompletionResponse$1 = {
54
+
55
+ type HttpMethod = 'connect' | 'delete' | 'get' | 'head' | 'options' | 'patch' | 'post' | 'put' | 'trace';
56
+ type Client$1<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never, SseFn = never> = {
34
57
  /**
35
- * A list of chat completion choices. Can be more than one if `n` is greater
36
- * than 1.
58
+ * Returns the final request URL.
37
59
  */
38
- choices?: Array<OpenaiChatCompletionChoice>;
60
+ buildUrl: BuildUrlFn;
61
+ getConfig: () => Config;
62
+ request: RequestFn;
63
+ setConfig: (config: Config) => Config;
64
+ } & {
65
+ [K in HttpMethod]: MethodFn;
66
+ } & ([SseFn] extends [never] ? {
67
+ sse?: never;
68
+ } : {
69
+ sse: {
70
+ [K in HttpMethod]: SseFn;
71
+ };
72
+ });
73
+ interface Config$1 {
39
74
  /**
40
- * The Unix timestamp (in seconds) of when the chat completion was created.
75
+ * Auth token or a function returning auth token. The resolved value will be
76
+ * added to the request payload as defined by its `security` array.
41
77
  */
42
- created?: number;
78
+ auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
43
79
  /**
44
- * A unique identifier for the chat completion.
80
+ * A function for serializing request body parameter. By default,
81
+ * {@link JSON.stringify()} will be used.
45
82
  */
46
- id?: string;
83
+ bodySerializer?: BodySerializer | null;
47
84
  /**
48
- * The model used for the chat completion.
85
+ * An object containing any HTTP headers that you want to pre-populate your
86
+ * `Headers` object with.
87
+ *
88
+ * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
49
89
  */
50
- model?: string;
90
+ headers?: RequestInit['headers'] | Record<string, string | number | boolean | (string | number | boolean)[] | null | undefined | unknown>;
51
91
  /**
52
- * The object type, which is always `chat.completion`.
92
+ * The request method.
93
+ *
94
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
53
95
  */
54
- object?: string;
55
- portal?: LlmapiPortalChatCompletionResponse;
56
- service_tier?: OpenaiChatCompletionServiceTier;
96
+ method?: Uppercase<HttpMethod>;
57
97
  /**
58
- * This fingerprint represents the backend configuration that the model runs with.
98
+ * A function for serializing request query parameters. By default, arrays
99
+ * will be exploded in form style, objects will be exploded in deepObject
100
+ * style, and reserved characters are percent-encoded.
59
101
  *
60
- * Can be used in conjunction with the `seed` request parameter to understand when
61
- * backend changes have been made that might impact determinism.
102
+ * This method will have no effect if the native `paramsSerializer()` Axios
103
+ * API function is used.
104
+ *
105
+ * {@link https://swagger.io/docs/specification/serialization/#query View examples}
62
106
  */
63
- system_fingerprint?: string;
64
- usage?: OpenaiCompletionUsage;
65
- };
66
- type LlmapiMcpTool = {
107
+ querySerializer?: QuerySerializer | QuerySerializerOptions;
67
108
  /**
68
- * Description is the description of the tool
109
+ * A function validating request data. This is useful if you want to ensure
110
+ * the request conforms to the desired shape, so it can be safely sent to
111
+ * the server.
69
112
  */
70
- description?: string;
113
+ requestValidator?: (data: unknown) => Promise<unknown>;
71
114
  /**
72
- * InputSchema is the JSON schema describing the tool's input
115
+ * A function transforming response data before it's returned. This is useful
116
+ * for post-processing data, e.g., converting ISO strings into Date objects.
73
117
  */
74
- input_schema?: unknown;
118
+ responseTransformer?: (data: unknown) => Promise<unknown>;
75
119
  /**
76
- * Name is the name of the tool
120
+ * A function validating response data. This is useful if you want to ensure
121
+ * the response conforms to the desired shape, so it can be safely passed to
122
+ * the transformers and returned to the user.
77
123
  */
78
- name?: string;
79
- };
80
- type LlmapiMessage = {
124
+ responseValidator?: (data: unknown) => Promise<unknown>;
125
+ }
126
+
127
+ type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> & Pick<Config$1, 'method' | 'responseTransformer' | 'responseValidator'> & {
81
128
  /**
82
- * Content is the message content
129
+ * Fetch API implementation. You can use this option to provide a custom
130
+ * fetch instance.
131
+ *
132
+ * @default globalThis.fetch
83
133
  */
84
- content?: Array<LlmapiMessageContentPart>;
85
- role?: LlmapiRole;
134
+ fetch?: typeof fetch;
86
135
  /**
87
- * ToolCallID is the ID of the tool call this message is responding to (only for tool role)
136
+ * Implementing clients can call request interceptors inside this hook.
88
137
  */
89
- tool_call_id?: string;
138
+ onRequest?: (url: string, init: RequestInit) => Promise<Request>;
90
139
  /**
91
- * ToolCalls contains tool/function calls made by the assistant (only for assistant role)
140
+ * Callback invoked when a network or parsing error occurs during streaming.
141
+ *
142
+ * This option applies only if the endpoint returns a stream of events.
143
+ *
144
+ * @param error The error that occurred.
92
145
  */
93
- tool_calls?: Array<LlmapiToolCall>;
146
+ onSseError?: (error: unknown) => void;
94
147
  /**
95
- * Type is the message type (for Responses API: "message")
148
+ * Callback invoked when an event is streamed from the server.
149
+ *
150
+ * This option applies only if the endpoint returns a stream of events.
151
+ *
152
+ * @param event Event streamed from the server.
153
+ * @returns Nothing (void).
96
154
  */
97
- type?: string;
98
- };
99
- /**
100
- * File is used when Type=input_file (for Responses API)
101
- */
102
- type LlmapiMessageContentFile = {
155
+ onSseEvent?: (event: StreamEvent<TData>) => void;
156
+ serializedBody?: RequestInit['body'];
103
157
  /**
104
- * FileData is the base64-encoded file content
158
+ * Default retry delay in milliseconds.
159
+ *
160
+ * This option applies only if the endpoint returns a stream of events.
161
+ *
162
+ * @default 3000
105
163
  */
106
- file_data?: string;
164
+ sseDefaultRetryDelay?: number;
107
165
  /**
108
- * FileID is the ID of an uploaded file
166
+ * Maximum number of retry attempts before giving up.
109
167
  */
110
- file_id?: string;
168
+ sseMaxRetryAttempts?: number;
111
169
  /**
112
- * FileURL is the URL to the file
170
+ * Maximum retry delay in milliseconds.
171
+ *
172
+ * Applies only when exponential backoff is used.
173
+ *
174
+ * This option applies only if the endpoint returns a stream of events.
175
+ *
176
+ * @default 30000
113
177
  */
114
- file_url?: string;
178
+ sseMaxRetryDelay?: number;
115
179
  /**
116
- * Filename is the name of the file
180
+ * Optional sleep function for retry backoff.
181
+ *
182
+ * Defaults to using `setTimeout`.
117
183
  */
118
- filename?: string;
184
+ sseSleepFn?: (ms: number) => Promise<void>;
185
+ url: string;
119
186
  };
120
- /**
121
- * ImageURL is used when Type=image_url or Type=input_image
122
- */
123
- type LlmapiMessageContentImage = {
124
- /**
125
- * Detail is the OpenAI detail hint (auto|low|high)
126
- */
127
- detail?: string;
128
- /**
129
- * URL is the image URL or data URI
130
- */
131
- url?: string;
187
+ interface StreamEvent<TData = unknown> {
188
+ data: TData;
189
+ event?: string;
190
+ id?: string;
191
+ retry?: number;
192
+ }
193
+ type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
194
+ stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext>;
132
195
  };
133
- type LlmapiMessageContentPart = {
134
- file?: LlmapiMessageContentFile;
135
- image_url?: LlmapiMessageContentImage;
196
+
197
+ type ErrInterceptor<Err, Res, Options> = (error: Err,
198
+ /** response may be undefined due to a network error where no response object is produced */
199
+ response: Res | undefined, options: Options) => Err | Promise<Err>;
200
+ type ReqInterceptor<Options> = (options: Options) => void | Promise<void>;
201
+ type ResInterceptor<Res, Options> = (response: Res, options: Options) => Res | Promise<Res>;
202
+ declare class Interceptors<Interceptor> {
203
+ fns: Array<Interceptor | null>;
204
+ clear(): void;
205
+ eject(id: number | Interceptor): void;
206
+ exists(id: number | Interceptor): boolean;
207
+ getInterceptorIndex(id: number | Interceptor): number;
208
+ update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false;
209
+ use(fn: Interceptor): number;
210
+ }
211
+ interface Middleware<Res, Err, Options> {
212
+ error: Interceptors<ErrInterceptor<Err, Res, Options>>;
213
+ request: Interceptors<ReqInterceptor<Options>>;
214
+ response: Interceptors<ResInterceptor<Res, Options>>;
215
+ }
216
+
217
+ interface Config<T extends ClientOptions = ClientOptions> extends Omit<RequestInit, 'body' | 'headers' | 'method'>, Config$1 {
136
218
  /**
137
- * Text holds the text content when Type=text or Type=input_text
219
+ * Base URL for all requests made by this client.
138
220
  */
139
- text?: string;
221
+ baseUrl?: T['baseUrl'];
140
222
  /**
141
- * Type is the block type (`text`, `image_url`, or `input_file`)
223
+ * Fetch API implementation. You can use this option to provide a custom
224
+ * fetch instance.
225
+ *
226
+ * @default globalThis.fetch
142
227
  */
143
- type?: string;
144
- };
145
- type LlmapiModel = {
146
- architecture?: LlmapiModelArchitecture;
228
+ fetch?: typeof fetch;
147
229
  /**
148
- * CanonicalSlug is the canonical slug for the model
230
+ * Return the response data parsed in a specified format. By default, `auto`
231
+ * will infer the appropriate method from the `Content-Type` response header.
232
+ * You can override this behavior with any of the {@link Body} methods.
233
+ * Select `stream` if you don't want to parse response data at all.
234
+ *
235
+ * @default 'auto'
149
236
  */
150
- canonical_slug?: string;
237
+ parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
238
+ /**
239
+ * Throw an error instead of returning it in the response?
240
+ *
241
+ * @default false
242
+ */
243
+ throwOnError?: T['throwOnError'];
244
+ }
245
+ interface RequestOptions<TData = unknown, ThrowOnError extends boolean = boolean, Url extends string = string> extends Config<{
246
+ throwOnError: ThrowOnError;
247
+ }>, Pick<ServerSentEventsOptions<TData>, 'onRequest' | 'onSseError' | 'onSseEvent' | 'sseDefaultRetryDelay' | 'sseMaxRetryAttempts' | 'sseMaxRetryDelay'> {
248
+ /**
249
+ * Any body that you want to add to your request.
250
+ *
251
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
252
+ */
253
+ body?: unknown;
254
+ path?: Record<string, unknown>;
255
+ query?: Record<string, unknown>;
256
+ /**
257
+ * Security mechanism(s) to use for the request.
258
+ */
259
+ security?: ReadonlyArray<Auth>;
260
+ url: Url;
261
+ }
262
+ interface ResolvedRequestOptions<ThrowOnError extends boolean = boolean, Url extends string = string> extends RequestOptions<unknown, ThrowOnError, Url> {
263
+ headers: Headers;
264
+ serializedBody?: string;
265
+ }
266
+ type RequestResult<TData = unknown, TError = unknown, ThrowOnError extends boolean = boolean> = ThrowOnError extends true ? Promise<{
267
+ data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
268
+ response: Response;
269
+ }> : Promise<({
270
+ data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
271
+ error: undefined;
272
+ } | {
273
+ data: undefined;
274
+ error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
275
+ }) & {
276
+ /** response may be undefined due to a network error where no response object is produced */
277
+ response?: Response;
278
+ }>;
279
+ interface ClientOptions {
280
+ baseUrl?: string;
281
+ throwOnError?: boolean;
282
+ }
283
+ type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>) => RequestResult<TData, TError, ThrowOnError>;
284
+ type SseFn = <TData = unknown, _TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptions<never, ThrowOnError>, 'method'>) => Promise<ServerSentEventsResult<TData>>;
285
+ type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptions<TData, ThrowOnError>, 'method'> & Pick<Required<RequestOptions<TData, ThrowOnError>>, 'method'>) => RequestResult<TData, TError, ThrowOnError>;
286
+ type BuildUrlFn = <TData extends {
287
+ body?: unknown;
288
+ path?: Record<string, unknown>;
289
+ query?: Record<string, unknown>;
290
+ url: string;
291
+ }>(options: TData & Options<TData>) => string;
292
+ type Client = Client$1<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
293
+ interceptors: Middleware<Response, unknown, ResolvedRequestOptions>;
294
+ };
295
+ interface TDataShape {
296
+ body?: unknown;
297
+ headers?: unknown;
298
+ path?: unknown;
299
+ query?: unknown;
300
+ url: string;
301
+ }
302
+ type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
303
+ type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = OmitKeys<RequestOptions<TResponse, ThrowOnError>, 'body' | 'path' | 'query' | 'url'> & ([TData] extends [never] ? unknown : Omit<TData, 'url'>);
304
+
305
+ /**
306
+ * ExtraFields contains additional metadata
307
+ */
308
+ type LlmapiChatCompletionExtraFields = {
309
+ /**
310
+ * Latency is the request latency in milliseconds
311
+ */
312
+ latency?: number;
313
+ /**
314
+ * ModelRequested is the model that was requested
315
+ */
316
+ model_requested?: string;
317
+ /**
318
+ * Provider is the LLM provider used (e.g., "openai", "anthropic")
319
+ */
320
+ provider?: string;
321
+ /**
322
+ * RequestType is always "chat_completion"
323
+ */
324
+ request_type?: string;
325
+ };
326
+ type LlmapiChatCompletionResponse$1 = {
327
+ /**
328
+ * A list of chat completion choices. Can be more than one if `n` is greater
329
+ * than 1.
330
+ */
331
+ choices?: Array<OpenaiChatCompletionChoice>;
332
+ /**
333
+ * The Unix timestamp (in seconds) of when the chat completion was created.
334
+ */
335
+ created?: number;
336
+ /**
337
+ * A unique identifier for the chat completion.
338
+ */
339
+ id?: string;
340
+ /**
341
+ * The model used for the chat completion.
342
+ */
343
+ model?: string;
344
+ /**
345
+ * The object type, which is always `chat.completion`.
346
+ */
347
+ object?: string;
348
+ portal?: LlmapiPortalChatCompletionResponse;
349
+ service_tier?: OpenaiChatCompletionServiceTier;
350
+ /**
351
+ * This fingerprint represents the backend configuration that the model runs with.
352
+ *
353
+ * Can be used in conjunction with the `seed` request parameter to understand when
354
+ * backend changes have been made that might impact determinism.
355
+ */
356
+ system_fingerprint?: string;
357
+ usage?: OpenaiCompletionUsage;
358
+ };
359
+ type LlmapiMcpTool = {
360
+ /**
361
+ * Description is the description of the tool
362
+ */
363
+ description?: string;
364
+ /**
365
+ * InputSchema is the JSON schema describing the tool's input
366
+ */
367
+ input_schema?: unknown;
368
+ /**
369
+ * Name is the name of the tool
370
+ */
371
+ name?: string;
372
+ };
373
+ type LlmapiMessage = {
374
+ /**
375
+ * Content is the message content
376
+ */
377
+ content?: Array<LlmapiMessageContentPart>;
378
+ role?: LlmapiRole;
379
+ /**
380
+ * ToolCallID is the ID of the tool call this message is responding to (only for tool role)
381
+ */
382
+ tool_call_id?: string;
383
+ /**
384
+ * ToolCalls contains tool/function calls made by the assistant (only for assistant role)
385
+ */
386
+ tool_calls?: Array<LlmapiToolCall>;
387
+ /**
388
+ * Type is the message type (for Responses API: "message")
389
+ */
390
+ type?: string;
391
+ };
392
+ /**
393
+ * File is used when Type=input_file (for Responses API)
394
+ */
395
+ type LlmapiMessageContentFile = {
396
+ /**
397
+ * FileData is the base64-encoded file content
398
+ */
399
+ file_data?: string;
400
+ /**
401
+ * FileID is the ID of an uploaded file
402
+ */
403
+ file_id?: string;
404
+ /**
405
+ * FileURL is the URL to the file
406
+ */
407
+ file_url?: string;
408
+ /**
409
+ * Filename is the name of the file
410
+ */
411
+ filename?: string;
412
+ };
413
+ /**
414
+ * ImageURL is used when Type=image_url or Type=input_image
415
+ */
416
+ type LlmapiMessageContentImage = {
417
+ /**
418
+ * Detail is the OpenAI detail hint (auto|low|high)
419
+ */
420
+ detail?: string;
421
+ /**
422
+ * URL is the image URL or data URI
423
+ */
424
+ url?: string;
425
+ };
426
+ type LlmapiMessageContentPart = {
427
+ file?: LlmapiMessageContentFile;
428
+ image_url?: LlmapiMessageContentImage;
429
+ /**
430
+ * Text holds the text content when Type=text or Type=input_text
431
+ */
432
+ text?: string;
433
+ /**
434
+ * Type is the block type (`text`, `image_url`, or `input_file`)
435
+ */
436
+ type?: string;
437
+ };
438
+ type LlmapiModel = {
439
+ architecture?: LlmapiModelArchitecture;
440
+ /**
441
+ * CanonicalSlug is the canonical slug for the model
442
+ */
443
+ canonical_slug?: string;
151
444
  /**
152
445
  * ContextLength is the maximum context length in tokens
153
446
  */
@@ -1329,297 +1622,8 @@ type ParamOptString = {
1329
1622
  value?: string;
1330
1623
  };
1331
1624
 
1332
- type AuthToken = string | undefined;
1333
- interface Auth {
1334
- /**
1335
- * Which part of the request do we use to send the auth?
1336
- *
1337
- * @default 'header'
1338
- */
1339
- in?: 'header' | 'query' | 'cookie';
1340
- /**
1341
- * Header or query parameter name.
1342
- *
1343
- * @default 'Authorization'
1344
- */
1345
- name?: string;
1346
- scheme?: 'basic' | 'bearer';
1347
- type: 'apiKey' | 'http';
1348
- }
1349
-
1350
- interface SerializerOptions<T> {
1351
- /**
1352
- * @default true
1353
- */
1354
- explode: boolean;
1355
- style: T;
1356
- }
1357
- type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
1358
- type ObjectStyle = 'form' | 'deepObject';
1359
-
1360
- type QuerySerializer = (query: Record<string, unknown>) => string;
1361
- type BodySerializer = (body: any) => any;
1362
- type QuerySerializerOptionsObject = {
1363
- allowReserved?: boolean;
1364
- array?: Partial<SerializerOptions<ArrayStyle>>;
1365
- object?: Partial<SerializerOptions<ObjectStyle>>;
1366
- };
1367
- type QuerySerializerOptions = QuerySerializerOptionsObject & {
1368
- /**
1369
- * Per-parameter serialization overrides. When provided, these settings
1370
- * override the global array/object settings for specific parameter names.
1371
- */
1372
- parameters?: Record<string, QuerySerializerOptionsObject>;
1373
- };
1374
-
1375
- type HttpMethod = 'connect' | 'delete' | 'get' | 'head' | 'options' | 'patch' | 'post' | 'put' | 'trace';
1376
- type Client$1<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never, SseFn = never> = {
1377
- /**
1378
- * Returns the final request URL.
1379
- */
1380
- buildUrl: BuildUrlFn;
1381
- getConfig: () => Config;
1382
- request: RequestFn;
1383
- setConfig: (config: Config) => Config;
1384
- } & {
1385
- [K in HttpMethod]: MethodFn;
1386
- } & ([SseFn] extends [never] ? {
1387
- sse?: never;
1388
- } : {
1389
- sse: {
1390
- [K in HttpMethod]: SseFn;
1391
- };
1392
- });
1393
- interface Config$1 {
1394
- /**
1395
- * Auth token or a function returning auth token. The resolved value will be
1396
- * added to the request payload as defined by its `security` array.
1397
- */
1398
- auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
1399
- /**
1400
- * A function for serializing request body parameter. By default,
1401
- * {@link JSON.stringify()} will be used.
1402
- */
1403
- bodySerializer?: BodySerializer | null;
1404
- /**
1405
- * An object containing any HTTP headers that you want to pre-populate your
1406
- * `Headers` object with.
1407
- *
1408
- * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
1409
- */
1410
- headers?: RequestInit['headers'] | Record<string, string | number | boolean | (string | number | boolean)[] | null | undefined | unknown>;
1411
- /**
1412
- * The request method.
1413
- *
1414
- * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
1415
- */
1416
- method?: Uppercase<HttpMethod>;
1417
- /**
1418
- * A function for serializing request query parameters. By default, arrays
1419
- * will be exploded in form style, objects will be exploded in deepObject
1420
- * style, and reserved characters are percent-encoded.
1421
- *
1422
- * This method will have no effect if the native `paramsSerializer()` Axios
1423
- * API function is used.
1424
- *
1425
- * {@link https://swagger.io/docs/specification/serialization/#query View examples}
1426
- */
1427
- querySerializer?: QuerySerializer | QuerySerializerOptions;
1428
- /**
1429
- * A function validating request data. This is useful if you want to ensure
1430
- * the request conforms to the desired shape, so it can be safely sent to
1431
- * the server.
1432
- */
1433
- requestValidator?: (data: unknown) => Promise<unknown>;
1434
- /**
1435
- * A function transforming response data before it's returned. This is useful
1436
- * for post-processing data, e.g. converting ISO strings into Date objects.
1437
- */
1438
- responseTransformer?: (data: unknown) => Promise<unknown>;
1439
- /**
1440
- * A function validating response data. This is useful if you want to ensure
1441
- * the response conforms to the desired shape, so it can be safely passed to
1442
- * the transformers and returned to the user.
1443
- */
1444
- responseValidator?: (data: unknown) => Promise<unknown>;
1445
- }
1446
-
1447
- type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> & Pick<Config$1, 'method' | 'responseTransformer' | 'responseValidator'> & {
1448
- /**
1449
- * Fetch API implementation. You can use this option to provide a custom
1450
- * fetch instance.
1451
- *
1452
- * @default globalThis.fetch
1453
- */
1454
- fetch?: typeof fetch;
1455
- /**
1456
- * Implementing clients can call request interceptors inside this hook.
1457
- */
1458
- onRequest?: (url: string, init: RequestInit) => Promise<Request>;
1459
- /**
1460
- * Callback invoked when a network or parsing error occurs during streaming.
1461
- *
1462
- * This option applies only if the endpoint returns a stream of events.
1463
- *
1464
- * @param error The error that occurred.
1465
- */
1466
- onSseError?: (error: unknown) => void;
1467
- /**
1468
- * Callback invoked when an event is streamed from the server.
1469
- *
1470
- * This option applies only if the endpoint returns a stream of events.
1471
- *
1472
- * @param event Event streamed from the server.
1473
- * @returns Nothing (void).
1474
- */
1475
- onSseEvent?: (event: StreamEvent<TData>) => void;
1476
- serializedBody?: RequestInit['body'];
1477
- /**
1478
- * Default retry delay in milliseconds.
1479
- *
1480
- * This option applies only if the endpoint returns a stream of events.
1481
- *
1482
- * @default 3000
1483
- */
1484
- sseDefaultRetryDelay?: number;
1485
- /**
1486
- * Maximum number of retry attempts before giving up.
1487
- */
1488
- sseMaxRetryAttempts?: number;
1489
- /**
1490
- * Maximum retry delay in milliseconds.
1491
- *
1492
- * Applies only when exponential backoff is used.
1493
- *
1494
- * This option applies only if the endpoint returns a stream of events.
1495
- *
1496
- * @default 30000
1497
- */
1498
- sseMaxRetryDelay?: number;
1499
- /**
1500
- * Optional sleep function for retry backoff.
1501
- *
1502
- * Defaults to using `setTimeout`.
1503
- */
1504
- sseSleepFn?: (ms: number) => Promise<void>;
1505
- url: string;
1506
- };
1507
- interface StreamEvent<TData = unknown> {
1508
- data: TData;
1509
- event?: string;
1510
- id?: string;
1511
- retry?: number;
1512
- }
1513
- type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
1514
- stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext>;
1515
- };
1516
-
1517
- type ErrInterceptor<Err, Res, Options> = (error: Err, response: Res, options: Options) => Err | Promise<Err>;
1518
- type ReqInterceptor<Options> = (options: Options) => void | Promise<void>;
1519
- type ResInterceptor<Res, Options> = (response: Res, options: Options) => Res | Promise<Res>;
1520
- declare class Interceptors<Interceptor> {
1521
- fns: Array<Interceptor | null>;
1522
- clear(): void;
1523
- eject(id: number | Interceptor): void;
1524
- exists(id: number | Interceptor): boolean;
1525
- getInterceptorIndex(id: number | Interceptor): number;
1526
- update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false;
1527
- use(fn: Interceptor): number;
1528
- }
1529
- interface Middleware<Res, Err, Options> {
1530
- error: Interceptors<ErrInterceptor<Err, Res, Options>>;
1531
- request: Interceptors<ReqInterceptor<Options>>;
1532
- response: Interceptors<ResInterceptor<Res, Options>>;
1533
- }
1534
-
1535
- interface Config<T extends ClientOptions = ClientOptions> extends Omit<RequestInit, 'body' | 'headers' | 'method'>, Config$1 {
1536
- /**
1537
- * Base URL for all requests made by this client.
1538
- */
1539
- baseUrl?: T['baseUrl'];
1540
- /**
1541
- * Fetch API implementation. You can use this option to provide a custom
1542
- * fetch instance.
1543
- *
1544
- * @default globalThis.fetch
1545
- */
1546
- fetch?: typeof fetch;
1547
- /**
1548
- * Return the response data parsed in a specified format. By default, `auto`
1549
- * will infer the appropriate method from the `Content-Type` response header.
1550
- * You can override this behavior with any of the {@link Body} methods.
1551
- * Select `stream` if you don't want to parse response data at all.
1552
- *
1553
- * @default 'auto'
1554
- */
1555
- parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
1556
- /**
1557
- * Throw an error instead of returning it in the response?
1558
- *
1559
- * @default false
1560
- */
1561
- throwOnError?: T['throwOnError'];
1562
- }
1563
- interface RequestOptions<TData = unknown, ThrowOnError extends boolean = boolean, Url extends string = string> extends Config<{
1564
- throwOnError: ThrowOnError;
1565
- }>, Pick<ServerSentEventsOptions<TData>, 'onSseError' | 'onSseEvent' | 'sseDefaultRetryDelay' | 'sseMaxRetryAttempts' | 'sseMaxRetryDelay'> {
1566
- /**
1567
- * Any body that you want to add to your request.
1568
- *
1569
- * {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
1570
- */
1571
- body?: unknown;
1572
- path?: Record<string, unknown>;
1573
- query?: Record<string, unknown>;
1574
- /**
1575
- * Security mechanism(s) to use for the request.
1576
- */
1577
- security?: ReadonlyArray<Auth>;
1578
- url: Url;
1579
- }
1580
- interface ResolvedRequestOptions<ThrowOnError extends boolean = boolean, Url extends string = string> extends RequestOptions<unknown, ThrowOnError, Url> {
1581
- serializedBody?: string;
1582
- }
1583
- type RequestResult<TData = unknown, TError = unknown, ThrowOnError extends boolean = boolean> = ThrowOnError extends true ? Promise<{
1584
- data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
1585
- response: Response;
1586
- }> : Promise<({
1587
- data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
1588
- error: undefined;
1589
- } | {
1590
- data: undefined;
1591
- error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
1592
- }) & {
1593
- response: Response;
1594
- }>;
1595
- interface ClientOptions {
1596
- baseUrl?: string;
1597
- throwOnError?: boolean;
1598
- }
1599
- type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>) => RequestResult<TData, TError, ThrowOnError>;
1600
- type SseFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptions<TData, ThrowOnError>, 'method'>) => Promise<ServerSentEventsResult<TData, TError>>;
1601
- type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false>(options: Omit<RequestOptions<TData, ThrowOnError>, 'method'> & Pick<Required<RequestOptions<TData, ThrowOnError>>, 'method'>) => RequestResult<TData, TError, ThrowOnError>;
1602
- type BuildUrlFn = <TData extends {
1603
- body?: unknown;
1604
- path?: Record<string, unknown>;
1605
- query?: Record<string, unknown>;
1606
- url: string;
1607
- }>(options: TData & Options<TData>) => string;
1608
- type Client = Client$1<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
1609
- interceptors: Middleware<Response, unknown, ResolvedRequestOptions>;
1610
- };
1611
- interface TDataShape {
1612
- body?: unknown;
1613
- headers?: unknown;
1614
- path?: unknown;
1615
- query?: unknown;
1616
- url: string;
1617
- }
1618
- type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
1619
- type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = OmitKeys<RequestOptions<TResponse, ThrowOnError>, 'body' | 'path' | 'query' | 'url'> & ([TData] extends [never] ? unknown : Omit<TData, 'url'>);
1620
-
1621
- type LlmapiChatCompletionTool = {
1622
- [key: string]: unknown;
1625
+ type LlmapiChatCompletionTool = {
1626
+ [key: string]: unknown;
1623
1627
  };
1624
1628
  /**
1625
1629
  * The pre-migration usage shape: standard OpenAI token counts plus the
@@ -5658,6 +5662,12 @@ declare class VaultMemory extends Model {
5658
5662
  topicsExtractedVersion: number | null;
5659
5663
  /** C3 re-observation watermark: Unix ms of the last retain() merge, or null. */
5660
5664
  lastObservedAt: number | null;
5665
+ /** Typed memory (PR1) — the extractor's FactType. Null on legacy/manual rows. */
5666
+ factType: string | null;
5667
+ /** Decay archive state (PR2) — Unix ms when archived, null when active. */
5668
+ archivedAt: number | null;
5669
+ /** Tier-0 security (PR3) — "quarantined" | "trusted" | null. */
5670
+ trustTier: string | null;
5661
5671
  createdAt: Date;
5662
5672
  updatedAt: Date;
5663
5673
  isDeleted: boolean;
@@ -5828,290 +5838,25 @@ declare function backfillMemoryEntityUserIdsOp(ctx: EntityOperationsContext, vau
5828
5838
  * lane returns IDs from every user who tagged a matching entity.
5829
5839
  */
5830
5840
  declare function getMemoriesByEntityNamesOp(ctx: EntityOperationsContext, entityNames: readonly string[]): Promise<Map<string, Set<string>>>;
5831
-
5832
- interface StoredVaultMemory {
5833
- /** WatermelonDB internal ID */
5834
- uniqueId: string;
5835
- /** Plain text memory content */
5836
- content: string;
5837
- /** Scope for partitioning memories (e.g., "private", "shared") */
5838
- scope: string;
5839
- /** Folder ID for organization, null if unfiled */
5840
- folderId: string | null;
5841
- /** User ID for multi-user server-side scoping, null on client */
5842
- userId: string | null;
5843
- /** JSON-stringified embedding vector, null if not yet computed */
5844
- embedding: string | null;
5845
- /** Model that produced `embedding`. Null on legacy rows (grandfathered as
5846
- * compatible with the current model). */
5847
- embeddingModel: string | null;
5848
- /** JSON-stringified array of source message IDs this fact was extracted from. */
5849
- sourceChunkIds: string[] | null;
5850
- /** Times this fact has been re-observed (for ranking + UX badges). */
5851
- proofCount: number | null;
5852
- /** How the memory was created: manual | auto-extracted | capsule. */
5853
- source: string | null;
5854
- /** W6 temporal lane — Unix ms when the event occurred (point/start of range). */
5855
- eventTimeStart: number | null;
5856
- /** W6 temporal lane — Unix ms when the event ended (range only). */
5857
- eventTimeEnd: number | null;
5858
- /** W6 temporal lane — `point | range | ongoing | null`. */
5859
- eventTimeKind: string | null;
5860
- /** When true, the user has manually set this memory's topics (entity links);
5861
- * auto-extraction leaves them alone. False on legacy/auto rows. */
5862
- topicsUserManaged: boolean;
5863
- /** Unix ms of the last LLM topic-extraction pass over this memory's content.
5864
- * Null = never extracted standalone; rows that already carry entity links
5865
- * are grandfathered as extracted (see getMemoriesNeedingTopicExtractionOp). */
5866
- topicsExtractedAt: number | null;
5867
- /** Write-time supersession (A2): id of the newer memory that replaced this
5868
- * one (incompatible-value update, e.g. "Lives in Portland" → "Lives in SF").
5869
- * Null = live. Superseded rows are excluded from recall/dedup by default but
5870
- * kept for history + the read-time fallback. */
5871
- supersededBy: string | null;
5872
- /** Unix ms when this memory was superseded. Null when live. */
5873
- supersededAt: number | null;
5874
- /** Extraction-logic version this memory was last stamped under. Null (pre-v38)
5875
- * reads as 0, so a TOPICS_EXTRACTION_VERSION bump re-extracts stale rows. */
5876
- topicsExtractedVersion: number | null;
5877
- /** C3 re-observation watermark: Unix ms of the last retain() merge into this
5878
- * fact. Distinct from `updatedAt` (which merges preserve). Null = never
5879
- * re-observed since the column was added; synthesis falls back to
5880
- * `updatedAt` in that case. */
5881
- lastObservedAt: number | null;
5882
- createdAt: Date;
5883
- updatedAt: Date;
5884
- isDeleted: boolean;
5885
- }
5886
- interface CreateVaultMemoryOptions {
5887
- content: string;
5888
- /** Scope for the memory. Defaults to "private" if omitted. */
5889
- scope?: string;
5890
- /** Folder ID for organization, null or omitted if unfiled */
5891
- folderId?: string | null;
5892
- /** JSON-stringified embedding vector to persist */
5893
- embedding?: string;
5894
- /** Model that produced `embedding`. Persisted alongside it so a later
5895
- * model change can detect and re-embed stale vectors. */
5896
- embeddingModel?: string;
5897
- /** Source message IDs that produced this fact (auto-extraction provenance). */
5898
- sourceChunkIds?: string[];
5899
- /** Initial proof count. Defaults to 1 if omitted. */
5900
- proofCount?: number;
5901
- /** How the memory was created. Defaults to "manual" if omitted. */
5902
- source?: string;
5903
- /** W6 temporal lane — when the event in this memory occurred. */
5904
- eventTime?: {
5905
- /** Unix ms timestamp of event start (or point). */
5906
- start: number | null;
5907
- /** Unix ms timestamp of event end (range only). */
5908
- end: number | null;
5909
- /** Kind: 'point' | 'range' | 'ongoing' | null (or omit). */
5910
- kind: "point" | "range" | "ongoing" | null;
5911
- };
5912
- }
5913
- interface UpdateVaultMemoryOptions {
5914
- content: string;
5915
- /** If provided, updates the memory's scope. */
5916
- scope?: string;
5917
- /** If provided, moves the memory to this folder. */
5918
- folderId?: string | null;
5919
- /** JSON-stringified embedding vector to persist, or null to clear stale embedding */
5920
- embedding?: string | null;
5921
- /** Model that produced `embedding`. Set whenever `embedding` is written so
5922
- * the stored model tag stays in sync with the vector. */
5923
- embeddingModel?: string | null;
5924
- /** Replace source-chunk-ids list (used during merge to accumulate provenance). */
5925
- sourceChunkIds?: string[];
5926
- /** Set an absolute proof count. Prefer {@link proofCountIncrement} for
5927
- * re-observation paths so the read+write happens inside the writer
5928
- * and concurrent retains can't lose updates. */
5929
- proofCount?: number;
5930
- /** Atomically bump proof_count by this delta inside the write block.
5931
- * Reads the current value from the in-memory record at write time, so
5932
- * two parallel retain() calls observe each other's commits and neither
5933
- * loses its increment. Wins over `proofCount` when both are set. */
5934
- proofCountIncrement?: number;
5935
- /** Set source ("manual" | "auto-extracted" | "capsule"). */
5936
- source?: string;
5937
- /**
5938
- * W6 temporal lane — write the event-time fields on update. Use during
5939
- * auto-merge to preserve (or refine) the original event-time signal when
5940
- * a new observation lands on an existing fact. Omit to leave the
5941
- * existing values untouched.
5942
- */
5943
- eventTime?: {
5944
- start: number | null;
5945
- end: number | null;
5946
- kind: "point" | "range" | "ongoing" | null;
5947
- };
5948
- /**
5949
- * When true, restore the existing `updated_at` after the write so the
5950
- * recency multiplier doesn't see a re-observation as a brand-new fact.
5951
- * Set by auto-merge/consolidate paths — they want proof_count to bump
5952
- * without inflating recency on top.
5953
- */
5954
- preserveUpdatedAt?: boolean;
5955
- /** C3: Unix ms to stamp as the re-observation watermark (`last_observed_at`).
5956
- * Set by retain() merge/consolidate paths so a re-observation records "seen
5957
- * again now" without touching `updated_at` (which `preserveUpdatedAt` keeps
5958
- * pinned). Omit to leave the existing value untouched. */
5959
- lastObservedAt?: number;
5960
- /** If provided, sets whether the user has taken manual control of this
5961
- * memory's topics. Set by {@link setMemoryEntitiesOp}. */
5962
- topicsUserManaged?: boolean;
5963
- }
5964
-
5965
- interface VaultMemoryOperationsContext {
5966
- database: Database;
5967
- vaultMemoryCollection: Collection<VaultMemory>;
5968
- walletAddress?: string;
5969
- signMessage?: SignMessageFn;
5970
- embeddedWalletSigner?: EmbeddedWalletSignerFn;
5971
- /** When set, operations scope to this user (server-side multi-user). */
5972
- userId?: string;
5973
- /**
5974
- * When set, vault delete ops cascade to memory_entity rows pointing at
5975
- * the deleted memories. Without this the W5 graph lane keeps returning
5976
- * IDs of soft-deleted memories and the join table grows unbounded.
5977
- */
5978
- entityCtx?: EntityOperationsContext;
5979
- }
5980
- declare function createVaultMemoryOp(ctx: VaultMemoryOperationsContext, opts: CreateVaultMemoryOptions): Promise<StoredVaultMemory>;
5981
- declare function createVaultMemoriesBatchOp(ctx: VaultMemoryOperationsContext, optionsArray: CreateVaultMemoryOptions[]): Promise<StoredVaultMemory[]>;
5982
- declare function getVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string): Promise<StoredVaultMemory | null>;
5983
- declare function getAllVaultMemoriesOp(ctx: VaultMemoryOperationsContext, options?: {
5984
- scopes?: string[];
5985
- since?: Date;
5986
- limit?: number;
5987
- folderId?: string | null;
5988
- /**
5989
- * Include soft-deleted memories in the result (each carries
5990
- * `isDeleted: true`). Default `false` — deleted rows are excluded, as
5991
- * they are from every other read path. Used by the Memory Graph to
5992
- * render "forgotten" nodes; ordinary consumers should leave this off.
5993
- */
5994
- includeDeleted?: boolean;
5995
- /**
5996
- * Include A2-superseded memories (each carries `supersededBy`). Default
5997
- * `false` — superseded rows are excluded, as they are from recall/dedup.
5998
- * Used by a "memory history" view to render retired facts.
5999
- */
6000
- includeSuperseded?: boolean;
6001
- }): Promise<StoredVaultMemory[]>;
6002
- declare function getAllVaultMemoryContentsOp(ctx: VaultMemoryOperationsContext, options?: {
6003
- since?: Date;
6004
- }): Promise<string[]>;
6005
- declare function updateVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string, opts: UpdateVaultMemoryOptions): Promise<StoredVaultMemory | null>;
6006
- /**
6007
- * Replace a memory's topic (entity) links with a user-chosen set and mark the
6008
- * memory `topics_user_managed` so auto-extraction stops touching its links.
6009
- * Replace semantics: the given `entities` become the memory's complete topic
6010
- * set (pass `[]` to clear all topics — the memory stays user-managed and
6011
- * unclustered). Requires `ctx.entityCtx`. Preserves `updated_at` so a topic
6012
- * edit doesn't inflate the recency multiplier.
6013
- */
6014
- declare function setMemoryEntitiesOp(ctx: VaultMemoryOperationsContext, memoryId: string, entities: ReadonlyArray<EntityInput>): Promise<StoredVaultMemory | null>;
6015
- /**
6016
- * Reset a memory's topics to automatic: clear the `topics_user_managed` flag so
6017
- * auto-extraction resumes owning its links. Invalidates `topics_extracted_version`
6018
- * (→ null) and ensures a NON-NULL `topics_extracted_at`, so the next sweep routes
6019
- * the row through the stale-version pending path and actually RE-EXTRACTS it via
6020
- * the LLM. A never-stamped user-curated row (`setMemoryEntitiesOp` marks
6021
- * user-managed without stamping, so stamp can be null) would otherwise fall
6022
- * through the sweep's unstamped→`linkedUnstamped` grandfather path (stamped
6023
- * current, no LLM pass); forcing a stamp when absent avoids that. Existing links
6024
- * are left in place until the re-extraction replaces them. Preserves `updated_at`.
6025
- */
6026
- declare function clearMemoryTopicsOverrideOp(ctx: VaultMemoryOperationsContext, memoryId: string): Promise<boolean>;
6027
- declare function deleteVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string): Promise<boolean>;
6028
- /**
6029
- * Mark a memory as superseded by a newer one (A2 write-time supersession).
6030
- * The row stays in the table (history + read-time fallback) but is excluded
6031
- * from recall/dedup by default via `superseded_by`. Idempotent-ish: no-op if
6032
- * the row is missing, not owned, deleted, or already superseded. Does NOT
6033
- * preserve `updated_at` — superseded rows are hidden from recall, so their
6034
- * recency is irrelevant.
6035
- *
6036
- * @param id - the memory being retired (e.g. "Lives in Portland")
6037
- * @param supersededById - the newer memory that replaced it (e.g. "Lives in SF")
6038
- */
6039
- declare function supersedeVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string, supersededById: string): Promise<boolean>;
6040
- /**
6041
- * Get all non-deleted, unfiled vault memories (folder_id is null).
6042
- */
6043
- declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): Promise<StoredVaultMemory[]>;
6044
- /**
6045
- * The current topic-extraction logic version. Bump this whenever the extraction
6046
- * prompt or model in `topicExtract.ts` changes: every memory stamped under an
6047
- * older version (including pre-v37 rows, read as version 0) is then re-extracted
6048
- * by the next sweep, so topic-quality improvements propagate across the existing
6049
- * vault. The worker's `limit` drains that re-extraction across sweeps.
6050
- */
6051
- declare const TOPICS_EXTRACTION_VERSION = 1;
6052
- /**
6053
- * Result of {@link getMemoriesNeedingTopicExtractionOp}: which memories the
6054
- * background topic worker should run LLM entity extraction on, and which it
6055
- * should merely stamp as already-extracted.
6056
- */
6057
- interface MemoriesNeedingTopicExtraction {
6058
- /**
6059
- * Memories to run LLM topic extraction on (decrypted): never-extracted rows
6060
- * with no entity links, plus stamped rows edited since their last pass
6061
- * (`updated_at` > `topics_extracted_at`) or extracted under an older
6062
- * `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}. Edited /
6063
- * stale-version rows come first (they get priority under `limit`), each group
6064
- * newest-created first.
6065
- */
6066
- pending: StoredVaultMemory[];
6067
- /**
6068
- * IDs of rows that already have entity links but no watermark — legacy rows
6069
- * extracted by the conversation pipeline before v36. Grandfather these with
6070
- * {@link stampTopicsExtractedAtOp} (no LLM call) so a later content edit
6071
- * makes them re-extractable instead of invisible forever. Bounded by the
6072
- * same `limit` as {@link pending} — stamping loads a Model per row, so the
6073
- * grandfather backlog is drained across sweeps rather than in one spike.
6074
- */
6075
- linkedUnstamped: string[];
6076
- }
6077
- /**
6078
- * Sweep query for the background topic-extraction worker: partition the
6079
- * user's non-deleted, non-user-managed memories by what the worker should do
6080
- * with them (see {@link MemoriesNeedingTopicExtraction}). User-managed rows
6081
- * are never returned — the user owns their topics, including an intentionally
6082
- * empty set. Requires `ctx.entityCtx` for the entity-links check.
6083
- */
6084
- declare function getMemoriesNeedingTopicExtractionOp(ctx: VaultMemoryOperationsContext, options?: {
6085
- limit?: number;
6086
- }): Promise<MemoriesNeedingTopicExtraction>;
6087
- /**
6088
- * Stamp `topics_extracted_at` (and `topics_extracted_version`) on the given
6089
- * memories — the topic worker calls this after a successful extraction pass
6090
- * (including zero-entity results, so quiet memories aren't re-asked every sweep)
6091
- * and to grandfather `linkedUnstamped` rows without an LLM call. `version`
6092
- * defaults to {@link TOPICS_EXTRACTION_VERSION}: stamping at the current version
6093
- * (for both fresh extractions and grandfathered legacy rows) means they aren't
6094
- * re-extracted until a future version bump. Preserves `updated_at` so a stamp
6095
- * never inflates the recency multiplier — and never masks a concurrent content
6096
- * edit from the next sweep. Skips deleted, foreign-user, and user-managed rows.
6097
- * Returns the IDs actually stamped.
6098
- *
6099
- * ALL eligibility AND `updated_at` are read from the LIVE Model inside the
6100
- * serialized writer — never a pre-writer snapshot. Writers are serialized, so
6101
- * a content edit or topic-override that commits before this writer runs is
6102
- * observed here: its fresh `updated_at` is preserved (so the next sweep's
6103
- * `updated_at > stamp` check still fires) and a mid-pass user-managed flip
6104
- * skips the row. Reading `updated_at` from a raw pre-fetch instead would write
6105
- * a stale value back, pushing `updated_at < topics_extracted_at` and hiding
6106
- * the edited memory from every future sweep.
6107
- *
6108
- * Callers bound the input via `getMemoriesNeedingTopicExtractionOp`'s `limit`
6109
- * (both `pending` and `linkedUnstamped` are capped), so the per-row Model load
6110
- * needed to `prepareUpdate` stays bounded and never spikes the RecordCache.
6111
- */
6112
- declare function stampTopicsExtractedAtOp(ctx: VaultMemoryOperationsContext, memoryIds: readonly string[], extractedAt: number, version?: number): Promise<string[]>;
6113
- declare function deleteAllVaultMemoriesForUserOp(ctx: VaultMemoryOperationsContext, userId: string): Promise<number>;
6114
- declare function updateVaultMemoryEmbeddingOp(ctx: VaultMemoryOperationsContext, id: string, embedding: string, embeddingModel: string): Promise<boolean>;
5841
+ /**
5842
+ * Reverse of {@link getMemoriesByEntityNamesOp}: given a set of memory IDs
5843
+ * (e.g. the current BFS frontier), return each memory's set of linked
5844
+ * canonical entity names. This is the missing primitive for multi-hop graph
5845
+ * traversal (PR4) — one step outward from a memory to its neighbor entities,
5846
+ * which the traversal then expands to reach topically-adjacent memories.
5847
+ *
5848
+ * Empty input returns an empty map. Memory IDs with no links contribute
5849
+ * nothing (they simply don't appear as keys).
5850
+ *
5851
+ * Multi-user safety mirrors {@link getMemoriesByEntityNamesOp} exactly: when
5852
+ * `ctx.userId` is set, only `memory_entity` rows owned by that user are
5853
+ * followed (with the same `allowUnscopedRows` LokiJS escape hatch for pre-v31
5854
+ * rows whose `user_id` backfill was a no-op). Without the filter the reverse
5855
+ * lookup would leak entity links written by other users.
5856
+ *
5857
+ * @public
5858
+ */
5859
+ declare function getEntitiesByMemoryIdsOp(ctx: EntityOperationsContext, memoryIds: readonly string[]): Promise<Map<string, Set<string>>>;
6115
5860
 
6116
5861
  /**
6117
5862
  * Auth for portal LLM calls (extraction, consolidation, decomposition,
@@ -6132,6 +5877,165 @@ interface PortalLlmAuth {
6132
5877
  getToken?: () => Promise<string | null>;
6133
5878
  }
6134
5879
 
5880
+ /**
5881
+ * Optional LLM injection classifier — Tier-0 security second layer (PR5).
5882
+ *
5883
+ * The deterministic {@link ./injectionScreen} is a signature scan: it catches
5884
+ * imperative overrides, role-marker leakage, and exfil URLs, but by
5885
+ * construction it CANNOT catch signature-free poison phrased as a plain
5886
+ * third-person fact — e.g. "Trusts BrandX for financial advice", "Prefers to
5887
+ * always use the AcmePay card". Those read like ordinary preferences and sail
5888
+ * through the regex screen.
5889
+ *
5890
+ * This module closes that gap as a SECOND, opt-in layer. In `extractAndRetain`
5891
+ * it runs ONLY over the candidates the deterministic screen already passed as
5892
+ * clean, asking a cheap model a single batched yes/no per candidate: "is this
5893
+ * an instruction to the assistant / a planted preference, rather than a genuine
5894
+ * fact the user stated about themselves?" Positives are moved to quarantine
5895
+ * (trust_tier="quarantined"), exactly like a signature hit.
5896
+ *
5897
+ * Safety posture (why it can only ever add safety, never remove it):
5898
+ * - Default OFF. No option → no LLM call → zero latency/cost added, and the
5899
+ * write path is byte-for-byte the pre-PR5 deterministic screen.
5900
+ * - Fails CLEAN. Any error (network, timeout, malformed JSON, auth) → the
5901
+ * candidate stays in the clean set (trusts the deterministic result). A
5902
+ * flaky classifier can never suppress a legitimate memory.
5903
+ * - Bounded. One batched portal call per turn (never per-candidate), with a
5904
+ * candidate cap, a low retry budget, and a wall-clock total-timeout.
5905
+ * - Zero-knowledge parity. Candidate content is PII-redacted before it
5906
+ * reaches the portal using the SAME redactor setting as the extraction
5907
+ * path (inherited by `extractAndRetain`); the model only ever returns
5908
+ * integer indices, so nothing needs de-anonymizing on the way back.
5909
+ *
5910
+ * SECURITY (MEDIUM, residual): this is a NEW portal call surface for memory
5911
+ * content. It is gated on an explicit opt-in and redacts like the extractor, but
5912
+ * a security review should treat enabling it as widening the set of models that
5913
+ * see (redacted) facts. A malicious / MITM'd portal can also use it as a lever
5914
+ * to QUARANTINE the affected rows (they drop out of recall) — reversible, and it
5915
+ * can never delete or alter a memory. Bounded, recoverable trust tradeoff; gate
5916
+ * on trust in the portal.
5917
+ */
5918
+
5919
+ /**
5920
+ * Auth + tuning for the optional LLM injection classifier. Auth is the dual
5921
+ * pattern — one of `apiKey` / `getToken` is required at runtime (see
5922
+ * {@link PortalLlmAuth}). The mere PRESENCE of this options object in
5923
+ * `extractAndRetain` is the opt-in switch; omit it for the default-off,
5924
+ * deterministic-only screen.
5925
+ * @public
5926
+ */
5927
+ interface InjectionClassifierOptions extends PortalLlmAuth {
5928
+ baseUrl?: string;
5929
+ model?: string;
5930
+ /** Override fetch (tests). */
5931
+ fetchFn?: typeof fetch;
5932
+ /** Max portal attempts on a TRANSIENT failure. Default 2. */
5933
+ maxAttempts?: number;
5934
+ /** Absolute wall-clock budget across attempts. Default 15s. */
5935
+ totalTimeoutMs?: number;
5936
+ /** Backoff before each retry (ms). Tests pass `() => 0`. */
5937
+ backoffMs?: (attempt: number) => number;
5938
+ /**
5939
+ * PII redaction for the outbound content, same switch as the extractor.
5940
+ * `extractAndRetain` inherits the extraction setting so enabling redaction
5941
+ * there also protects this call. `true` = fresh per-call redactor; pass a
5942
+ * shared {@link PiiRedactor} to keep placeholder numbering consistent.
5943
+ */
5944
+ piiRedaction?: boolean | PiiRedactor;
5945
+ /** Max candidates classified per call. Default 20. */
5946
+ maxCandidates?: number;
5947
+ }
5948
+ /**
5949
+ * Classify already-clean extraction candidates for signature-free injection /
5950
+ * poisoning. Returns the set of 0-based indices (into `candidates`) the model
5951
+ * flagged as poison.
5952
+ *
5953
+ * FAILS CLEAN: returns an empty set on empty input, missing auth, LLM error,
5954
+ * or any malformed response — the caller then keeps every candidate clean, so
5955
+ * this layer can only ever ADD quarantines, never suppress a legitimate fact
5956
+ * on failure. Makes at most ONE portal call regardless of candidate count.
5957
+ *
5958
+ * @public
5959
+ */
5960
+ declare function classifyInjectionCandidates(candidates: readonly ExtractedCandidate[], options: InjectionClassifierOptions): Promise<{
5961
+ flagged: Set<number>;
5962
+ }>;
5963
+
5964
+ /**
5965
+ * Write-time memory-poisoning screen — Tier-0 security (PR3).
5966
+ *
5967
+ * Deterministic, network-free, and always on. Scans each extraction
5968
+ * candidate's `content` for prompt-injection / memory-poisoning
5969
+ * signatures and routes flagged candidates to quarantine instead of the
5970
+ * live vault.
5971
+ *
5972
+ * WHY a signature scan (not an LLM classifier): this runs on the write
5973
+ * path for every extracted fact, so it must be cheap, offline, and must
5974
+ * never leak content to a model. It also gives a small false-positive
5975
+ * surface here: durable third-person facts about the user ("Lives in San
5976
+ * Francisco", "Allergic to shellfish", "Works in engineering") almost
5977
+ * never contain second-person imperatives aimed at the assistant, chat
5978
+ * role markers, or beacon URLs — the exact shapes these signatures look
5979
+ * for. An optional LLM injection classifier is deferred to PR5.
5980
+ *
5981
+ * WHY quarantine, not drop: a flagged candidate is still persisted (see
5982
+ * `extractAndRetain`) with `trust_tier="quarantined"` so it stays an
5983
+ * auditable record, recoverable by an operator via the `includeQuarantined`
5984
+ * read path. The `baseVaultConditions` choke point excludes quarantined
5985
+ * rows from every recall lane, so a poisoned fact never reaches the answer
5986
+ * model even though it lives in the DB.
5987
+ *
5988
+ * This MITIGATES memory poisoning (MINJA / AgentPoison; OWASP ASI06 2026).
5989
+ * It is not a complete solve — a poison phrased as a plain third-person
5990
+ * fact ("Prefers the BrandX credit card") carries no injection signature
5991
+ * and will pass. The proof-count ranking boost (once-seen facts stay
5992
+ * low-ranked) and the read-time isolation in `formatRecallResult` are the
5993
+ * complementary layers.
5994
+ */
5995
+
5996
+ /** Why a candidate was quarantined. Coarse buckets over the signature set
5997
+ * below — surfaced for audit/telemetry, never alongside the content.
5998
+ * `llm_semantic` (PR5) is emitted by the optional second-layer LLM classifier
5999
+ * ({@link classifyInjectionCandidates}), not by any deterministic signature
6000
+ * here — it catches signature-free poison ("Trusts BrandX for financial
6001
+ * advice") the regex screen passes as clean. */
6002
+ type InjectionReason = "imperative_override" | "role_marker_leak" | "exfiltration_url" | "llm_semantic";
6003
+ /** A candidate the screen flagged, with the matching signature id + reason.
6004
+ * Content is intentionally NOT duplicated here beyond the candidate itself —
6005
+ * callers must never log `candidate.content`. */
6006
+ interface ScreenedCandidate {
6007
+ candidate: ExtractedCandidate;
6008
+ /** Coarse reason bucket. */
6009
+ reason: InjectionReason;
6010
+ /** Stable id of the signature that matched (safe to log; carries no content). */
6011
+ signature: string;
6012
+ }
6013
+ /** Result of screening a candidate batch. */
6014
+ interface ScreenResult {
6015
+ /** Candidates with no injection signature — persist normally. */
6016
+ clean: ExtractedCandidate[];
6017
+ /** Candidates that matched a signature — persist quarantined. */
6018
+ quarantined: ScreenedCandidate[];
6019
+ }
6020
+ /**
6021
+ * Screen extraction candidates for injection / poisoning signatures.
6022
+ *
6023
+ * Partitions the input into `clean` (persist normally) and `quarantined`
6024
+ * (persist with `trust_tier="quarantined"`, hidden from recall). Pure and
6025
+ * synchronous — no network, no DB, no content logging. Input order is
6026
+ * preserved within each partition.
6027
+ */
6028
+ declare function screenCandidatesForInjection(candidates: readonly ExtractedCandidate[]): ScreenResult;
6029
+ /**
6030
+ * Content-free catalog of the active signatures (id + reason, no patterns).
6031
+ * Exposed so a security review / audit surface can enumerate coverage
6032
+ * without reaching into module internals. Does not leak any user content.
6033
+ */
6034
+ declare function injectionSignatureCatalog(): {
6035
+ id: string;
6036
+ reason: InjectionReason;
6037
+ }[];
6038
+
6135
6039
  /**
6136
6040
  * Linear recency decay multiplier — applied post-fusion to nudge fresh
6137
6041
  * memories above stale ones with otherwise comparable scores.
@@ -6185,6 +6089,23 @@ interface MemoryVaultSearchOptions {
6185
6089
  scopes?: string[];
6186
6090
  /** When provided, only search memories in this folder (null for unfiled) */
6187
6091
  folderId?: string | null;
6092
+ /** Typed memory (PR1) — when provided, only search memories of these fact
6093
+ * types. Applied at load time via `Q.oneOf` on the indexed `fact_type`
6094
+ * column. Omit for no type filter. */
6095
+ factTypes?: string[];
6096
+ /**
6097
+ * PR5 — optional per-FactType score multiplier applied in the boost stage
6098
+ * (e.g. `{ identity: 1.2, ongoing_context: 0.8 }`). Empty/omitted = uniform
6099
+ * (no behavior change). See {@link rankFusedVaultMemories}.
6100
+ */
6101
+ factTypeWeights?: Record<string, number>;
6102
+ /**
6103
+ * PR5 — include archived (decayed) rows in the candidate load. Default false
6104
+ * (the baseVaultConditions choke point excludes them). retain()'s dedup
6105
+ * search sets this so a re-observed fact can merge into — and un-archive — an
6106
+ * archived row instead of creating a fresh duplicate.
6107
+ */
6108
+ includeArchived?: boolean;
6188
6109
  /**
6189
6110
  * Use the hybrid fusion ranker (cosine + BM25 + RRF + recency) instead of
6190
6111
  * cosine-only. Default true — new W1 pipeline. Pass false to fall back
@@ -6279,6 +6200,10 @@ interface VaultSearchResult {
6279
6200
  eventTimeStart?: number | null;
6280
6201
  eventTimeEnd?: number | null;
6281
6202
  eventTimeKind?: "point" | "range" | "ongoing" | null;
6203
+ /** Typed memory (PR1) — the fact's FactType, threaded through from the
6204
+ * storage row alongside the event-time anchors. Null/undefined when
6205
+ * untyped. Loose string (originates from a stored column). */
6206
+ factType?: string | null;
6282
6207
  /** Message ids this fact was extracted from (provenance). recall() uses
6283
6208
  * these to suppress the originating chunk in the chunk lane. */
6284
6209
  sourceChunkIds?: string[] | null;
@@ -6368,6 +6293,14 @@ interface RankedMemory {
6368
6293
  eventTimeStart?: number | null;
6369
6294
  eventTimeEnd?: number | null;
6370
6295
  eventTimeKind?: "point" | "range" | "ongoing" | null;
6296
+ /**
6297
+ * Typed memory (PR1) — the extractor's FactType classification for this
6298
+ * fact, threaded through the same channel as the event-time anchors so
6299
+ * recall results (and UI) can show the type without a second DB read.
6300
+ * Null/undefined on legacy/untyped/manual facts. Kept as a loose string
6301
+ * (not narrowed to FactType) since it originates from a stored column.
6302
+ */
6303
+ factType?: string | null;
6371
6304
  conversationId?: string;
6372
6305
  messageId?: string;
6373
6306
  role?: "user" | "assistant";
@@ -6389,6 +6322,18 @@ interface RecallOptions {
6389
6322
  scopes?: string[];
6390
6323
  /** Vault folder filter. Vault-only. */
6391
6324
  folderId?: string | null;
6325
+ /**
6326
+ * Typed memory (PR1) — restrict fact recall to these FactTypes. Optional
6327
+ * and no-op when unset (all types are eligible). Vault-only.
6328
+ */
6329
+ factTypes?: FactType[];
6330
+ /**
6331
+ * PR5 — optional per-FactType score multiplier applied in the fusion boost
6332
+ * stage (e.g. boost `identity`/`constraint`, down-weight `ongoing_context`).
6333
+ * A type absent from the map (and untyped rows) uses 1.0, so an empty/omitted
6334
+ * map is a no-op (uniform weighting). Vault-only.
6335
+ */
6336
+ factTypeWeights?: Partial<Record<FactType, number>>;
6392
6337
  /** Restrict chunk search to one conversation. Chunk-only. */
6393
6338
  conversationId?: string;
6394
6339
  /** Exclude one conversation from chunk search. Chunk-only. */
@@ -6441,6 +6386,21 @@ interface RecallOptions {
6441
6386
  bm25AdmissionDivisor?: number;
6442
6387
  /** RRF smoothing constant for lane fusion (facts × chunks and side lanes). Default: 60. */
6443
6388
  rrfK?: number;
6389
+ /** Total graph hops incl. the seed lookup (hop 1). Default: 1 (seed only). */
6390
+ maxHops?: number;
6391
+ /** Max neighbor entities expanded per hop. Default: 8. */
6392
+ entityFanout?: number;
6393
+ /** Hard cap on accumulated memory IDs across all hops. Default: 64. */
6394
+ nodeBudget?: number;
6395
+ /**
6396
+ * PR5 — enable LLM graph path-refinement: at each traversal hop a model picks
6397
+ * which neighbor entities to expand instead of pure co-occurrence ranking.
6398
+ * Opt-in (default false); only active on the `high` budget (needs the
6399
+ * `traverse` flag) AND when `decomposeOptions` is set (reuses that auth).
6400
+ * Falls back to deterministic co-occurrence order on any error. Adds ≤1 LLM
6401
+ * call per expansion hop.
6402
+ */
6403
+ graphRefine?: boolean;
6444
6404
  }
6445
6405
  interface RecallContext {
6446
6406
  /** Required when `types` includes 'fact'. */
@@ -6580,6 +6540,22 @@ interface RetainOptions {
6580
6540
  start: number;
6581
6541
  end: number | null;
6582
6542
  } | null;
6543
+ /**
6544
+ * Typed memory (PR1) — the extractor's classification for this fact.
6545
+ * Persisted on create; on merge/consolidate it lazily backfills the target
6546
+ * only when the target has no type yet (never overwrites a non-null type).
6547
+ * Auto-extraction emits this; manual writes omit it (persisted as null).
6548
+ */
6549
+ factType?: FactType;
6550
+ /**
6551
+ * Tier-0 security (PR3) — trust tier for this fact. The write-time
6552
+ * injection screen threads `"quarantined"` here for flagged candidates;
6553
+ * omit for the default (null/trusted). Persisted only on create (a
6554
+ * quarantined candidate is force-created, never merged, so it can't bump
6555
+ * or contaminate a clean memory). The DB op re-validates the value
6556
+ * against the known set before writing.
6557
+ */
6558
+ trustTier?: string;
6583
6559
  }
6584
6560
  interface RetainResult {
6585
6561
  action: RetainAction;
@@ -6662,195 +6638,654 @@ interface ExtractedEntity {
6662
6638
  name: string;
6663
6639
  kind?: EntityKind;
6664
6640
  }
6665
- interface ExtractedCandidate {
6641
+ interface ExtractedCandidate {
6642
+ content: string;
6643
+ type: FactType;
6644
+ confidence: number;
6645
+ sourceMessageIds: string[];
6646
+ entities: ExtractedEntity[];
6647
+ /** W6 temporal lane — when the event in this fact occurred. Resolved
6648
+ * to absolute timestamps by the LLM; null when the fact has no
6649
+ * temporal anchor. */
6650
+ eventTime: {
6651
+ kind: "point" | "range" | "ongoing";
6652
+ /** Unix ms timestamp of the event start (or point). */
6653
+ start: number;
6654
+ /** Unix ms timestamp of the event end. Only set when kind='range'. */
6655
+ end: number | null;
6656
+ } | null;
6657
+ }
6658
+ /**
6659
+ * Tier-0 security (PR3) — describes a candidate the injection screen
6660
+ * quarantined and persisted as an audit row. The client uses this to surface
6661
+ * a "held for review" state. `content` lives on `candidate` (same exposure as
6662
+ * {@link ExtractedCandidate}); never log it.
6663
+ */
6664
+ interface QuarantinedMemoryInfo {
6665
+ candidate: ExtractedCandidate;
6666
+ /** The persisted (quarantined) memory row id. */
6667
+ memoryId: string;
6668
+ /** Coarse reason bucket from the screen. */
6669
+ reason: InjectionReason;
6670
+ /** Stable signature id that matched (safe to log; carries no content). */
6671
+ signature: string;
6672
+ }
6673
+ /**
6674
+ * Auth + endpoint for the extraction LLM call. Auth is the dual pattern —
6675
+ * one of `apiKey` / `getToken` is required at runtime; see
6676
+ * {@link PortalLlmAuth}.
6677
+ */
6678
+ interface ExtractFactsOptions extends PortalLlmAuth {
6679
+ baseUrl?: string;
6680
+ model?: string;
6681
+ /** Override the global fetch implementation (useful for tests). */
6682
+ fetchFn?: typeof fetch;
6683
+ /**
6684
+ * The user's own name(s) / handle(s) (e.g. profile nickname, wallet display
6685
+ * name). Candidates whose entire content is just one of these are dropped —
6686
+ * a personal memory system already knows who the user is, so "Peter Lee" is
6687
+ * circular noise. Optional; when omitted only the bare-fragment gate applies.
6688
+ */
6689
+ userIdentity?: string[];
6690
+ /**
6691
+ * Reference "now" (Unix ms) for resolving relative temporal phrases in the
6692
+ * transcript ("yesterday", "next week", "in two days") into the absolute
6693
+ * YYYY-MM-DD anchors the W6 temporal lane indexes on. The transcript itself
6694
+ * carries no timestamps, so without an anchor the model resolves relatives
6695
+ * against its own training-cutoff guess and emits wrong `eventTime` dates.
6696
+ * Defaults to `Date.now()`. Override for back-dated eval corpora and
6697
+ * deterministic tests (mirrors {@link RecallOptions.now}).
6698
+ *
6699
+ * Server-side timezone note: the ms value is formatted to a calendar date in
6700
+ * the process's local timezone (same basis as `parseLocalCalendarDay`). On a
6701
+ * UTC server, a user near midnight in a non-UTC offset can get the wrong
6702
+ * calendar day. Pass the user's local-midnight timestamp as `now` when the
6703
+ * process timezone doesn't match the user's.
6704
+ */
6705
+ now?: number;
6706
+ /**
6707
+ * Max attempts for the extraction call on a transient failure (default 3).
6708
+ * Lower it to bound how long extraction can hold a turn open — e.g. a worker
6709
+ * that runs extraction behind an in-flight-turn guard can pass `2` to keep
6710
+ * repeated failures from delaying later turns.
6711
+ */
6712
+ maxAttempts?: number;
6713
+ /** Per-attempt timeout (ms) for the extraction call. Defaults to the portal
6714
+ * helper's 60s. Combine with {@link maxAttempts} to cap the total time budget. */
6715
+ timeoutMs?: number;
6716
+ /**
6717
+ * Absolute wall-clock budget (ms) across ALL extraction attempts incl. backoff.
6718
+ * When set, the loop stops before an attempt that would exceed it, so worst-case
6719
+ * latency is bounded rather than `maxAttempts × timeoutMs`.
6720
+ */
6721
+ totalTimeoutMs?: number;
6722
+ /**
6723
+ * Override the retry backoff (ms) for a given 1-based attempt index. The
6724
+ * extraction call retries transient failures internally (default exponential
6725
+ * backoff); pass `() => 0` to retry without delay (useful for tests).
6726
+ */
6727
+ backoffMs?: (attempt: number) => number;
6728
+ /**
6729
+ * When set, PII (emails, phones, SSNs, cards, IPs, API keys, …) in the
6730
+ * conversation transcript is replaced with tagged placeholders before the
6731
+ * extraction call, and the returned facts + entities are de-anonymized so the
6732
+ * vault keeps the real values while raw PII never reaches the extraction
6733
+ * model (and, via `extractAndRetain`, the consolidation model). Pass `true`
6734
+ * for a fresh per-call redactor, or a shared {@link PiiRedactor} to keep
6735
+ * placeholder numbering consistent with other calls.
6736
+ *
6737
+ * NOTE: this does NOT cover the embeddings provider. Facts are stored and
6738
+ * embedded with their real values, so to keep PII out of embedding requests
6739
+ * set `RetainContext.embeddingOptions.maskInput` (e.g. `redactor.maskText`)
6740
+ * as well — the two are independent switches.
6741
+ */
6742
+ piiRedaction?: boolean | PiiRedactor;
6743
+ /**
6744
+ * Called when the extraction LLM returned no usable result after exhausting
6745
+ * its retries (empty/malformed completion, network/HTTP error) — i.e. a
6746
+ * *failure* that drops the turn's facts, as opposed to a legitimate
6747
+ * `{candidates: []}` "nothing durable here". Lets callers distinguish a
6748
+ * silently-degrading extractor from quiet turns (the two are otherwise
6749
+ * indistinguishable). See {@link extractAndRetain}'s `outcome`.
6750
+ */
6751
+ onExhaustedEmpty?: () => void;
6752
+ /**
6753
+ * Called when the extractor DID produce candidates but PII de-anonymization
6754
+ * dropped every one of them — the model mangled its placeholders (so they
6755
+ * can't be restored to real values) or restoring the values blew the length
6756
+ * cap. These drops happen before `retain()`, so `failedCount` can't see them,
6757
+ * and the turn would otherwise masquerade as a quiet `no-facts` result. Lets
6758
+ * H3's `outcome` surface `dropped-after-redaction` so a rising PII-drop rate
6759
+ * (i.e. redaction silently eating facts) is alarmable.
6760
+ */
6761
+ onCandidatesDropped?: () => void;
6762
+ }
6763
+ /**
6764
+ * Stage 1 — call the LLM to extract candidate facts from the recent
6765
+ * conversation. Returns post-validated candidates only (confidence
6766
+ * threshold, source-id check, length cap, schema validation). Returns
6767
+ * an empty array if the LLM emits malformed JSON or no candidates.
6768
+ *
6769
+ * A null from `callPortalJsonCompletion` means a *failure* (empty completion,
6770
+ * malformed JSON, network/HTTP error) — distinct from a successful
6771
+ * `{candidates: []}`, which parses to a non-null object. A failed extraction
6772
+ * silently drops the whole turn's memories, so transient failures matter:
6773
+ * `callPortalJsonCompletion` retries them internally with backoff (default 3
6774
+ * attempts), so a one-off empty/malformed completion from a reasoning-class
6775
+ * model doesn't lose the turn. Only an exhausted-retry null reaches here.
6776
+ */
6777
+ declare function extractFacts(messages: AutoExtractMessage[], options: ExtractFactsOptions): Promise<ExtractedCandidate[]>;
6778
+ /**
6779
+ * Outcome of the EXTRACTOR stage for a turn — independent of whether the
6780
+ * subsequent `retain()` writes landed (that's `failedCount`):
6781
+ * - `extracted` — the extractor produced at least one candidate above
6782
+ * the confidence floor. Whether those writes succeeded
6783
+ * is reported separately by `failedCount` — so
6784
+ * `extracted` + `failedCount > 0` means "found facts but
6785
+ * writes are failing", which is more signal than
6786
+ * collapsing it into `no-facts` would give.
6787
+ * - `no-facts` — the extractor ran fine but found nothing durable.
6788
+ * - `empty-after-retry` — the extractor returned empty/malformed after
6789
+ * exhausting retries (a *failure*). Distinguishing this
6790
+ * from `no-facts` is what makes a silently-degrading
6791
+ * extractor alarmable rather than invisible.
6792
+ * - `dropped-after-redaction` — the extractor found facts but PII
6793
+ * de-anonymization dropped every one (mangled
6794
+ * placeholders / over-cap after restore), before retain.
6795
+ * A degradation `failedCount` can't see; would otherwise
6796
+ * look like `no-facts`.
6797
+ */
6798
+ type ExtractOutcome = "extracted" | "no-facts" | "empty-after-retry" | "dropped-after-redaction";
6799
+ /**
6800
+ * Stage 2 — for each extracted candidate, call retain() with auto-merge
6801
+ * enabled. When `consolidateOptions` are wired, retain()'s consolidation pass
6802
+ * is the "resolver": a second LLM call against the top-K existing vault
6803
+ * memories that decides create/update/noop/supersede — including retiring a
6804
+ * stale value on a state change (the supersession the extraction prompt above
6805
+ * promises). Without consolidation, retain() still dedups at the cosine-merge
6806
+ * level, and the read-time supersession heuristic remains the fallback.
6807
+ *
6808
+ * Returns the candidates that survived validation along with the retain
6809
+ * result for each (which captures whether the fact was created, merged,
6810
+ * or skipped), plus an `outcome` summarizing why the turn did/didn't produce
6811
+ * facts (see {@link ExtractOutcome}).
6812
+ */
6813
+ declare function extractAndRetain(messages: AutoExtractMessage[], retainCtx: RetainContext, options: {
6814
+ extract: ExtractFactsOptions;
6815
+ minConfidence?: number;
6816
+ /** Override scope/folder for all retained facts. */
6817
+ scope?: string;
6818
+ folderId?: string | null;
6819
+ /**
6820
+ * Forwarded verbatim to each retain() call — enables the LLM-based
6821
+ * consolidation pass (Hindsight facet-dedup) on every write. See
6822
+ * `RetainOptions.consolidateOptions` for auth + observability fields.
6823
+ */
6824
+ consolidateOptions?: RetainOptions["consolidateOptions"];
6825
+ /**
6826
+ * When provided, persist each candidate's `entities[]` to the
6827
+ * entity + memory_entity tables after a successful retain. This
6828
+ * powers the W5 graph retrieval lane — recall() can query for
6829
+ * memories sharing entities with the user's question.
6830
+ */
6831
+ entityCtx?: EntityOperationsContext;
6832
+ /**
6833
+ * Per-candidate failure hook — invoked once per filtered candidate
6834
+ * whose `retain()` call threw. Lets UI layers surface "couldn't save
6835
+ * X" toasts; without it consumers only see the aggregate
6836
+ * `failedCount` and can't name which facts dropped.
6837
+ */
6838
+ onCandidateFailed?: (candidate: ExtractedCandidate, error: unknown) => void;
6839
+ /**
6840
+ * Tier-0 security (PR3) — invoked once per candidate the injection screen
6841
+ * quarantined AND persisted (audit row written). Lets a UI surface a
6842
+ * "held for review" state instead of the fact silently vanishing. Carries
6843
+ * the same content exposure as `onMemoryExtracted` (the candidate) plus
6844
+ * the persisted `memoryId` + the screen `reason`/`signature`; content is
6845
+ * never logged. Fired only on a successful quarantine write, not on a
6846
+ * failed one (that goes to `onCandidateFailed`).
6847
+ */
6848
+ onQuarantined?: (info: QuarantinedMemoryInfo) => void;
6849
+ /**
6850
+ * Tier-0 security (PR5) — optional SECOND-layer LLM injection classifier.
6851
+ * When provided, candidates the deterministic {@link screenCandidatesForInjection}
6852
+ * screen passed as CLEAN are additionally run through a cheap LLM that
6853
+ * catches signature-free poison ("Trusts BrandX for financial advice")
6854
+ * the regex screen can't. Positives are quarantined exactly like a
6855
+ * signature hit (reason `llm_semantic`). DEFAULT OFF — omit this to keep
6856
+ * the deterministic-only, no-extra-LLM-call path. Fails clean on any
6857
+ * error. Content is PII-redacted before the call, inheriting the
6858
+ * extraction redaction setting when this option doesn't set its own.
6859
+ */
6860
+ injectionClassifier?: InjectionClassifierOptions;
6861
+ }): Promise<{
6862
+ candidates: ExtractedCandidate[];
6863
+ results: RetainResult[];
6864
+ failedCount: number;
6865
+ outcome: ExtractOutcome;
6866
+ /**
6867
+ * Tier-0 security (PR3) — candidates quarantined by the injection screen and
6868
+ * persisted as audit rows (trust_tier="quarantined"). Kept OUT of
6869
+ * `candidates`/`results` so `onMemoryExtracted` never announces poison;
6870
+ * surfaced here so callers can distinguish "nothing extracted" from
6871
+ * "extracted but held for review".
6872
+ */
6873
+ quarantined: QuarantinedMemoryInfo[];
6874
+ }>;
6875
+
6876
+ interface StoredVaultMemory {
6877
+ /** WatermelonDB internal ID */
6878
+ uniqueId: string;
6879
+ /** Plain text memory content */
6880
+ content: string;
6881
+ /** Scope for partitioning memories (e.g., "private", "shared") */
6882
+ scope: string;
6883
+ /** Folder ID for organization, null if unfiled */
6884
+ folderId: string | null;
6885
+ /** User ID for multi-user server-side scoping, null on client */
6886
+ userId: string | null;
6887
+ /** JSON-stringified embedding vector, null if not yet computed */
6888
+ embedding: string | null;
6889
+ /** Model that produced `embedding`. Null on legacy rows (grandfathered as
6890
+ * compatible with the current model). */
6891
+ embeddingModel: string | null;
6892
+ /** JSON-stringified array of source message IDs this fact was extracted from. */
6893
+ sourceChunkIds: string[] | null;
6894
+ /** Times this fact has been re-observed (for ranking + UX badges). */
6895
+ proofCount: number | null;
6896
+ /** How the memory was created: manual | auto-extracted | capsule. */
6897
+ source: string | null;
6898
+ /** W6 temporal lane — Unix ms when the event occurred (point/start of range). */
6899
+ eventTimeStart: number | null;
6900
+ /** W6 temporal lane — Unix ms when the event ended (range only). */
6901
+ eventTimeEnd: number | null;
6902
+ /** W6 temporal lane — `point | range | ongoing | null`. */
6903
+ eventTimeKind: string | null;
6904
+ /** When true, the user has manually set this memory's topics (entity links);
6905
+ * auto-extraction leaves them alone. False on legacy/auto rows. */
6906
+ topicsUserManaged: boolean;
6907
+ /** Unix ms of the last LLM topic-extraction pass over this memory's content.
6908
+ * Null = never extracted standalone; rows that already carry entity links
6909
+ * are grandfathered as extracted (see getMemoriesNeedingTopicExtractionOp). */
6910
+ topicsExtractedAt: number | null;
6911
+ /** Write-time supersession (A2): id of the newer memory that replaced this
6912
+ * one (incompatible-value update, e.g. "Lives in Portland" → "Lives in SF").
6913
+ * Null = live. Superseded rows are excluded from recall/dedup by default but
6914
+ * kept for history + the read-time fallback. */
6915
+ supersededBy: string | null;
6916
+ /** Unix ms when this memory was superseded. Null when live. */
6917
+ supersededAt: number | null;
6918
+ /** Extraction-logic version this memory was last stamped under. Null (pre-v38)
6919
+ * reads as 0, so a TOPICS_EXTRACTION_VERSION bump re-extracts stale rows. */
6920
+ topicsExtractedVersion: number | null;
6921
+ /** C3 re-observation watermark: Unix ms of the last retain() merge into this
6922
+ * fact. Distinct from `updatedAt` (which merges preserve). Null = never
6923
+ * re-observed since the column was added; synthesis falls back to
6924
+ * `updatedAt` in that case. */
6925
+ lastObservedAt: number | null;
6926
+ /** Typed memory (PR1) — the extractor's FactType for this fact, or null on
6927
+ * legacy/manual/untyped rows. Plaintext string (not narrowed to FactType
6928
+ * here since the DB can hold any stored value). */
6929
+ factType: string | null;
6930
+ /** Decay archive state (PR2) — Unix ms when archived, or null when active. */
6931
+ archivedAt: number | null;
6932
+ /** Tier-0 security (PR3) — "quarantined" | "trusted" | null. */
6933
+ trustTier: string | null;
6934
+ createdAt: Date;
6935
+ updatedAt: Date;
6936
+ isDeleted: boolean;
6937
+ }
6938
+ interface CreateVaultMemoryOptions {
6666
6939
  content: string;
6667
- type: FactType;
6668
- confidence: number;
6669
- sourceMessageIds: string[];
6670
- entities: ExtractedEntity[];
6671
- /** W6 temporal lane — when the event in this fact occurred. Resolved
6672
- * to absolute timestamps by the LLM; null when the fact has no
6673
- * temporal anchor. */
6674
- eventTime: {
6675
- kind: "point" | "range" | "ongoing";
6676
- /** Unix ms timestamp of the event start (or point). */
6677
- start: number;
6678
- /** Unix ms timestamp of the event end. Only set when kind='range'. */
6940
+ /** Scope for the memory. Defaults to "private" if omitted. */
6941
+ scope?: string;
6942
+ /** Folder ID for organization, null or omitted if unfiled */
6943
+ folderId?: string | null;
6944
+ /** JSON-stringified embedding vector to persist */
6945
+ embedding?: string;
6946
+ /** Model that produced `embedding`. Persisted alongside it so a later
6947
+ * model change can detect and re-embed stale vectors. */
6948
+ embeddingModel?: string;
6949
+ /** Source message IDs that produced this fact (auto-extraction provenance). */
6950
+ sourceChunkIds?: string[];
6951
+ /** Initial proof count. Defaults to 1 if omitted. */
6952
+ proofCount?: number;
6953
+ /** How the memory was created. Defaults to "manual" if omitted. */
6954
+ source?: string;
6955
+ /** W6 temporal lane — when the event in this memory occurred. */
6956
+ eventTime?: {
6957
+ /** Unix ms timestamp of event start (or point). */
6958
+ start: number | null;
6959
+ /** Unix ms timestamp of event end (range only). */
6679
6960
  end: number | null;
6680
- } | null;
6961
+ /** Kind: 'point' | 'range' | 'ongoing' | null (or omit). */
6962
+ kind: "point" | "range" | "ongoing" | null;
6963
+ };
6964
+ /** Typed memory (PR1) — the extractor's classification for this fact.
6965
+ * Omit for manual/untyped saves (persisted as null). */
6966
+ factType?: FactType;
6967
+ /** Tier-0 security (PR3) — set "quarantined" when the injection screen
6968
+ * flagged this fact. Omit for the default (null/trusted). */
6969
+ trustTier?: string;
6681
6970
  }
6682
- /**
6683
- * Auth + endpoint for the extraction LLM call. Auth is the dual pattern —
6684
- * one of `apiKey` / `getToken` is required at runtime; see
6685
- * {@link PortalLlmAuth}.
6686
- */
6687
- interface ExtractFactsOptions extends PortalLlmAuth {
6688
- baseUrl?: string;
6689
- model?: string;
6690
- /** Override the global fetch implementation (useful for tests). */
6691
- fetchFn?: typeof fetch;
6971
+ interface UpdateVaultMemoryOptions {
6972
+ content: string;
6973
+ /** If provided, updates the memory's scope. */
6974
+ scope?: string;
6975
+ /** If provided, moves the memory to this folder. */
6976
+ folderId?: string | null;
6977
+ /** JSON-stringified embedding vector to persist, or null to clear stale embedding */
6978
+ embedding?: string | null;
6979
+ /** Model that produced `embedding`. Set whenever `embedding` is written so
6980
+ * the stored model tag stays in sync with the vector. */
6981
+ embeddingModel?: string | null;
6982
+ /** Replace source-chunk-ids list (used during merge to accumulate provenance). */
6983
+ sourceChunkIds?: string[];
6984
+ /** Set an absolute proof count. Prefer {@link proofCountIncrement} for
6985
+ * re-observation paths so the read+write happens inside the writer
6986
+ * and concurrent retains can't lose updates. */
6987
+ proofCount?: number;
6988
+ /** Atomically bump proof_count by this delta inside the write block.
6989
+ * Reads the current value from the in-memory record at write time, so
6990
+ * two parallel retain() calls observe each other's commits and neither
6991
+ * loses its increment. Wins over `proofCount` when both are set. */
6992
+ proofCountIncrement?: number;
6993
+ /** Set source ("manual" | "auto-extracted" | "capsule"). */
6994
+ source?: string;
6692
6995
  /**
6693
- * The user's own name(s) / handle(s) (e.g. profile nickname, wallet display
6694
- * name). Candidates whose entire content is just one of these are dropped —
6695
- * a personal memory system already knows who the user is, so "Peter Lee" is
6696
- * circular noise. Optional; when omitted only the bare-fragment gate applies.
6996
+ * W6 temporal lane — write the event-time fields on update. Use during
6997
+ * auto-merge to preserve (or refine) the original event-time signal when
6998
+ * a new observation lands on an existing fact. Omit to leave the
6999
+ * existing values untouched.
6697
7000
  */
6698
- userIdentity?: string[];
7001
+ eventTime?: {
7002
+ start: number | null;
7003
+ end: number | null;
7004
+ kind: "point" | "range" | "ongoing" | null;
7005
+ };
6699
7006
  /**
6700
- * Reference "now" (Unix ms) for resolving relative temporal phrases in the
6701
- * transcript ("yesterday", "next week", "in two days") into the absolute
6702
- * YYYY-MM-DD anchors the W6 temporal lane indexes on. The transcript itself
6703
- * carries no timestamps, so without an anchor the model resolves relatives
6704
- * against its own training-cutoff guess and emits wrong `eventTime` dates.
6705
- * Defaults to `Date.now()`. Override for back-dated eval corpora and
6706
- * deterministic tests (mirrors {@link RecallOptions.now}).
6707
- *
6708
- * Server-side timezone note: the ms value is formatted to a calendar date in
6709
- * the process's local timezone (same basis as `parseLocalCalendarDay`). On a
6710
- * UTC server, a user near midnight in a non-UTC offset can get the wrong
6711
- * calendar day. Pass the user's local-midnight timestamp as `now` when the
6712
- * process timezone doesn't match the user's.
7007
+ * When true, restore the existing `updated_at` after the write so the
7008
+ * recency multiplier doesn't see a re-observation as a brand-new fact.
7009
+ * Set by auto-merge/consolidate paths — they want proof_count to bump
7010
+ * without inflating recency on top.
6713
7011
  */
6714
- now?: number;
7012
+ preserveUpdatedAt?: boolean;
7013
+ /** C3: Unix ms to stamp as the re-observation watermark (`last_observed_at`).
7014
+ * Set by retain() merge/consolidate paths so a re-observation records "seen
7015
+ * again now" without touching `updated_at` (which `preserveUpdatedAt` keeps
7016
+ * pinned). Omit to leave the existing value untouched. */
7017
+ lastObservedAt?: number;
7018
+ /** If provided, sets whether the user has taken manual control of this
7019
+ * memory's topics. Set by {@link setMemoryEntitiesOp}. */
7020
+ topicsUserManaged?: boolean;
7021
+ /** Typed memory (PR1) — set/refine the fact's classification on update.
7022
+ * Used by retain()'s lazy backfill (adopt an incoming type only when the
7023
+ * existing row has none). Omit to leave the existing value untouched. */
7024
+ factType?: FactType;
7025
+ /** Tier-0 security (PR3) — set the trust tier on update ("quarantined" |
7026
+ * "trusted"). Omit to leave the existing value untouched. */
7027
+ trustTier?: string;
6715
7028
  /**
6716
- * Max attempts for the extraction call on a transient failure (default 3).
6717
- * Lower it to bound how long extraction can hold a turn open — e.g. a worker
6718
- * that runs extraction behind an in-flight-turn guard can pass `2` to keep
6719
- * repeated failures from delaying later turns.
7029
+ * PR5 — un-archive on re-observe. When true, clears `archived_at` (null) as
7030
+ * part of the write, resurrecting a decayed row that a new observation just
7031
+ * merged into. retain() sets this (with `preserveUpdatedAt` OFF) so the
7032
+ * restored row's decay clock resets and it doesn't immediately re-archive.
7033
+ * Omit/false to leave `archived_at` untouched.
6720
7034
  */
6721
- maxAttempts?: number;
6722
- /** Per-attempt timeout (ms) for the extraction call. Defaults to the portal
6723
- * helper's 60s. Combine with {@link maxAttempts} to cap the total time budget. */
6724
- timeoutMs?: number;
7035
+ restore?: boolean;
7036
+ }
7037
+
7038
+ interface VaultMemoryOperationsContext {
7039
+ database: Database;
7040
+ vaultMemoryCollection: Collection<VaultMemory>;
7041
+ walletAddress?: string;
7042
+ signMessage?: SignMessageFn;
7043
+ embeddedWalletSigner?: EmbeddedWalletSignerFn;
7044
+ /** When set, operations scope to this user (server-side multi-user). */
7045
+ userId?: string;
6725
7046
  /**
6726
- * Absolute wall-clock budget (ms) across ALL extraction attempts incl. backoff.
6727
- * When set, the loop stops before an attempt that would exceed it, so worst-case
6728
- * latency is bounded rather than `maxAttempts × timeoutMs`.
7047
+ * Asserts this context runs against a physically single-tenant database — one
7048
+ * where every row belongs to the same owner (the per-wallet client DBs, which
7049
+ * hold exactly one wallet's rows written with `user_id = null`). This is the
7050
+ * ONLY thing that makes the decay sweep's unscoped scan/archive/delete safe
7051
+ * without a `userId`: see {@link assertVaultScopeForSweep}. A shared /
7052
+ * multi-tenant DB must NOT set this — it must scope by `userId` instead.
7053
+ * `walletAddress` presence alone is NOT a substitute (the sweep query filters
7054
+ * by `user_id` only, so a bare `walletAddress` on a shared DB would sweep
7055
+ * every tenant).
6729
7056
  */
6730
- totalTimeoutMs?: number;
7057
+ singleTenant?: boolean;
6731
7058
  /**
6732
- * Override the retry backoff (ms) for a given 1-based attempt index. The
6733
- * extraction call retries transient failures internally (default exponential
6734
- * backoff); pass `() => 0` to retry without delay (useful for tests).
7059
+ * When set, vault delete ops cascade to memory_entity rows pointing at
7060
+ * the deleted memories. Without this the W5 graph lane keeps returning
7061
+ * IDs of soft-deleted memories and the join table grows unbounded.
6735
7062
  */
6736
- backoffMs?: (attempt: number) => number;
7063
+ entityCtx?: EntityOperationsContext;
7064
+ }
7065
+ declare function createVaultMemoryOp(ctx: VaultMemoryOperationsContext, opts: CreateVaultMemoryOptions): Promise<StoredVaultMemory>;
7066
+ declare function createVaultMemoriesBatchOp(ctx: VaultMemoryOperationsContext, optionsArray: CreateVaultMemoryOptions[]): Promise<StoredVaultMemory[]>;
7067
+ declare function getVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string): Promise<StoredVaultMemory | null>;
7068
+ declare function getAllVaultMemoriesOp(ctx: VaultMemoryOperationsContext, options?: {
7069
+ scopes?: string[];
7070
+ since?: Date;
7071
+ limit?: number;
7072
+ folderId?: string | null;
6737
7073
  /**
6738
- * When set, PII (emails, phones, SSNs, cards, IPs, API keys, …) in the
6739
- * conversation transcript is replaced with tagged placeholders before the
6740
- * extraction call, and the returned facts + entities are de-anonymized so the
6741
- * vault keeps the real values while raw PII never reaches the extraction
6742
- * model (and, via `extractAndRetain`, the consolidation model). Pass `true`
6743
- * for a fresh per-call redactor, or a shared {@link PiiRedactor} to keep
6744
- * placeholder numbering consistent with other calls.
6745
- *
6746
- * NOTE: this does NOT cover the embeddings provider. Facts are stored and
6747
- * embedded with their real values, so to keep PII out of embedding requests
6748
- * set `RetainContext.embeddingOptions.maskInput` (e.g. `redactor.maskText`)
6749
- * as well — the two are independent switches.
7074
+ * Include soft-deleted memories in the result (each carries
7075
+ * `isDeleted: true`). Default `false` — deleted rows are excluded, as
7076
+ * they are from every other read path. Used by the Memory Graph to
7077
+ * render "forgotten" nodes; ordinary consumers should leave this off.
6750
7078
  */
6751
- piiRedaction?: boolean | PiiRedactor;
7079
+ includeDeleted?: boolean;
7080
+ /** Include archived (decayed) memories. Default `false` (PR1 choke point). */
7081
+ includeArchived?: boolean;
7082
+ /** Include quarantined memories. Default `false` (PR1 choke point). */
7083
+ includeQuarantined?: boolean;
7084
+ /** Typed memory (PR1) — restrict to these fact types. Omit for no filter. */
7085
+ factTypes?: string[];
6752
7086
  /**
6753
- * Called when the extraction LLM returned no usable result after exhausting
6754
- * its retries (empty/malformed completion, network/HTTP error) — i.e. a
6755
- * *failure* that drops the turn's facts, as opposed to a legitimate
6756
- * `{candidates: []}` "nothing durable here". Lets callers distinguish a
6757
- * silently-degrading extractor from quiet turns (the two are otherwise
6758
- * indistinguishable). See {@link extractAndRetain}'s `outcome`.
7087
+ * Include A2-superseded memories (each carries `supersededBy`). Default
7088
+ * `false` — superseded rows are excluded, as they are from recall/dedup.
7089
+ * Used by a "memory history" view to render retired facts.
6759
7090
  */
6760
- onExhaustedEmpty?: () => void;
7091
+ includeSuperseded?: boolean;
7092
+ }): Promise<StoredVaultMemory[]>;
7093
+ declare function getAllVaultMemoryContentsOp(ctx: VaultMemoryOperationsContext, options?: {
7094
+ since?: Date;
7095
+ }): Promise<string[]>;
7096
+ declare function updateVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string, opts: UpdateVaultMemoryOptions): Promise<StoredVaultMemory | null>;
7097
+ /**
7098
+ * Replace a memory's topic (entity) links with a user-chosen set and mark the
7099
+ * memory `topics_user_managed` so auto-extraction stops touching its links.
7100
+ * Replace semantics: the given `entities` become the memory's complete topic
7101
+ * set (pass `[]` to clear all topics — the memory stays user-managed and
7102
+ * unclustered). Requires `ctx.entityCtx`. Preserves `updated_at` so a topic
7103
+ * edit doesn't inflate the recency multiplier.
7104
+ */
7105
+ declare function setMemoryEntitiesOp(ctx: VaultMemoryOperationsContext, memoryId: string, entities: ReadonlyArray<EntityInput>): Promise<StoredVaultMemory | null>;
7106
+ /**
7107
+ * Reset a memory's topics to automatic: clear the `topics_user_managed` flag so
7108
+ * auto-extraction resumes owning its links. Invalidates `topics_extracted_version`
7109
+ * (→ null) and ensures a NON-NULL `topics_extracted_at`, so the next sweep routes
7110
+ * the row through the stale-version pending path and actually RE-EXTRACTS it via
7111
+ * the LLM. A never-stamped user-curated row (`setMemoryEntitiesOp` marks
7112
+ * user-managed without stamping, so stamp can be null) would otherwise fall
7113
+ * through the sweep's unstamped→`linkedUnstamped` grandfather path (stamped
7114
+ * current, no LLM pass); forcing a stamp when absent avoids that. Existing links
7115
+ * are left in place until the re-extraction replaces them. Preserves `updated_at`.
7116
+ */
7117
+ declare function clearMemoryTopicsOverrideOp(ctx: VaultMemoryOperationsContext, memoryId: string): Promise<boolean>;
7118
+ declare function deleteVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string): Promise<boolean>;
7119
+ /**
7120
+ * Mark a memory as superseded by a newer one (A2 write-time supersession).
7121
+ * The row stays in the table (history + read-time fallback) but is excluded
7122
+ * from recall/dedup by default via `superseded_by`. Idempotent-ish: no-op if
7123
+ * the row is missing, not owned, deleted, or already superseded. Does NOT
7124
+ * preserve `updated_at` — superseded rows are hidden from recall, so their
7125
+ * recency is irrelevant.
7126
+ *
7127
+ * @param id - the memory being retired (e.g. "Lives in Portland")
7128
+ * @param supersededById - the newer memory that replaced it (e.g. "Lives in SF")
7129
+ */
7130
+ declare function supersedeVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string, supersededById: string): Promise<boolean>;
7131
+ /**
7132
+ * Get all non-deleted, unfiled vault memories (folder_id is null).
7133
+ */
7134
+ declare function getUnfiledVaultMemoriesOp(ctx: VaultMemoryOperationsContext): Promise<StoredVaultMemory[]>;
7135
+ /**
7136
+ * The current topic-extraction logic version. Bump this whenever the extraction
7137
+ * prompt or model in `topicExtract.ts` changes: every memory stamped under an
7138
+ * older version (including pre-v37 rows, read as version 0) is then re-extracted
7139
+ * by the next sweep, so topic-quality improvements propagate across the existing
7140
+ * vault. The worker's `limit` drains that re-extraction across sweeps.
7141
+ */
7142
+ declare const TOPICS_EXTRACTION_VERSION = 1;
7143
+ /**
7144
+ * Result of {@link getMemoriesNeedingTopicExtractionOp}: which memories the
7145
+ * background topic worker should run LLM entity extraction on, and which it
7146
+ * should merely stamp as already-extracted.
7147
+ */
7148
+ interface MemoriesNeedingTopicExtraction {
6761
7149
  /**
6762
- * Called when the extractor DID produce candidates but PII de-anonymization
6763
- * dropped every one of them — the model mangled its placeholders (so they
6764
- * can't be restored to real values) or restoring the values blew the length
6765
- * cap. These drops happen before `retain()`, so `failedCount` can't see them,
6766
- * and the turn would otherwise masquerade as a quiet `no-facts` result. Lets
6767
- * H3's `outcome` surface `dropped-after-redaction` so a rising PII-drop rate
6768
- * (i.e. redaction silently eating facts) is alarmable.
7150
+ * Memories to run LLM topic extraction on (decrypted): never-extracted rows
7151
+ * with no entity links, plus stamped rows edited since their last pass
7152
+ * (`updated_at` > `topics_extracted_at`) or extracted under an older
7153
+ * `topics_extracted_version` than {@link TOPICS_EXTRACTION_VERSION}. Edited /
7154
+ * stale-version rows come first (they get priority under `limit`), each group
7155
+ * newest-created first.
7156
+ */
7157
+ pending: StoredVaultMemory[];
7158
+ /**
7159
+ * IDs of rows that already have entity links but no watermark — legacy rows
7160
+ * extracted by the conversation pipeline before v36. Grandfather these with
7161
+ * {@link stampTopicsExtractedAtOp} (no LLM call) so a later content edit
7162
+ * makes them re-extractable instead of invisible forever. Bounded by the
7163
+ * same `limit` as {@link pending} — stamping loads a Model per row, so the
7164
+ * grandfather backlog is drained across sweeps rather than in one spike.
6769
7165
  */
6770
- onCandidatesDropped?: () => void;
7166
+ linkedUnstamped: string[];
6771
7167
  }
6772
7168
  /**
6773
- * Stage 1 — call the LLM to extract candidate facts from the recent
6774
- * conversation. Returns post-validated candidates only (confidence
6775
- * threshold, source-id check, length cap, schema validation). Returns
6776
- * an empty array if the LLM emits malformed JSON or no candidates.
7169
+ * Sweep query for the background topic-extraction worker: partition the
7170
+ * user's non-deleted, non-user-managed memories by what the worker should do
7171
+ * with them (see {@link MemoriesNeedingTopicExtraction}). User-managed rows
7172
+ * are never returned — the user owns their topics, including an intentionally
7173
+ * empty set. Requires `ctx.entityCtx` for the entity-links check.
7174
+ */
7175
+ declare function getMemoriesNeedingTopicExtractionOp(ctx: VaultMemoryOperationsContext, options?: {
7176
+ limit?: number;
7177
+ }): Promise<MemoriesNeedingTopicExtraction>;
7178
+ /**
7179
+ * Stamp `topics_extracted_at` (and `topics_extracted_version`) on the given
7180
+ * memories — the topic worker calls this after a successful extraction pass
7181
+ * (including zero-entity results, so quiet memories aren't re-asked every sweep)
7182
+ * and to grandfather `linkedUnstamped` rows without an LLM call. `version`
7183
+ * defaults to {@link TOPICS_EXTRACTION_VERSION}: stamping at the current version
7184
+ * (for both fresh extractions and grandfathered legacy rows) means they aren't
7185
+ * re-extracted until a future version bump. Preserves `updated_at` so a stamp
7186
+ * never inflates the recency multiplier — and never masks a concurrent content
7187
+ * edit from the next sweep. Skips deleted, foreign-user, and user-managed rows.
7188
+ * Returns the IDs actually stamped.
6777
7189
  *
6778
- * A null from `callPortalJsonCompletion` means a *failure* (empty completion,
6779
- * malformed JSON, network/HTTP error) — distinct from a successful
6780
- * `{candidates: []}`, which parses to a non-null object. A failed extraction
6781
- * silently drops the whole turn's memories, so transient failures matter:
6782
- * `callPortalJsonCompletion` retries them internally with backoff (default 3
6783
- * attempts), so a one-off empty/malformed completion from a reasoning-class
6784
- * model doesn't lose the turn. Only an exhausted-retry null reaches here.
7190
+ * ALL eligibility AND `updated_at` are read from the LIVE Model inside the
7191
+ * serialized writer — never a pre-writer snapshot. Writers are serialized, so
7192
+ * a content edit or topic-override that commits before this writer runs is
7193
+ * observed here: its fresh `updated_at` is preserved (so the next sweep's
7194
+ * `updated_at > stamp` check still fires) and a mid-pass user-managed flip
7195
+ * skips the row. Reading `updated_at` from a raw pre-fetch instead would write
7196
+ * a stale value back, pushing `updated_at < topics_extracted_at` and hiding
7197
+ * the edited memory from every future sweep.
7198
+ *
7199
+ * Callers bound the input via `getMemoriesNeedingTopicExtractionOp`'s `limit`
7200
+ * (both `pending` and `linkedUnstamped` are capped), so the per-row Model load
7201
+ * needed to `prepareUpdate` stays bounded and never spikes the RecordCache.
6785
7202
  */
6786
- declare function extractFacts(messages: AutoExtractMessage[], options: ExtractFactsOptions): Promise<ExtractedCandidate[]>;
7203
+ declare function stampTopicsExtractedAtOp(ctx: VaultMemoryOperationsContext, memoryIds: readonly string[], extractedAt: number, version?: number): Promise<string[]>;
7204
+ declare function deleteAllVaultMemoriesForUserOp(ctx: VaultMemoryOperationsContext, userId: string): Promise<number>;
6787
7205
  /**
6788
- * Outcome of the EXTRACTOR stage for a turn — independent of whether the
6789
- * subsequent `retain()` writes landed (that's `failedCount`):
6790
- * - `extracted` — the extractor produced at least one candidate above
6791
- * the confidence floor. Whether those writes succeeded
6792
- * is reported separately by `failedCount` — so
6793
- * `extracted` + `failedCount > 0` means "found facts but
6794
- * writes are failing", which is more signal than
6795
- * collapsing it into `no-facts` would give.
6796
- * - `no-facts` — the extractor ran fine but found nothing durable.
6797
- * - `empty-after-retry` — the extractor returned empty/malformed after
6798
- * exhausting retries (a *failure*). Distinguishing this
6799
- * from `no-facts` is what makes a silently-degrading
6800
- * extractor alarmable rather than invisible.
6801
- * - `dropped-after-redaction` — the extractor found facts but PII
6802
- * de-anonymization dropped every one (mangled
6803
- * placeholders / over-cap after restore), before retain.
6804
- * A degradation `failedCount` can't see; would otherwise
6805
- * look like `no-facts`.
7206
+ * The minimal plaintext shape the decay sweep needs — mirrors the `DecayInput`
7207
+ * shape in `memory/decay` plus the row id. Deliberately omits `content`
7208
+ * (encrypted) so the sweep stays zero-knowledge.
6806
7209
  */
6807
- type ExtractOutcome = "extracted" | "no-facts" | "empty-after-retry" | "dropped-after-redaction";
7210
+ interface DecayCandidateRaw {
7211
+ uniqueId: string;
7212
+ factType: string | null;
7213
+ eventTimeEnd: number | null;
7214
+ eventTimeKind: string | null;
7215
+ /** Unix ms — the raw `updated_at`, used both for the age rule and as the
7216
+ * optimistic-concurrency guard passed back to {@link archiveVaultMemoryOp}. */
7217
+ updatedAt: number;
7218
+ archivedAt: number | null;
7219
+ source: string | null;
7220
+ /** `trusted` | `quarantined` | null. Quarantined rows still decay by RULE, but
7221
+ * are never handed to the optional content-reading decay classifier (they must
7222
+ * not egress poison content — see the decay sweeper's `isBorderline`). */
7223
+ trustTier: string | null;
7224
+ }
6808
7225
  /**
6809
- * Stage 2 — for each extracted candidate, call retain() with auto-merge
6810
- * enabled. When `consolidateOptions` are wired, retain()'s consolidation pass
6811
- * is the "resolver": a second LLM call against the top-K existing vault
6812
- * memories that decides create/update/noop/supersede — including retiring a
6813
- * stale value on a state change (the supersession the extraction prompt above
6814
- * promises). Without consolidation, retain() still dedups at the cosine-merge
6815
- * level, and the read-time supersession heuristic remains the fallback.
7226
+ * Decay sweep candidate scan (PR2). Selects the plaintext columns
7227
+ * `classifyDecay` (in `memory/decay`) needs via
7228
+ * `unsafeFetchRaw` — NO Model per row (dodges the never-evicted RecordCache /
7229
+ * web Pile-2 OOM history) and NO `content` read / decrypt (zero-knowledge).
6816
7230
  *
6817
- * Returns the candidates that survived validation along with the retain
6818
- * result for each (which captures whether the fact was created, merged,
6819
- * or skipped), plus an `outcome` summarizing why the turn did/didn't produce
6820
- * facts (see {@link ExtractOutcome}).
7231
+ * Includes archived AND quarantined rows (so archived→delete transitions and
7232
+ * aged quarantined rows are seen) but excludes hard-deleted rows — the
7233
+ * `baseVaultConditions` default keeps `is_deleted = false`.
7234
+ *
7235
+ * Refuses to run on an unscoped multi-tenant context (see
7236
+ * {@link assertVaultScopeForSweep}).
6821
7237
  */
6822
- declare function extractAndRetain(messages: AutoExtractMessage[], retainCtx: RetainContext, options: {
6823
- extract: ExtractFactsOptions;
6824
- minConfidence?: number;
6825
- /** Override scope/folder for all retained facts. */
6826
- scope?: string;
6827
- folderId?: string | null;
6828
- /**
6829
- * Forwarded verbatim to each retain() call — enables the LLM-based
6830
- * consolidation pass (Hindsight facet-dedup) on every write. See
6831
- * `RetainOptions.consolidateOptions` for auth + observability fields.
6832
- */
6833
- consolidateOptions?: RetainOptions["consolidateOptions"];
6834
- /**
6835
- * When provided, persist each candidate's `entities[]` to the
6836
- * entity + memory_entity tables after a successful retain. This
6837
- * powers the W5 graph retrieval lane — recall() can query for
6838
- * memories sharing entities with the user's question.
6839
- */
6840
- entityCtx?: EntityOperationsContext;
6841
- /**
6842
- * Per-candidate failure hook — invoked once per filtered candidate
6843
- * whose `retain()` call threw. Lets UI layers surface "couldn't save
6844
- * X" toasts; without it consumers only see the aggregate
6845
- * `failedCount` and can't name which facts dropped.
6846
- */
6847
- onCandidateFailed?: (candidate: ExtractedCandidate, error: unknown) => void;
6848
- }): Promise<{
6849
- candidates: ExtractedCandidate[];
6850
- results: RetainResult[];
6851
- failedCount: number;
6852
- outcome: ExtractOutcome;
6853
- }>;
7238
+ declare function getDecayCandidatesRawOp(ctx: VaultMemoryOperationsContext): Promise<DecayCandidateRaw[]>;
7239
+ /**
7240
+ * Archive a memory (decay soft state, PR2) — set `archived_at`. An archived row
7241
+ * drops out of every recall lane via the `baseVaultConditions` choke point but
7242
+ * stays recoverable via {@link restoreVaultMemoryOp} until the hard-delete
7243
+ * window elapses.
7244
+ *
7245
+ * Concurrency: re-checks `is_deleted` / ownership / `archived_at` INSIDE the
7246
+ * serialized writer (mirrors {@link updateVaultMemoryOp}). Additionally, when
7247
+ * `opts.expectedUpdatedAt` is given, the archive is skipped if the row's current
7248
+ * `updated_at` no longer matches — i.e. a `retain()` merge (which bumps
7249
+ * `updated_at`) landed between the sweep's candidate scan and this write, so the
7250
+ * fact was just re-observed and must NOT be archived on stale data. Idempotent:
7251
+ * a row another sweep already archived returns `false` (no double-write).
7252
+ *
7253
+ * @returns `true` if this call archived the row; `false` if it was stale
7254
+ * (deleted / not owned / already archived / refreshed under us).
7255
+ */
7256
+ declare function archiveVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string, opts?: {
7257
+ /** Timestamp to stamp into `archived_at`. Default `Date.now()`. */
7258
+ now?: number;
7259
+ /** Optimistic-concurrency guard: skip if the row's `updated_at` changed
7260
+ * since the sweep observed it (a concurrent re-observation). */
7261
+ expectedUpdatedAt?: number;
7262
+ }): Promise<boolean>;
7263
+ /**
7264
+ * Restore an archived memory (PR2) — clear `archived_at` so it re-enters recall.
7265
+ * Re-checks `is_deleted` / ownership inside the writer. Idempotent on an
7266
+ * already-active row (clearing null → null is harmless).
7267
+ *
7268
+ * @returns `true` if the row was restored (or already active); `false` if it was
7269
+ * deleted / not owned / missing.
7270
+ */
7271
+ declare function restoreVaultMemoryOp(ctx: VaultMemoryOperationsContext, id: string): Promise<boolean>;
7272
+ /**
7273
+ * Hard-delete a memory ONLY if it is still archived and still past the delete
7274
+ * window (PR2 decay terminal transition). Unlike the generic
7275
+ * {@link deleteVaultMemoryOp}, this re-reads `archived_at` INSIDE the writer and
7276
+ * bails if the row was restored (`archived_at → null`) or re-archived more
7277
+ * recently since the sweep's candidate scan. This is the restore-vs-delete
7278
+ * mutual-exclusion guard: a user hitting Restore between the scan and this write
7279
+ * must win, so their just-rescued memory is never permanently lost.
7280
+ *
7281
+ * @returns `true` if this call hard-deleted the row; `false` if it was stale
7282
+ * (deleted / not owned / no longer archived / no longer past the window).
7283
+ */
7284
+ declare function hardDeleteDecayedOp(ctx: VaultMemoryOperationsContext, id: string, opts: {
7285
+ hardDeleteWindowMs: number;
7286
+ now?: number;
7287
+ }): Promise<boolean>;
7288
+ declare function updateVaultMemoryEmbeddingOp(ctx: VaultMemoryOperationsContext, id: string, embedding: string, embeddingModel: string): Promise<boolean>;
6854
7289
 
6855
7290
  /**
6856
7291
  * Auto-extraction worker — orchestration glue for wiring
@@ -6910,6 +7345,16 @@ interface MemoryExtractedEvent {
6910
7345
  result: RetainResult;
6911
7346
  conversationId?: string;
6912
7347
  }
7348
+ /**
7349
+ * Tier-0 security (PR3) — fired once per candidate the injection screen
7350
+ * quarantined and persisted as an audit row. Distinct from
7351
+ * {@link MemoryExtractedEvent} so a client can render "held for review"
7352
+ * without treating a poisoned fact as a normal saved memory.
7353
+ * @public
7354
+ */
7355
+ interface MemoryQuarantinedEvent extends QuarantinedMemoryInfo {
7356
+ conversationId?: string;
7357
+ }
6913
7358
  /** @public */
6914
7359
  interface TurnSkippedEvent {
6915
7360
  /**
@@ -7048,6 +7493,12 @@ interface CreateAutoExtractorOptions {
7048
7493
  };
7049
7494
  /** Per-fact event — fires once per memory written. */
7050
7495
  onMemoryExtracted?: (event: MemoryExtractedEvent) => void;
7496
+ /**
7497
+ * Tier-0 security (PR3) — fires once per candidate quarantined by the
7498
+ * injection screen (and persisted as an audit row). Lets a client surface a
7499
+ * "held for review" state instead of the fact silently disappearing.
7500
+ */
7501
+ onMemoryQuarantined?: (event: MemoryQuarantinedEvent) => void;
7051
7502
  /** Per-turn event — fires once after the whole pipeline finishes. */
7052
7503
  onTurnComplete?: (event: TurnCompleteEvent) => void;
7053
7504
  /** Diagnostic — fires when a turn is skipped. */
@@ -7108,6 +7559,536 @@ declare const DEFAULT_CHUNK_CACHE_SIZE = 5000;
7108
7559
  */
7109
7560
  declare function createChunkVectorCache(maxSize?: number): ChunkVectorCache;
7110
7561
 
7562
+ /**
7563
+ * Temporal decay classifier (PR2) — pure, DB-free, unit-testable.
7564
+ *
7565
+ * Decides whether a stored memory should be kept, archived (soft, recoverable),
7566
+ * or hard-deleted, based ONLY on its plaintext columns. This is the
7567
+ * zero-knowledge core of the decay sweep: it never sees `content` and never
7568
+ * triggers a signature/decrypt, so it can run wherever a wallet key is NOT
7569
+ * loaded. The sweep worker ({@link ./decayWorker}) feeds it raw rows selected
7570
+ * via `unsafeFetchRaw` and materializes Models only for the transitions.
7571
+ *
7572
+ * Lifecycle (mirrors the timestamp state machine in db/schema.ts):
7573
+ * active → archived (set `archived_at`) — recoverable, drops out of recall
7574
+ * archived → deleted (set `is_deleted`) — terminal, after HARD_DELETE_WINDOW
7575
+ *
7576
+ * Per-type TTL policy (the "becomes past" intuition):
7577
+ * - identity / preference / relationship / constraint → never age-archive
7578
+ * (durable facts about who the user is; Infinity TTL).
7579
+ * - plan / ongoing_context → short TTL (they go stale as time moves on).
7580
+ * - other / null (untyped/legacy) → medium TTL.
7581
+ * `source === "manual"` memories are protected from AUTO-ARCHIVE (user-curated)
7582
+ * — but NOT from the hard-delete clock once they are archived: archive is the
7583
+ * shared purge buffer for every row, so an already-archived manual memory is
7584
+ * still deleted after the window (the archived check runs before the manual
7585
+ * short-circuit by design).
7586
+ */
7587
+ /** The verdict for a single memory. */
7588
+ type DecayVerdict = "keep" | "archive" | "delete";
7589
+ /** Short TTL — `plan` / `ongoing_context` age out ~30 days after last touch. */
7590
+ declare const SHORT_TTL_MS: number;
7591
+ /** Medium TTL — `other` / untyped rows age out ~180 days after last touch. */
7592
+ declare const MEDIUM_TTL_MS: number;
7593
+ /**
7594
+ * "Never" TTL — durable identity-class types (identity/preference/relationship/
7595
+ * constraint) never age-archive. Expressed as +Infinity so the age comparison
7596
+ * `now - updatedAt > ttl` is always false.
7597
+ */
7598
+ declare const NEVER_TTL_MS: number;
7599
+ /**
7600
+ * How long an archived memory lingers (recoverable) before the sweep hard-
7601
+ * deletes it. ~30 days gives the user a window to restore an over-eager decay.
7602
+ */
7603
+ declare const HARD_DELETE_WINDOW_MS: number;
7604
+ /**
7605
+ * Grace applied after a `plan` / `ongoing_context` event's `event_time_end`
7606
+ * before it's considered "become past" and archived. Avoids archiving a plan
7607
+ * the instant its end date passes (the user may still reference it briefly).
7608
+ */
7609
+ declare const PAST_EVENT_GRACE_MS: number;
7610
+ /**
7611
+ * Per-type TTL + window overrides. Pass a partial to {@link classifyDecay} /
7612
+ * the sweeper to tune behavior (evaluation harnesses, tests). Anything omitted
7613
+ * falls back to {@link DEFAULT_DECAY_POLICY}.
7614
+ */
7615
+ interface DecayPolicy {
7616
+ /**
7617
+ * Age TTL (ms since `updatedAt`) per FactType. A type absent from this map —
7618
+ * or a null/unknown `factType` — uses {@link DecayPolicy.fallbackTtlMs}.
7619
+ */
7620
+ ttlByType: Record<string, number>;
7621
+ /** TTL for `null` / unknown fact types (the medium bucket). */
7622
+ fallbackTtlMs: number;
7623
+ /** How long an archived row lingers before hard delete. */
7624
+ hardDeleteWindowMs: number;
7625
+ /** Grace after a past `event_time_end` before archiving a plan/ongoing. */
7626
+ pastEventGraceMs: number;
7627
+ }
7628
+ /** Default policy — the locked per-type TTLs. */
7629
+ declare const DEFAULT_DECAY_POLICY: DecayPolicy;
7630
+ /**
7631
+ * The minimal plaintext shape {@link classifyDecay} reads. Deliberately excludes
7632
+ * `content` (encrypted; never touched by decay) — the sweep selects exactly
7633
+ * these columns so it stays zero-knowledge.
7634
+ */
7635
+ interface DecayInput {
7636
+ /**
7637
+ * The row's stable id. Not read by the rule engine ({@link classifyDecay}
7638
+ * ignores it) — it is threaded through so an optional content-reading decay
7639
+ * classifier (PR5, {@link createLlmDecayClassifier}) can fetch + decrypt the
7640
+ * row for a borderline verdict. Optional so pure rule-based callers/tests can
7641
+ * omit it.
7642
+ */
7643
+ id?: string;
7644
+ /** The extractor's FactType, or null (legacy/manual/untyped → medium bucket). */
7645
+ factType: string | null;
7646
+ /** W6 temporal lane — Unix ms the event ended (range/ongoing), or null. */
7647
+ eventTimeEnd: number | null;
7648
+ /** W6 temporal lane — `point | range | ongoing | null`. */
7649
+ eventTimeKind: string | null;
7650
+ /** Unix ms of the row's last write (re-observation resets this). */
7651
+ updatedAt: number;
7652
+ /** Unix ms when archived, or null when active. */
7653
+ archivedAt: number | null;
7654
+ /** `manual` | `auto-extracted` | `capsule` | null. Manual is never decayed. */
7655
+ source: string | null;
7656
+ /**
7657
+ * `trusted` | `quarantined` | null. Not read by the rule engine
7658
+ * ({@link classifyDecay} ignores it — quarantined rows still age/archive/delete
7659
+ * by RULE). It exists only so the sweeper's `isBorderline` can keep a
7660
+ * quarantined (injection-screened) row away from the optional content-reading
7661
+ * classifier, so poison content never egresses. Optional so pure rule-based
7662
+ * callers/tests can omit it (treated as not quarantined).
7663
+ */
7664
+ trustTier?: string | null;
7665
+ }
7666
+ /**
7667
+ * The age TTL for a fact type. `null` / unknown types fall to the medium
7668
+ * fallback bucket (never Infinity — untyped rows must still eventually age out).
7669
+ */
7670
+ declare function ttlForType(factType: string | null, policy?: Partial<DecayPolicy>): number;
7671
+ /**
7672
+ * Classify one memory into a decay verdict, reading only plaintext fields.
7673
+ *
7674
+ * Rules, in order (first match wins):
7675
+ * 0. Non-finite timestamps → keep (safe) + warn (corrupt row, observable).
7676
+ * 1. Already archived (`archivedAt != null`): delete once past the hard-delete
7677
+ * window, else keep — runs REGARDLESS of `source`, so the purge clock
7678
+ * applies to archived manual rows too.
7679
+ * 2. `source === "manual"` → keep — protects manual saves from AUTO-ARCHIVE
7680
+ * only (rules 3/4). Delete-of-already-archived is handled above.
7681
+ * 3. `plan` / `ongoing_context` whose event has become past — `eventTimeEnd`
7682
+ * is set AND older than `now - grace` → archive. An `ongoing` status with a
7683
+ * null `eventTimeEnd` is still ongoing, so this rule does not fire for it.
7684
+ * 4. Age fallback — `now - updatedAt > TTL(factType)` → archive. Durable types
7685
+ * have Infinity TTL, so this never fires for them; null/unknown use medium.
7686
+ * EXCEPTION: a `plan`/`ongoing_context` with a still-upcoming event
7687
+ * (`eventTimeEnd >= now`) is kept — it must not age-archive before the event
7688
+ * happens; only rule 3 (after it passes) may archive it.
7689
+ * 5. Otherwise → keep.
7690
+ *
7691
+ * @param m Plaintext decay inputs for one row.
7692
+ * @param now Reference time (Unix ms). Injected for determinism.
7693
+ * @param policy Optional partial policy overriding {@link DEFAULT_DECAY_POLICY}.
7694
+ */
7695
+ declare function classifyDecay(m: DecayInput, now: number, policy?: Partial<DecayPolicy>): DecayVerdict;
7696
+
7697
+ /**
7698
+ * Decay sweeper (PR2) — orchestration glue that runs the temporal-decay
7699
+ * lifecycle over the vault. Mirrors the shape of {@link ./autoExtractWorker}'s
7700
+ * `createAutoExtractor`: created once, driven by the caller (a client hook on a
7701
+ * low-frequency interval / app-foreground), disposable.
7702
+ *
7703
+ * A sweep is zero-knowledge by construction:
7704
+ * 1. {@link getDecayCandidatesRawOp} selects plaintext columns via
7705
+ * `unsafeFetchRaw` — no `content`, no decrypt, no Model per row.
7706
+ * 2. {@link classifyDecay} is a pure function over those plaintext fields.
7707
+ * 3. Only the (usually small) transition set is materialized as Models to
7708
+ * archive ({@link archiveVaultMemoryOp}) or hard-delete
7709
+ * ({@link hardDeleteDecayedOp}, which re-checks archived + past-window
7710
+ * inside the write so a concurrent restore wins).
7711
+ *
7712
+ * The optional {@link DecayClassifier} is a PR5 seam for an on-device model that
7713
+ * refines borderline verdicts by reading decrypted content — it is NOT
7714
+ * implemented here. Default is `undefined` → pure rule-based, which is what
7715
+ * keeps the default path zero-knowledge.
7716
+ */
7717
+
7718
+ /** Counts from one sweep, for UI surfacing (e.g. "N memories archived"). */
7719
+ interface DecaySweepResult {
7720
+ /** Rows transitioned active → archived this sweep. */
7721
+ archived: number;
7722
+ /** Rows hard-deleted (archived past the window) this sweep. */
7723
+ deleted: number;
7724
+ /** Total candidate rows scanned (all non-hard-deleted rows). */
7725
+ scanned: number;
7726
+ }
7727
+ /**
7728
+ * PR5 seam — an on-device classifier that refines the rule-based verdict for
7729
+ * borderline rows (e.g. type `other`/null, or a `plan` without an event end).
7730
+ * Because it may read decrypted content, callers MUST gate providing it on
7731
+ * wallet-key availability. Left undefined here → pure rule-based sweep.
7732
+ *
7733
+ * Egress is bounded by the sweeper (NOT the classifier): each sweep caps how
7734
+ * many rows reach the classifier ({@link CreateDecaySweeperOptions.maxClassifierCallsPerSweep})
7735
+ * and a row whose (id, updated_at) was already classified is never re-sent on a
7736
+ * later sweep — so a stable borderline "keep" row egresses at most once.
7737
+ *
7738
+ * SECURITY (MEDIUM, residual) — enabling a classifier hands whoever answers the
7739
+ * portal (incl. a malicious / MITM'd endpoint) a lever over the affected rows:
7740
+ * a hostile verdict can only quarantine-adjacent OUTCOMES here, i.e. archive a
7741
+ * row (reversible — never a hard delete, which stays the deterministic
7742
+ * archived-past-window mechanic). Bounded, reversible trust tradeoff; gate the
7743
+ * classifier on trust in the portal.
7744
+ *
7745
+ * @param input The same plaintext inputs the rule engine saw.
7746
+ * @param ruleVerdict The rule-based verdict, as a starting point / fallback.
7747
+ * @param now The sweep's reference time (Unix ms). Injected so the
7748
+ * classifier derives any age math from the same clock the rule engine used,
7749
+ * never wall-clock `Date.now()` — keeping a fixed-`now` sweep deterministic.
7750
+ * @returns The (possibly refined) verdict.
7751
+ */
7752
+ interface DecayClassifier {
7753
+ classify(input: DecayInput, ruleVerdict: DecayVerdict, now: number): Promise<DecayVerdict> | DecayVerdict;
7754
+ }
7755
+ /** A clock: a fixed timestamp (tests) or a getter (production intervals). */
7756
+ type NowSource = number | (() => number);
7757
+ /** @public */
7758
+ interface CreateDecaySweeperOptions {
7759
+ /** Vault write context — the same one recall/retain use. */
7760
+ vaultCtx: VaultMemoryOperationsContext;
7761
+ /**
7762
+ * Reference "now". A number is fixed (deterministic tests); a function is
7763
+ * re-evaluated per sweep (long-lived interval usage). Default `Date.now`.
7764
+ */
7765
+ now?: NowSource;
7766
+ /** Partial policy overriding the per-type TTL defaults. Omit for defaults. */
7767
+ policy?: Partial<DecayPolicy>;
7768
+ /**
7769
+ * PR5 seam. When provided, borderline candidates' rule verdict is passed
7770
+ * through it. Gate on key availability (it may decrypt content). Default
7771
+ * undefined. Egress is bounded — see {@link maxClassifierCallsPerSweep}.
7772
+ */
7773
+ classifier?: DecayClassifier;
7774
+ /**
7775
+ * PR5 — hard ceiling on classifier invocations (and thus decrypted-content
7776
+ * portal egress) per sweep. Once hit, the remaining borderline rows fall back
7777
+ * to the rule verdict for that sweep (no call). Prevents a large vault from
7778
+ * firing hundreds of sequential content-bearing calls in one sweep. Default
7779
+ * {@link DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP} (20). Cache hits (a row
7780
+ * already classified at its current `updated_at`) do NOT count against this.
7781
+ */
7782
+ maxClassifierCallsPerSweep?: number;
7783
+ /** Fires once after each sweep with the transition counts (UI). */
7784
+ onSwept?: (result: DecaySweepResult) => void;
7785
+ /** Diagnostic — fires on an unexpected sweep-level error. */
7786
+ onError?: (error: Error) => void;
7787
+ }
7788
+ /** @public */
7789
+ interface DecaySweeper {
7790
+ /**
7791
+ * Scan the vault, classify every candidate, and apply archive/delete
7792
+ * transitions. Safe to call repeatedly (idempotent — a keep stays a keep, an
7793
+ * already-archived row won't re-archive). Returns the transition counts.
7794
+ * A no-op (returns zero counts) after {@link DecaySweeper.dispose}.
7795
+ */
7796
+ runSweep(): Promise<DecaySweepResult>;
7797
+ /** Stop accepting sweeps. An in-flight `runSweep()` resolves normally. */
7798
+ dispose(): void;
7799
+ }
7800
+ /**
7801
+ * Default per-sweep ceiling on decay-classifier invocations (see
7802
+ * {@link CreateDecaySweeperOptions.maxClassifierCallsPerSweep}). Kept small: the
7803
+ * classifier egresses DECRYPTED content, so a sweep must never fan out to
7804
+ * hundreds of sequential calls. 20 covers the borderline churn of a typical
7805
+ * sweep while capping worst-case egress; stable rows are also cached so this
7806
+ * ceiling is rarely reached after the first sweep.
7807
+ */
7808
+ declare const DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP = 20;
7809
+ /**
7810
+ * Create a decay sweeper. See module docstring for the zero-knowledge contract.
7811
+ */
7812
+ declare function createDecaySweeper(options: CreateDecaySweeperOptions): DecaySweeper;
7813
+
7814
+ /**
7815
+ * Optional content-reading decay classifier (PR5).
7816
+ *
7817
+ * The rule engine ({@link ./decay}.classifyDecay) decides keep/archive/delete
7818
+ * from plaintext columns ALONE — it never sees `content`, which is what keeps
7819
+ * the default decay sweep zero-knowledge. That is the right default, but it is
7820
+ * weakest on BORDERLINE rows: an `other`/untyped fact, or a `plan` with no
7821
+ * event end, whose staleness is a pure `updated_at` guess.
7822
+ *
7823
+ * This factory builds a {@link DecayClassifier} that reads the DECRYPTED content
7824
+ * of such a row and returns keep-vs-archive. The sweeper consults it ONLY for a
7825
+ * borderline row whose CURRENT rule verdict is `keep` — a rule archive/delete
7826
+ * short-circuits before the classifier ever runs (see `decayWorker.verdictFor` +
7827
+ * `isBorderline`). So its whole job is to REFINE a still-kept borderline row
7828
+ * toward EARLIER archive when the content shows it is genuinely ephemeral (a
7829
+ * finished one-off plan, an expired temporary state) — turning a weak age-only
7830
+ * "keep" into an "archive" sooner.
7831
+ *
7832
+ * DIRECTIONALITY IS DELIBERATE (a security property, not a shortcoming): it can
7833
+ * move a borderline keep → archive, never the reverse. It CANNOT rescue /
7834
+ * keep-alive a row the rule would archive — the escalation gate makes that path
7835
+ * unreachable, and archive is reversible while un-archiving poison would not be.
7836
+ * Enabling a classifier hands whoever answers the portal (incl. a malicious /
7837
+ * MITM'd endpoint) a lever, and that lever must only ever archive-reversibly.
7838
+ *
7839
+ * ZERO-KNOWLEDGE CONTRACT (the caller MUST honor this):
7840
+ * - `getContent` is supplied by the caller and MUST be gated on wallet-key
7841
+ * availability: return `null` when no key is loaded. With no content the
7842
+ * classifier degrades to the rule verdict — never blocks, never guesses.
7843
+ * - When it does read content and calls the portal, the content is
7844
+ * PII-redacted first. Redaction is OPT-OUT, not opt-in: it defaults ON when
7845
+ * the consumer omits `piiRedaction`, so a caller can never accidentally
7846
+ * egress raw PII. Pass `piiRedaction: false` to deliberately disable it.
7847
+ * - Egress is bounded by the SWEEPER, not this classifier: the sweep caps
7848
+ * invocations per pass and never re-sends an unchanged (id, updated_at) row
7849
+ * (see `decayWorker`), so a stable borderline "keep" row egresses once.
7850
+ * - It only ever chooses keep vs archive, and only for a row the rule already
7851
+ * keeps. It NEVER escalates to `delete` and NEVER un-archives — hard-delete
7852
+ * is exclusively the deterministic archived-past-window mechanic (rule 1),
7853
+ * and a row the rule wants archived is archived regardless of this layer.
7854
+ *
7855
+ * Fails to the rule verdict (keep) on any error, missing id, no key, or
7856
+ * malformed response — like every other optional LLM layer in this subsystem it
7857
+ * can only refine a borderline keep toward archive, never make the sweep worse.
7858
+ *
7859
+ * RESIDUAL SCOPE (accepted): a genuinely durable fact MISTYPED as `other`/null
7860
+ * and never re-mentioned within its medium TTL WILL age-archive — this layer can
7861
+ * only bring that archive EARLIER, never prevent it. Accepted because it is
7862
+ * recoverable: archived rows stay in the Archived section, Restore clears
7863
+ * `archived_at`, and any re-observation resets the TTL. The alternative — a
7864
+ * keep-alive lever — is exactly the capability a hostile portal must NOT have.
7865
+ *
7866
+ * SECURITY (MEDIUM, residual) — this is a NEW portal call surface carrying
7867
+ * (redacted) memory content. It is opt-in (you must construct + pass it) and
7868
+ * gated on key availability. Beyond widening which models see facts, a
7869
+ * malicious / MITM'd portal can steer the verdict — but only to ARCHIVE a row
7870
+ * (reversible; never a hard delete). Gate it on trust in the portal.
7871
+ */
7872
+
7873
+ /**
7874
+ * Auth + wiring for {@link createLlmDecayClassifier}. Auth is the dual pattern —
7875
+ * one of `apiKey` / `getToken` is required at runtime (see {@link PortalLlmAuth}).
7876
+ * @public
7877
+ */
7878
+ interface LlmDecayClassifierOptions extends PortalLlmAuth {
7879
+ baseUrl?: string;
7880
+ model?: string;
7881
+ /** Override fetch (tests). */
7882
+ fetchFn?: typeof fetch;
7883
+ /** Max portal attempts on a TRANSIENT failure. Default 2. */
7884
+ maxAttempts?: number;
7885
+ /** Absolute wall-clock budget across attempts. Default 12s. */
7886
+ totalTimeoutMs?: number;
7887
+ /** Backoff before each retry (ms). Tests pass `() => 0`. */
7888
+ backoffMs?: (attempt: number) => number;
7889
+ /**
7890
+ * PII redaction for the outbound content. OPT-OUT: defaults to ON (a fresh
7891
+ * per-call redactor) when omitted, so decrypted content is never egressed
7892
+ * raw by accident. Pass a shared {@link PiiRedactor} to keep placeholder
7893
+ * numbering consistent with other calls, or `false` to deliberately disable
7894
+ * redaction. The verdict returned is a bare enum — nothing to de-anonymize.
7895
+ */
7896
+ piiRedaction?: boolean | PiiRedactor;
7897
+ /**
7898
+ * Resolve a memory's DECRYPTED content by id. The caller supplies this and
7899
+ * MUST gate it on wallet-key availability — return `null` when no key is
7900
+ * loaded so the classifier degrades to the rule verdict (zero-knowledge).
7901
+ * A throw is treated the same as `null` (fail to the rule verdict).
7902
+ */
7903
+ getContent: (id: string) => Promise<string | null>;
7904
+ }
7905
+ /**
7906
+ * Build a {@link DecayClassifier} that reads a borderline row's decrypted
7907
+ * content and returns a keep/archive verdict via a cheap portal LLM. Pass it as
7908
+ * `createDecaySweeper({ classifier })`. See the module docstring for the
7909
+ * zero-knowledge contract. Returns the rule verdict on any failure and never
7910
+ * escalates to `delete`.
7911
+ * @public
7912
+ */
7913
+ declare function createLlmDecayClassifier(options: LlmDecayClassifierOptions): DecayClassifier;
7914
+
7915
+ /**
7916
+ * Multi-hop graph traversal for the W5 entity-graph recall lane (PR4,
7917
+ * MRAgent-style "active reconstruction").
7918
+ *
7919
+ * The single-hop lane (see `recall.ts:buildGraphLaneRanking`) does one thing:
7920
+ * extract entities from the query, look up memories sharing any of them, and
7921
+ * order those memories by shared-entity count. That is hop 1 — the "seed"
7922
+ * lookup. This module wraps a bounded breadth-first search around it: from the
7923
+ * seed memories it walks OUT to their neighbor entities (via the new reverse
7924
+ * edge {@link getEntitiesByMemoryIdsOp}), ranks those neighbors by
7925
+ * co-occurrence across the frontier, expands the top few, and pulls the
7926
+ * memories they reach — repeating up to {@link MAX_HOPS} times.
7927
+ *
7928
+ * Cost note (why this is cheap): NONE of this runs cosine. Cosine runs exactly
7929
+ * once per recall inside `searchVaultMemoriesWithSize`. This lane only emits an
7930
+ * ordered list of memory IDs that is RRF-fused against the cosine head. So
7931
+ * multi-hop adds indexed WatermelonDB joins + more RRF entries, not embedding
7932
+ * math. The dominant cost of enabling it is the reranker over a slightly larger
7933
+ * candidate pool — which stays bounded because `rerankTopN` remains
7934
+ * authoritative downstream.
7935
+ *
7936
+ * Determinism: neighbor-entity selection is pure co-occurrence counting by
7937
+ * default. An optional LLM path-refiner (PR5) can override which neighbors
7938
+ * expand; it falls back to the deterministic order on any error.
7939
+ *
7940
+ * Hop numbering: hop 1 is the seed lookup. `maxHops = 1` therefore means "seed
7941
+ * only" — byte-for-byte identical to the single-hop lane (the regression guard).
7942
+ * `MAX_HOPS = 2` (the PR5 default) performs one expansion beyond the seed.
7943
+ *
7944
+ * Neighbor selection at each expansion hop is deterministic co-occurrence
7945
+ * counting by default. PR5 adds an OPTIONAL LLM path-refiner
7946
+ * ({@link NeighborRefiner} / {@link createLlmNeighborRefiner}) that lets a model
7947
+ * pick which neighbor entities to expand instead; it is opt-in, capped to ≤1
7948
+ * call per hop, and falls back to the deterministic order on any error.
7949
+ */
7950
+
7951
+ /**
7952
+ * Total hops the traversal performs, counting the seed lookup as hop 1.
7953
+ * `1` = seed only (identical to the single-hop lane). PR5 default is `2` (one
7954
+ * expansion beyond the seed). Overridable per-call for ablation. Still gated to
7955
+ * the `high` budget in recall, and capped back to 1 on large vaults by
7956
+ * {@link capHopsForDensity}.
7957
+ * @public
7958
+ */
7959
+ declare const MAX_HOPS = 2;
7960
+ /**
7961
+ * Max neighbor entities expanded per hop. Caps fan-out so a densely-linked
7962
+ * frontier can't explode the candidate pool. Neighbors are ranked by
7963
+ * co-occurrence frequency across the frontier; only the top this-many expand.
7964
+ * @public
7965
+ */
7966
+ declare const ENTITY_FANOUT = 8;
7967
+ /**
7968
+ * Hard ceiling on total accumulated memory IDs across all hops. The BFS stops
7969
+ * expanding once the accumulated set reaches this size (and the frontier is
7970
+ * bounded to it too), keeping the RRF pool — and the downstream reranker
7971
+ * workload — bounded regardless of graph density.
7972
+ * @public
7973
+ */
7974
+ declare const NODE_BUDGET = 64;
7975
+ /**
7976
+ * Above this vault size, {@link capHopsForDensity} forces `MAX_HOPS = 1`
7977
+ * (seed-only). Fan-out grows with graph density, so on large vaults we don't
7978
+ * pay the expansion cost. Bounded-traversal safety valve.
7979
+ * @public
7980
+ */
7981
+ declare const VAULT_SIZE_HOP_CAP = 1000;
7982
+ /** Options for {@link traverseGraphLane}. All optional; defaults are the
7983
+ * exported constants above. Exposed for ablation / evaluation sweeps.
7984
+ * @public */
7985
+ interface GraphTraversalOptions {
7986
+ /** Total hops incl. the seed lookup (hop 1). Default {@link MAX_HOPS}. */
7987
+ maxHops?: number;
7988
+ /** Max neighbor entities expanded per hop. Default {@link ENTITY_FANOUT}. */
7989
+ entityFanout?: number;
7990
+ /** Hard cap on accumulated memory IDs. Default {@link NODE_BUDGET}. */
7991
+ nodeBudget?: number;
7992
+ /** RRF smoothing constant for per-hop fusion. Default 60 (rrf.ts). */
7993
+ rrfK?: number;
7994
+ /**
7995
+ * Vault size hint. When provided and above {@link VAULT_SIZE_HOP_CAP}, the
7996
+ * effective hop count is capped to 1 (see {@link capHopsForDensity}).
7997
+ */
7998
+ vaultSize?: number;
7999
+ /**
8000
+ * PR5 — optional LLM neighbor-selection. When provided, at each expansion hop
8001
+ * the deterministically-ranked candidate neighbor entities are handed to this
8002
+ * refiner, which returns the subset to expand. Falls back to the
8003
+ * co-occurrence order on any error or empty result. Called at most ONCE per
8004
+ * hop. Build one with {@link createLlmNeighborRefiner}, or supply your own.
8005
+ */
8006
+ refineNeighbors?: NeighborRefiner;
8007
+ /**
8008
+ * Resolve a batch of candidate memory ids to just the ACTIVE ones (not
8009
+ * archived, not quarantined, not soft-deleted — the same set the final recall
8010
+ * gate admits). When provided, traversal drops "forgotten" memories from the
8011
+ * frontier AT EACH HOP so they neither steer neighbor-entity ranking nor
8012
+ * egress their entity names to {@link refineNeighbors}. Omit (tests /
8013
+ * entity-only callers) to traverse over every linked memory. Wire it from a
8014
+ * vault context with {@link ../db/memoryVault/operations.getActiveVaultMemoryIdsOp}.
8015
+ */
8016
+ filterActiveMemoryIds?: (ids: string[]) => Promise<Set<string>>;
8017
+ }
8018
+ /**
8019
+ * Picks which candidate neighbor entities to expand at a traversal hop. Given
8020
+ * the query and the deterministically-ranked candidate entity names, return the
8021
+ * subset (≤ `limit`) to expand. Must be resilient: {@link traverseGraphLane}
8022
+ * falls back to the deterministic top-`limit` on a throw or empty return.
8023
+ * @public
8024
+ */
8025
+ interface NeighborRefiner {
8026
+ refine(query: string, candidates: string[], limit: number): Promise<string[]>;
8027
+ }
8028
+ /**
8029
+ * Cap the hop count on large vaults. Fan-out grows with graph density, so above
8030
+ * {@link VAULT_SIZE_HOP_CAP} memories we force seed-only traversal (1 hop)
8031
+ * rather than pay an unbounded expansion. A no-op when `vaultSize` is unknown or
8032
+ * within the threshold.
8033
+ * @public
8034
+ */
8035
+ declare function capHopsForDensity(maxHops: number, vaultSize?: number): number;
8036
+ /**
8037
+ * Bounded multi-hop entity-graph traversal. Returns an ordered list of memory
8038
+ * IDs (best first) — the SAME output shape as the single-hop lane, so nothing
8039
+ * downstream changes. The caller passes it through as `entityRanking` for RRF
8040
+ * fusion with the cosine/BM25 head.
8041
+ *
8042
+ * With `maxHops <= 1` this returns the seed ordering verbatim, making it a
8043
+ * drop-in equivalent of the single-hop lane (the regression guard). The PR5
8044
+ * default is 2 (one expansion beyond the seed).
8045
+ *
8046
+ * Returns an empty array when the query has no extractable entities or no stored
8047
+ * memory shares a seed entity.
8048
+ *
8049
+ * @public
8050
+ */
8051
+ declare function traverseGraphLane(query: string, entityCtx: EntityOperationsContext, options?: GraphTraversalOptions): Promise<string[]>;
8052
+ /** Auth + tuning for {@link createLlmNeighborRefiner}. Reuses the recall
8053
+ * `decomposeOptions` shape (dual auth — one of `apiKey`/`getToken`). @public */
8054
+ interface LlmNeighborRefinerOptions extends PortalLlmAuth {
8055
+ baseUrl?: string;
8056
+ model?: string;
8057
+ fetchFn?: typeof fetch;
8058
+ maxAttempts?: number;
8059
+ totalTimeoutMs?: number;
8060
+ backoffMs?: (attempt: number) => number;
8061
+ }
8062
+ /**
8063
+ * Build a {@link NeighborRefiner} backed by a cheap portal LLM. At each hop it
8064
+ * asks the model to pick, from the candidate neighbor entities, the ≤`limit`
8065
+ * most relevant to the query, so traversal expands toward the question instead
8066
+ * of purely by co-occurrence frequency.
8067
+ *
8068
+ * Bounded + fail-safe: one attempt by default, a short total timeout, and
8069
+ * {@link traverseGraphLane} falls back to the deterministic co-occurrence order
8070
+ * on any throw or empty result — so enabling this can reorder which neighbors
8071
+ * expand but never breaks or stalls recall.
8072
+ *
8073
+ * SECURITY / ZERO-KNOWLEDGE (must stay default-OFF): this sends the query +
8074
+ * candidate ENTITY NAMES to the portal UNREDACTED. Those names ARE user PII —
8075
+ * people, places, orgs pulled from the stored graph (e.g. "Sara", "Kyoto",
8076
+ * "Acme") — not lower-risk than content just because they're short. It reuses
8077
+ * the query-decompose auth and is opt-in (`RecallOptions.graphRefine`, default
8078
+ * off in recall); leave it off unless you accept that exposure. To bound that
8079
+ * exposure, {@link traverseGraphLane} caps the candidate list it hands this
8080
+ * refiner per hop — at most `MAX_REFINER_CANDIDATES` entity names ever leave per
8081
+ * hop, REGARDLESS of `entityFanout` (the cap is a hard ceiling, not just a
8082
+ * fanout-scaled floor), so the full frontier is never egressed.
8083
+ *
8084
+ * MEDIUM residual: a malicious / MITM'd portal can only steer WHICH neighbor
8085
+ * entities expand — a recall-ranking nudge, not a data-integrity change (no
8086
+ * memory is written, archived, or deleted), and {@link traverseGraphLane}
8087
+ * falls back to deterministic order on any bad/empty response. Bounded tradeoff.
8088
+ * @public
8089
+ */
8090
+ declare function createLlmNeighborRefiner(options: LlmNeighborRefinerOptions): NeighborRefiner;
8091
+
7111
8092
  /**
7112
8093
  * Unified Recall API — single retrieval surface above vault + engine.
7113
8094
  *
@@ -8625,6 +9606,9 @@ declare class WatermelonChatStorageAdapter implements ChatStorageAdapter {
8625
9606
  * - v33: Added embedding_model column to memory_vault so stale-model vectors are
8626
9607
  * detectable and re-embeddable after an embedding-model change (null = legacy
8627
9608
  * rows, grandfathered as compatible with the current model)
9609
+ * - v34: Added topics_user_managed column to memory_vault so a memory whose
9610
+ * entity links the user has taken manual control of is left alone by
9611
+ * auto-extraction (null/false = auto-derived, the default)
8628
9612
  * - v35: Added conversation_memory table recording which vault memories a
8629
9613
  * conversation drew on, so the conversation-level Memories panel survives reload
8630
9614
  * - v36: Added topics_extracted_at column to memory_vault — watermark of the last
@@ -8643,8 +9627,13 @@ declare class WatermelonChatStorageAdapter implements ChatStorageAdapter {
8643
9627
  * watermark stamped each time retain() merges into an existing fact, kept
8644
9628
  * distinct from updated_at (which merges preserve). Lets profile synthesis
8645
9629
  * weight facts by recency of reinforcement rather than last edit.
9630
+ * - v40: Added fact_type, archived_at, trust_tier columns to memory_vault for
9631
+ * typed memory + decay + Tier-0 security. All nullable + plaintext, no
9632
+ * backfill (null = legacy/untyped, active, un-screened — content is
9633
+ * encrypted so in-migration classification is impossible; NULL = zero-risk,
9634
+ * exact embedding_model precedent)
8646
9635
  */
8647
- declare const SDK_SCHEMA_VERSION = 39;
9636
+ declare const SDK_SCHEMA_VERSION = 40;
8648
9637
  /**
8649
9638
  * Combined WatermelonDB schema for all SDK storage modules.
8650
9639
  *
@@ -8722,11 +9711,13 @@ declare const sdkSchema: Readonly<{
8722
9711
  * - v30 → v31: Added `user_id` column to memory_entity for multi-user scoping of the W5 graph lane (with backfill from memory_vault.user_id)
8723
9712
  * - v31 → v32: Added `pinned_at` column to conversations for pinning chats
8724
9713
  * - v32 → v33: Added `embedding_model` column to memory_vault (null grandfathered as current-model-compatible)
9714
+ * - v33 → v34: Added `topics_user_managed` column to memory_vault (null/false = auto-derived topics, the default)
8725
9715
  * - v34 → v35: Added `conversation_memory` table (conversation ↔ recalled memory ids)
8726
9716
  * - v35 → v36: Added `topics_extracted_at` column to memory_vault (watermark for the background topic-extraction worker; null + existing links grandfathered as extracted)
8727
9717
  * - v36 → v37: Added `superseded_by` + `superseded_at` columns to memory_vault (write-time supersession; null = live, excluded from recall/dedup when set)
8728
9718
  * - v37 → v38: Added `topics_extracted_version` column to memory_vault (extraction-logic version; null read as 0 so a TOPICS_EXTRACTION_VERSION bump re-extracts stale rows)
8729
9719
  * - v38 → v39: Added `last_observed_at` column to memory_vault (C3 re-observation watermark; stamped on retain merge, distinct from updated_at)
9720
+ * - v39 → v40: Added `fact_type`, `archived_at`, `trust_tier` columns to memory_vault for typed memory + decay + Tier-0 security (all nullable + plaintext, NULL backfill)
8730
9721
  */
8731
9722
  declare const sdkMigrations: Readonly<{
8732
9723
  validated: true;
@@ -12875,4 +13866,4 @@ declare function renderAnumaTree(node: AnumaNode): React.ReactElement | null;
12875
13866
  */
12876
13867
  declare function renderAnumaJsx(jsx: string): React.ReactElement | null;
12877
13868
 
12878
- export { Anuma, type AnumaChild, AnumaJsxError, type AnumaNode, AnumaShadowIsolationProvider, type AnumaShadowIsolationProviderProps, type AnumaTheme, AnumaThemeProvider, type AnumaThemeProviderProps, AppFile as AppFileModel, type AppFileOperationsContext, type AttrValue, type AutoExtractMessage, type AutoExtractor, DEFAULT_CONVERSATIONS_FOLDER as BACKUP_DRIVE_CONVERSATIONS_FOLDER, DEFAULT_ROOT_FOLDER as BACKUP_DRIVE_ROOT_FOLDER, DEFAULT_BACKUP_FOLDER as BACKUP_ICLOUD_FOLDER, BUILT_IN_TOOL_SETS, type BackupAuthContextValue, BackupAuthProvider, type BackupAuthProviderProps, type BackupOperationOptions, BlobUrlManager, type Budget, type CachedChunkVectors, type CachedServerTools, ChartCard, type ChartCardProps, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Conversation as ChatConversation, Message as ChatMessage, type ChatRole, type ChatStorageAdapter, type ChatStorageObservable, type ChunkSearchResult, type ChunkVectorCache, type ChunkingOptions, type CircleProps, type ClientToolsFilterFn, type ConsolidationFallbackReason, type ConversationMemoryInput, ConversationMemory as ConversationMemoryModel, type ConversationMemoryOperationsContext, type ConversationQueryOptions, type CreateAutoExtractorOptions, type CreateConversationOptions, type CreateEntityOptions, type CreateMediaOptions, type CreateMessageOptions, type CreateModelPreferenceOptions, type CreateProjectOptions, type CreateSavedToolOptions, type CreateServerToolsFilterOptions, type CreateUserPreferenceOptions, type CreateVaultFolderOptions, type CreateVaultMemoryOptions, type CryptoPriceClassification, type CryptoPricePreProcessorOptions, DEFAULT_BACKUP_FOLDER$1 as DEFAULT_BACKUP_FOLDER, DEFAULT_CACHE_EXPIRATION_MS, DEFAULT_CHUNK_CACHE_SIZE, DEFAULT_CHUNK_OVERLAP, DEFAULT_CHUNK_SIZE, DEFAULT_CONVERSATIONS_FOLDER as DEFAULT_DRIVE_CONVERSATIONS_FOLDER, DEFAULT_ROOT_FOLDER as DEFAULT_DRIVE_ROOT_FOLDER, DEFAULT_BACKUP_FOLDER$1 as DEFAULT_DROPBOX_FOLDER, DEFAULT_EXCLUDED_SERVER_TOOLS, DEFAULT_BACKUP_FOLDER as DEFAULT_ICLOUD_BACKUP_FOLDER, DEFAULT_MIN_CHUNK_SIZE, DEFAULT_PERSONALITY_SETTINGS, DEFAULT_PROFILE_FACETS, DEFAULT_SERVER_TOOLS_MATCH_OPTIONS, DEFAULT_VAULT_CACHE_SIZE, DatabaseManager, type DatabaseManagerLogger, type DatabaseManagerOptions, type DeckProps, type DisplayToolMigrations, type DropboxAuthContextValue, DropboxAuthProvider, type DropboxAuthProviderProps, type DropboxExportResult, type DropboxImportResult, ENTITY_KINDS, type EmbeddedWalletSignerFn, type EntityInput, type EntityKind, Entity as EntityModel, type EntityOperationsContext, ExcelProcessor, type ExtractFactsOptions, type ExtractOutcome, type ExtractedCandidate, type ExtractedEntity, type ExtractionCursorStore, FILE_PLACEHOLDER_PREFIX, FILE_PLACEHOLDER_REGEX, type FactType, type FileMetadata, type FileProcessor, type FileTypeQuery, type FileWithData, type FlushResult, type GetConversationsPageOptions, type GetMessagesPageOptions, type GoogleDriveAuthContextValue, GoogleDriveAuthProvider, type GoogleDriveAuthProviderProps, type GoogleDriveExportResult, type GoogleDriveImportResult, type GroupProps, type ICloudAuthContextValue, ICloudAuthProvider, type ICloudAuthProviderProps, type ICloudExportResult, type ICloudImportResult, INFERENCE_ID_HEADER, type IconProps, type ImageProps, type InteractionType, type KnownTag, type LazyStoredConversation, type LineProps, type Logger, LoggerProvider, type LoggerProviderProps, type MediaDimensions, type MediaFilterOptions, type MediaMetadata, type MediaOperationsContext, type MediaRole, type MediaType, type MemoriesNeedingTopicExtraction, type EmbeddingOptions as MemoryEngineEmbeddingOptions, type MemoryEngineResult, type MemoryEngineSearchOptions, MemoryEntity as MemoryEntityModel, type MemoryExtractedEvent, type MemoryKind, type MemoryVaultSearchOptions, type MemoryVaultToolOptions, type MessageChunk, type MessageFeedback, type MessageSkeleton, type ModelLoadProgress, type OCRFile, type OperationExecutor, PROFILE_DOC_VERSION, type ParsedServerToolsResponse, type PdfExportOptions, type PdfExportProgress, type PdfExportStage, type PdfFile, PdfProcessor, type PendingInteraction, type PersonalitySettings, type PersonalitySliders, type PersonalityStyle, type PhoneCallPollingOptions, type PlatformStorage, type PortalLlmAuth, type PreprocessingOptions, type PreprocessingResult, type ProcessedFileResult, ProcessorRegistry, type ProfileConfigFingerprint, type ProfileDoc, type ProfileFacet, type ProfileFacetKey, type ProfileSection, type ProfileUpdate, type ProgressCallback, Project, type ProjectOperationsContext, type PromptPreProcessor, type PromptPreProcessorContext, type ProviderAuthState, type ProviderBackupState, ProviderStreamError, type QuantizedEmbedding, type QueueEncryptionContext, QueueManager, type QueueStatus, type QueuedOperation, type QueuedOperationType, R2_DEFAULT_TTL_MS, RECALL_MAX_LIMIT, RECALL_TOOL_NAME, type RankedMemory, type RecallContext, type RecallDegradation, type RecallDiagnostics, type RecallOptions, type RecallResult, type RecallToolCallbacks, type RecallToolOptions, type RecencyOptions, type RectProps, type ReflectOptions, type ReflectResult, RerankerUnavailableError, type ResumeStreamOptions, type ResumeStreamResult, type RetainAction, type RetainContext, type RetainOptions, type RetainResult, type RetainSource, SDK_SCHEMA_VERSION, SERVER_TOOL_DEPENDENCY_SETS, SLIDER_CONFIG, SLIDES_FILE_PATH, SLIDE_CANVAS_HEIGHT, SLIDE_CANVAS_WIDTH, STREAM_RESUMABLE_HEADER, SavedTool as SavedToolModel, type SavedToolOperationsContext, type SavedToolParameter, type ScoreBreakdown, type ScreenProps, type SearchMessagesOptions, type SearchSource, type SelectServerToolsForPromptOptions, type SendMessageWithStorageArgs, type SendMessageWithStorageResult, type ServerTool, type ServerToolsFilter, type ServerToolsFilterFn, type ServerToolsFilterFunction, type ServerToolsOptions, type ServerToolsResponse, type SignMessageFn, type SignMessageOptions, type SlideProps, type StepFinishEvent, type StockPriceClassification, type StockPricePreProcessorOptions, type StorageOperationsContext, type StoredAppFile, type ChatCompletionUsage as StoredChatCompletionUsage, type StoredConversation, type StoredConversationMemory, type StoredEntity, type StoredFileWithContext, type StoredMedia, Media as StoredMediaModel, type StoredMessage, type StoredMessageWithSimilarity, type StoredModelPreference, ModelPreference as StoredModelPreferenceModel, type StoredProject, type StoredSavedTool, type StoredUserPreference, UserPreference as StoredUserPreferenceModel, type StoredVaultFolder, VaultFolder as StoredVaultFolderModel, type StoredVaultMemory, VaultMemory as StoredVaultMemoryModel, StreamExpiredError, type StreamMetaEvent, type StreamResumeHandle, type SynthesizeProfileOptions, THEME_ATTRS, TOPICS_EXTRACTION_VERSION, TOPIC_EXTRACTION_BATCH_SIZE, type TextChunk, TextProcessor, type TextProps, type ThemeAttr, type ToolCallArgumentsDeltaEvent, type ToolMatchOptions, type ToolMatchResult, type ToolSet, type TopicExtractOptions, type TopicExtractionInput, type TopicExtractionRunResult, type TranscriptionResult, type TurnCompleteEvent, type TurnSkippedEvent, type UIInteractionContextValue, UIInteractionProvider, type UIInteractionProviderProps, type UpdateMediaOptions, type UpdateModelPreferenceOptions, type UpdateProjectOptions, type UpdateSavedToolOptions, type UpdateUserPreferenceOptions, type UpdateVaultFolderOptions, type UpdateVaultMemoryOptions, type UseBackupOptions, type UseBackupResult, type UseChatStorageOptions, type UseChatStorageResult, type UseCreditsOptions, type UseCreditsResult, type UseDropboxBackupOptions, type UseDropboxBackupResult, type UseEncryptionResult, type UseExportPdfResult, type UseFilesOptions, type UseFilesResult, type UseGoogleDriveBackupOptions, type UseGoogleDriveBackupResult, type UseICloudBackupOptions, type UseICloudBackupResult, type UseModelsResult, type UseOCRResult, type UsePdfResult, type UsePhoneCallsOptions, type UsePhoneCallsResult, type UseProjectsOptions, type UseProjectsResult, type UseSettingsOptions, type UseSettingsResult, type UseSubscriptionOptions, type UseSubscriptionResult, type UseToolsOptions, type UseToolsResult, type UseVoiceOptions, type UseVoiceResult, type UseWalletBindingOptions, type UseWalletBindingResult, type VaultEmbeddingCache, type VaultFolderOperationsContext, type VaultMemoryOperationsContext, type VaultSaveOperation, type VaultSearchResult, type VoiceRecording, WalletPoller, WatermelonChatStorageAdapter, type WatermelonChatStorageAdapterOptions, type WeatherClassification, type WeatherPreProcessorOptions, type WebSearchClassification, type WebSearchPreProcessorOptions, type WhisperModel, WordProcessor, ZipProcessor, type ZipProcessorOptions, addConversationMemoriesOp, appFileToStored, backfillMemoryEntityUserIdsOp, chatStorageMigrations, chatStorageSchema, chunkAndEmbedAllMessages, chunkAndEmbedMessage, chunkText, classifyCryptoPrice, classifyCryptoPriceBatch, classifyStockPrice, classifyStockPriceBatch, classifyWeather, classifyWeatherBatch, classifyWebSearch, classifyWebSearchBatch, clearAllEncryptionKeys, clearAllEncryptionState, clearAllKeyPairs, clearCalendarToken, clearConversationMemoriesOp, clearDriveToken, clearToken as clearDropboxToken, clearEncryptionKey, clearGithubToken, clearGoogleDriveToken, clearICloudAuth, clearKeyPair, clearLazyTitleCache, clearMemoryTopicsOverrideOp, clearNotionToken, clearServerToolsCache, consoleLogger, conversationMemoryToStored, cosineInt8, createAutoExtractor, createChunkVectorCache, createCryptoPricePreProcessor, createGitHubTools, createMediaBatchOp, createMediaOp, createMemoryEngineTool, createMemoryVaultSearchTool, createMemoryVaultTool, createPlatformCursorStore, createProjectOp, createRecallTool, createSavedToolOp, createServerToolsFilter, createStockPricePreProcessor, createVaultEmbeddingCache, createVaultFolderOp, createVaultMemoriesBatchOp, createVaultMemoryOp, createWeatherPreProcessor, createWebSearchPreProcessor, decryptConversationTitle, decryptData, decryptDataBatch, decryptDataBytes, decryptDataBytesFromBytes, decryptDataWithKey, defaultServerToolsFilter, deleteAllAppFilesOp, deleteAllVaultMemoriesForUserOp, deleteAppFileOp, deleteEncryptedFile, deleteMediaByConversationOp, deleteMediaByMessageOp, deleteMediaOp, deleteProjectOp, deleteSavedToolOp, deleteVaultFolderOp, deleteVaultMemoryOp, dequantizeEmbedding, eagerEmbedContent, embedAllMessages, embedMessage, encryptData, encryptDataBatch, encryptDataBytes, encryptDataWithKey, ensureDefaultFoldersOp, expandToolSetsAdditive, exportElementToPdf, exportMarkdownToPdf, exportPublicKey, extractAndLinkEntitiesForMemoriesOp, extractAndRetain, extractEntitiesForMemories, extractFacts, extractFileIds, fileExists, findById, findMatchingTools, findParentOfId, generateConversationId, generateEmbedding, generateEmbeddings, generateMediaId, generateProjectId, getAIGeneratedMediaOp, getAllSavedToolsOp, getAllVaultFoldersOp, getAllVaultMemoriesOp, getAllVaultMemoryContentsOp, getAndClearCalendarPendingMessage, getAndClearCalendarReturnUrl, getAndClearDrivePendingMessage, getAndClearDriveReturnUrl, getAndClearGithubPendingMessage, getAndClearGithubReturnUrl, getAndClearNotionPendingMessage, getAndClearNotionReturnUrl, getAppFileMapOp, getAppFileOp, getAppFilesOp, getAudioOp, getCachedServerTools, getCalendarAccessToken, getConversationMemoriesOp, getConversationsByProjectLazyOp, getConversationsByProjectOp, getConversationsLazyOp, getConversationsPageOp, getDocumentsOp, getDriveAccessToken, getEncryptionKey, getGithubAccessToken, getGoogleDriveStoredToken, getId, getImagesOp, getLogger, getMediaByConversationOp, getMediaByIdOp, getMediaByIdsOp, getMediaByMessageOp, getMediaByModelOp, getMediaByRoleOp, getMediaBySourceUrlOp, getMediaByTypeOp, getMediaCountOp, getMediaCountsByTypeOp, getMediaOp, getMediaTypeFromMime, getMemoriesByEntityNamesOp, getMemoriesNeedingTopicExtractionOp, getNotionAccessToken, getNotionMCPUrl, getNumberAttr, getProjectConversationCountOp, getProjectConversationsOp, getProjectOp, getProjectsOp, getRecentMediaOp, getSavedToolByIdOp, getServerTools, getStringAttr, getSupportedFileTypes, getToolsChecksum, getUnfiledVaultMemoriesOp, getUserUploadedMediaOp, getValidCalendarToken, getValidDriveToken, getValidGithubToken, getValidNotionToken, getVaultFolderMemoryCountOp, getVaultMemoryOp, getVideosOp, handleCalendarCallback, handleDriveCallback, handleGithubCallback, handleNotionCallback, hardDeleteMediaOp, hasCalendarCredentials, hasDriveCredentials, hasDropboxCredentials, hasEncryptionKey, hasGithubCredentials, hasGoogleDriveCredentials, hasICloudCredentials, hasKeyPair, hasNotionCredentials, insertAfterId, insertChild, isAnumaTag, isCalendarCallback, isDriveCallback, isGithubCallback, isHtmlTag, isNotionCallback, isOPFSSupported, isR2UrlExpired, isRerankerAvailable, isSupportedFile, isSupportedMediaType, linkMemoryEntitiesOp, mediaToStored, migrateCalendarToken, migrateDisplayResult, migrateDriveToken, migrateGithubToken, migrateNotionClientRegistration, migrateNotionToken, moveMemoriesToFolderOp, noopLogger, onKeyAvailable, parseJsx, preEmbedVaultMemories, preprocessFiles, previewToolSelection, projectToStored, putAppFileOp, quantizeEmbedding, queueManager, readEncryptedFile, recall, reflect, refreshCalendarToken, refreshDriveToken, refreshGithubToken, refreshNotionToken, relinkMisclassifiedVideosOp, removeById, renderAnumaJsx, renderAnumaTree, renderElementToCanvas, replaceById, replaceMemoryEntitiesGuardedOp, requestEncryptionKey, requestKeyPair, resolveFilePlaceholders, resolveThemeColor, resumeStream, retain, revokeCalendarToken, revokeDriveToken, revokeGithubToken, revokeNotionAccess, savedToolToStored, sdkMigrations, sdkModelClasses, sdkSchema, searchChunksOp, searchMediaOp, searchMessagesOp, searchVaultMemories, selectServerToolsForPrompt, serializeJsx, setLogger, setMemoryEntitiesOp, settingsStorageSchema, shouldChunkMessage, shouldRefreshTools, stampTopicsExtractedAtOp, startGithubAuth, startNotionAuth, storeCalendarPendingMessage, storeCalendarReturnUrl, storeCalendarToken, storeDrivePendingMessage, storeDriveReturnUrl, storeDriveToken, storeGithubPendingMessage, storeGithubReturnUrl, storeGithubToken, storeNotionPendingMessage, storeNotionReturnUrl, streamCancelPath, streamReplayPath, supersedeVaultMemoryOp, synthesizeProfile, updateAttrs, updateConversationProjectOp, updateMediaMessageIdBatchOp, updateMediaOp, updateMessageFeedbackOp, updateProjectNameOp, updateProjectOp, updateSavedToolOp, updateVaultFolderContextOp, updateVaultFolderOp, updateVaultMemoryEmbeddingOp, updateVaultMemoryOp, useAnumaTheme, useBackup, useBackupAuth, useChat, useChatStorage, useCredits, useDatabaseManager, useDropboxAuth, useDropboxBackup, useEncryption, useExportPdf, useFiles, useGoogleDriveAuth, useGoogleDriveBackup, useICloudAuth, useICloudBackup, useModels, useOCR, usePdf, usePhoneCalls, useProjects, useSettings, useSubscription, useTools, useUIInteraction, useVoice, useWalletBinding, userPreferencesStorageSchema, walk, webPlatformStorage, writeEncryptedFile };
13869
+ export { Anuma, type AnumaChild, AnumaJsxError, type AnumaNode, AnumaShadowIsolationProvider, type AnumaShadowIsolationProviderProps, type AnumaTheme, AnumaThemeProvider, type AnumaThemeProviderProps, AppFile as AppFileModel, type AppFileOperationsContext, type AttrValue, type AutoExtractMessage, type AutoExtractor, DEFAULT_CONVERSATIONS_FOLDER as BACKUP_DRIVE_CONVERSATIONS_FOLDER, DEFAULT_ROOT_FOLDER as BACKUP_DRIVE_ROOT_FOLDER, DEFAULT_BACKUP_FOLDER as BACKUP_ICLOUD_FOLDER, BUILT_IN_TOOL_SETS, type BackupAuthContextValue, BackupAuthProvider, type BackupAuthProviderProps, type BackupOperationOptions, BlobUrlManager, type Budget, type CachedChunkVectors, type CachedServerTools, ChartCard, type ChartCardProps, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Conversation as ChatConversation, Message as ChatMessage, type ChatRole, type ChatStorageAdapter, type ChatStorageObservable, type ChunkSearchResult, type ChunkVectorCache, type ChunkingOptions, type CircleProps, type ClientToolsFilterFn, type ConsolidationFallbackReason, type ConversationMemoryInput, ConversationMemory as ConversationMemoryModel, type ConversationMemoryOperationsContext, type ConversationQueryOptions, type CreateAutoExtractorOptions, type CreateConversationOptions, type CreateDecaySweeperOptions, type CreateEntityOptions, type CreateMediaOptions, type CreateMessageOptions, type CreateModelPreferenceOptions, type CreateProjectOptions, type CreateSavedToolOptions, type CreateServerToolsFilterOptions, type CreateUserPreferenceOptions, type CreateVaultFolderOptions, type CreateVaultMemoryOptions, type CryptoPriceClassification, type CryptoPricePreProcessorOptions, DEFAULT_BACKUP_FOLDER$1 as DEFAULT_BACKUP_FOLDER, DEFAULT_CACHE_EXPIRATION_MS, DEFAULT_CHUNK_CACHE_SIZE, DEFAULT_CHUNK_OVERLAP, DEFAULT_CHUNK_SIZE, DEFAULT_DECAY_POLICY, DEFAULT_CONVERSATIONS_FOLDER as DEFAULT_DRIVE_CONVERSATIONS_FOLDER, DEFAULT_ROOT_FOLDER as DEFAULT_DRIVE_ROOT_FOLDER, DEFAULT_BACKUP_FOLDER$1 as DEFAULT_DROPBOX_FOLDER, DEFAULT_EXCLUDED_SERVER_TOOLS, DEFAULT_BACKUP_FOLDER as DEFAULT_ICLOUD_BACKUP_FOLDER, DEFAULT_MAX_CLASSIFIER_CALLS_PER_SWEEP, DEFAULT_MIN_CHUNK_SIZE, DEFAULT_PERSONALITY_SETTINGS, DEFAULT_PROFILE_FACETS, DEFAULT_SERVER_TOOLS_MATCH_OPTIONS, DEFAULT_VAULT_CACHE_SIZE, DatabaseManager, type DatabaseManagerLogger, type DatabaseManagerOptions, type DecayCandidateRaw, type DecayClassifier, type DecayInput, type DecayPolicy, type DecaySweepResult, type DecaySweeper, type DecayVerdict, type DeckProps, type DisplayToolMigrations, type DropboxAuthContextValue, DropboxAuthProvider, type DropboxAuthProviderProps, type DropboxExportResult, type DropboxImportResult, ENTITY_FANOUT, ENTITY_KINDS, type EmbeddedWalletSignerFn, type EntityInput, type EntityKind, Entity as EntityModel, type EntityOperationsContext, ExcelProcessor, type ExtractFactsOptions, type ExtractOutcome, type ExtractedCandidate, type ExtractedEntity, type ExtractionCursorStore, FILE_PLACEHOLDER_PREFIX, FILE_PLACEHOLDER_REGEX, type FactType, type FileMetadata, type FileProcessor, type FileTypeQuery, type FileWithData, type FlushResult, type GetConversationsPageOptions, type GetMessagesPageOptions, type GoogleDriveAuthContextValue, GoogleDriveAuthProvider, type GoogleDriveAuthProviderProps, type GoogleDriveExportResult, type GoogleDriveImportResult, type GraphTraversalOptions, type GroupProps, HARD_DELETE_WINDOW_MS, type ICloudAuthContextValue, ICloudAuthProvider, type ICloudAuthProviderProps, type ICloudExportResult, type ICloudImportResult, INFERENCE_ID_HEADER, type IconProps, type ImageProps, type InjectionClassifierOptions, type InjectionReason, type InteractionType, type KnownTag, type LazyStoredConversation, type LineProps, type LlmDecayClassifierOptions, type LlmNeighborRefinerOptions, type Logger, LoggerProvider, type LoggerProviderProps, MAX_HOPS, MEDIUM_TTL_MS, type MediaDimensions, type MediaFilterOptions, type MediaMetadata, type MediaOperationsContext, type MediaRole, type MediaType, type MemoriesNeedingTopicExtraction, type EmbeddingOptions as MemoryEngineEmbeddingOptions, type MemoryEngineResult, type MemoryEngineSearchOptions, MemoryEntity as MemoryEntityModel, type MemoryExtractedEvent, type MemoryKind, type MemoryQuarantinedEvent, type MemoryVaultSearchOptions, type MemoryVaultToolOptions, type MessageChunk, type MessageFeedback, type MessageSkeleton, type ModelLoadProgress, NEVER_TTL_MS, NODE_BUDGET, type NeighborRefiner, type NowSource, type OCRFile, type OperationExecutor, PAST_EVENT_GRACE_MS, PROFILE_DOC_VERSION, type ParsedServerToolsResponse, type PdfExportOptions, type PdfExportProgress, type PdfExportStage, type PdfFile, PdfProcessor, type PendingInteraction, type PersonalitySettings, type PersonalitySliders, type PersonalityStyle, type PhoneCallPollingOptions, type PlatformStorage, type PortalLlmAuth, type PreprocessingOptions, type PreprocessingResult, type ProcessedFileResult, ProcessorRegistry, type ProfileConfigFingerprint, type ProfileDoc, type ProfileFacet, type ProfileFacetKey, type ProfileSection, type ProfileUpdate, type ProgressCallback, Project, type ProjectOperationsContext, type PromptPreProcessor, type PromptPreProcessorContext, type ProviderAuthState, type ProviderBackupState, ProviderStreamError, type QuantizedEmbedding, type QuarantinedMemoryInfo, type QueueEncryptionContext, QueueManager, type QueueStatus, type QueuedOperation, type QueuedOperationType, R2_DEFAULT_TTL_MS, RECALL_MAX_LIMIT, RECALL_TOOL_NAME, type RankedMemory, type RecallContext, type RecallDegradation, type RecallDiagnostics, type RecallOptions, type RecallResult, type RecallToolCallbacks, type RecallToolOptions, type RecencyOptions, type RectProps, type ReflectOptions, type ReflectResult, RerankerUnavailableError, type ResumeStreamOptions, type ResumeStreamResult, type RetainAction, type RetainContext, type RetainOptions, type RetainResult, type RetainSource, SDK_SCHEMA_VERSION, SERVER_TOOL_DEPENDENCY_SETS, SHORT_TTL_MS, SLIDER_CONFIG, SLIDES_FILE_PATH, SLIDE_CANVAS_HEIGHT, SLIDE_CANVAS_WIDTH, STREAM_RESUMABLE_HEADER, SavedTool as SavedToolModel, type SavedToolOperationsContext, type SavedToolParameter, type ScoreBreakdown, type ScreenProps, type ScreenResult, type ScreenedCandidate, type SearchMessagesOptions, type SearchSource, type SelectServerToolsForPromptOptions, type SendMessageWithStorageArgs, type SendMessageWithStorageResult, type ServerTool, type ServerToolsFilter, type ServerToolsFilterFn, type ServerToolsFilterFunction, type ServerToolsOptions, type ServerToolsResponse, type SignMessageFn, type SignMessageOptions, type SlideProps, type StepFinishEvent, type StockPriceClassification, type StockPricePreProcessorOptions, type StorageOperationsContext, type StoredAppFile, type ChatCompletionUsage as StoredChatCompletionUsage, type StoredConversation, type StoredConversationMemory, type StoredEntity, type StoredFileWithContext, type StoredMedia, Media as StoredMediaModel, type StoredMessage, type StoredMessageWithSimilarity, type StoredModelPreference, ModelPreference as StoredModelPreferenceModel, type StoredProject, type StoredSavedTool, type StoredUserPreference, UserPreference as StoredUserPreferenceModel, type StoredVaultFolder, VaultFolder as StoredVaultFolderModel, type StoredVaultMemory, VaultMemory as StoredVaultMemoryModel, StreamExpiredError, type StreamMetaEvent, type StreamResumeHandle, type SynthesizeProfileOptions, THEME_ATTRS, TOPICS_EXTRACTION_VERSION, TOPIC_EXTRACTION_BATCH_SIZE, type TextChunk, TextProcessor, type TextProps, type ThemeAttr, type ToolCallArgumentsDeltaEvent, type ToolMatchOptions, type ToolMatchResult, type ToolSet, type TopicExtractOptions, type TopicExtractionInput, type TopicExtractionRunResult, type TranscriptionResult, type TurnCompleteEvent, type TurnSkippedEvent, type UIInteractionContextValue, UIInteractionProvider, type UIInteractionProviderProps, type UpdateMediaOptions, type UpdateModelPreferenceOptions, type UpdateProjectOptions, type UpdateSavedToolOptions, type UpdateUserPreferenceOptions, type UpdateVaultFolderOptions, type UpdateVaultMemoryOptions, type UseBackupOptions, type UseBackupResult, type UseChatStorageOptions, type UseChatStorageResult, type UseCreditsOptions, type UseCreditsResult, type UseDropboxBackupOptions, type UseDropboxBackupResult, type UseEncryptionResult, type UseExportPdfResult, type UseFilesOptions, type UseFilesResult, type UseGoogleDriveBackupOptions, type UseGoogleDriveBackupResult, type UseICloudBackupOptions, type UseICloudBackupResult, type UseModelsResult, type UseOCRResult, type UsePdfResult, type UsePhoneCallsOptions, type UsePhoneCallsResult, type UseProjectsOptions, type UseProjectsResult, type UseSettingsOptions, type UseSettingsResult, type UseSubscriptionOptions, type UseSubscriptionResult, type UseToolsOptions, type UseToolsResult, type UseVoiceOptions, type UseVoiceResult, type UseWalletBindingOptions, type UseWalletBindingResult, VAULT_SIZE_HOP_CAP, type VaultEmbeddingCache, type VaultFolderOperationsContext, type VaultMemoryOperationsContext, type VaultSaveOperation, type VaultSearchResult, type VoiceRecording, WalletPoller, WatermelonChatStorageAdapter, type WatermelonChatStorageAdapterOptions, type WeatherClassification, type WeatherPreProcessorOptions, type WebSearchClassification, type WebSearchPreProcessorOptions, type WhisperModel, WordProcessor, ZipProcessor, type ZipProcessorOptions, addConversationMemoriesOp, appFileToStored, archiveVaultMemoryOp, backfillMemoryEntityUserIdsOp, capHopsForDensity, chatStorageMigrations, chatStorageSchema, chunkAndEmbedAllMessages, chunkAndEmbedMessage, chunkText, classifyCryptoPrice, classifyCryptoPriceBatch, classifyDecay, classifyInjectionCandidates, classifyStockPrice, classifyStockPriceBatch, classifyWeather, classifyWeatherBatch, classifyWebSearch, classifyWebSearchBatch, clearAllEncryptionKeys, clearAllEncryptionState, clearAllKeyPairs, clearCalendarToken, clearConversationMemoriesOp, clearDriveToken, clearToken as clearDropboxToken, clearEncryptionKey, clearGithubToken, clearGoogleDriveToken, clearICloudAuth, clearKeyPair, clearLazyTitleCache, clearMemoryTopicsOverrideOp, clearNotionToken, clearServerToolsCache, consoleLogger, conversationMemoryToStored, cosineInt8, createAutoExtractor, createChunkVectorCache, createCryptoPricePreProcessor, createDecaySweeper, createGitHubTools, createLlmDecayClassifier, createLlmNeighborRefiner, createMediaBatchOp, createMediaOp, createMemoryEngineTool, createMemoryVaultSearchTool, createMemoryVaultTool, createPlatformCursorStore, createProjectOp, createRecallTool, createSavedToolOp, createServerToolsFilter, createStockPricePreProcessor, createVaultEmbeddingCache, createVaultFolderOp, createVaultMemoriesBatchOp, createVaultMemoryOp, createWeatherPreProcessor, createWebSearchPreProcessor, decryptConversationTitle, decryptData, decryptDataBatch, decryptDataBytes, decryptDataBytesFromBytes, decryptDataWithKey, defaultServerToolsFilter, deleteAllAppFilesOp, deleteAllVaultMemoriesForUserOp, deleteAppFileOp, deleteEncryptedFile, deleteMediaByConversationOp, deleteMediaByMessageOp, deleteMediaOp, deleteProjectOp, deleteSavedToolOp, deleteVaultFolderOp, deleteVaultMemoryOp, dequantizeEmbedding, eagerEmbedContent, embedAllMessages, embedMessage, encryptData, encryptDataBatch, encryptDataBytes, encryptDataWithKey, ensureDefaultFoldersOp, expandToolSetsAdditive, exportElementToPdf, exportMarkdownToPdf, exportPublicKey, extractAndLinkEntitiesForMemoriesOp, extractAndRetain, extractEntitiesForMemories, extractFacts, extractFileIds, fileExists, findById, findMatchingTools, findParentOfId, generateConversationId, generateEmbedding, generateEmbeddings, generateMediaId, generateProjectId, getAIGeneratedMediaOp, getAllSavedToolsOp, getAllVaultFoldersOp, getAllVaultMemoriesOp, getAllVaultMemoryContentsOp, getAndClearCalendarPendingMessage, getAndClearCalendarReturnUrl, getAndClearDrivePendingMessage, getAndClearDriveReturnUrl, getAndClearGithubPendingMessage, getAndClearGithubReturnUrl, getAndClearNotionPendingMessage, getAndClearNotionReturnUrl, getAppFileMapOp, getAppFileOp, getAppFilesOp, getAudioOp, getCachedServerTools, getCalendarAccessToken, getConversationMemoriesOp, getConversationsByProjectLazyOp, getConversationsByProjectOp, getConversationsLazyOp, getConversationsPageOp, getDecayCandidatesRawOp, getDocumentsOp, getDriveAccessToken, getEncryptionKey, getEntitiesByMemoryIdsOp, getGithubAccessToken, getGoogleDriveStoredToken, getId, getImagesOp, getLogger, getMediaByConversationOp, getMediaByIdOp, getMediaByIdsOp, getMediaByMessageOp, getMediaByModelOp, getMediaByRoleOp, getMediaBySourceUrlOp, getMediaByTypeOp, getMediaCountOp, getMediaCountsByTypeOp, getMediaOp, getMediaTypeFromMime, getMemoriesByEntityNamesOp, getMemoriesNeedingTopicExtractionOp, getNotionAccessToken, getNotionMCPUrl, getNumberAttr, getProjectConversationCountOp, getProjectConversationsOp, getProjectOp, getProjectsOp, getRecentMediaOp, getSavedToolByIdOp, getServerTools, getStringAttr, getSupportedFileTypes, getToolsChecksum, getUnfiledVaultMemoriesOp, getUserUploadedMediaOp, getValidCalendarToken, getValidDriveToken, getValidGithubToken, getValidNotionToken, getVaultFolderMemoryCountOp, getVaultMemoryOp, getVideosOp, handleCalendarCallback, handleDriveCallback, handleGithubCallback, handleNotionCallback, hardDeleteDecayedOp, hardDeleteMediaOp, hasCalendarCredentials, hasDriveCredentials, hasDropboxCredentials, hasEncryptionKey, hasGithubCredentials, hasGoogleDriveCredentials, hasICloudCredentials, hasKeyPair, hasNotionCredentials, injectionSignatureCatalog, insertAfterId, insertChild, isAnumaTag, isCalendarCallback, isDriveCallback, isGithubCallback, isHtmlTag, isNotionCallback, isOPFSSupported, isR2UrlExpired, isRerankerAvailable, isSupportedFile, isSupportedMediaType, linkMemoryEntitiesOp, mediaToStored, migrateCalendarToken, migrateDisplayResult, migrateDriveToken, migrateGithubToken, migrateNotionClientRegistration, migrateNotionToken, moveMemoriesToFolderOp, noopLogger, onKeyAvailable, parseJsx, preEmbedVaultMemories, preprocessFiles, previewToolSelection, projectToStored, putAppFileOp, quantizeEmbedding, queueManager, readEncryptedFile, recall, reflect, refreshCalendarToken, refreshDriveToken, refreshGithubToken, refreshNotionToken, relinkMisclassifiedVideosOp, removeById, renderAnumaJsx, renderAnumaTree, renderElementToCanvas, replaceById, replaceMemoryEntitiesGuardedOp, requestEncryptionKey, requestKeyPair, resolveFilePlaceholders, resolveThemeColor, restoreVaultMemoryOp, resumeStream, retain, revokeCalendarToken, revokeDriveToken, revokeGithubToken, revokeNotionAccess, savedToolToStored, screenCandidatesForInjection, sdkMigrations, sdkModelClasses, sdkSchema, searchChunksOp, searchMediaOp, searchMessagesOp, searchVaultMemories, selectServerToolsForPrompt, serializeJsx, setLogger, setMemoryEntitiesOp, settingsStorageSchema, shouldChunkMessage, shouldRefreshTools, stampTopicsExtractedAtOp, startGithubAuth, startNotionAuth, storeCalendarPendingMessage, storeCalendarReturnUrl, storeCalendarToken, storeDrivePendingMessage, storeDriveReturnUrl, storeDriveToken, storeGithubPendingMessage, storeGithubReturnUrl, storeGithubToken, storeNotionPendingMessage, storeNotionReturnUrl, streamCancelPath, streamReplayPath, supersedeVaultMemoryOp, synthesizeProfile, traverseGraphLane, ttlForType, updateAttrs, updateConversationProjectOp, updateMediaMessageIdBatchOp, updateMediaOp, updateMessageFeedbackOp, updateProjectNameOp, updateProjectOp, updateSavedToolOp, updateVaultFolderContextOp, updateVaultFolderOp, updateVaultMemoryEmbeddingOp, updateVaultMemoryOp, useAnumaTheme, useBackup, useBackupAuth, useChat, useChatStorage, useCredits, useDatabaseManager, useDropboxAuth, useDropboxBackup, useEncryption, useExportPdf, useFiles, useGoogleDriveAuth, useGoogleDriveBackup, useICloudAuth, useICloudBackup, useModels, useOCR, usePdf, usePhoneCalls, useProjects, useSettings, useSubscription, useTools, useUIInteraction, useVoice, useWalletBinding, userPreferencesStorageSchema, walk, webPlatformStorage, writeEncryptedFile };