@llmnesia/mcp 0.2.9 → 0.2.10
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/dist/{chunk-YT6GNKKG.js → chunk-GLCLSBT6.js} +1 -1
- package/dist/{chunk-BWEDXPNM.js → chunk-XRA6OJC5.js} +68 -16
- package/dist/{cli-KHY7ADCU.js → cli-2IIJ77ZQ.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/llmnesia-claude-host.mjs +53 -7
- package/dist/llmnesia.mcpb +0 -0
- package/dist/mcp.js +19 -12
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -3,7 +3,7 @@ import { createRequire as __llmnesiaCreateRequire } from "node:module";
|
|
|
3
3
|
const require = __llmnesiaCreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
VERSION
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GLCLSBT6.js";
|
|
7
7
|
|
|
8
8
|
// src/config.ts
|
|
9
9
|
import { readFileSync } from "fs";
|
|
@@ -47,7 +47,7 @@ function expandHome(p) {
|
|
|
47
47
|
import { join as join2 } from "path";
|
|
48
48
|
import { readdir } from "fs/promises";
|
|
49
49
|
import { createHash } from "crypto";
|
|
50
|
-
var INDEX_FORMAT_VERSION =
|
|
50
|
+
var INDEX_FORMAT_VERSION = 7;
|
|
51
51
|
function indexDbFilename(version) {
|
|
52
52
|
return version === 1 ? "llmnesia.db" : `llmnesia-v${version}.db`;
|
|
53
53
|
}
|
|
@@ -217,6 +217,13 @@ function canonicalConversationDoc(c) {
|
|
|
217
217
|
observedAt: c.providerProject.observedAt
|
|
218
218
|
};
|
|
219
219
|
}
|
|
220
|
+
if (c.providerWorkspace) {
|
|
221
|
+
out.providerWorkspace = {
|
|
222
|
+
workspaceId: c.providerWorkspace.workspaceId,
|
|
223
|
+
source: c.providerWorkspace.source,
|
|
224
|
+
observedAt: c.providerWorkspace.observedAt
|
|
225
|
+
};
|
|
226
|
+
}
|
|
220
227
|
if (c.models && c.models.length > 0) out.models = [...c.models];
|
|
221
228
|
assignIfDefined(out, "modelMetadataUpdatedAt", c.modelMetadataUpdatedAt);
|
|
222
229
|
if (c.summary) {
|
|
@@ -721,6 +728,17 @@ var EMPTY_REPORT = {
|
|
|
721
728
|
messages: 0,
|
|
722
729
|
malformedLines: 0
|
|
723
730
|
};
|
|
731
|
+
async function upsertIndexedConversation(corpus, record, index) {
|
|
732
|
+
const result = await corpus.upsert(record);
|
|
733
|
+
if (index) {
|
|
734
|
+
const saved = await corpus.getFromPlatform(record.conversation.platform, result.docId);
|
|
735
|
+
if (!saved) {
|
|
736
|
+
throw new Error(`Saved conversation '${result.docId}' could not be read for indexing`);
|
|
737
|
+
}
|
|
738
|
+
index.upsertConversation(saved);
|
|
739
|
+
}
|
|
740
|
+
return result;
|
|
741
|
+
}
|
|
724
742
|
async function ingestFile(corpus, file, index) {
|
|
725
743
|
const report = { ...EMPTY_REPORT };
|
|
726
744
|
let current = null;
|
|
@@ -730,11 +748,8 @@ async function ingestFile(corpus, file, index) {
|
|
|
730
748
|
return;
|
|
731
749
|
}
|
|
732
750
|
const record = { conversation: current, messages: buffered };
|
|
733
|
-
const result = await corpus
|
|
751
|
+
const result = await upsertIndexedConversation(corpus, record, index);
|
|
734
752
|
tally(report, result);
|
|
735
|
-
if (index && result.outcome !== "skipped") {
|
|
736
|
-
index.upsertConversation(record);
|
|
737
|
-
}
|
|
738
753
|
report.conversations += 1;
|
|
739
754
|
report.messages += buffered.length;
|
|
740
755
|
current = null;
|
|
@@ -771,9 +786,9 @@ async function ingestFile(corpus, file, index) {
|
|
|
771
786
|
}
|
|
772
787
|
continue;
|
|
773
788
|
}
|
|
774
|
-
if (type === "message"
|
|
789
|
+
if (type === "message") {
|
|
775
790
|
const docId = typeof record.docId === "string" ? record.docId : "";
|
|
776
|
-
if (docId !== current.docId) {
|
|
791
|
+
if (!current || docId !== current.docId) {
|
|
777
792
|
report.malformedLines += 1;
|
|
778
793
|
continue;
|
|
779
794
|
}
|
|
@@ -1044,6 +1059,8 @@ CREATE TABLE IF NOT EXISTS conversations (
|
|
|
1044
1059
|
pinned INTEGER NOT NULL,
|
|
1045
1060
|
accountId TEXT,
|
|
1046
1061
|
accountLabel TEXT,
|
|
1062
|
+
providerProject TEXT,
|
|
1063
|
+
providerWorkspace TEXT,
|
|
1047
1064
|
models TEXT,
|
|
1048
1065
|
fingerprint TEXT NOT NULL
|
|
1049
1066
|
);
|
|
@@ -1113,14 +1130,14 @@ var SearchIndex = class {
|
|
|
1113
1130
|
deleteFts: this.db.prepare("DELETE FROM messages_fts WHERE rowid = ?"),
|
|
1114
1131
|
deleteMessageRows: this.db.prepare("DELETE FROM message_rows WHERE docId = ?"),
|
|
1115
1132
|
insertMessageRow: this.db.prepare(
|
|
1116
|
-
"INSERT INTO message_rows (docId, msgIndex, role) VALUES (?, ?, ?)"
|
|
1133
|
+
"INSERT INTO message_rows (docId, msgIndex, role) VALUES (?, ?, ?) RETURNING rowid"
|
|
1117
1134
|
),
|
|
1118
1135
|
insertFts: this.db.prepare("INSERT INTO messages_fts (rowid, text) VALUES (?, ?)"),
|
|
1119
1136
|
deleteConversation: this.db.prepare("DELETE FROM conversations WHERE docId = ?"),
|
|
1120
1137
|
insertConversation: this.db.prepare(
|
|
1121
1138
|
`INSERT INTO conversations
|
|
1122
|
-
(docId, platform, title, url, createdAt, updatedAt, messageCount, preview, pinned, accountId, accountLabel, models, fingerprint)
|
|
1123
|
-
VALUES (@docId, @platform, @title, @url, @createdAt, @updatedAt, @messageCount, @preview, @pinned, @accountId, @accountLabel, @models, @fingerprint)`
|
|
1139
|
+
(docId, platform, title, url, createdAt, updatedAt, messageCount, preview, pinned, accountId, accountLabel, providerProject, providerWorkspace, models, fingerprint)
|
|
1140
|
+
VALUES (@docId, @platform, @title, @url, @createdAt, @updatedAt, @messageCount, @preview, @pinned, @accountId, @accountLabel, @providerProject, @providerWorkspace, @models, @fingerprint)`
|
|
1124
1141
|
),
|
|
1125
1142
|
deleteMemoryFts: this.db.prepare("DELETE FROM memories_fts WHERE memoryId = ?"),
|
|
1126
1143
|
insertMemoryFts: this.db.prepare(
|
|
@@ -1139,6 +1156,8 @@ var SearchIndex = class {
|
|
|
1139
1156
|
FROM temp.snippet_fts WHERE snippet_fts MATCH ?`
|
|
1140
1157
|
)
|
|
1141
1158
|
};
|
|
1159
|
+
this.stmts.selectFtsRows.setReadBigInts(true);
|
|
1160
|
+
this.stmts.insertMessageRow.setReadBigInts(true);
|
|
1142
1161
|
}
|
|
1143
1162
|
/** True when the stored format version was missing or stale — caller rebuilds. */
|
|
1144
1163
|
needsRebuild() {
|
|
@@ -1164,14 +1183,18 @@ var SearchIndex = class {
|
|
|
1164
1183
|
const orderBy = sort === "oldest" ? "createdAt ASC, updatedAt ASC" : sort === "newest" ? "createdAt DESC, updatedAt DESC" : "updatedAt DESC, createdAt DESC";
|
|
1165
1184
|
const rows = this.db.prepare(
|
|
1166
1185
|
`SELECT docId, platform, title, url, createdAt, updatedAt, messageCount, preview, pinned,
|
|
1167
|
-
accountId, accountLabel, models
|
|
1186
|
+
accountId, accountLabel, providerProject, providerWorkspace, models
|
|
1168
1187
|
FROM conversations ORDER BY ${orderBy} LIMIT ?`
|
|
1169
1188
|
).all(limit);
|
|
1170
1189
|
return rows.map((r) => {
|
|
1171
|
-
const { accountId, accountLabel, models, ...rest } = r;
|
|
1190
|
+
const { accountId, accountLabel, providerProject, providerWorkspace, models, ...rest } = r;
|
|
1172
1191
|
const entry = { ...rest, pinned: r.pinned === 1 };
|
|
1173
1192
|
if (accountId) entry.accountId = accountId;
|
|
1174
1193
|
if (accountLabel) entry.accountLabel = accountLabel;
|
|
1194
|
+
const project = parseObservation(providerProject);
|
|
1195
|
+
if (project) entry.providerProject = project;
|
|
1196
|
+
const workspace = parseObservation(providerWorkspace);
|
|
1197
|
+
if (workspace) entry.providerWorkspace = workspace;
|
|
1175
1198
|
const parsedModels = parseModels(models);
|
|
1176
1199
|
if (parsedModels.length > 0) entry.models = parsedModels;
|
|
1177
1200
|
return entry;
|
|
@@ -1277,13 +1300,15 @@ var SearchIndex = class {
|
|
|
1277
1300
|
pinned: conversation.pinned ? 1 : 0,
|
|
1278
1301
|
accountId: conversation.accountId ?? null,
|
|
1279
1302
|
accountLabel: conversation.accountLabel ?? null,
|
|
1303
|
+
providerProject: observationJson(conversation.providerProject),
|
|
1304
|
+
providerWorkspace: observationJson(conversation.providerWorkspace),
|
|
1280
1305
|
models: conversation.models?.length ? JSON.stringify(conversation.models) : null,
|
|
1281
1306
|
fingerprint: fingerprintConversation(rec)
|
|
1282
1307
|
});
|
|
1283
1308
|
}
|
|
1284
1309
|
insertFtsRow(docId, msgIndex, role, text) {
|
|
1285
|
-
const inserted = this.stmts.insertMessageRow.
|
|
1286
|
-
this.stmts.insertFts.run(inserted.
|
|
1310
|
+
const inserted = this.stmts.insertMessageRow.get(docId, msgIndex, role);
|
|
1311
|
+
this.stmts.insertFts.run(inserted.rowid, text);
|
|
1287
1312
|
}
|
|
1288
1313
|
deleteFtsRows(docId) {
|
|
1289
1314
|
const rows = this.stmts.selectFtsRows.all(docId);
|
|
@@ -1339,11 +1364,20 @@ var SearchIndex = class {
|
|
|
1339
1364
|
clauses.push("c.createdAt <= @dateTo");
|
|
1340
1365
|
params.dateTo = filters.dateTo;
|
|
1341
1366
|
}
|
|
1367
|
+
if (filters.providerProjectId) {
|
|
1368
|
+
clauses.push("json_extract(c.providerProject, '$.projectId') = @providerProjectId");
|
|
1369
|
+
params.providerProjectId = filters.providerProjectId;
|
|
1370
|
+
}
|
|
1371
|
+
if (filters.providerWorkspaceId) {
|
|
1372
|
+
clauses.push("json_extract(c.providerWorkspace, '$.workspaceId') = @providerWorkspaceId");
|
|
1373
|
+
params.providerWorkspaceId = filters.providerWorkspaceId;
|
|
1374
|
+
}
|
|
1342
1375
|
const scanCap = Math.min(2e3, Math.max(200, limit * 40));
|
|
1343
1376
|
const sql = `
|
|
1344
1377
|
SELECT
|
|
1345
1378
|
c.docId, c.platform, c.title, c.url, c.createdAt, c.updatedAt,
|
|
1346
|
-
c.messageCount, c.preview, c.pinned, c.accountId, c.accountLabel,
|
|
1379
|
+
c.messageCount, c.preview, c.pinned, c.accountId, c.accountLabel,
|
|
1380
|
+
c.providerProject, c.providerWorkspace, c.models,
|
|
1347
1381
|
m.msgIndex AS msgIndex, m.role AS role,
|
|
1348
1382
|
bm25(messages_fts) AS bm25
|
|
1349
1383
|
FROM messages_fts
|
|
@@ -1379,6 +1413,10 @@ var SearchIndex = class {
|
|
|
1379
1413
|
};
|
|
1380
1414
|
if (row.accountId) hit.accountId = row.accountId;
|
|
1381
1415
|
if (row.accountLabel) hit.accountLabel = row.accountLabel;
|
|
1416
|
+
const project = parseObservation(row.providerProject);
|
|
1417
|
+
if (project) hit.providerProject = project;
|
|
1418
|
+
const workspace = parseObservation(row.providerWorkspace);
|
|
1419
|
+
if (workspace) hit.providerWorkspace = workspace;
|
|
1382
1420
|
const models = parseModels(row.models);
|
|
1383
1421
|
if (models.length > 0) hit.models = models;
|
|
1384
1422
|
hits.push(hit);
|
|
@@ -1474,6 +1512,19 @@ function parseModels(value) {
|
|
|
1474
1512
|
return [];
|
|
1475
1513
|
}
|
|
1476
1514
|
}
|
|
1515
|
+
function observationJson(observation) {
|
|
1516
|
+
if (!observation) return null;
|
|
1517
|
+
return JSON.stringify(observation);
|
|
1518
|
+
}
|
|
1519
|
+
function parseObservation(value) {
|
|
1520
|
+
if (!value) return void 0;
|
|
1521
|
+
try {
|
|
1522
|
+
const parsed = JSON.parse(value);
|
|
1523
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
1524
|
+
} catch {
|
|
1525
|
+
return void 0;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1477
1528
|
|
|
1478
1529
|
// src/storageMaintenance.ts
|
|
1479
1530
|
import { promises as fs4 } from "fs";
|
|
@@ -2147,6 +2198,7 @@ export {
|
|
|
2147
2198
|
resolveCorpusDir,
|
|
2148
2199
|
staleIndexFiles,
|
|
2149
2200
|
Corpus,
|
|
2201
|
+
upsertIndexedConversation,
|
|
2150
2202
|
ingestFile,
|
|
2151
2203
|
pendingInboxFiles,
|
|
2152
2204
|
drainInbox,
|
|
@@ -17,13 +17,13 @@ import {
|
|
|
17
17
|
runtimeBinDir,
|
|
18
18
|
staleIndexFiles,
|
|
19
19
|
uninstallRuntime
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-XRA6OJC5.js";
|
|
21
21
|
import {
|
|
22
22
|
VERSION,
|
|
23
23
|
__commonJS,
|
|
24
24
|
__require,
|
|
25
25
|
__toESM
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-GLCLSBT6.js";
|
|
27
27
|
|
|
28
28
|
// ../node_modules/isexe/windows.js
|
|
29
29
|
var require_windows = __commonJS({
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire as __llmnesiaCreateRequire } from "node:module";
|
|
|
3
3
|
const require = __llmnesiaCreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
VERSION
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-GLCLSBT6.js";
|
|
7
7
|
|
|
8
8
|
// src/nodeDownload.ts
|
|
9
9
|
var NODE_DOWNLOAD_URLS = {
|
|
@@ -141,7 +141,7 @@ async function bootstrap() {
|
|
|
141
141
|
await guideUnsupportedNodeVersion(process.versions.node);
|
|
142
142
|
return 1;
|
|
143
143
|
}
|
|
144
|
-
const { main } = await import("./cli-
|
|
144
|
+
const { main } = await import("./cli-2IIJ77ZQ.js");
|
|
145
145
|
return main();
|
|
146
146
|
}
|
|
147
147
|
bootstrap().then((code) => {
|
|
@@ -78,9 +78,29 @@ const DEFAULT_CODEX_HOME = process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
|
78
78
|
// Codex nests rollouts as sessions/<year>/<month>/<day>/*.jsonl. Bounded so a
|
|
79
79
|
// misconfigured codexHome can't turn into an unbounded filesystem walk.
|
|
80
80
|
const CODEX_MAX_DEPTH = 3;
|
|
81
|
-
// Conservative chunk size
|
|
82
|
-
//
|
|
83
|
-
|
|
81
|
+
// Conservative chunk size. Native messaging caps a single message at 1 MB,
|
|
82
|
+
// and the wire size of a chunk is the JSON-ESCAPED UTF-8 length of `data`
|
|
83
|
+
// (an astral character is 4 raw bytes; a literal backslash doubles), so
|
|
84
|
+
// chunks are budgeted by measuring exactly that as they are built: a chunk
|
|
85
|
+
// can never push the framed message over the ceiling no matter what the
|
|
86
|
+
// transcript contains.
|
|
87
|
+
const MAX_CHUNK_ESCAPED_BYTES = 256 * 1024;
|
|
88
|
+
// JSON-escaped UTF-8 byte length of one UTF-16 code unit of `text` as
|
|
89
|
+
// JSON.stringify would emit it: quotes/backslashes and the short escapes
|
|
90
|
+
// double, other control characters become \u00XX (6 bytes), a lone surrogate
|
|
91
|
+
// becomes \udXXX, BMP non-ASCII passes through at its UTF-8 width, and a
|
|
92
|
+
// surrogate PAIR is one 4-byte astral character.
|
|
93
|
+
function escapedUnitBytes(unit, nextUnit) {
|
|
94
|
+
if (unit >= 0xd800 && unit <= 0xdbff) {
|
|
95
|
+
return nextUnit >= 0xdc00 && nextUnit <= 0xdfff ? 4 : 6; // astral char or lone high surrogate
|
|
96
|
+
}
|
|
97
|
+
if (unit >= 0xdc00 && unit <= 0xdfff) return 6; // lone low surrogate
|
|
98
|
+
if (unit === 0x22 || unit === 0x5c) return 2; // " and \
|
|
99
|
+
if (unit < 0x20) return [0x08, 0x09, 0x0a, 0x0c, 0x0d].includes(unit) ? 2 : 6;
|
|
100
|
+
if (unit < 0x80) return 1;
|
|
101
|
+
if (unit < 0x800) return 2;
|
|
102
|
+
return 3;
|
|
103
|
+
}
|
|
84
104
|
// Matches companion/src/corpus.ts DIR_MODE/FILE_MODE — the corpus holds
|
|
85
105
|
// plaintext conversation history, so writes here should be no more readable
|
|
86
106
|
// than the browser profile it was copied out of.
|
|
@@ -690,14 +710,31 @@ async function handle(message) {
|
|
|
690
710
|
}
|
|
691
711
|
text = await readFile(match.path, "utf8");
|
|
692
712
|
}
|
|
693
|
-
const
|
|
694
|
-
|
|
713
|
+
const chunks = [];
|
|
714
|
+
let chunk = "";
|
|
715
|
+
let chunkBytes = 0;
|
|
716
|
+
for (let i = 0; i < text.length; i++) {
|
|
717
|
+
const unit = text.charCodeAt(i);
|
|
718
|
+
const size = escapedUnitBytes(unit, i + 1 < text.length ? text.charCodeAt(i + 1) : NaN);
|
|
719
|
+
if (chunk && chunkBytes + size > MAX_CHUNK_ESCAPED_BYTES) {
|
|
720
|
+
chunks.push(chunk);
|
|
721
|
+
chunk = "";
|
|
722
|
+
chunkBytes = 0;
|
|
723
|
+
}
|
|
724
|
+
chunk += text[i];
|
|
725
|
+
chunkBytes += size;
|
|
726
|
+
}
|
|
727
|
+
if (chunk) {
|
|
728
|
+
chunks.push(chunk);
|
|
729
|
+
}
|
|
730
|
+
const total = Math.max(1, chunks.length);
|
|
731
|
+
for (let seq = 0; seq < total; seq++) {
|
|
695
732
|
send({
|
|
696
733
|
type: "chunk",
|
|
697
734
|
sessionId: message.sessionId,
|
|
698
735
|
seq,
|
|
699
736
|
total,
|
|
700
|
-
data:
|
|
737
|
+
data: chunks[seq] ?? ""
|
|
701
738
|
});
|
|
702
739
|
}
|
|
703
740
|
send({ type: "sessionDone", sessionId: message.sessionId });
|
|
@@ -728,7 +765,16 @@ process.stdin.on("data", (data) => {
|
|
|
728
765
|
// Serialize handling so chunk ordering per session is preserved.
|
|
729
766
|
processing = processing
|
|
730
767
|
.then(() => handle(message))
|
|
731
|
-
.catch((error) =>
|
|
768
|
+
.catch((error) =>
|
|
769
|
+
// Attribute the failure to the command's session when it names one, so
|
|
770
|
+
// the extension's fetch loop can drop a STALE error that arrives after
|
|
771
|
+
// it gave up on that session instead of failing the next one.
|
|
772
|
+
send({
|
|
773
|
+
type: "error",
|
|
774
|
+
...(typeof message.sessionId === "string" ? { sessionId: message.sessionId } : {}),
|
|
775
|
+
error: String((error && error.message) || error)
|
|
776
|
+
})
|
|
777
|
+
);
|
|
732
778
|
}
|
|
733
779
|
});
|
|
734
780
|
|
package/dist/llmnesia.mcpb
CHANGED
|
Binary file
|
package/dist/mcp.js
CHANGED
|
@@ -12,14 +12,15 @@ import {
|
|
|
12
12
|
readNativeHostViewerExtensionId,
|
|
13
13
|
resolveCorpusDir,
|
|
14
14
|
runAutomaticMaintenance,
|
|
15
|
-
scheduleSelfUpdate
|
|
16
|
-
|
|
15
|
+
scheduleSelfUpdate,
|
|
16
|
+
upsertIndexedConversation
|
|
17
|
+
} from "./chunk-XRA6OJC5.js";
|
|
17
18
|
import {
|
|
18
19
|
VERSION,
|
|
19
20
|
__commonJS,
|
|
20
21
|
__export,
|
|
21
22
|
__toESM
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GLCLSBT6.js";
|
|
23
24
|
|
|
24
25
|
// ../node_modules/ajv/dist/compile/codegen/code.js
|
|
25
26
|
var require_code = __commonJS({
|
|
@@ -21704,10 +21705,7 @@ var CompanionService = class _CompanionService {
|
|
|
21704
21705
|
async saveConversation(payload) {
|
|
21705
21706
|
const input = saveConversationSchema.parse(payload);
|
|
21706
21707
|
const record2 = normalizeSaveInput(input);
|
|
21707
|
-
const result = await this.corpus.
|
|
21708
|
-
if (result.outcome !== "skipped") {
|
|
21709
|
-
this.index.upsertConversation(record2);
|
|
21710
|
-
}
|
|
21708
|
+
const result = await upsertIndexedConversation(this.corpus, record2, this.index);
|
|
21711
21709
|
return { docId: result.docId, outcome: result.outcome, messageCount: record2.messages.length };
|
|
21712
21710
|
}
|
|
21713
21711
|
/**
|
|
@@ -21810,16 +21808,15 @@ function viewerExtensionId() {
|
|
|
21810
21808
|
const configured = process.env.LLMNESIA_VIEWER_EXTENSION_ID?.trim() ?? readNativeHostViewerExtensionId();
|
|
21811
21809
|
return configured && EXTENSION_ID_RE.test(configured) ? configured : STORE_EXTENSION_ID;
|
|
21812
21810
|
}
|
|
21813
|
-
function viewerSourceUrl(docId
|
|
21814
|
-
const fragment = new URLSearchParams({ docId
|
|
21811
|
+
function viewerSourceUrl(docId) {
|
|
21812
|
+
const fragment = new URLSearchParams({ docId });
|
|
21815
21813
|
return `${VIEWER_HANDOFF_URL}#${fragment.toString()}`;
|
|
21816
21814
|
}
|
|
21817
21815
|
function sourceLinks(docId, originalUrl) {
|
|
21818
|
-
const
|
|
21819
|
-
const localViewerUrl = `chrome-extension://${extensionId}/viewer.html?docId=${encodeURIComponent(docId)}`;
|
|
21816
|
+
const localViewerUrl = `chrome-extension://${viewerExtensionId()}/viewer.html?docId=${encodeURIComponent(docId)}`;
|
|
21820
21817
|
return originalUrl ? { viewerUrl: localViewerUrl, sourceUrl: originalUrl, sourceKind: "original" } : {
|
|
21821
21818
|
viewerUrl: localViewerUrl,
|
|
21822
|
-
sourceUrl: viewerSourceUrl(docId
|
|
21819
|
+
sourceUrl: viewerSourceUrl(docId),
|
|
21823
21820
|
sourceKind: "viewer"
|
|
21824
21821
|
};
|
|
21825
21822
|
}
|
|
@@ -21902,6 +21899,8 @@ async function runServe() {
|
|
|
21902
21899
|
"How to combine query terms. 'any' (default) ORs them: highest recall, but common words in the query match almost everything, so results cannot be counted or used to prove something was discussed. 'all' requires every term in the same turn. 'phrase' requires the exact wording, adjacent and in order. Use 'all' or 'phrase' for existence and frequency questions, and strip filler words from the query first."
|
|
21903
21900
|
),
|
|
21904
21901
|
platform: external_exports.string().optional().describe("Restrict to one platform, e.g. 'claude', 'chatgpt', 'gemini'."),
|
|
21902
|
+
project_id: external_exports.string().optional().describe("Only conversations observed inside this ChatGPT Project (g-p-...)."),
|
|
21903
|
+
workspace_id: external_exports.string().optional().describe("Only conversations observed under this provider workspace (a Claude organization id)."),
|
|
21905
21904
|
title: external_exports.string().optional().describe("Only conversations whose title contains this substring."),
|
|
21906
21905
|
date_from: external_exports.string().optional().describe("Only conversations created on/after this date (ISO or epoch ms)."),
|
|
21907
21906
|
date_to: external_exports.string().optional().describe("Only conversations created on/before this date (ISO or epoch ms)."),
|
|
@@ -21917,6 +21916,8 @@ async function runServe() {
|
|
|
21917
21916
|
async (args) => withService(async (service2) => {
|
|
21918
21917
|
const filters = {
|
|
21919
21918
|
platform: args.platform,
|
|
21919
|
+
providerProjectId: args.project_id,
|
|
21920
|
+
providerWorkspaceId: args.workspace_id,
|
|
21920
21921
|
title: args.title,
|
|
21921
21922
|
dateFrom: parseDate(args.date_from),
|
|
21922
21923
|
dateTo: parseDate(args.date_to),
|
|
@@ -21944,6 +21945,8 @@ async function runServe() {
|
|
|
21944
21945
|
};
|
|
21945
21946
|
if (h.accountId) entry.accountId = h.accountId;
|
|
21946
21947
|
if (h.accountLabel) entry.accountLabel = h.accountLabel;
|
|
21948
|
+
if (h.providerProject) entry.providerProject = h.providerProject;
|
|
21949
|
+
if (h.providerWorkspace) entry.providerWorkspace = h.providerWorkspace;
|
|
21947
21950
|
if (h.models?.length) entry.models = h.models;
|
|
21948
21951
|
return entry;
|
|
21949
21952
|
})
|
|
@@ -22026,6 +22029,8 @@ async function runServe() {
|
|
|
22026
22029
|
};
|
|
22027
22030
|
if (e.accountId) entry.accountId = e.accountId;
|
|
22028
22031
|
if (e.accountLabel) entry.accountLabel = e.accountLabel;
|
|
22032
|
+
if (e.providerProject) entry.providerProject = e.providerProject;
|
|
22033
|
+
if (e.providerWorkspace) entry.providerWorkspace = e.providerWorkspace;
|
|
22029
22034
|
if (e.models?.length) entry.models = e.models;
|
|
22030
22035
|
return entry;
|
|
22031
22036
|
})
|
|
@@ -22070,6 +22075,8 @@ async function runServe() {
|
|
|
22070
22075
|
};
|
|
22071
22076
|
if (e.accountId) entry.accountId = e.accountId;
|
|
22072
22077
|
if (e.accountLabel) entry.accountLabel = e.accountLabel;
|
|
22078
|
+
if (e.providerProject) entry.providerProject = e.providerProject;
|
|
22079
|
+
if (e.providerWorkspace) entry.providerWorkspace = e.providerWorkspace;
|
|
22073
22080
|
if (e.models?.length) entry.models = e.models;
|
|
22074
22081
|
return entry;
|
|
22075
22082
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llmnesia/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"comment:mcpName": "The MCP Registry's ownership marker: it must equal server.json's `name`, and the namespace must match how you authenticate with mcp-publisher. `com.llmnesia/...` requires DNS auth (a TXT record on llmnesia.com) — see docs/MCP_INSTALLER_BOARD.md.",
|
package/server.json
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"name": "com.llmnesia/mcp",
|
|
4
4
|
"title": "LLMnesia",
|
|
5
5
|
"description": "Search your AI chat history from Claude, Cursor, Codex, and other MCP clients.",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.10",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
11
11
|
"identifier": "@llmnesia/mcp",
|
|
12
|
-
"version": "0.2.
|
|
12
|
+
"version": "0.2.10",
|
|
13
13
|
"transport": {
|
|
14
14
|
"type": "stdio"
|
|
15
15
|
}
|