@aeriondyseti/vector-memory-mcp 1.1.0-dev.6 → 2.0.0-rc
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 +22 -4
- package/package.json +12 -18
- package/scripts/migrate-from-lancedb.ts +56 -0
- package/scripts/smoke-test.ts +699 -0
- package/scripts/test-runner.ts +11 -1
- package/src/db/connection.ts +18 -4
- package/src/db/conversation.repository.ts +164 -79
- package/src/db/memory.repository.ts +182 -170
- package/src/db/migrations.ts +70 -0
- package/src/db/sqlite-utils.ts +78 -0
- package/src/http/server.ts +40 -35
- package/src/index.ts +33 -3
- package/src/mcp/server.ts +2 -1
- package/src/migration.ts +254 -0
- package/dist/package.json +0 -71
- package/dist/scripts/test-runner.d.ts +0 -9
- package/dist/scripts/test-runner.d.ts.map +0 -1
- package/dist/scripts/test-runner.js +0 -61
- package/dist/scripts/test-runner.js.map +0 -1
- package/dist/scripts/warmup.d.ts +0 -8
- package/dist/scripts/warmup.d.ts.map +0 -1
- package/dist/scripts/warmup.js +0 -61
- package/dist/scripts/warmup.js.map +0 -1
- package/dist/src/config/index.d.ts +0 -41
- package/dist/src/config/index.d.ts.map +0 -1
- package/dist/src/config/index.js +0 -75
- package/dist/src/config/index.js.map +0 -1
- package/dist/src/db/connection.d.ts +0 -3
- package/dist/src/db/connection.d.ts.map +0 -1
- package/dist/src/db/connection.js +0 -10
- package/dist/src/db/connection.js.map +0 -1
- package/dist/src/db/conversation.repository.d.ts +0 -26
- package/dist/src/db/conversation.repository.d.ts.map +0 -1
- package/dist/src/db/conversation.repository.js +0 -73
- package/dist/src/db/conversation.repository.js.map +0 -1
- package/dist/src/db/conversation.schema.d.ts +0 -4
- package/dist/src/db/conversation.schema.d.ts.map +0 -1
- package/dist/src/db/conversation.schema.js +0 -15
- package/dist/src/db/conversation.schema.js.map +0 -1
- package/dist/src/db/lancedb-utils.d.ts +0 -57
- package/dist/src/db/lancedb-utils.d.ts.map +0 -1
- package/dist/src/db/lancedb-utils.js +0 -124
- package/dist/src/db/lancedb-utils.js.map +0 -1
- package/dist/src/db/memory.repository.d.ts +0 -40
- package/dist/src/db/memory.repository.d.ts.map +0 -1
- package/dist/src/db/memory.repository.js +0 -183
- package/dist/src/db/memory.repository.js.map +0 -1
- package/dist/src/db/schema.d.ts +0 -7
- package/dist/src/db/schema.d.ts.map +0 -1
- package/dist/src/db/schema.js +0 -19
- package/dist/src/db/schema.js.map +0 -1
- package/dist/src/http/mcp-transport.d.ts +0 -19
- package/dist/src/http/mcp-transport.d.ts.map +0 -1
- package/dist/src/http/mcp-transport.js +0 -191
- package/dist/src/http/mcp-transport.js.map +0 -1
- package/dist/src/http/server.d.ts +0 -13
- package/dist/src/http/server.d.ts.map +0 -1
- package/dist/src/http/server.js +0 -224
- package/dist/src/http/server.js.map +0 -1
- package/dist/src/index.d.ts +0 -3
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js +0 -68
- package/dist/src/index.js.map +0 -1
- package/dist/src/mcp/handlers.d.ts +0 -15
- package/dist/src/mcp/handlers.d.ts.map +0 -1
- package/dist/src/mcp/handlers.js +0 -313
- package/dist/src/mcp/handlers.js.map +0 -1
- package/dist/src/mcp/server.d.ts +0 -5
- package/dist/src/mcp/server.d.ts.map +0 -1
- package/dist/src/mcp/server.js +0 -22
- package/dist/src/mcp/server.js.map +0 -1
- package/dist/src/mcp/tools.d.ts +0 -13
- package/dist/src/mcp/tools.d.ts.map +0 -1
- package/dist/src/mcp/tools.js +0 -352
- package/dist/src/mcp/tools.js.map +0 -1
- package/dist/src/services/conversation.service.d.ts +0 -38
- package/dist/src/services/conversation.service.d.ts.map +0 -1
- package/dist/src/services/conversation.service.js +0 -252
- package/dist/src/services/conversation.service.js.map +0 -1
- package/dist/src/services/embeddings.service.d.ts +0 -12
- package/dist/src/services/embeddings.service.d.ts.map +0 -1
- package/dist/src/services/embeddings.service.js +0 -37
- package/dist/src/services/embeddings.service.js.map +0 -1
- package/dist/src/services/memory.service.d.ts +0 -40
- package/dist/src/services/memory.service.d.ts.map +0 -1
- package/dist/src/services/memory.service.js +0 -258
- package/dist/src/services/memory.service.js.map +0 -1
- package/dist/src/services/parsers/claude-code.parser.d.ts +0 -8
- package/dist/src/services/parsers/claude-code.parser.d.ts.map +0 -1
- package/dist/src/services/parsers/claude-code.parser.js +0 -191
- package/dist/src/services/parsers/claude-code.parser.js.map +0 -1
- package/dist/src/services/parsers/types.d.ts +0 -9
- package/dist/src/services/parsers/types.d.ts.map +0 -1
- package/dist/src/services/parsers/types.js +0 -2
- package/dist/src/services/parsers/types.js.map +0 -1
- package/dist/src/types/conversation.d.ts +0 -99
- package/dist/src/types/conversation.d.ts.map +0 -1
- package/dist/src/types/conversation.js +0 -2
- package/dist/src/types/conversation.js.map +0 -1
- package/dist/src/types/memory.d.ts +0 -30
- package/dist/src/types/memory.d.ts.map +0 -1
- package/dist/src/types/memory.js +0 -18
- package/dist/src/types/memory.js.map +0 -1
- package/src/db/conversation.schema.ts +0 -33
- package/src/db/lancedb-utils.ts +0 -142
- package/src/db/schema.ts +0 -38
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { readFile, readdir, stat } from "fs/promises";
|
|
2
|
-
import { basename, dirname, join } from "path";
|
|
3
|
-
// UUID pattern for session IDs
|
|
4
|
-
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
5
|
-
/** Extract text content from an assistant message's content array */
|
|
6
|
-
function extractAssistantText(content) {
|
|
7
|
-
return content
|
|
8
|
-
.filter((block) => block.type === "text" && block.text)
|
|
9
|
-
.map((block) => block.text)
|
|
10
|
-
.join("\n");
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Extract project name from path-encoded directory name.
|
|
14
|
-
* Claude Code encodes paths by replacing `/` with `-`, e.g. `/home/user/project` → `-home-user-project`.
|
|
15
|
-
* This is a lossy encoding: directory names containing literal dashes (e.g. `my-project`)
|
|
16
|
-
* cannot be distinguished from path separators, so `my-project` decodes as `my/project`.
|
|
17
|
-
* This is a known limitation of Claude Code's encoding scheme.
|
|
18
|
-
*/
|
|
19
|
-
function extractProjectFromDir(dirName) {
|
|
20
|
-
return dirName.startsWith("-")
|
|
21
|
-
? dirName.slice(1).replace(/-/g, "/")
|
|
22
|
-
: dirName;
|
|
23
|
-
}
|
|
24
|
-
export class ClaudeCodeSessionParser {
|
|
25
|
-
async parse(filePath, indexSubagents = false) {
|
|
26
|
-
const fileContent = await readFile(filePath, "utf-8");
|
|
27
|
-
const lines = fileContent.split("\n").filter((line) => line.trim());
|
|
28
|
-
const messages = [];
|
|
29
|
-
let messageIndex = 0;
|
|
30
|
-
// Derive session ID and project from file path
|
|
31
|
-
const fileName = basename(filePath, ".jsonl");
|
|
32
|
-
const parentDir = basename(dirname(filePath));
|
|
33
|
-
// Check if this is inside a subagents directory
|
|
34
|
-
const isSubagentFile = filePath.includes("/subagents/");
|
|
35
|
-
// For subagent files, project dir is 3 levels up: <project>/<session>/subagents/<file>
|
|
36
|
-
// For main files, project dir is direct parent
|
|
37
|
-
const projectDir = isSubagentFile
|
|
38
|
-
? basename(dirname(dirname(dirname(filePath))))
|
|
39
|
-
: parentDir;
|
|
40
|
-
const project = extractProjectFromDir(projectDir);
|
|
41
|
-
for (const line of lines) {
|
|
42
|
-
let entry;
|
|
43
|
-
try {
|
|
44
|
-
entry = JSON.parse(line);
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// Skip malformed lines
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const type = entry.type;
|
|
51
|
-
// Skip non-message entries
|
|
52
|
-
if (type === "progress" || type === "file-history-snapshot") {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
// Skip subagent messages unless configured to include them
|
|
56
|
-
if (!indexSubagents && (entry.isSidechain === true || isSubagentFile)) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
if (type !== "user" && type !== "assistant") {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
const message = entry.message;
|
|
63
|
-
if (!message)
|
|
64
|
-
continue;
|
|
65
|
-
const role = message.role;
|
|
66
|
-
if (role !== "user" && role !== "assistant")
|
|
67
|
-
continue;
|
|
68
|
-
let content = null;
|
|
69
|
-
if (role === "user") {
|
|
70
|
-
const msgContent = message.content;
|
|
71
|
-
if (typeof msgContent === "string") {
|
|
72
|
-
content = msgContent;
|
|
73
|
-
}
|
|
74
|
-
else if (Array.isArray(msgContent)) {
|
|
75
|
-
// Array content in user messages = tool_result entries, skip
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
else if (role === "assistant") {
|
|
80
|
-
const msgContent = message.content;
|
|
81
|
-
if (Array.isArray(msgContent)) {
|
|
82
|
-
content = extractAssistantText(msgContent);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// Skip empty content
|
|
86
|
-
if (!content || content.trim().length === 0) {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
const sessionId = entry.sessionId ?? fileName;
|
|
90
|
-
messages.push({
|
|
91
|
-
uuid: entry.uuid ?? `${sessionId}-${messageIndex}`,
|
|
92
|
-
role: role,
|
|
93
|
-
content: content.trim(),
|
|
94
|
-
timestamp: entry.timestamp
|
|
95
|
-
? new Date(entry.timestamp)
|
|
96
|
-
: new Date(),
|
|
97
|
-
messageIndex,
|
|
98
|
-
sessionId,
|
|
99
|
-
project,
|
|
100
|
-
gitBranch: entry.gitBranch,
|
|
101
|
-
isSubagent: entry.isSidechain ?? isSubagentFile,
|
|
102
|
-
agentId: entry.agentId,
|
|
103
|
-
});
|
|
104
|
-
messageIndex++;
|
|
105
|
-
}
|
|
106
|
-
return messages;
|
|
107
|
-
}
|
|
108
|
-
async findSessionFiles(dirPath, since, indexSubagents = false) {
|
|
109
|
-
const files = [];
|
|
110
|
-
let dirents;
|
|
111
|
-
try {
|
|
112
|
-
dirents = await readdir(dirPath, { withFileTypes: true });
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
return files;
|
|
116
|
-
}
|
|
117
|
-
for (const dirent of dirents) {
|
|
118
|
-
const entryPath = join(dirPath, dirent.name);
|
|
119
|
-
if (dirent.isDirectory()) {
|
|
120
|
-
if (dirent.name === "subagents") {
|
|
121
|
-
if (indexSubagents) {
|
|
122
|
-
const subFiles = await this.findSubagentFiles(entryPath, since, basename(dirname(dirname(entryPath))));
|
|
123
|
-
files.push(...subFiles);
|
|
124
|
-
}
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
const subFiles = await this.findSessionFiles(entryPath, since, indexSubagents);
|
|
128
|
-
files.push(...subFiles);
|
|
129
|
-
}
|
|
130
|
-
else if (dirent.name.endsWith(".jsonl")) {
|
|
131
|
-
const sessionId = basename(dirent.name, ".jsonl");
|
|
132
|
-
if (!UUID_PATTERN.test(sessionId))
|
|
133
|
-
continue;
|
|
134
|
-
let entryStat;
|
|
135
|
-
try {
|
|
136
|
-
entryStat = await stat(entryPath);
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
const lastModified = entryStat.mtime;
|
|
142
|
-
if (since && lastModified <= since)
|
|
143
|
-
continue;
|
|
144
|
-
const projectDir = basename(dirPath);
|
|
145
|
-
const project = extractProjectFromDir(projectDir);
|
|
146
|
-
files.push({
|
|
147
|
-
filePath: entryPath,
|
|
148
|
-
sessionId,
|
|
149
|
-
project,
|
|
150
|
-
lastModified,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return files;
|
|
155
|
-
}
|
|
156
|
-
async findSubagentFiles(subagentsDir, since, projectDir) {
|
|
157
|
-
const files = [];
|
|
158
|
-
let entries;
|
|
159
|
-
try {
|
|
160
|
-
entries = await readdir(subagentsDir);
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
return files;
|
|
164
|
-
}
|
|
165
|
-
for (const entry of entries) {
|
|
166
|
-
if (!entry.endsWith(".jsonl"))
|
|
167
|
-
continue;
|
|
168
|
-
const entryPath = join(subagentsDir, entry);
|
|
169
|
-
let entryStat;
|
|
170
|
-
try {
|
|
171
|
-
entryStat = await stat(entryPath);
|
|
172
|
-
}
|
|
173
|
-
catch {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
const lastModified = entryStat.mtime;
|
|
177
|
-
if (since && lastModified <= since)
|
|
178
|
-
continue;
|
|
179
|
-
const sessionId = basename(entry, ".jsonl");
|
|
180
|
-
const project = extractProjectFromDir(projectDir);
|
|
181
|
-
files.push({
|
|
182
|
-
filePath: entryPath,
|
|
183
|
-
sessionId,
|
|
184
|
-
project,
|
|
185
|
-
lastModified,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return files;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
//# sourceMappingURL=claude-code.parser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.parser.js","sourceRoot":"","sources":["../../../../src/services/parsers/claude-code.parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ParsedMessage, SessionFileInfo } from "../../types/conversation.js";
|
|
2
|
-
/** Interface for parsing session log files into structured messages */
|
|
3
|
-
export interface SessionLogParser {
|
|
4
|
-
/** Parse a session log file into ordered messages */
|
|
5
|
-
parse(filePath: string, indexSubagents?: boolean): Promise<ParsedMessage[]>;
|
|
6
|
-
/** Discover session log files in a directory */
|
|
7
|
-
findSessionFiles(dirPath: string, since?: Date, indexSubagents?: boolean): Promise<SessionFileInfo[]>;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/parsers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAElF,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAE5E,gDAAgD;IAChD,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,IAAI,EACZ,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CAC/B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/services/parsers/types.ts"],"names":[],"mappings":""}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/** A single parsed message from a session log */
|
|
2
|
-
export interface ParsedMessage {
|
|
3
|
-
uuid: string;
|
|
4
|
-
role: "user" | "assistant";
|
|
5
|
-
content: string;
|
|
6
|
-
timestamp: Date;
|
|
7
|
-
messageIndex: number;
|
|
8
|
-
sessionId: string;
|
|
9
|
-
project: string;
|
|
10
|
-
gitBranch?: string;
|
|
11
|
-
isSubagent: boolean;
|
|
12
|
-
agentId?: string;
|
|
13
|
-
}
|
|
14
|
-
/** Metadata stored per conversation chunk in the database */
|
|
15
|
-
export interface ConversationChunkMetadata {
|
|
16
|
-
session_id: string;
|
|
17
|
-
timestamp: string;
|
|
18
|
-
role: string;
|
|
19
|
-
message_index_start: number;
|
|
20
|
-
message_index_end: number;
|
|
21
|
-
project: string;
|
|
22
|
-
git_branch?: string;
|
|
23
|
-
is_subagent: boolean;
|
|
24
|
-
agent_id?: string;
|
|
25
|
-
}
|
|
26
|
-
/** A chunk of conversation ready for indexing */
|
|
27
|
-
export interface ConversationChunk {
|
|
28
|
-
id: string;
|
|
29
|
-
content: string;
|
|
30
|
-
sessionId: string;
|
|
31
|
-
timestamp: Date;
|
|
32
|
-
endTimestamp: Date;
|
|
33
|
-
role: string;
|
|
34
|
-
messageIndexStart: number;
|
|
35
|
-
messageIndexEnd: number;
|
|
36
|
-
project: string;
|
|
37
|
-
metadata: ConversationChunkMetadata;
|
|
38
|
-
}
|
|
39
|
-
/** Tracking record for an indexed session */
|
|
40
|
-
export interface IndexedSession {
|
|
41
|
-
sessionId: string;
|
|
42
|
-
filePath: string;
|
|
43
|
-
project: string;
|
|
44
|
-
lastModified: number;
|
|
45
|
-
chunkCount: number;
|
|
46
|
-
messageCount: number;
|
|
47
|
-
indexedAt: Date;
|
|
48
|
-
firstMessageAt: Date;
|
|
49
|
-
lastMessageAt: Date;
|
|
50
|
-
}
|
|
51
|
-
/** Raw row from conversation_history table with RRF score */
|
|
52
|
-
export interface ConversationHybridRow {
|
|
53
|
-
id: string;
|
|
54
|
-
content: string;
|
|
55
|
-
metadata: Record<string, unknown>;
|
|
56
|
-
createdAt: Date;
|
|
57
|
-
rrfScore: number;
|
|
58
|
-
}
|
|
59
|
-
/** Unified search result with source provenance */
|
|
60
|
-
export interface SearchResult {
|
|
61
|
-
id: string;
|
|
62
|
-
content: string;
|
|
63
|
-
metadata: Record<string, unknown>;
|
|
64
|
-
createdAt: Date;
|
|
65
|
-
updatedAt: Date;
|
|
66
|
-
source: "memory" | "conversation_history";
|
|
67
|
-
score: number;
|
|
68
|
-
supersededBy?: string | null;
|
|
69
|
-
usefulness?: number;
|
|
70
|
-
accessCount?: number;
|
|
71
|
-
lastAccessed?: Date | null;
|
|
72
|
-
sessionId?: string;
|
|
73
|
-
role?: string;
|
|
74
|
-
messageIndexStart?: number;
|
|
75
|
-
messageIndexEnd?: number;
|
|
76
|
-
}
|
|
77
|
-
/** Session file info returned by the parser's file discovery */
|
|
78
|
-
export interface SessionFileInfo {
|
|
79
|
-
filePath: string;
|
|
80
|
-
sessionId: string;
|
|
81
|
-
project: string;
|
|
82
|
-
lastModified: Date;
|
|
83
|
-
}
|
|
84
|
-
/** Search filter options for conversation history */
|
|
85
|
-
export interface HistoryFilters {
|
|
86
|
-
sessionId?: string;
|
|
87
|
-
role?: string;
|
|
88
|
-
project?: string;
|
|
89
|
-
after?: Date;
|
|
90
|
-
before?: Date;
|
|
91
|
-
}
|
|
92
|
-
/** Options for the integrated search across both sources */
|
|
93
|
-
export interface SearchOptions {
|
|
94
|
-
includeHistory?: boolean;
|
|
95
|
-
historyOnly?: boolean;
|
|
96
|
-
historyWeight?: number;
|
|
97
|
-
historyFilters?: HistoryFilters;
|
|
98
|
-
}
|
|
99
|
-
//# sourceMappingURL=conversation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../../src/types/conversation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../../src/types/conversation.ts"],"names":[],"mappings":""}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export declare const DELETED_TOMBSTONE = "DELETED";
|
|
2
|
-
export interface Memory {
|
|
3
|
-
id: string;
|
|
4
|
-
content: string;
|
|
5
|
-
embedding: number[];
|
|
6
|
-
metadata: Record<string, unknown>;
|
|
7
|
-
createdAt: Date;
|
|
8
|
-
updatedAt: Date;
|
|
9
|
-
supersededBy: string | null;
|
|
10
|
-
usefulness: number;
|
|
11
|
-
accessCount: number;
|
|
12
|
-
lastAccessed: Date | null;
|
|
13
|
-
}
|
|
14
|
-
export declare function isDeleted(memory: Memory): boolean;
|
|
15
|
-
export declare function memoryToDict(memory: Memory): Record<string, unknown>;
|
|
16
|
-
export type SearchIntent = 'continuity' | 'fact_check' | 'frequent' | 'associative' | 'explore';
|
|
17
|
-
export interface IntentProfile {
|
|
18
|
-
weights: {
|
|
19
|
-
relevance: number;
|
|
20
|
-
recency: number;
|
|
21
|
-
utility: number;
|
|
22
|
-
};
|
|
23
|
-
jitter: number;
|
|
24
|
-
}
|
|
25
|
-
/** Augments any entity type with an RRF score from hybrid search. */
|
|
26
|
-
export type WithRrfScore<T> = T & {
|
|
27
|
-
rrfScore: number;
|
|
28
|
-
};
|
|
29
|
-
export type HybridRow = WithRrfScore<Memory>;
|
|
30
|
-
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/types/memory.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAE3C,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,IAAI,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYpE;AAED,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC;AAEhG,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qEAAqE;AACrE,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/src/types/memory.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const DELETED_TOMBSTONE = "DELETED";
|
|
2
|
-
export function isDeleted(memory) {
|
|
3
|
-
return memory.supersededBy === DELETED_TOMBSTONE;
|
|
4
|
-
}
|
|
5
|
-
export function memoryToDict(memory) {
|
|
6
|
-
return {
|
|
7
|
-
id: memory.id,
|
|
8
|
-
content: memory.content,
|
|
9
|
-
metadata: memory.metadata,
|
|
10
|
-
createdAt: memory.createdAt.toISOString(),
|
|
11
|
-
updatedAt: memory.updatedAt.toISOString(),
|
|
12
|
-
supersededBy: memory.supersededBy,
|
|
13
|
-
usefulness: memory.usefulness,
|
|
14
|
-
accessCount: memory.accessCount,
|
|
15
|
-
lastAccessed: memory.lastAccessed?.toISOString() ?? null,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=memory.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../../src/types/memory.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAe3C,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,MAAM,CAAC,YAAY,KAAK,iBAAiB,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE;QACzC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE;QACzC,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,IAAI;KACzD,CAAC;AACJ,CAAC"}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Schema,
|
|
3
|
-
Field,
|
|
4
|
-
FixedSizeList,
|
|
5
|
-
Float32,
|
|
6
|
-
Utf8,
|
|
7
|
-
Timestamp,
|
|
8
|
-
TimeUnit,
|
|
9
|
-
Int32,
|
|
10
|
-
} from "apache-arrow";
|
|
11
|
-
|
|
12
|
-
export const CONVERSATION_TABLE_NAME = "conversation_history";
|
|
13
|
-
|
|
14
|
-
export const conversationSchema = new Schema([
|
|
15
|
-
new Field("id", new Utf8(), false),
|
|
16
|
-
new Field(
|
|
17
|
-
"vector",
|
|
18
|
-
new FixedSizeList(384, new Field("item", new Float32(), false)),
|
|
19
|
-
false
|
|
20
|
-
),
|
|
21
|
-
new Field("content", new Utf8(), false),
|
|
22
|
-
new Field("metadata", new Utf8(), false), // JSON string
|
|
23
|
-
new Field(
|
|
24
|
-
"created_at",
|
|
25
|
-
new Timestamp(TimeUnit.MILLISECOND, "UTC"),
|
|
26
|
-
false
|
|
27
|
-
),
|
|
28
|
-
new Field("session_id", new Utf8(), false),
|
|
29
|
-
new Field("role", new Utf8(), false),
|
|
30
|
-
new Field("message_index_start", new Int32(), false),
|
|
31
|
-
new Field("message_index_end", new Int32(), false),
|
|
32
|
-
new Field("project", new Utf8(), false),
|
|
33
|
-
]);
|
package/src/db/lancedb-utils.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import * as lancedb from "@lancedb/lancedb";
|
|
2
|
-
import { Index, rerankers, type Table } from "@lancedb/lancedb";
|
|
3
|
-
import type { Schema } from "apache-arrow";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Escape a string value for safe interpolation into LanceDB/DataFusion SQL WHERE clauses.
|
|
7
|
-
*
|
|
8
|
-
* DataFusion uses ANSI SQL string literal rules:
|
|
9
|
-
* - String literals are delimited by single quotes
|
|
10
|
-
* - Single quotes within strings are escaped by doubling: ' -> ''
|
|
11
|
-
* - Backslashes are NOT escape characters (treated literally)
|
|
12
|
-
*/
|
|
13
|
-
export function escapeSql(value: string): string {
|
|
14
|
-
return value.replace(/'/g, "''");
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** Default k parameter for Reciprocal Rank Fusion reranking. */
|
|
18
|
-
export const RRF_K = 60;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Converts LanceDB's Arrow Vector type to a plain number[].
|
|
22
|
-
* LanceDB returns an Arrow Vector object which is iterable but not an array.
|
|
23
|
-
*/
|
|
24
|
-
export function arrowVectorToArray(value: unknown): number[] {
|
|
25
|
-
return Array.isArray(value)
|
|
26
|
-
? value
|
|
27
|
-
: (Array.from(value as Iterable<number>) as number[]);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Converts an Arrow Timestamp value to a JavaScript Date.
|
|
32
|
-
*
|
|
33
|
-
* LanceDB/Arrow can return timestamp column values as:
|
|
34
|
-
* - number (most common: raw int64 ms since epoch, fits in JS float64)
|
|
35
|
-
* - BigInt (large int64 values that overflow float64 — rare for timestamps)
|
|
36
|
-
* - Date (hypothetical: some future Arrow-JS build may decode for us)
|
|
37
|
-
*
|
|
38
|
-
* Doing `new Date(row.ts as number)` is a TypeScript lie that silently breaks
|
|
39
|
-
* when Arrow returns a BigInt. This helper handles all three cases safely.
|
|
40
|
-
*/
|
|
41
|
-
export function arrowTimestampToDate(value: unknown): Date {
|
|
42
|
-
if (value instanceof Date) return new Date(value.getTime());
|
|
43
|
-
if (typeof value === "bigint") return new Date(Number(value));
|
|
44
|
-
return new Date(value as number);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Safely parse a JSON string into an object, returning an empty object on failure.
|
|
49
|
-
*/
|
|
50
|
-
export function safeParseJsonObject(raw: string): Record<string, unknown> {
|
|
51
|
-
try {
|
|
52
|
-
return JSON.parse(raw);
|
|
53
|
-
} catch {
|
|
54
|
-
return {};
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Opens an existing table or creates it with the given schema.
|
|
60
|
-
* Does NOT cache — callers should cache the returned Table if desired.
|
|
61
|
-
*/
|
|
62
|
-
export async function getOrCreateTable(
|
|
63
|
-
db: lancedb.Connection,
|
|
64
|
-
name: string,
|
|
65
|
-
schema: Schema
|
|
66
|
-
): Promise<Table> {
|
|
67
|
-
try {
|
|
68
|
-
return await db.openTable(name);
|
|
69
|
-
} catch (err: unknown) {
|
|
70
|
-
// Only proceed to create if the table was not found
|
|
71
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
72
|
-
if (!message.includes("was not found") && !message.includes("does not exist")) {
|
|
73
|
-
throw err;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
return await db.createTable(name, [], { schema });
|
|
78
|
-
} catch {
|
|
79
|
-
// Another caller may have created it concurrently
|
|
80
|
-
return await db.openTable(name);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Creates a mutex-guarded function that ensures an FTS index exists on a table's content column.
|
|
86
|
-
*
|
|
87
|
-
* Once the FTS index is confirmed/created, the promise is retained for the lifetime of the
|
|
88
|
-
* caller — the index persists in LanceDB, so re-checking is unnecessary. On error, the
|
|
89
|
-
* mutex resets so the next call can retry.
|
|
90
|
-
*
|
|
91
|
-
* The key design constraint: the promise must be captured synchronously (before any await)
|
|
92
|
-
* to prevent concurrent callers from racing past the guard.
|
|
93
|
-
*/
|
|
94
|
-
export function createFtsMutex(
|
|
95
|
-
getTable: () => Promise<Table>
|
|
96
|
-
): () => Promise<void> {
|
|
97
|
-
let promise: Promise<void> | null = null;
|
|
98
|
-
|
|
99
|
-
return () => {
|
|
100
|
-
if (promise) return promise;
|
|
101
|
-
|
|
102
|
-
promise = (async () => {
|
|
103
|
-
const table = await getTable();
|
|
104
|
-
const indices = await table.listIndices();
|
|
105
|
-
const hasFtsIndex = indices.some(
|
|
106
|
-
(idx) => idx.columns.includes("content") && idx.indexType === "FTS"
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
if (!hasFtsIndex) {
|
|
110
|
-
await table.createIndex("content", {
|
|
111
|
-
config: Index.fts(),
|
|
112
|
-
});
|
|
113
|
-
await table.waitForIndex(["content_idx"], 30);
|
|
114
|
-
}
|
|
115
|
-
})().catch((error) => {
|
|
116
|
-
promise = null;
|
|
117
|
-
throw error;
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
return promise;
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Creates a promise-mutex for RRFReranker instantiation.
|
|
126
|
-
* Same pattern as createFtsMutex: create once, cache forever, reset on error.
|
|
127
|
-
*/
|
|
128
|
-
export function createRerankerMutex(
|
|
129
|
-
k: number = RRF_K
|
|
130
|
-
): () => Promise<rerankers.RRFReranker> {
|
|
131
|
-
let promise: Promise<rerankers.RRFReranker> | null = null;
|
|
132
|
-
|
|
133
|
-
return () => {
|
|
134
|
-
if (!promise) {
|
|
135
|
-
promise = rerankers.RRFReranker.create(k).catch((e) => {
|
|
136
|
-
promise = null;
|
|
137
|
-
throw e;
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
return promise;
|
|
141
|
-
};
|
|
142
|
-
}
|
package/src/db/schema.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Schema,
|
|
3
|
-
Field,
|
|
4
|
-
FixedSizeList,
|
|
5
|
-
Float32,
|
|
6
|
-
Utf8,
|
|
7
|
-
Timestamp,
|
|
8
|
-
TimeUnit,
|
|
9
|
-
Int32,
|
|
10
|
-
} from "apache-arrow";
|
|
11
|
-
|
|
12
|
-
// Shared field helpers — used by both memory and conversation history schemas
|
|
13
|
-
export const EMBEDDING_DIMENSION = 384;
|
|
14
|
-
|
|
15
|
-
export const vectorField = () =>
|
|
16
|
-
new Field(
|
|
17
|
-
"vector",
|
|
18
|
-
new FixedSizeList(EMBEDDING_DIMENSION, new Field("item", new Float32())),
|
|
19
|
-
false
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
export const timestampField = (name: string, nullable = false) =>
|
|
23
|
-
new Field(name, new Timestamp(TimeUnit.MILLISECOND, "UTC"), nullable);
|
|
24
|
-
|
|
25
|
-
export const TABLE_NAME = "memories";
|
|
26
|
-
|
|
27
|
-
export const memorySchema = new Schema([
|
|
28
|
-
new Field("id", new Utf8(), false),
|
|
29
|
-
vectorField(),
|
|
30
|
-
new Field("content", new Utf8(), false),
|
|
31
|
-
new Field("metadata", new Utf8(), false), // JSON string
|
|
32
|
-
timestampField("created_at"),
|
|
33
|
-
timestampField("updated_at"),
|
|
34
|
-
new Field("superseded_by", new Utf8(), true), // Nullable
|
|
35
|
-
new Field("usefulness", new Float32(), false),
|
|
36
|
-
new Field("access_count", new Int32(), false),
|
|
37
|
-
timestampField("last_accessed", true),
|
|
38
|
-
]);
|