nlm-memory 0.7.0 → 0.9.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/dist/cli/nlm.js +36 -0
- package/dist/cli/nlm.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +1 -0
- package/dist/core/hook/pointer-block.js +7 -1
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/query-extract.d.ts +5 -0
- package/dist/core/hook/query-extract.js +36 -0
- package/dist/core/hook/query-extract.js.map +1 -0
- package/dist/core/hook/select.d.ts +1 -0
- package/dist/core/hook/select.js.map +1 -1
- package/dist/core/recall/citation-log.d.ts +1 -0
- package/dist/core/recall/citation-log.js +37 -0
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/precision.d.ts +16 -0
- package/dist/core/recall/precision.js +46 -0
- package/dist/core/recall/precision.js.map +1 -0
- package/dist/core/recall/query-log.d.ts +4 -0
- package/dist/core/recall/query-log.js +39 -0
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.js +20 -1
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/reranker.d.ts +7 -0
- package/dist/core/recall/reranker.js +29 -0
- package/dist/core/recall/reranker.js.map +1 -0
- package/dist/core/storage/pg-session-store.js +21 -0
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-session-store.js +11 -0
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/supersedence-log.d.ts +5 -0
- package/dist/core/storage/supersedence-log.js +34 -1
- package/dist/core/storage/supersedence-log.js.map +1 -1
- package/dist/hook/recall-over-http.js +6 -1
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/session-start-hook.js +1 -0
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/mcp/server.js +13 -2
- package/dist/mcp/server.js.map +1 -1
- package/nlm/index.js +151 -3
- package/package.json +1 -1
- package/plugin/scripts/prompt-recall-hook.mjs +151 -3
package/nlm/index.js
CHANGED
|
@@ -48,12 +48,154 @@ function hookAuthHeaders(extra = {}) {
|
|
|
48
48
|
return { ...extra, authorization: `Bearer ${token}` };
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// src/core/hook/query-extract.ts
|
|
52
|
+
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
53
|
+
"a",
|
|
54
|
+
"an",
|
|
55
|
+
"the",
|
|
56
|
+
"is",
|
|
57
|
+
"are",
|
|
58
|
+
"was",
|
|
59
|
+
"were",
|
|
60
|
+
"be",
|
|
61
|
+
"been",
|
|
62
|
+
"being",
|
|
63
|
+
"have",
|
|
64
|
+
"has",
|
|
65
|
+
"had",
|
|
66
|
+
"do",
|
|
67
|
+
"does",
|
|
68
|
+
"did",
|
|
69
|
+
"will",
|
|
70
|
+
"would",
|
|
71
|
+
"could",
|
|
72
|
+
"should",
|
|
73
|
+
"may",
|
|
74
|
+
"might",
|
|
75
|
+
"shall",
|
|
76
|
+
"can",
|
|
77
|
+
"dare",
|
|
78
|
+
"ought",
|
|
79
|
+
"yes",
|
|
80
|
+
"no",
|
|
81
|
+
"not",
|
|
82
|
+
"please",
|
|
83
|
+
"thank",
|
|
84
|
+
"thanks",
|
|
85
|
+
"ok",
|
|
86
|
+
"okay",
|
|
87
|
+
"i",
|
|
88
|
+
"me",
|
|
89
|
+
"my",
|
|
90
|
+
"we",
|
|
91
|
+
"us",
|
|
92
|
+
"our",
|
|
93
|
+
"you",
|
|
94
|
+
"your",
|
|
95
|
+
"it",
|
|
96
|
+
"its",
|
|
97
|
+
"this",
|
|
98
|
+
"that",
|
|
99
|
+
"these",
|
|
100
|
+
"those",
|
|
101
|
+
"and",
|
|
102
|
+
"or",
|
|
103
|
+
"but",
|
|
104
|
+
"if",
|
|
105
|
+
"so",
|
|
106
|
+
"to",
|
|
107
|
+
"of",
|
|
108
|
+
"in",
|
|
109
|
+
"on",
|
|
110
|
+
"at",
|
|
111
|
+
"by",
|
|
112
|
+
"for",
|
|
113
|
+
"from",
|
|
114
|
+
"with",
|
|
115
|
+
"about",
|
|
116
|
+
"into",
|
|
117
|
+
"through",
|
|
118
|
+
"during",
|
|
119
|
+
"before",
|
|
120
|
+
"after",
|
|
121
|
+
"above",
|
|
122
|
+
"below",
|
|
123
|
+
"up",
|
|
124
|
+
"down",
|
|
125
|
+
"out",
|
|
126
|
+
"off",
|
|
127
|
+
"over",
|
|
128
|
+
"under",
|
|
129
|
+
"again",
|
|
130
|
+
"further",
|
|
131
|
+
"then",
|
|
132
|
+
"once",
|
|
133
|
+
"here",
|
|
134
|
+
"there",
|
|
135
|
+
"when",
|
|
136
|
+
"where",
|
|
137
|
+
"why",
|
|
138
|
+
"how",
|
|
139
|
+
"all",
|
|
140
|
+
"both",
|
|
141
|
+
"each",
|
|
142
|
+
"few",
|
|
143
|
+
"more",
|
|
144
|
+
"most",
|
|
145
|
+
"other",
|
|
146
|
+
"some",
|
|
147
|
+
"such",
|
|
148
|
+
"than",
|
|
149
|
+
"too",
|
|
150
|
+
"very",
|
|
151
|
+
"just",
|
|
152
|
+
"now",
|
|
153
|
+
"also",
|
|
154
|
+
"get",
|
|
155
|
+
"let",
|
|
156
|
+
"what",
|
|
157
|
+
"which",
|
|
158
|
+
"who",
|
|
159
|
+
"whom",
|
|
160
|
+
"whose",
|
|
161
|
+
"any",
|
|
162
|
+
"much",
|
|
163
|
+
"many",
|
|
164
|
+
"sounds",
|
|
165
|
+
"good",
|
|
166
|
+
"great",
|
|
167
|
+
"sure",
|
|
168
|
+
"right",
|
|
169
|
+
"well",
|
|
170
|
+
"done",
|
|
171
|
+
"nice",
|
|
172
|
+
"cool",
|
|
173
|
+
"perfect",
|
|
174
|
+
"exactly",
|
|
175
|
+
"proceed",
|
|
176
|
+
"continue",
|
|
177
|
+
"go",
|
|
178
|
+
"ahead",
|
|
179
|
+
"next",
|
|
180
|
+
"help"
|
|
181
|
+
]);
|
|
182
|
+
var MIN_CONTENT_WORDS = 2;
|
|
183
|
+
var MIN_WORD_LEN = 3;
|
|
184
|
+
function extractRecallQuery(prompt) {
|
|
185
|
+
const tokens = prompt.trim().split(/\s+/).map((t) => t.replace(/^[^\w-]+|[^\w-]+$/g, "")).filter((t) => t.length >= MIN_WORD_LEN);
|
|
186
|
+
const contentWords = tokens.filter((t) => !STOPWORDS.has(t.toLowerCase()));
|
|
187
|
+
if (contentWords.length < MIN_CONTENT_WORDS) return null;
|
|
188
|
+
return contentWords.join(" ");
|
|
189
|
+
}
|
|
190
|
+
|
|
51
191
|
// src/hook/recall-over-http.ts
|
|
52
192
|
var RECALL_LIMIT = 5;
|
|
53
193
|
var RECALL_TIMEOUT_MS = 2e3;
|
|
54
194
|
async function recallOverHttp(prompt, runtime) {
|
|
195
|
+
const query = extractRecallQuery(prompt);
|
|
196
|
+
if (query === null) return { hits: [], facts: [] };
|
|
55
197
|
const portValue = process.env["NLM_PORT"] ?? "3940";
|
|
56
|
-
const url = `http://localhost:${portValue}/api/recall?q=${encodeURIComponent(
|
|
198
|
+
const url = `http://localhost:${portValue}/api/recall?q=${encodeURIComponent(query)}&mode=keyword&limit=${RECALL_LIMIT}&withFacts=true`;
|
|
57
199
|
const controller = new AbortController();
|
|
58
200
|
const timer = setTimeout(() => controller.abort(), RECALL_TIMEOUT_MS);
|
|
59
201
|
try {
|
|
@@ -74,7 +216,8 @@ async function recallOverHttp(prompt, runtime) {
|
|
|
74
216
|
id: r.id,
|
|
75
217
|
label: r.label,
|
|
76
218
|
startedAt: r.startedAt,
|
|
77
|
-
matchScore: r.matchScore
|
|
219
|
+
matchScore: r.matchScore,
|
|
220
|
+
...r.summary !== void 0 ? { summary: r.summary } : {}
|
|
78
221
|
}));
|
|
79
222
|
const facts = (body.relatedFacts ?? []).map((f) => ({
|
|
80
223
|
subject: f.subject,
|
|
@@ -158,7 +301,12 @@ function formatPointerBlock(hits, facts = []) {
|
|
|
158
301
|
if (hits.length > 0) {
|
|
159
302
|
out.push("## Possibly-relevant prior sessions (nlm-memory)");
|
|
160
303
|
for (const h of hits) {
|
|
161
|
-
|
|
304
|
+
const datePart = h.startedAt.slice(0, 10);
|
|
305
|
+
if (h.summary) {
|
|
306
|
+
out.push(`- ${h.id} \xB7 ${h.label} (${datePart}) \u2014 ${h.summary.slice(0, 120)}`);
|
|
307
|
+
} else {
|
|
308
|
+
out.push(`- ${h.id} \xB7 ${h.label} (${datePart})`);
|
|
309
|
+
}
|
|
162
310
|
}
|
|
163
311
|
}
|
|
164
312
|
if (facts.length > 0) {
|
package/package.json
CHANGED
|
@@ -70,7 +70,12 @@ function formatPointerBlock(hits, facts = []) {
|
|
|
70
70
|
if (hits.length > 0) {
|
|
71
71
|
out.push("## Possibly-relevant prior sessions (nlm-memory)");
|
|
72
72
|
for (const h of hits) {
|
|
73
|
-
|
|
73
|
+
const datePart = h.startedAt.slice(0, 10);
|
|
74
|
+
if (h.summary) {
|
|
75
|
+
out.push(`- ${h.id} \xB7 ${h.label} (${datePart}) \u2014 ${h.summary.slice(0, 120)}`);
|
|
76
|
+
} else {
|
|
77
|
+
out.push(`- ${h.id} \xB7 ${h.label} (${datePart})`);
|
|
78
|
+
}
|
|
74
79
|
}
|
|
75
80
|
}
|
|
76
81
|
if (facts.length > 0) {
|
|
@@ -148,12 +153,154 @@ function hookAuthHeaders(extra = {}) {
|
|
|
148
153
|
return { ...extra, authorization: `Bearer ${token}` };
|
|
149
154
|
}
|
|
150
155
|
|
|
156
|
+
// src/core/hook/query-extract.ts
|
|
157
|
+
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
158
|
+
"a",
|
|
159
|
+
"an",
|
|
160
|
+
"the",
|
|
161
|
+
"is",
|
|
162
|
+
"are",
|
|
163
|
+
"was",
|
|
164
|
+
"were",
|
|
165
|
+
"be",
|
|
166
|
+
"been",
|
|
167
|
+
"being",
|
|
168
|
+
"have",
|
|
169
|
+
"has",
|
|
170
|
+
"had",
|
|
171
|
+
"do",
|
|
172
|
+
"does",
|
|
173
|
+
"did",
|
|
174
|
+
"will",
|
|
175
|
+
"would",
|
|
176
|
+
"could",
|
|
177
|
+
"should",
|
|
178
|
+
"may",
|
|
179
|
+
"might",
|
|
180
|
+
"shall",
|
|
181
|
+
"can",
|
|
182
|
+
"dare",
|
|
183
|
+
"ought",
|
|
184
|
+
"yes",
|
|
185
|
+
"no",
|
|
186
|
+
"not",
|
|
187
|
+
"please",
|
|
188
|
+
"thank",
|
|
189
|
+
"thanks",
|
|
190
|
+
"ok",
|
|
191
|
+
"okay",
|
|
192
|
+
"i",
|
|
193
|
+
"me",
|
|
194
|
+
"my",
|
|
195
|
+
"we",
|
|
196
|
+
"us",
|
|
197
|
+
"our",
|
|
198
|
+
"you",
|
|
199
|
+
"your",
|
|
200
|
+
"it",
|
|
201
|
+
"its",
|
|
202
|
+
"this",
|
|
203
|
+
"that",
|
|
204
|
+
"these",
|
|
205
|
+
"those",
|
|
206
|
+
"and",
|
|
207
|
+
"or",
|
|
208
|
+
"but",
|
|
209
|
+
"if",
|
|
210
|
+
"so",
|
|
211
|
+
"to",
|
|
212
|
+
"of",
|
|
213
|
+
"in",
|
|
214
|
+
"on",
|
|
215
|
+
"at",
|
|
216
|
+
"by",
|
|
217
|
+
"for",
|
|
218
|
+
"from",
|
|
219
|
+
"with",
|
|
220
|
+
"about",
|
|
221
|
+
"into",
|
|
222
|
+
"through",
|
|
223
|
+
"during",
|
|
224
|
+
"before",
|
|
225
|
+
"after",
|
|
226
|
+
"above",
|
|
227
|
+
"below",
|
|
228
|
+
"up",
|
|
229
|
+
"down",
|
|
230
|
+
"out",
|
|
231
|
+
"off",
|
|
232
|
+
"over",
|
|
233
|
+
"under",
|
|
234
|
+
"again",
|
|
235
|
+
"further",
|
|
236
|
+
"then",
|
|
237
|
+
"once",
|
|
238
|
+
"here",
|
|
239
|
+
"there",
|
|
240
|
+
"when",
|
|
241
|
+
"where",
|
|
242
|
+
"why",
|
|
243
|
+
"how",
|
|
244
|
+
"all",
|
|
245
|
+
"both",
|
|
246
|
+
"each",
|
|
247
|
+
"few",
|
|
248
|
+
"more",
|
|
249
|
+
"most",
|
|
250
|
+
"other",
|
|
251
|
+
"some",
|
|
252
|
+
"such",
|
|
253
|
+
"than",
|
|
254
|
+
"too",
|
|
255
|
+
"very",
|
|
256
|
+
"just",
|
|
257
|
+
"now",
|
|
258
|
+
"also",
|
|
259
|
+
"get",
|
|
260
|
+
"let",
|
|
261
|
+
"what",
|
|
262
|
+
"which",
|
|
263
|
+
"who",
|
|
264
|
+
"whom",
|
|
265
|
+
"whose",
|
|
266
|
+
"any",
|
|
267
|
+
"much",
|
|
268
|
+
"many",
|
|
269
|
+
"sounds",
|
|
270
|
+
"good",
|
|
271
|
+
"great",
|
|
272
|
+
"sure",
|
|
273
|
+
"right",
|
|
274
|
+
"well",
|
|
275
|
+
"done",
|
|
276
|
+
"nice",
|
|
277
|
+
"cool",
|
|
278
|
+
"perfect",
|
|
279
|
+
"exactly",
|
|
280
|
+
"proceed",
|
|
281
|
+
"continue",
|
|
282
|
+
"go",
|
|
283
|
+
"ahead",
|
|
284
|
+
"next",
|
|
285
|
+
"help"
|
|
286
|
+
]);
|
|
287
|
+
var MIN_CONTENT_WORDS = 2;
|
|
288
|
+
var MIN_WORD_LEN = 3;
|
|
289
|
+
function extractRecallQuery(prompt) {
|
|
290
|
+
const tokens = prompt.trim().split(/\s+/).map((t) => t.replace(/^[^\w-]+|[^\w-]+$/g, "")).filter((t) => t.length >= MIN_WORD_LEN);
|
|
291
|
+
const contentWords = tokens.filter((t) => !STOPWORDS.has(t.toLowerCase()));
|
|
292
|
+
if (contentWords.length < MIN_CONTENT_WORDS) return null;
|
|
293
|
+
return contentWords.join(" ");
|
|
294
|
+
}
|
|
295
|
+
|
|
151
296
|
// src/hook/recall-over-http.ts
|
|
152
297
|
var RECALL_LIMIT = 5;
|
|
153
298
|
var RECALL_TIMEOUT_MS = 2e3;
|
|
154
299
|
async function recallOverHttp(prompt, runtime) {
|
|
300
|
+
const query = extractRecallQuery(prompt);
|
|
301
|
+
if (query === null) return { hits: [], facts: [] };
|
|
155
302
|
const portValue = process.env["NLM_PORT"] ?? "3940";
|
|
156
|
-
const url = `http://localhost:${portValue}/api/recall?q=${encodeURIComponent(
|
|
303
|
+
const url = `http://localhost:${portValue}/api/recall?q=${encodeURIComponent(query)}&mode=keyword&limit=${RECALL_LIMIT}&withFacts=true`;
|
|
157
304
|
const controller = new AbortController();
|
|
158
305
|
const timer = setTimeout(() => controller.abort(), RECALL_TIMEOUT_MS);
|
|
159
306
|
try {
|
|
@@ -174,7 +321,8 @@ async function recallOverHttp(prompt, runtime) {
|
|
|
174
321
|
id: r.id,
|
|
175
322
|
label: r.label,
|
|
176
323
|
startedAt: r.startedAt,
|
|
177
|
-
matchScore: r.matchScore
|
|
324
|
+
matchScore: r.matchScore,
|
|
325
|
+
...r.summary !== void 0 ? { summary: r.summary } : {}
|
|
178
326
|
}));
|
|
179
327
|
const facts = (body.relatedFacts ?? []).map((f) => ({
|
|
180
328
|
subject: f.subject,
|