@melandlabs/memory-store 1.3.7 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/config-Cnk2b7fH.d.ts +571 -0
- package/dist/contracts.d.ts +3 -1
- package/dist/evidence-selector-C_ZUQsio.d.ts +626 -0
- package/dist/http.d.ts +2 -1
- package/dist/http.js +981 -214
- package/dist/index.d.ts +6 -4
- package/dist/index.js +1066 -208
- package/dist/mcp.d.ts +2 -1
- package/dist/mcp.js +990 -216
- package/dist/search/derive.d.ts +2 -1
- package/dist/search/derive.js +6 -2
- package/dist/search/distill.d.ts +2 -1
- package/dist/search/evidence-selector.d.ts +4 -0
- package/dist/search/evidence-selector.js +153 -0
- package/dist/search/unified-search.d.ts +3 -2
- package/dist/search/unified-search.js +887 -196
- package/dist/server/cli-http.js +1455 -332
- package/dist/server/cli-mcp.js +1464 -334
- package/dist/server/cli-shared.d.ts +18 -2
- package/dist/server/cli-shared.js +493 -119
- package/dist/storage/postgres-raw-message-factory.d.ts +2 -1
- package/dist/storage/raw-message-store.d.ts +10 -2
- package/dist/storage/sqlite-raw-message-store.d.ts +2 -1
- package/dist/storage/sqlite-vector-index.d.ts +2 -1
- package/dist/{unified-search-CtFFRj2O.d.ts → unified-search-DfAYG3S9.d.ts} +3 -2
- package/package.json +16 -14
- package/dist/config-BuWr-nvt.d.ts +0 -988
package/README.md
CHANGED
|
@@ -73,6 +73,11 @@ Both bins accept the same `--embedding-provider` / `--*-backend` flag surface
|
|
|
73
73
|
with `--reasoning`, which reads `OPENCONTEXT_LLM_API_KEY` /
|
|
74
74
|
`OPENCONTEXT_LLM_BASE_URL` / `OPENCONTEXT_LLM_MODEL` from the environment:
|
|
75
75
|
|
|
76
|
+
For reproducible OpenRouter runs, set `OPENCONTEXT_LLM_PROVIDER` to one
|
|
77
|
+
provider name. The CLI disables provider fallback and rejects a response
|
|
78
|
+
reported from a different provider; leaving it unset preserves automatic
|
|
79
|
+
routing.
|
|
80
|
+
|
|
76
81
|
```bash
|
|
77
82
|
# HTTP daemon with local embeddings + sqlite-vec memory + LLM reasoning
|
|
78
83
|
opencontext-memory-http \
|
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
import * as _melandlabs_memory_consolidation from '@melandlabs/memory-consolidation';
|
|
2
|
+
import { MemoryApplicabilityContext } from '@melandlabs/memory-consolidation';
|
|
3
|
+
import * as _melandlabs_contracts_peer from '@melandlabs/contracts/peer';
|
|
4
|
+
import { Peer } from '@melandlabs/contracts/peer';
|
|
5
|
+
import { h as SearchEvidenceProvenance, j as SearchSourceState, o as UnifiedMemoryRrfWeights, k as SessionNeighborExpansionOptions, E as EvidenceSelector, l as UnifiedMemoryMergeStrategy, J as IterativeRecallPlanner, n as UnifiedMemoryReasoningStrategy } from './evidence-selector-C_ZUQsio.js';
|
|
6
|
+
import { FactType } from '@melandlabs/contracts';
|
|
7
|
+
import { DerivedFact } from '@melandlabs/contracts/derived-fact';
|
|
8
|
+
import { EntityEdge } from '@melandlabs/contracts/entity-edge';
|
|
9
|
+
import { RawMessage, RawMessageSearchChunk } from '@melandlabs/indexeddb';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Reranker adapter contract.
|
|
13
|
+
*
|
|
14
|
+
* A `Reranker` is an optional plug-in applied to the unified-search output
|
|
15
|
+
* after per-source merge but before the final `slice(0, limit)`. It lets a
|
|
16
|
+
* host swap in a cross-encoder, a learned ranker, or any other deterministic
|
|
17
|
+
* ordering without changing the retrieval pipeline.
|
|
18
|
+
*
|
|
19
|
+
* Implementations MUST be deterministic for the same `(query, candidates)`
|
|
20
|
+
* pair — non-deterministic orderings would defeat the existing
|
|
21
|
+
* `rrfScore`/`similarity` tie-break tests.
|
|
22
|
+
*/
|
|
23
|
+
interface RerankerCandidate {
|
|
24
|
+
id: string;
|
|
25
|
+
content: string;
|
|
26
|
+
metadata?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
interface RerankerInput {
|
|
29
|
+
query: string;
|
|
30
|
+
candidates: RerankerCandidate[];
|
|
31
|
+
topK?: number;
|
|
32
|
+
}
|
|
33
|
+
interface RerankerScore {
|
|
34
|
+
id: string;
|
|
35
|
+
score: number;
|
|
36
|
+
evidenceScores?: Array<{
|
|
37
|
+
sourceChunkId?: string;
|
|
38
|
+
startPosition?: number;
|
|
39
|
+
endPosition?: number;
|
|
40
|
+
contentSha256: string;
|
|
41
|
+
score: number;
|
|
42
|
+
inputTokens: number;
|
|
43
|
+
queryTruncated: boolean;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
interface Reranker {
|
|
47
|
+
rerank(input: RerankerInput): Promise<RerankerScore[]>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface SearchExecutionBudget {
|
|
51
|
+
signal?: AbortSignal;
|
|
52
|
+
/** Maximum wait per external retrieval operation. Defaults to five seconds. */
|
|
53
|
+
sourceTimeoutMs?: number;
|
|
54
|
+
/** Maximum wait for the complete search, including optional ranking. */
|
|
55
|
+
searchTimeoutMs?: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Query rewriting for memory retrieval.
|
|
60
|
+
*
|
|
61
|
+
* The memory corpus is usually a first-person chat log ("I told you ...",
|
|
62
|
+
* "I prefer ..."). A query asked in the assistant's register ("What does the
|
|
63
|
+
* user prefer?") often misses the best evidence. A rewriter rephrases the
|
|
64
|
+
* question into the register the memory was written in, improving dense
|
|
65
|
+
* retrieval without changing the underlying index.
|
|
66
|
+
*
|
|
67
|
+
* The module is provider-agnostic: callers inject a `complete` callback that
|
|
68
|
+
* talks to whatever LLM they already use.
|
|
69
|
+
*/
|
|
70
|
+
interface QueryRewriterInput {
|
|
71
|
+
query: string;
|
|
72
|
+
userId: string;
|
|
73
|
+
authToken?: string;
|
|
74
|
+
}
|
|
75
|
+
interface QueryRewriter {
|
|
76
|
+
/**
|
|
77
|
+
* Return one or more query variants. The first element is always the
|
|
78
|
+
* original query; subsequent elements are rewritten variants.
|
|
79
|
+
*/
|
|
80
|
+
rewrite(input: QueryRewriterInput): Promise<string[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Optional hook that reports whether the most recent `rewrite` call
|
|
83
|
+
* silently degraded to the original query (for example because the LLM
|
|
84
|
+
* call failed or produced no usable variants).
|
|
85
|
+
*/
|
|
86
|
+
lastDegraded?(): boolean;
|
|
87
|
+
}
|
|
88
|
+
interface QueryRewriterOptions {
|
|
89
|
+
/** Optional evidence-oriented retrieval expressions; legacy user voice remains default. */
|
|
90
|
+
style?: "user-voice" | "evidence";
|
|
91
|
+
/**
|
|
92
|
+
* LLM completion callback. Receives the full prompt and returns the raw
|
|
93
|
+
* model output. The rewriter parses the output and falls back to the
|
|
94
|
+
* original query on any failure.
|
|
95
|
+
*/
|
|
96
|
+
complete: (prompt: string) => Promise<string>;
|
|
97
|
+
/**
|
|
98
|
+
* Maximum number of rewritten variants to return in addition to the
|
|
99
|
+
* original query. Use `0` to return only the original. Higher values ask
|
|
100
|
+
* the LLM for more alternatives and multiply embedding/search cost
|
|
101
|
+
* proportionally, so callers should bound it (typical: 1–3).
|
|
102
|
+
* @default 1
|
|
103
|
+
*/
|
|
104
|
+
maxVariants?: number;
|
|
105
|
+
/**
|
|
106
|
+
* When true, the rewriter returns only the original query and skips the
|
|
107
|
+
* LLM call. Useful as a kill-switch.
|
|
108
|
+
* @default false
|
|
109
|
+
*/
|
|
110
|
+
disabled?: boolean;
|
|
111
|
+
}
|
|
112
|
+
declare function createUserVoiceRewriter(options: QueryRewriterOptions): QueryRewriter;
|
|
113
|
+
/**
|
|
114
|
+
* A no-op rewriter that always returns the original query.
|
|
115
|
+
*/
|
|
116
|
+
declare function createIdentityRewriter(): QueryRewriter;
|
|
117
|
+
|
|
118
|
+
interface MemoryStoreDb {
|
|
119
|
+
/** Resolve the active Drizzle DB handle. Must be server-side. */
|
|
120
|
+
getDb(): unknown;
|
|
121
|
+
/** Whether the DB has finished initializing (optional, for startup gating). */
|
|
122
|
+
isDbInitialized?(): boolean;
|
|
123
|
+
/** Initialize the DB (optional, called by `createMemoryStore` if present). */
|
|
124
|
+
initDb?(): unknown;
|
|
125
|
+
/**
|
|
126
|
+
* Drizzle table references for the postgres backend. Required when
|
|
127
|
+
* running outside Tauri mode without a registered factory. The host
|
|
128
|
+
* application owns the actual schema.
|
|
129
|
+
*/
|
|
130
|
+
tables?: {
|
|
131
|
+
rawMessages?: unknown;
|
|
132
|
+
memorySummaries?: unknown;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Placeholder for the historical host-injected environment. The fields
|
|
137
|
+
* it used to expose (`isTauriMode`, `getTauriDbPath`, `getTauriDataDir`)
|
|
138
|
+
* were Tauri-specific and have been removed. Backend selection is now
|
|
139
|
+
* driven entirely by the `OPENCONTEXT_MEMORY_STORE_BACKEND` env var.
|
|
140
|
+
*
|
|
141
|
+
* The interface is kept (empty) so existing `env?: MemoryStoreEnv`
|
|
142
|
+
* parameters on the public surface still type-check, but new code
|
|
143
|
+
* should not need to construct a value of this type.
|
|
144
|
+
*/
|
|
145
|
+
interface MemoryStoreEnv {
|
|
146
|
+
}
|
|
147
|
+
type VectorBackend = "sqlite-vec" | "chroma" | "lancedb" | "milvus";
|
|
148
|
+
interface MemoryStoreVectorConfig {
|
|
149
|
+
/** Active backend selector. Defaults to env-based detection. */
|
|
150
|
+
backend?: VectorBackend;
|
|
151
|
+
/** SQLite-vec options (used when backend === "sqlite-vec"). */
|
|
152
|
+
sqliteVec?: {
|
|
153
|
+
dbPath?: string;
|
|
154
|
+
insightsCollection?: string;
|
|
155
|
+
};
|
|
156
|
+
/** Chroma options (used when backend === "chroma"). */
|
|
157
|
+
chroma?: {
|
|
158
|
+
url?: string;
|
|
159
|
+
rawMessagesCollection?: string;
|
|
160
|
+
insightsCollection?: string;
|
|
161
|
+
};
|
|
162
|
+
/** LanceDB options (used when backend === "lancedb"). */
|
|
163
|
+
lancedb?: {
|
|
164
|
+
uri: string;
|
|
165
|
+
table?: string;
|
|
166
|
+
};
|
|
167
|
+
/** Milvus options (used when backend === "milvus"). */
|
|
168
|
+
milvus?: {
|
|
169
|
+
address: string;
|
|
170
|
+
token?: string;
|
|
171
|
+
database?: string;
|
|
172
|
+
collection?: string;
|
|
173
|
+
dimension?: number;
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
type EmbedQueryFn = (input: {
|
|
177
|
+
userId: string;
|
|
178
|
+
query: string;
|
|
179
|
+
authToken?: string;
|
|
180
|
+
}) => Promise<number[]>;
|
|
181
|
+
type EmbedDocumentsFn = (input: {
|
|
182
|
+
userId: string;
|
|
183
|
+
texts: string[];
|
|
184
|
+
authToken?: string;
|
|
185
|
+
}) => Promise<number[][]>;
|
|
186
|
+
interface UnifiedSearchKnowledgeResult {
|
|
187
|
+
chunkId: string;
|
|
188
|
+
documentId: string;
|
|
189
|
+
documentName: string;
|
|
190
|
+
content: string;
|
|
191
|
+
similarity: number;
|
|
192
|
+
chunkIndex: number;
|
|
193
|
+
}
|
|
194
|
+
/** Text candidates shared by host-owned insight and file retrieval. */
|
|
195
|
+
interface UnifiedSearchTextResult {
|
|
196
|
+
id: string;
|
|
197
|
+
content: string;
|
|
198
|
+
similarity: number;
|
|
199
|
+
metadata: Record<string, unknown>;
|
|
200
|
+
provenance?: Partial<SearchEvidenceProvenance>;
|
|
201
|
+
}
|
|
202
|
+
type UnifiedSearchInsightsResult = UnifiedSearchTextResult;
|
|
203
|
+
interface UnifiedSearchReasoningDeps {
|
|
204
|
+
/** Optional extractive context selection after ranking. Disabled unless supplied. */
|
|
205
|
+
evidenceSelector?: EvidenceSelector;
|
|
206
|
+
/**
|
|
207
|
+
* LLM single-turn synthesis callback. Wired into
|
|
208
|
+
* `search({ synthesize: true })` so a host that wants synthesis
|
|
209
|
+
* responses only has to drop in one callable. When omitted, the
|
|
210
|
+
* synthesis path returns the gathered evidence with a
|
|
211
|
+
* `synthesize_llm_not_configured` warning instead of throwing.
|
|
212
|
+
*/
|
|
213
|
+
complete?: (prompt: string) => Promise<string>;
|
|
214
|
+
/** Default merge strategy used by `searchUnifiedMemory` when the caller does not specify one. @default "rrf" */
|
|
215
|
+
defaultMergeStrategy?: UnifiedMemoryMergeStrategy;
|
|
216
|
+
/** Optional query rewriter. When present, "rewrite" strategy is available. */
|
|
217
|
+
queryRewriter?: QueryRewriter;
|
|
218
|
+
/** Also search rewritten expressions with BM25 under RRF. At most four distinct queries, including the original. @default false */
|
|
219
|
+
rewriteLexical?: boolean;
|
|
220
|
+
/** Optional rank fusion across semantic query variants under RRF. @default "max-score" */
|
|
221
|
+
rewriteSemanticMerge?: "max-score" | "rrf";
|
|
222
|
+
/** Optional iterative recall planner. When present, "iterative" strategy is available. */
|
|
223
|
+
iterativePlanner?: IterativeRecallPlanner;
|
|
224
|
+
/** Default reasoning strategy when callers do not specify one. @default "none" */
|
|
225
|
+
defaultStrategy?: UnifiedMemoryReasoningStrategy;
|
|
226
|
+
}
|
|
227
|
+
interface MemorySummaryHit {
|
|
228
|
+
summaryId: string;
|
|
229
|
+
summaryText: string;
|
|
230
|
+
summaryTier?: "L1" | "L2" | "L3";
|
|
231
|
+
keywords?: string[];
|
|
232
|
+
startTimestamp?: number;
|
|
233
|
+
endTimestamp?: number;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Trusted applicability fields forwarded together to retrieval providers.
|
|
237
|
+
* They are absent for legacy unscoped searches and always present together
|
|
238
|
+
* for scoped searches. Providers must enforce the canonical applicability
|
|
239
|
+
* contract at `applicabilityAt`; these values must not be derived from public
|
|
240
|
+
* request payloads.
|
|
241
|
+
*/
|
|
242
|
+
interface SearchProviderApplicabilityInput {
|
|
243
|
+
applicabilityContexts?: readonly MemoryApplicabilityContext[];
|
|
244
|
+
/** Epoch milliseconds resolved once at the `search()` boundary. */
|
|
245
|
+
applicabilityAt?: number;
|
|
246
|
+
}
|
|
247
|
+
interface UnifiedSearchDeps extends SearchExecutionBudget {
|
|
248
|
+
/** Host-owned file search; the host must enforce trusted scope before querying. */
|
|
249
|
+
searchWorkspace?: (input: SearchProviderApplicabilityInput & {
|
|
250
|
+
userId: string;
|
|
251
|
+
query: string;
|
|
252
|
+
limit: number;
|
|
253
|
+
}) => Promise<{
|
|
254
|
+
hits: UnifiedSearchTextResult[];
|
|
255
|
+
status: SearchSourceState["status"];
|
|
256
|
+
message?: string;
|
|
257
|
+
}>;
|
|
258
|
+
/** Default rank-fusion weights; omitted channels use weight 1. */
|
|
259
|
+
defaultRrfWeights?: UnifiedMemoryRrfWeights;
|
|
260
|
+
/** Default reciprocal-rank damping constant. */
|
|
261
|
+
defaultRrfK?: number;
|
|
262
|
+
/** Default opt-in session-neighbor expansion configuration. */
|
|
263
|
+
defaultSessionNeighborExpansion?: SessionNeighborExpansionOptions;
|
|
264
|
+
/** Embed a query string using the active user's provider. */
|
|
265
|
+
embedQuery?: EmbedQueryFn;
|
|
266
|
+
/** Batch document embedding used by child indexing when the provider supports it. */
|
|
267
|
+
embedDocuments?: EmbedDocumentsFn;
|
|
268
|
+
/** Model-tokenizer chunking for new writes; omitted hosts retain legacy splitting. */
|
|
269
|
+
getDocumentChunking?: () => Promise<{
|
|
270
|
+
maxTokens: number;
|
|
271
|
+
overlapTokens: number;
|
|
272
|
+
countTokens: (text: string) => number;
|
|
273
|
+
}>;
|
|
274
|
+
/** Safe, non-secret identity used by health checks and child-index metadata. */
|
|
275
|
+
embeddingInfo?: {
|
|
276
|
+
provider?: string;
|
|
277
|
+
model?: string;
|
|
278
|
+
dimensions?: number;
|
|
279
|
+
maxTokens?: number;
|
|
280
|
+
};
|
|
281
|
+
/** Runtime-safe retrieval readiness used by health and diagnostics. */
|
|
282
|
+
getRawMessageRetrievalStatus?: () => Promise<{
|
|
283
|
+
backend: string;
|
|
284
|
+
embeddingProvider?: string;
|
|
285
|
+
embeddingModel?: string;
|
|
286
|
+
embeddingDimensions?: number;
|
|
287
|
+
childCount: number;
|
|
288
|
+
embeddedChildCount: number;
|
|
289
|
+
indexedDimensions: number[];
|
|
290
|
+
semanticReady: boolean;
|
|
291
|
+
lexicalReady: boolean;
|
|
292
|
+
semanticDegradedReason?: string;
|
|
293
|
+
rerankerProvider?: string;
|
|
294
|
+
rerankerModel?: string;
|
|
295
|
+
rerankerReady?: boolean;
|
|
296
|
+
}>;
|
|
297
|
+
/** Optional external child-vector index used by the shared write path. */
|
|
298
|
+
rawMessageChildIndex?: {
|
|
299
|
+
replaceMessages(messages: RawMessage[], chunks: RawMessageSearchChunk[]): Promise<void>;
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Dense raw-message search supplied by the selected child-vector backend.
|
|
303
|
+
* External Postgres hosts may also provide their legacy parent-level
|
|
304
|
+
* implementation here; Postgres schema changes are outside this package.
|
|
305
|
+
*/
|
|
306
|
+
searchRawMessagesAnn?: (input: SearchProviderApplicabilityInput & {
|
|
307
|
+
userId: string;
|
|
308
|
+
queryEmbedding: number[];
|
|
309
|
+
limit: number;
|
|
310
|
+
threshold: number;
|
|
311
|
+
botId?: string;
|
|
312
|
+
/**
|
|
313
|
+
* Forward `includeDeprecated` from `UnifiedMemorySearchInput` so
|
|
314
|
+
* supersession-aware callers can opt into deprecated rows for
|
|
315
|
+
* audits. Default `false` preserves the current-truth behaviour.
|
|
316
|
+
*/
|
|
317
|
+
includeDeprecated?: boolean;
|
|
318
|
+
/**
|
|
319
|
+
* Forward `asOf` from `UnifiedMemorySearchInput` so time-travel
|
|
320
|
+
* callers can ask "what was true at this instant?". Implementations
|
|
321
|
+
* that don't yet honour the field should ignore it — the rest of
|
|
322
|
+
* the unified pipeline stays correct.
|
|
323
|
+
*/
|
|
324
|
+
asOf?: string;
|
|
325
|
+
/** Optional peer scope resolved from `UnifiedMemorySearchInput.peerFilter`. */
|
|
326
|
+
peers?: ReadonlyArray<Peer>;
|
|
327
|
+
/** Optional `FactType` filter resolved from `UnifiedMemorySearchInput.factTypes`. */
|
|
328
|
+
factTypes?: FactType[];
|
|
329
|
+
}) => Promise<Array<{
|
|
330
|
+
id: string;
|
|
331
|
+
content: string;
|
|
332
|
+
similarity: number;
|
|
333
|
+
metadata: Record<string, unknown>;
|
|
334
|
+
}>>;
|
|
335
|
+
/** Native dense+BM25 path for backends such as LanceDB and Milvus. */
|
|
336
|
+
searchRawMessagesHybrid?: (input: SearchProviderApplicabilityInput & {
|
|
337
|
+
userId: string;
|
|
338
|
+
query: string;
|
|
339
|
+
queryEmbedding: number[];
|
|
340
|
+
limit: number;
|
|
341
|
+
botId?: string;
|
|
342
|
+
}) => Promise<Array<{
|
|
343
|
+
id: string;
|
|
344
|
+
content: string;
|
|
345
|
+
similarity: number;
|
|
346
|
+
metadata: Record<string, unknown>;
|
|
347
|
+
}>>;
|
|
348
|
+
/** RAG over uploaded knowledge documents. Returns a list of chunk hits. */
|
|
349
|
+
searchKnowledge?: (input: SearchProviderApplicabilityInput & {
|
|
350
|
+
userId: string;
|
|
351
|
+
query: string;
|
|
352
|
+
options: {
|
|
353
|
+
limit: number;
|
|
354
|
+
threshold: number;
|
|
355
|
+
documentIds?: string[];
|
|
356
|
+
};
|
|
357
|
+
authToken?: string;
|
|
358
|
+
/** Optional peer scope resolved from `UnifiedMemorySearchInput.peerFilter`. */
|
|
359
|
+
peers?: ReadonlyArray<Peer>;
|
|
360
|
+
}) => Promise<UnifiedSearchKnowledgeResult[]>;
|
|
361
|
+
/** Semantic search over extracted insights. */
|
|
362
|
+
searchInsights?: (input: SearchProviderApplicabilityInput & {
|
|
363
|
+
userId: string;
|
|
364
|
+
query: string;
|
|
365
|
+
limit: number;
|
|
366
|
+
threshold: number;
|
|
367
|
+
botIds?: string[];
|
|
368
|
+
includeArchived?: boolean;
|
|
369
|
+
authToken?: string;
|
|
370
|
+
/** Optional peer scope resolved from `UnifiedMemorySearchInput.peerFilter`. */
|
|
371
|
+
peers?: ReadonlyArray<Peer>;
|
|
372
|
+
}) => Promise<UnifiedSearchInsightsResult[]>;
|
|
373
|
+
/**
|
|
374
|
+
* Optional BM25 (lexical) sub-query for the memory source. Mirrors the
|
|
375
|
+
* `searchRawMessagesAnn` shape but operates on FTS5 keywords instead of
|
|
376
|
+
* dense embeddings. When absent, the unified pipeline skips the lexical
|
|
377
|
+
* path and emits a `memory_lexical_search_not_configured` warning.
|
|
378
|
+
*/
|
|
379
|
+
searchRawMessagesLexical?: (input: SearchProviderApplicabilityInput & {
|
|
380
|
+
userId: string;
|
|
381
|
+
keywords: string[];
|
|
382
|
+
limit: number;
|
|
383
|
+
botId?: string;
|
|
384
|
+
/**
|
|
385
|
+
* Forward `includeDeprecated` from `UnifiedMemorySearchInput` so
|
|
386
|
+
* supersession-aware callers can opt into deprecated rows for
|
|
387
|
+
* audits. Default `false` preserves the current-truth behaviour.
|
|
388
|
+
*/
|
|
389
|
+
includeDeprecated?: boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Forward `asOf` from `UnifiedMemorySearchInput` so time-travel
|
|
392
|
+
* callers can ask "what was true at this instant?". Implementations
|
|
393
|
+
* that don't yet honour the field should ignore it — the rest of
|
|
394
|
+
* the unified pipeline stays correct.
|
|
395
|
+
*/
|
|
396
|
+
asOf?: string;
|
|
397
|
+
/** Optional peer scope resolved from `UnifiedMemorySearchInput.peerFilter`. */
|
|
398
|
+
peers?: ReadonlyArray<Peer>;
|
|
399
|
+
/** Optional `FactType` filter resolved from `UnifiedMemorySearchInput.factTypes`. */
|
|
400
|
+
factTypes?: FactType[];
|
|
401
|
+
}) => Promise<Array<{
|
|
402
|
+
id: string;
|
|
403
|
+
content: string;
|
|
404
|
+
similarity: number;
|
|
405
|
+
metadata: Record<string, unknown>;
|
|
406
|
+
}>>;
|
|
407
|
+
/** Optional bounded lookup for messages adjacent to fused seed messages. */
|
|
408
|
+
searchRawMessageNeighbors?: (input: {
|
|
409
|
+
userId: string;
|
|
410
|
+
sessionId: string;
|
|
411
|
+
messageSequences: number[];
|
|
412
|
+
window: number;
|
|
413
|
+
includeDeprecated?: boolean;
|
|
414
|
+
}) => Promise<Array<{
|
|
415
|
+
id: string;
|
|
416
|
+
content: string;
|
|
417
|
+
metadata: Record<string, unknown>;
|
|
418
|
+
similarity: number;
|
|
419
|
+
}>>;
|
|
420
|
+
/**
|
|
421
|
+
* Optional summary-tier search. When wired in, `reflect()` consults the
|
|
422
|
+
* summary tier alongside raw messages and emits a
|
|
423
|
+
* `reflect_summaries_unavailable` warning if the call fails.
|
|
424
|
+
*/
|
|
425
|
+
searchSummaries?: (input: SearchProviderApplicabilityInput & {
|
|
426
|
+
userId: string;
|
|
427
|
+
query: string;
|
|
428
|
+
keywords: string[];
|
|
429
|
+
limit: number;
|
|
430
|
+
threshold: number;
|
|
431
|
+
dateFrom?: string;
|
|
432
|
+
dateTo?: string;
|
|
433
|
+
authToken?: string;
|
|
434
|
+
/** Optional peer scope resolved from `UnifiedMemorySearchInput.peerFilter`. */
|
|
435
|
+
peers?: ReadonlyArray<Peer>;
|
|
436
|
+
}) => Promise<MemorySummaryHit[]>;
|
|
437
|
+
/**
|
|
438
|
+
* Optional entity sub-query provider. Hosts wire this in to opt
|
|
439
|
+
* into the `entity` channel of unified search: matches are
|
|
440
|
+
* projected back as `UnifiedMemorySearchResult`s and fused with
|
|
441
|
+
* semantic + lexical via RRF. Without it, the entity channel is
|
|
442
|
+
* skipped silently (with a `memory_entity_search_not_configured`
|
|
443
|
+
* warning when RRF was requested).
|
|
444
|
+
*
|
|
445
|
+
* The provider is intentionally narrow: it returns `(messageId,
|
|
446
|
+
* label, score)` tuples. The host is responsible for keeping its
|
|
447
|
+
* own entity store (graph nodes, separate SQLite table, etc.) —
|
|
448
|
+
* the SDK never persists entity edges itself.
|
|
449
|
+
*/
|
|
450
|
+
entitySearch?: (input: SearchProviderApplicabilityInput & {
|
|
451
|
+
userId: string;
|
|
452
|
+
keywords: string[];
|
|
453
|
+
limit: number;
|
|
454
|
+
botId?: string;
|
|
455
|
+
/** Optional peer scope resolved from `UnifiedMemorySearchInput.peerFilter`. */
|
|
456
|
+
peers?: ReadonlyArray<Peer>;
|
|
457
|
+
}) => Promise<Array<{
|
|
458
|
+
messageId: string;
|
|
459
|
+
label: string;
|
|
460
|
+
score: number;
|
|
461
|
+
}>>;
|
|
462
|
+
/**
|
|
463
|
+
* Optional entity extractor wired into the `distill` primitive. The
|
|
464
|
+
* extractor receives the raw message text and returns a batch of
|
|
465
|
+
* `EntityEdge`s the host may persist via the `persist` callback
|
|
466
|
+
* supplied on the `distill` input.
|
|
467
|
+
*
|
|
468
|
+
* When omitted, `distill` short-circuits with a
|
|
469
|
+
* `distill_extractor_not_configured` warning — matching the
|
|
470
|
+
* `memory_iterative_planner_not_configured` precedent.
|
|
471
|
+
*/
|
|
472
|
+
entityExtractor?: (input: {
|
|
473
|
+
userId: string;
|
|
474
|
+
messageId: string;
|
|
475
|
+
content: string;
|
|
476
|
+
}) => Promise<EntityEdge[]>;
|
|
477
|
+
/**
|
|
478
|
+
* Optional deriver wired into the `derive` primitive. The deriver
|
|
479
|
+
* receives a window of candidate fact texts and returns a batch of
|
|
480
|
+
* `DerivedFact`s the host may persist via the `persist` callback
|
|
481
|
+
* supplied on the `derive` input.
|
|
482
|
+
*
|
|
483
|
+
* When omitted, `derive` short-circuits with a
|
|
484
|
+
* `derive_deriver_not_configured` warning — same precedent.
|
|
485
|
+
*/
|
|
486
|
+
deriver?: (input: {
|
|
487
|
+
userId: string;
|
|
488
|
+
userScope: {
|
|
489
|
+
userId: string;
|
|
490
|
+
botIds?: string[];
|
|
491
|
+
dateFrom?: string;
|
|
492
|
+
dateTo?: string;
|
|
493
|
+
};
|
|
494
|
+
recentFactTexts: string[];
|
|
495
|
+
window?: {
|
|
496
|
+
from: number;
|
|
497
|
+
to: number;
|
|
498
|
+
};
|
|
499
|
+
}) => Promise<DerivedFact[]>;
|
|
500
|
+
/**
|
|
501
|
+
* Optional host-side check that validates whether a `peerFilter` peer is
|
|
502
|
+
* actually reachable from this `userId`. Used by
|
|
503
|
+
* `resolveScopePeer` to drop out-of-scope peers with a warning
|
|
504
|
+
* rather than broadening the search. May be omitted for hosts that
|
|
505
|
+
* have no peer-permission model.
|
|
506
|
+
*/
|
|
507
|
+
peerScopeCheck?: (input: {
|
|
508
|
+
userId: string;
|
|
509
|
+
peers: ReadonlyArray<_melandlabs_contracts_peer.Peer>;
|
|
510
|
+
}) => Promise<boolean> | boolean;
|
|
511
|
+
/** Optional reasoning providers. */
|
|
512
|
+
reasoning?: UnifiedSearchReasoningDeps;
|
|
513
|
+
/**
|
|
514
|
+
* Optional reranker applied after per-source merge and before the
|
|
515
|
+
* final limit. Defaults to an identity pass-through so the merge order
|
|
516
|
+
* is preserved.
|
|
517
|
+
*/
|
|
518
|
+
reranker?: Reranker;
|
|
519
|
+
/** Safe, non-secret reranker identity surfaced by health and diagnostics. */
|
|
520
|
+
rerankerInfo?: {
|
|
521
|
+
provider: string;
|
|
522
|
+
model?: string;
|
|
523
|
+
maxTokens?: number;
|
|
524
|
+
ready: boolean;
|
|
525
|
+
};
|
|
526
|
+
/**
|
|
527
|
+
* Optional logger. When set (e.g. via `MemoryStoreConfig.logger`),
|
|
528
|
+
* `reflect` / `consolidate` log through it instead of `console`.
|
|
529
|
+
* Falls back to `console` when omitted.
|
|
530
|
+
*/
|
|
531
|
+
logger?: Pick<Console, "log" | "warn" | "error">;
|
|
532
|
+
}
|
|
533
|
+
interface MemoryStoreConfig {
|
|
534
|
+
/**
|
|
535
|
+
* Database handle factory. Required for the Postgres backend
|
|
536
|
+
* (`OPENCONTEXT_MEMORY_STORE_BACKEND=postgres`).
|
|
537
|
+
*/
|
|
538
|
+
db?: MemoryStoreDb;
|
|
539
|
+
/**
|
|
540
|
+
* Custom SQLite database file path for the default SQLite backend.
|
|
541
|
+
*
|
|
542
|
+
* If provided, this takes precedence over the `MEMORY_STORE_DB_PATH`
|
|
543
|
+
* environment variable and the default `~/.opencontext/memory/store.db`.
|
|
544
|
+
*
|
|
545
|
+
* For backward compatibility with early tutorials, `db.path` is also
|
|
546
|
+
* honoured when `db` is supplied as `{ type, path }`.
|
|
547
|
+
*/
|
|
548
|
+
dbPath?: string;
|
|
549
|
+
/** Environment helpers. Defaults to a process.env-only stub if omitted. */
|
|
550
|
+
env?: MemoryStoreEnv;
|
|
551
|
+
/** Vector backend config. Defaults to env-based detection. */
|
|
552
|
+
vector?: MemoryStoreVectorConfig;
|
|
553
|
+
/** Optional cross-source search providers. */
|
|
554
|
+
unified?: UnifiedSearchDeps;
|
|
555
|
+
/**
|
|
556
|
+
* Optional write-back graph store. When set, `createMemoryStore` wires
|
|
557
|
+
* it into `store.graphStore` and forwards it to `consolidate`. Hosts
|
|
558
|
+
* that prefer post-construction wiring can use `attachMemoryGraphStore`.
|
|
559
|
+
*/
|
|
560
|
+
graphStore?: _melandlabs_memory_consolidation.MemoryGraphStoreWithOperationHistory;
|
|
561
|
+
/**
|
|
562
|
+
* Optional storage adapter carrying `deprecateRecords`. Forwarded into
|
|
563
|
+
* `consolidate` for callers that want deprecation writes without
|
|
564
|
+
* attaching a full graph store.
|
|
565
|
+
*/
|
|
566
|
+
storage?: _melandlabs_memory_consolidation.MemoryStorageAdapterLike;
|
|
567
|
+
/** Optional logger. Defaults to console. */
|
|
568
|
+
logger?: Pick<Console, "log" | "warn" | "error">;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
export { type EmbedQueryFn as E, type MemoryStoreConfig as M, type QueryRewriter as Q, type SearchProviderApplicabilityInput as S, type UnifiedSearchDeps as U, type VectorBackend as V, type MemoryStoreEnv as a, type MemoryStoreDb as b, type QueryRewriterInput as c, type QueryRewriterOptions as d, type UnifiedSearchInsightsResult as e, type UnifiedSearchKnowledgeResult as f, type UnifiedSearchReasoningDeps as g, type UnifiedSearchTextResult as h, createIdentityRewriter as i, createUserVoiceRewriter as j };
|
package/dist/contracts.d.ts
CHANGED
|
@@ -30,7 +30,9 @@ interface RawMessage {
|
|
|
30
30
|
userId: string;
|
|
31
31
|
channel?: string;
|
|
32
32
|
person?: string;
|
|
33
|
-
timestamp
|
|
33
|
+
timestamp?: number;
|
|
34
|
+
/** Storage-assigned, per-user insertion order; not an event timestamp. */
|
|
35
|
+
messageSequence?: number;
|
|
34
36
|
content: string;
|
|
35
37
|
attachments?: Array<{
|
|
36
38
|
name: string;
|