@bubstack/moe-memory 0.1.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/.mcp.json +18 -0
- package/README.md +47 -0
- package/agents/search-conversations.md +171 -0
- package/dist/LICENSE +25 -0
- package/dist/cli.d.ts +25 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +125 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-hook-trust.d.ts +4 -0
- package/dist/codex-hook-trust.d.ts.map +1 -0
- package/dist/codex-hook-trust.js +114 -0
- package/dist/codex-hook-trust.js.map +1 -0
- package/dist/codex-support.d.ts +6 -0
- package/dist/codex-support.d.ts.map +1 -0
- package/dist/codex-support.js +29 -0
- package/dist/codex-support.js.map +1 -0
- package/dist/constants.d.ts +14 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +14 -0
- package/dist/constants.js.map +1 -0
- package/dist/db.d.ts +103 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +430 -0
- package/dist/db.js.map +1 -0
- package/dist/doctor-cli.d.ts +3 -0
- package/dist/doctor-cli.d.ts.map +1 -0
- package/dist/doctor-cli.js +43 -0
- package/dist/doctor-cli.js.map +1 -0
- package/dist/doctor.d.ts +17 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +98 -0
- package/dist/doctor.js.map +1 -0
- package/dist/embedding-migration.d.ts +73 -0
- package/dist/embedding-migration.d.ts.map +1 -0
- package/dist/embedding-migration.js +120 -0
- package/dist/embedding-migration.js.map +1 -0
- package/dist/embeddings.d.ts +78 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +180 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/file-lock.d.ts +39 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +91 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/index-cli.d.ts +10 -0
- package/dist/index-cli.d.ts.map +1 -0
- package/dist/index-cli.js +195 -0
- package/dist/index-cli.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +4 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +318 -0
- package/dist/indexer.js.map +1 -0
- package/dist/install-check.d.ts +48 -0
- package/dist/install-check.d.ts.map +1 -0
- package/dist/install-check.js +82 -0
- package/dist/install-check.js.map +1 -0
- package/dist/journal/index.d.ts +5 -0
- package/dist/journal/index.d.ts.map +1 -0
- package/dist/journal/index.js +5 -0
- package/dist/journal/index.js.map +1 -0
- package/dist/journal/legacy-sidecars.d.ts +74 -0
- package/dist/journal/legacy-sidecars.d.ts.map +1 -0
- package/dist/journal/legacy-sidecars.js +151 -0
- package/dist/journal/legacy-sidecars.js.map +1 -0
- package/dist/journal/markdown.d.ts +91 -0
- package/dist/journal/markdown.d.ts.map +1 -0
- package/dist/journal/markdown.js +234 -0
- package/dist/journal/markdown.js.map +1 -0
- package/dist/journal/search.d.ts +91 -0
- package/dist/journal/search.d.ts.map +1 -0
- package/dist/journal/search.js +203 -0
- package/dist/journal/search.js.map +1 -0
- package/dist/journal/store.d.ts +96 -0
- package/dist/journal/store.d.ts.map +1 -0
- package/dist/journal/store.js +270 -0
- package/dist/journal/store.js.map +1 -0
- package/dist/journal-cli.d.ts +19 -0
- package/dist/journal-cli.d.ts.map +1 -0
- package/dist/journal-cli.js +153 -0
- package/dist/journal-cli.js.map +1 -0
- package/dist/logging.d.ts +6 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +20 -0
- package/dist/logging.js.map +1 -0
- package/dist/mcp-server.d.ts +34 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +607 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/parser.d.ts +11 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +445 -0
- package/dist/parser.js.map +1 -0
- package/dist/paths.d.ts +103 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +258 -0
- package/dist/paths.js.map +1 -0
- package/dist/search-cli.d.ts +3 -0
- package/dist/search-cli.d.ts.map +1 -0
- package/dist/search-cli.js +138 -0
- package/dist/search-cli.js.map +1 -0
- package/dist/search.d.ts +36 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +371 -0
- package/dist/search.js.map +1 -0
- package/dist/show-cli.d.ts +3 -0
- package/dist/show-cli.d.ts.map +1 -0
- package/dist/show-cli.js +60 -0
- package/dist/show-cli.js.map +1 -0
- package/dist/show.d.ts +3 -0
- package/dist/show.d.ts.map +1 -0
- package/dist/show.js +984 -0
- package/dist/show.js.map +1 -0
- package/dist/stats-cli.d.ts +3 -0
- package/dist/stats-cli.d.ts.map +1 -0
- package/dist/stats-cli.js +51 -0
- package/dist/stats-cli.js.map +1 -0
- package/dist/stats.d.ts +19 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +116 -0
- package/dist/stats.js.map +1 -0
- package/dist/summarizer.d.ts +83 -0
- package/dist/summarizer.d.ts.map +1 -0
- package/dist/summarizer.js +526 -0
- package/dist/summarizer.js.map +1 -0
- package/dist/summary-sentinel.d.ts +31 -0
- package/dist/summary-sentinel.d.ts.map +1 -0
- package/dist/summary-sentinel.js +80 -0
- package/dist/summary-sentinel.js.map +1 -0
- package/dist/sync-cli.d.ts +15 -0
- package/dist/sync-cli.d.ts.map +1 -0
- package/dist/sync-cli.js +202 -0
- package/dist/sync-cli.js.map +1 -0
- package/dist/sync.d.ts +35 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +204 -0
- package/dist/sync.js.map +1 -0
- package/dist/types.d.ts +125 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +30 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +174 -0
- package/dist/verify.js.map +1 -0
- package/dist/version.d.ts +13 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/hooks/hooks.json +15 -0
- package/package.json +71 -0
- package/prompts/search-agent.md +160 -0
- package/skills/remembering-conversations/MCP-TOOLS.md +147 -0
- package/skills/remembering-conversations/SKILL.md +97 -0
package/dist/search.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation-exchange retrieval: sqlite-vec KNN, SQL LIKE, or both.
|
|
3
|
+
*
|
|
4
|
+
* This is the implementation that WON the reconciliation. private-journal-mcp's
|
|
5
|
+
* `search.ts` scanned every `.embedding` JSON sidecar into memory and scored it
|
|
6
|
+
* in JS; journal entries now get rows in the same store and are queried through
|
|
7
|
+
* journal/search.ts, which reuses `l2DistanceToCosineSimilarity` from here.
|
|
8
|
+
*/
|
|
9
|
+
import fs from "node:fs";
|
|
10
|
+
import readline from "node:readline";
|
|
11
|
+
import { initDatabase } from "./db.js";
|
|
12
|
+
import { generateQueryEmbedding, initEmbeddings } from "./embeddings.js";
|
|
13
|
+
import { isErroredSentinel } from "./summary-sentinel.js";
|
|
14
|
+
/**
|
|
15
|
+
* Build the AND-clause and bound-parameter list that constrains a search
|
|
16
|
+
* by the optional time and metadata filters. Bound parameters keep us
|
|
17
|
+
* safe from SQL injection without regex-based input scrubbing.
|
|
18
|
+
*/
|
|
19
|
+
function buildSearchFilters(options) {
|
|
20
|
+
const parts = [];
|
|
21
|
+
const params = [];
|
|
22
|
+
if (options.after) {
|
|
23
|
+
parts.push("e.timestamp >= ?");
|
|
24
|
+
params.push(options.after);
|
|
25
|
+
}
|
|
26
|
+
if (options.before) {
|
|
27
|
+
parts.push("e.timestamp <= ?");
|
|
28
|
+
params.push(options.before);
|
|
29
|
+
}
|
|
30
|
+
if (options.project) {
|
|
31
|
+
parts.push("e.project = ?");
|
|
32
|
+
params.push(options.project);
|
|
33
|
+
}
|
|
34
|
+
if (options.session_id) {
|
|
35
|
+
parts.push("e.session_id = ?");
|
|
36
|
+
params.push(options.session_id);
|
|
37
|
+
}
|
|
38
|
+
if (options.git_branch) {
|
|
39
|
+
parts.push("e.git_branch = ?");
|
|
40
|
+
params.push(options.git_branch);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
sql: parts.length ? `AND ${parts.join(" AND ")}` : "",
|
|
44
|
+
params,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function hasMetadataFilters(options) {
|
|
48
|
+
return Boolean(options.project || options.session_id || options.git_branch);
|
|
49
|
+
}
|
|
50
|
+
const EXCHANGE_SELECT_COLUMNS = `
|
|
51
|
+
e.id,
|
|
52
|
+
e.project,
|
|
53
|
+
e.timestamp,
|
|
54
|
+
e.user_message,
|
|
55
|
+
e.assistant_message,
|
|
56
|
+
e.archive_path,
|
|
57
|
+
e.line_start,
|
|
58
|
+
e.line_end,
|
|
59
|
+
e.parent_uuid,
|
|
60
|
+
e.is_sidechain,
|
|
61
|
+
e.harness,
|
|
62
|
+
e.session_id,
|
|
63
|
+
e.cwd,
|
|
64
|
+
e.git_branch,
|
|
65
|
+
e.claude_version,
|
|
66
|
+
e.agent_version,
|
|
67
|
+
e.model,
|
|
68
|
+
e.model_provider,
|
|
69
|
+
e.thinking_level,
|
|
70
|
+
e.thinking_disabled,
|
|
71
|
+
e.thinking_triggers`;
|
|
72
|
+
function exchangeFromRow(row) {
|
|
73
|
+
return {
|
|
74
|
+
id: row.id,
|
|
75
|
+
project: row.project,
|
|
76
|
+
timestamp: row.timestamp,
|
|
77
|
+
userMessage: row.user_message,
|
|
78
|
+
assistantMessage: row.assistant_message,
|
|
79
|
+
archivePath: row.archive_path,
|
|
80
|
+
lineStart: row.line_start,
|
|
81
|
+
lineEnd: row.line_end,
|
|
82
|
+
parentUuid: row.parent_uuid || undefined,
|
|
83
|
+
isSidechain: Boolean(row.is_sidechain),
|
|
84
|
+
harness: row.harness === "codex" ? "codex" : "claude",
|
|
85
|
+
sessionId: row.session_id || undefined,
|
|
86
|
+
cwd: row.cwd || undefined,
|
|
87
|
+
gitBranch: row.git_branch || undefined,
|
|
88
|
+
claudeVersion: row.claude_version || undefined,
|
|
89
|
+
agentVersion: row.agent_version || undefined,
|
|
90
|
+
model: row.model || undefined,
|
|
91
|
+
modelProvider: row.model_provider || undefined,
|
|
92
|
+
thinkingLevel: row.thinking_level || undefined,
|
|
93
|
+
thinkingDisabled: row.thinking_disabled === null ? undefined : Boolean(row.thinking_disabled),
|
|
94
|
+
thinkingTriggers: row.thinking_triggers || undefined,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Convert an L2 (Euclidean) distance between two unit-normalized vectors
|
|
99
|
+
* into a cosine similarity in [-1, 1].
|
|
100
|
+
*
|
|
101
|
+
* For unit vectors u, v: ||u - v||^2 = 2 - 2 * cos(u, v)
|
|
102
|
+
* Therefore: cos(u, v) = 1 - d^2 / 2
|
|
103
|
+
*
|
|
104
|
+
* ⚠️ Valid ONLY because src/embeddings.ts passes `normalize: true`. That coupling
|
|
105
|
+
* is invisible to the compiler: flip normalisation and every score here is
|
|
106
|
+
* silently wrong with no type error and no exception. Both record types share the
|
|
107
|
+
* encoder, so both share this constraint — journal/search.ts calls this function.
|
|
108
|
+
*/
|
|
109
|
+
export function l2DistanceToCosineSimilarity(distance) {
|
|
110
|
+
const similarity = 1 - (distance * distance) / 2;
|
|
111
|
+
return Math.max(-1, Math.min(1, similarity));
|
|
112
|
+
}
|
|
113
|
+
function validateISODate(dateStr, paramName) {
|
|
114
|
+
const isoDateRegex = /^\d{4}-\d{2}-\d{2}$/;
|
|
115
|
+
if (!isoDateRegex.test(dateStr)) {
|
|
116
|
+
throw new Error(`Invalid ${paramName} date: "${dateStr}". Expected YYYY-MM-DD format (e.g., 2025-10-01)`);
|
|
117
|
+
}
|
|
118
|
+
// Verify it's actually a valid date
|
|
119
|
+
const date = new Date(dateStr);
|
|
120
|
+
if (Number.isNaN(date.getTime())) {
|
|
121
|
+
throw new Error(`Invalid ${paramName} date: "${dateStr}". Not a valid calendar date.`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export async function searchConversations(query, options = {}) {
|
|
125
|
+
const { limit = 10, mode = "both", after, before } = options;
|
|
126
|
+
// Validate date parameters
|
|
127
|
+
if (after)
|
|
128
|
+
validateISODate(after, "--after");
|
|
129
|
+
if (before)
|
|
130
|
+
validateISODate(before, "--before");
|
|
131
|
+
const db = initDatabase();
|
|
132
|
+
let results = [];
|
|
133
|
+
const { sql: filterClause, params: filterParams } = buildSearchFilters(options);
|
|
134
|
+
if (mode === "vector" || mode === "both") {
|
|
135
|
+
// Vector similarity search.
|
|
136
|
+
// vec0 applies KNN before WHERE, so when extra metadata filters are
|
|
137
|
+
// active we ask for more candidates than `limit` and trim afterwards.
|
|
138
|
+
await initEmbeddings();
|
|
139
|
+
const queryEmbedding = await generateQueryEmbedding(query);
|
|
140
|
+
const k = hasMetadataFilters(options) ? limit * 3 : limit;
|
|
141
|
+
const stmt = db.prepare(`
|
|
142
|
+
SELECT
|
|
143
|
+
${EXCHANGE_SELECT_COLUMNS},
|
|
144
|
+
vec.distance
|
|
145
|
+
FROM vec_exchanges AS vec
|
|
146
|
+
JOIN exchanges AS e ON vec.id = e.id
|
|
147
|
+
WHERE vec.embedding MATCH ?
|
|
148
|
+
AND k = ?
|
|
149
|
+
AND e.is_sidechain = 0
|
|
150
|
+
${filterClause}
|
|
151
|
+
ORDER BY vec.distance ASC
|
|
152
|
+
`);
|
|
153
|
+
results = stmt.all(Buffer.from(new Float32Array(queryEmbedding).buffer), k, ...filterParams);
|
|
154
|
+
if (results.length > limit) {
|
|
155
|
+
results = results.slice(0, limit);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (mode === "text" || mode === "both") {
|
|
159
|
+
// Text search
|
|
160
|
+
const textStmt = db.prepare(`
|
|
161
|
+
SELECT
|
|
162
|
+
${EXCHANGE_SELECT_COLUMNS},
|
|
163
|
+
0 as distance
|
|
164
|
+
FROM exchanges AS e
|
|
165
|
+
WHERE (e.user_message LIKE ? OR e.assistant_message LIKE ?)
|
|
166
|
+
AND e.is_sidechain = 0
|
|
167
|
+
${filterClause}
|
|
168
|
+
ORDER BY e.timestamp DESC
|
|
169
|
+
LIMIT ?
|
|
170
|
+
`);
|
|
171
|
+
const textResults = textStmt.all(`%${query}%`, `%${query}%`, ...filterParams, limit);
|
|
172
|
+
if (mode === "both") {
|
|
173
|
+
// Merge and deduplicate by ID
|
|
174
|
+
const seenIds = new Set(results.map((r) => r.id));
|
|
175
|
+
for (const textResult of textResults) {
|
|
176
|
+
if (!seenIds.has(textResult.id)) {
|
|
177
|
+
results.push(textResult);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
results = textResults;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
db.close();
|
|
186
|
+
return results.map((row) => {
|
|
187
|
+
const exchange = exchangeFromRow(row);
|
|
188
|
+
// Try to load summary if available. Skip error sentinels (#96) so failed
|
|
189
|
+
// summarizations don't surface as the conversation's summary in results.
|
|
190
|
+
const summaryPath = row.archive_path.replace(".jsonl", "-summary.txt");
|
|
191
|
+
let summary;
|
|
192
|
+
if (fs.existsSync(summaryPath)) {
|
|
193
|
+
const raw = fs.readFileSync(summaryPath, "utf-8");
|
|
194
|
+
if (!isErroredSentinel(raw)) {
|
|
195
|
+
summary = raw.trim();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Create snippet (first 200 chars, collapse newlines)
|
|
199
|
+
const snippetText = exchange.userMessage.substring(0, 200).replace(/\s+/g, " ").trim();
|
|
200
|
+
const snippet = snippetText + (exchange.userMessage.length > 200 ? "..." : "");
|
|
201
|
+
return {
|
|
202
|
+
exchange,
|
|
203
|
+
similarity: mode === "text" ? undefined : l2DistanceToCosineSimilarity(row.distance),
|
|
204
|
+
snippet,
|
|
205
|
+
summary,
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
// Helper function to count lines in a file efficiently
|
|
210
|
+
async function countLines(filePath) {
|
|
211
|
+
try {
|
|
212
|
+
const fileStream = fs.createReadStream(filePath);
|
|
213
|
+
const rl = readline.createInterface({
|
|
214
|
+
input: fileStream,
|
|
215
|
+
crlfDelay: Number.POSITIVE_INFINITY,
|
|
216
|
+
});
|
|
217
|
+
let count = 0;
|
|
218
|
+
for await (const line of rl) {
|
|
219
|
+
if (line.trim())
|
|
220
|
+
count++;
|
|
221
|
+
}
|
|
222
|
+
return count;
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return 0; // Return 0 if file can't be read
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Helper function to get file size in KB
|
|
229
|
+
function getFileSizeInKB(filePath) {
|
|
230
|
+
try {
|
|
231
|
+
const stats = fs.statSync(filePath);
|
|
232
|
+
return Math.round((stats.size / 1024) * 10) / 10; // Round to 1 decimal place
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
return 0;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function isoDay(timestamp) {
|
|
239
|
+
const parsed = new Date(timestamp);
|
|
240
|
+
if (Number.isNaN(parsed.getTime()))
|
|
241
|
+
return timestamp;
|
|
242
|
+
return parsed.toISOString().slice(0, 10);
|
|
243
|
+
}
|
|
244
|
+
function toolSummaryLine(exchange) {
|
|
245
|
+
if (!exchange.toolCalls || exchange.toolCalls.length === 0)
|
|
246
|
+
return null;
|
|
247
|
+
const toolCounts = new Map();
|
|
248
|
+
for (const tc of exchange.toolCalls) {
|
|
249
|
+
toolCounts.set(tc.toolName, (toolCounts.get(tc.toolName) || 0) + 1);
|
|
250
|
+
}
|
|
251
|
+
return Array.from(toolCounts.entries())
|
|
252
|
+
.map(([name, count]) => `${name}(${count})`)
|
|
253
|
+
.join(", ");
|
|
254
|
+
}
|
|
255
|
+
export async function formatResults(results) {
|
|
256
|
+
if (results.length === 0) {
|
|
257
|
+
return "No results found.";
|
|
258
|
+
}
|
|
259
|
+
let output = `Found ${results.length} relevant conversation${results.length > 1 ? "s" : ""}:\n\n`;
|
|
260
|
+
// Process results sequentially to get file metadata
|
|
261
|
+
let index = 0;
|
|
262
|
+
for (const result of results) {
|
|
263
|
+
index++;
|
|
264
|
+
const date = isoDay(result.exchange.timestamp);
|
|
265
|
+
const simPct = result.similarity !== undefined ? Math.round(result.similarity * 100) : null;
|
|
266
|
+
// Header with match percentage
|
|
267
|
+
output += `${index}. [${result.exchange.project}, ${date}]`;
|
|
268
|
+
if (simPct !== null) {
|
|
269
|
+
output += ` - ${simPct}% match`;
|
|
270
|
+
}
|
|
271
|
+
output += "\n";
|
|
272
|
+
// Show summary only if it's concise (< 300 chars)
|
|
273
|
+
if (result.summary && result.summary.length < 300) {
|
|
274
|
+
output += ` ${result.summary}\n`;
|
|
275
|
+
}
|
|
276
|
+
// Show snippet
|
|
277
|
+
output += ` "${result.snippet}"\n`;
|
|
278
|
+
const tools = toolSummaryLine(result.exchange);
|
|
279
|
+
if (tools)
|
|
280
|
+
output += ` Tools: ${tools}\n`;
|
|
281
|
+
// Get file metadata
|
|
282
|
+
const fileSizeKB = getFileSizeInKB(result.exchange.archivePath);
|
|
283
|
+
const totalLines = await countLines(result.exchange.archivePath);
|
|
284
|
+
const lineRange = `${result.exchange.lineStart}-${result.exchange.lineEnd}`;
|
|
285
|
+
// File information with metadata (clean format for smart tool selection)
|
|
286
|
+
output += ` Lines ${lineRange} in ${result.exchange.archivePath} (${fileSizeKB}KB, ${totalLines} lines)\n\n`;
|
|
287
|
+
}
|
|
288
|
+
return output;
|
|
289
|
+
}
|
|
290
|
+
export async function searchMultipleConcepts(concepts, options = {}) {
|
|
291
|
+
const { limit = 10 } = options;
|
|
292
|
+
if (concepts.length === 0) {
|
|
293
|
+
return [];
|
|
294
|
+
}
|
|
295
|
+
// Search for each concept independently
|
|
296
|
+
const conceptResults = await Promise.all(concepts.map((concept) => searchConversations(concept, { ...options, limit: limit * 5, mode: "vector" })));
|
|
297
|
+
// Build map of conversation path -> array of results (one per concept)
|
|
298
|
+
const conversationMap = new Map();
|
|
299
|
+
conceptResults.forEach((results, conceptIndex) => {
|
|
300
|
+
for (const result of results) {
|
|
301
|
+
const key = result.exchange.archivePath;
|
|
302
|
+
const bucket = conversationMap.get(key);
|
|
303
|
+
if (bucket) {
|
|
304
|
+
bucket.push({ ...result, conceptIndex });
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
conversationMap.set(key, [{ ...result, conceptIndex }]);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
// Find conversations that match ALL concepts
|
|
312
|
+
const multiConceptResults = [];
|
|
313
|
+
for (const results of conversationMap.values()) {
|
|
314
|
+
// Check if all concepts are represented
|
|
315
|
+
const representedConcepts = new Set(results.map((r) => r.conceptIndex));
|
|
316
|
+
if (representedConcepts.size !== concepts.length)
|
|
317
|
+
continue;
|
|
318
|
+
const conceptSimilarities = concepts.map((_concept, index) => {
|
|
319
|
+
const result = results.find((r) => r.conceptIndex === index);
|
|
320
|
+
return result?.similarity ?? 0;
|
|
321
|
+
});
|
|
322
|
+
const averageSimilarity = conceptSimilarities.reduce((sum, sim) => sum + sim, 0) / conceptSimilarities.length;
|
|
323
|
+
// Use the first result's exchange data (they're all from the same conversation)
|
|
324
|
+
const firstResult = results[0];
|
|
325
|
+
if (!firstResult)
|
|
326
|
+
continue;
|
|
327
|
+
multiConceptResults.push({
|
|
328
|
+
exchange: firstResult.exchange,
|
|
329
|
+
snippet: firstResult.snippet,
|
|
330
|
+
conceptSimilarities,
|
|
331
|
+
averageSimilarity,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
// Sort by average similarity (highest first)
|
|
335
|
+
multiConceptResults.sort((a, b) => b.averageSimilarity - a.averageSimilarity);
|
|
336
|
+
// Apply limit
|
|
337
|
+
return multiConceptResults.slice(0, limit);
|
|
338
|
+
}
|
|
339
|
+
export async function formatMultiConceptResults(results, concepts) {
|
|
340
|
+
if (results.length === 0) {
|
|
341
|
+
return `No conversations found matching all concepts: ${concepts.join(", ")}`;
|
|
342
|
+
}
|
|
343
|
+
let output = `Found ${results.length} conversation${results.length > 1 ? "s" : ""} matching all concepts [${concepts.join(" + ")}]:\n\n`;
|
|
344
|
+
// Process results sequentially to get file metadata
|
|
345
|
+
let index = 0;
|
|
346
|
+
for (const result of results) {
|
|
347
|
+
index++;
|
|
348
|
+
const date = isoDay(result.exchange.timestamp);
|
|
349
|
+
const avgPct = Math.round(result.averageSimilarity * 100);
|
|
350
|
+
// Header with average match percentage
|
|
351
|
+
output += `${index}. [${result.exchange.project}, ${date}] - ${avgPct}% avg match\n`;
|
|
352
|
+
// Show individual concept scores
|
|
353
|
+
const scores = result.conceptSimilarities
|
|
354
|
+
.map((sim, i) => `${concepts[i] ?? `concept ${i + 1}`}: ${Math.round(sim * 100)}%`)
|
|
355
|
+
.join(", ");
|
|
356
|
+
output += ` Concepts: ${scores}\n`;
|
|
357
|
+
// Show snippet
|
|
358
|
+
output += ` "${result.snippet}"\n`;
|
|
359
|
+
const tools = toolSummaryLine(result.exchange);
|
|
360
|
+
if (tools)
|
|
361
|
+
output += ` Tools: ${tools}\n`;
|
|
362
|
+
// Get file metadata
|
|
363
|
+
const fileSizeKB = getFileSizeInKB(result.exchange.archivePath);
|
|
364
|
+
const totalLines = await countLines(result.exchange.archivePath);
|
|
365
|
+
const lineRange = `${result.exchange.lineStart}-${result.exchange.lineEnd}`;
|
|
366
|
+
// File information with metadata (clean format for smart tool selection)
|
|
367
|
+
output += ` Lines ${lineRange} in ${result.exchange.archivePath} (${fileSizeKB}KB, ${totalLines} lines)\n\n`;
|
|
368
|
+
}
|
|
369
|
+
return output;
|
|
370
|
+
}
|
|
371
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show-cli.d.ts","sourceRoot":"","sources":["../src/show-cli.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAyBzE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAyC9C"}
|
package/dist/show-cli.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** `moe-memory show` — render a transcript JSONL as markdown or HTML. */
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { formatConversationAsHTML, formatConversationAsMarkdown } from "./show.js";
|
|
4
|
+
const HELP = `
|
|
5
|
+
Usage: moe-memory show [OPTIONS] <file>
|
|
6
|
+
|
|
7
|
+
Display a conversation from a JSONL file in a human-readable format.
|
|
8
|
+
|
|
9
|
+
OPTIONS:
|
|
10
|
+
--format, -f FORMAT Output format: markdown or html (default: markdown)
|
|
11
|
+
--help, -h Show this help
|
|
12
|
+
|
|
13
|
+
EXAMPLES:
|
|
14
|
+
# Show conversation as markdown
|
|
15
|
+
moe-memory show conversation.jsonl
|
|
16
|
+
|
|
17
|
+
# Generate HTML for browser viewing
|
|
18
|
+
moe-memory show --format html conversation.jsonl > output.html
|
|
19
|
+
|
|
20
|
+
# View with pipe
|
|
21
|
+
moe-memory show conversation.jsonl | less
|
|
22
|
+
`;
|
|
23
|
+
export function runShow(args) {
|
|
24
|
+
let format = "markdown";
|
|
25
|
+
let filePath = null;
|
|
26
|
+
for (let i = 0; i < args.length; i++) {
|
|
27
|
+
const arg = args[i];
|
|
28
|
+
if (arg === "--format" || arg === "-f") {
|
|
29
|
+
const value = args[++i];
|
|
30
|
+
if (value !== "markdown" && value !== "html") {
|
|
31
|
+
console.error(`Invalid --format value: ${value ?? "(missing)"}. Expected markdown or html.`);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
format = value;
|
|
35
|
+
}
|
|
36
|
+
else if (arg === "--help" || arg === "-h") {
|
|
37
|
+
console.log(HELP);
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
else if (!filePath && arg !== undefined) {
|
|
41
|
+
filePath = arg;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!filePath) {
|
|
45
|
+
console.error("Error: No file specified");
|
|
46
|
+
console.error("Usage: moe-memory show [OPTIONS] <file>");
|
|
47
|
+
console.error("Try: moe-memory show --help");
|
|
48
|
+
return 1;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const jsonl = readFileSync(filePath, "utf-8");
|
|
52
|
+
console.log(format === "html" ? formatConversationAsHTML(jsonl) : formatConversationAsMarkdown(jsonl));
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.error(`Error reading file: ${error instanceof Error ? error.message : String(error)}`);
|
|
57
|
+
return 1;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=show-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show-cli.js","sourceRoot":"","sources":["../src/show-cli.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AAEnF,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;CAkBZ,CAAC;AAEF,MAAM,UAAU,OAAO,CAAC,IAAc;IACpC,IAAI,MAAM,GAAwB,UAAU,CAAC;IAC7C,IAAI,QAAQ,GAAkB,IAAI,CAAC;IAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEpB,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACxB,IAAI,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBAC7C,OAAO,CAAC,KAAK,CACX,2BAA2B,KAAK,IAAI,WAAW,8BAA8B,CAC9E,CAAC;gBACF,OAAO,CAAC,CAAC;YACX,CAAC;YACD,MAAM,GAAG,KAAK,CAAC;QACjB,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,CAAC,CAAC;QACX,CAAC;aAAM,IAAI,CAAC,QAAQ,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YAC1C,QAAQ,GAAG,GAAG,CAAC;QACjB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC1C,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACzD,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC7C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CACT,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAC1F,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,uBAAuB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/F,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
|
package/dist/show.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"show.d.ts","sourceRoot":"","sources":["../src/show.ts"],"names":[],"mappings":"AA2BA,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,CAoNR;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoiB9D"}
|