mnueron 0.4.0 → 0.6.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/INSTALL.md +125 -0
- package/LICENSE +28 -21
- package/NOTICE +164 -0
- package/README.md +443 -422
- package/dist/cli.js +114 -26
- package/dist/cli.js.map +1 -1
- package/dist/config.js +4 -1
- package/dist/config.js.map +1 -1
- package/dist/detectors/codex.js +138 -0
- package/dist/detectors/codex.js.map +1 -0
- package/dist/detectors/index.js +2 -0
- package/dist/detectors/index.js.map +1 -1
- package/dist/detectors/json_detector.js +1 -1
- package/dist/lib/context-engine/confidence.js +153 -0
- package/dist/lib/context-engine/confidence.js.map +1 -0
- package/dist/lib/context-engine/entities.js +179 -0
- package/dist/lib/context-engine/entities.js.map +1 -0
- package/dist/lib/context-engine/index.js +74 -0
- package/dist/lib/context-engine/index.js.map +1 -0
- package/dist/lib/context-engine/intent.js +139 -0
- package/dist/lib/context-engine/intent.js.map +1 -0
- package/dist/lib/context-engine/runbook-detector.js +206 -0
- package/dist/lib/context-engine/runbook-detector.js.map +1 -0
- package/dist/lib/date-anchors.js +351 -0
- package/dist/lib/date-anchors.js.map +1 -0
- package/dist/lib/temporal-intent.js +98 -0
- package/dist/lib/temporal-intent.js.map +1 -0
- package/dist/runbook/auto-extract.js +415 -0
- package/dist/runbook/auto-extract.js.map +1 -0
- package/dist/runbook/capture.js +214 -0
- package/dist/runbook/capture.js.map +1 -0
- package/dist/runbook/explain.js +154 -0
- package/dist/runbook/explain.js.map +1 -0
- package/dist/runbook/fingerprint.js +128 -0
- package/dist/runbook/fingerprint.js.map +1 -0
- package/dist/runbook/search.js +76 -0
- package/dist/runbook/search.js.map +1 -0
- package/dist/runbook/types.js +15 -0
- package/dist/runbook/types.js.map +1 -0
- package/dist/setup.js +32 -4
- package/dist/setup.js.map +1 -1
- package/dist/store/entity-extractor.js +69 -2
- package/dist/store/entity-extractor.js.map +1 -1
- package/dist/store/local-db.js +33 -0
- package/dist/store/local-db.js.map +1 -0
- package/dist/store/local.js +230 -229
- package/dist/store/local.js.map +1 -1
- package/dist/store/procedural.js +185 -0
- package/dist/store/procedural.js.map +1 -1
- package/dist/store/remote.js +73 -0
- package/dist/store/remote.js.map +1 -1
- package/dist/tools.js +393 -8
- package/dist/tools.js.map +1 -1
- package/package.json +63 -55
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date-anchor extraction from natural-language text.
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - LocalProvider.save() — Tier 3: stamps extracted anchors as
|
|
6
|
+
* metadata.temporal_anchors at ingestion time, so retrieval can
|
|
7
|
+
* answer "when did X happen" without LLM-side date arithmetic.
|
|
8
|
+
* - Benchmark adapter — Tier 4: extracts anchor from the QUERY,
|
|
9
|
+
* re-ranks retrieved memories by proximity to it.
|
|
10
|
+
* - LocalProvider.search() (future) — Tier 2: temporal-intent boost.
|
|
11
|
+
*
|
|
12
|
+
* Scope (intentional limits):
|
|
13
|
+
* - English-only patterns. The LoCoMo benchmark + Claude/ChatGPT
|
|
14
|
+
* dialogs are overwhelmingly English; non-English support is a
|
|
15
|
+
* separate hard problem and not on the roadmap.
|
|
16
|
+
* - Regex-only (no LLM call). Tradeoff: lower recall on weird
|
|
17
|
+
* phrasings like "the spring before last", but ~5 ms per extraction
|
|
18
|
+
* vs $0.0001 per LLM call. For a 700-memory session that's the
|
|
19
|
+
* difference between 3.5s of CPU and $0.07.
|
|
20
|
+
* - Year-disambiguation uses the anchor date as "now". A phrase like
|
|
21
|
+
* "last March" resolves relative to when the memory was saved.
|
|
22
|
+
*
|
|
23
|
+
* Returns absolute epoch-ms timestamps per anchor so downstream code
|
|
24
|
+
* doesn't have to re-parse anything. Each anchor preserves the original
|
|
25
|
+
* phrase for explainability ("matched 'last March' in memory X").
|
|
26
|
+
*/
|
|
27
|
+
// ─── Month + day vocabulary ───────────────────────────────────────────────
|
|
28
|
+
const MONTHS = {
|
|
29
|
+
january: 0, jan: 0,
|
|
30
|
+
february: 1, feb: 1,
|
|
31
|
+
march: 2, mar: 2,
|
|
32
|
+
april: 3, apr: 3,
|
|
33
|
+
may: 4,
|
|
34
|
+
june: 5, jun: 5,
|
|
35
|
+
july: 6, jul: 6,
|
|
36
|
+
august: 7, aug: 7,
|
|
37
|
+
september: 8, sep: 8, sept: 8,
|
|
38
|
+
october: 9, oct: 9,
|
|
39
|
+
november: 10, nov: 10,
|
|
40
|
+
december: 11, dec: 11,
|
|
41
|
+
};
|
|
42
|
+
const WEEKDAYS = {
|
|
43
|
+
sunday: 0, sun: 0,
|
|
44
|
+
monday: 1, mon: 1,
|
|
45
|
+
tuesday: 2, tue: 2, tues: 2,
|
|
46
|
+
wednesday: 3, wed: 3,
|
|
47
|
+
thursday: 4, thu: 4, thur: 4, thurs: 4,
|
|
48
|
+
friday: 5, fri: 5,
|
|
49
|
+
saturday: 6, sat: 6,
|
|
50
|
+
};
|
|
51
|
+
const RELATIVE_UNIT_MS = {
|
|
52
|
+
second: 1000, seconds: 1000, sec: 1000, secs: 1000,
|
|
53
|
+
minute: 60_000, minutes: 60_000, min: 60_000, mins: 60_000,
|
|
54
|
+
hour: 3_600_000, hours: 3_600_000, hr: 3_600_000, hrs: 3_600_000,
|
|
55
|
+
day: 86_400_000, days: 86_400_000,
|
|
56
|
+
week: 604_800_000, weeks: 604_800_000, wk: 604_800_000, wks: 604_800_000,
|
|
57
|
+
month: 2_629_800_000, months: 2_629_800_000, // ~30.44 days
|
|
58
|
+
year: 31_557_600_000, years: 31_557_600_000, // 365.25 days
|
|
59
|
+
};
|
|
60
|
+
const NUMBER_WORDS = {
|
|
61
|
+
one: 1, two: 2, three: 3, four: 4, five: 5,
|
|
62
|
+
six: 6, seven: 7, eight: 8, nine: 9, ten: 10,
|
|
63
|
+
eleven: 11, twelve: 12, dozen: 12,
|
|
64
|
+
a: 1, an: 1, // "a week ago" = 1 week
|
|
65
|
+
};
|
|
66
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
67
|
+
/**
|
|
68
|
+
* Extract every date phrase from `text` and resolve to absolute epoch-ms.
|
|
69
|
+
*
|
|
70
|
+
* `anchor` is the reference time for relative phrases. If a memory was
|
|
71
|
+
* saved on 2024-05-15 and contains "last March", anchor=2024-05-15 →
|
|
72
|
+
* resolved="2024-03 (i.e. 3 months ago)". If anchor is omitted, defaults
|
|
73
|
+
* to Date.now().
|
|
74
|
+
*
|
|
75
|
+
* Returns anchors sorted by resolved_ms ascending. Empty array if none found.
|
|
76
|
+
*/
|
|
77
|
+
export function extractDateAnchors(text, anchor) {
|
|
78
|
+
if (!text)
|
|
79
|
+
return [];
|
|
80
|
+
const anchorDate = anchor instanceof Date
|
|
81
|
+
? anchor
|
|
82
|
+
: new Date(typeof anchor === 'number' ? anchor : Date.now());
|
|
83
|
+
const out = [];
|
|
84
|
+
const seenSpans = new Set(); // dedup by exact-phrase span
|
|
85
|
+
for (const fn of [
|
|
86
|
+
extractIsoDates,
|
|
87
|
+
extractNumericDates,
|
|
88
|
+
extractWrittenDates,
|
|
89
|
+
extractAbsoluteMonths,
|
|
90
|
+
extractQuarters,
|
|
91
|
+
extractRelativeNAgo,
|
|
92
|
+
extractRelativeUnit,
|
|
93
|
+
extractWeekdays,
|
|
94
|
+
]) {
|
|
95
|
+
for (const anch of fn(text, anchorDate)) {
|
|
96
|
+
const key = `${anch.phrase}@${anch.resolved_ms}`;
|
|
97
|
+
if (seenSpans.has(key))
|
|
98
|
+
continue;
|
|
99
|
+
seenSpans.add(key);
|
|
100
|
+
out.push(anch);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
out.sort((a, b) => a.resolved_ms - b.resolved_ms);
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
// ─── Extractors ───────────────────────────────────────────────────────────
|
|
107
|
+
/** ISO 8601: 2024-03-15 or 2024-03-15T10:30:00Z. */
|
|
108
|
+
function extractIsoDates(text, _anchor) {
|
|
109
|
+
const out = [];
|
|
110
|
+
const re = /\b(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2}))?(?:Z|[+-]\d{2}:?\d{2})?)?\b/g;
|
|
111
|
+
let m;
|
|
112
|
+
while ((m = re.exec(text))) {
|
|
113
|
+
const [, y, mo, d, hh, mm, ss] = m;
|
|
114
|
+
const ms = Date.UTC(+y, +mo - 1, +d, +(hh ?? 0), +(mm ?? 0), +(ss ?? 0));
|
|
115
|
+
if (!Number.isFinite(ms))
|
|
116
|
+
continue;
|
|
117
|
+
out.push({
|
|
118
|
+
phrase: m[0],
|
|
119
|
+
resolved_ms: ms,
|
|
120
|
+
kind: 'absolute-date',
|
|
121
|
+
confidence: 0.99,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
/** MM/DD/YYYY or M/D/YY (US-style; ambiguous DD/MM/YY accepted with lower conf). */
|
|
127
|
+
function extractNumericDates(text, _anchor) {
|
|
128
|
+
const out = [];
|
|
129
|
+
// 5/15/24, 05/15/2024
|
|
130
|
+
const re = /\b(\d{1,2})\/(\d{1,2})\/(\d{2,4})\b/g;
|
|
131
|
+
let m;
|
|
132
|
+
while ((m = re.exec(text))) {
|
|
133
|
+
let [, a, b, y] = m;
|
|
134
|
+
let yy = +y;
|
|
135
|
+
if (yy < 100)
|
|
136
|
+
yy += yy >= 50 ? 1900 : 2000;
|
|
137
|
+
// Assume US MM/DD ordering. If first part > 12, assume DD/MM (less common).
|
|
138
|
+
let month = +a - 1;
|
|
139
|
+
let day = +b;
|
|
140
|
+
if (+a > 12) {
|
|
141
|
+
month = +b - 1;
|
|
142
|
+
day = +a;
|
|
143
|
+
}
|
|
144
|
+
if (month < 0 || month > 11 || day < 1 || day > 31)
|
|
145
|
+
continue;
|
|
146
|
+
const ms = Date.UTC(yy, month, day);
|
|
147
|
+
out.push({
|
|
148
|
+
phrase: m[0],
|
|
149
|
+
resolved_ms: ms,
|
|
150
|
+
kind: 'absolute-date',
|
|
151
|
+
confidence: +a > 12 ? 0.7 : 0.85,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
/** "March 15, 2024", "Mar 15 2024", "15 March 2024", "15th of March 2024". */
|
|
157
|
+
function extractWrittenDates(text, _anchor) {
|
|
158
|
+
const out = [];
|
|
159
|
+
const monthAlt = Object.keys(MONTHS).join('|');
|
|
160
|
+
// "March 15, 2024" / "March 15 2024" / "Mar 15th, 2024"
|
|
161
|
+
const re1 = new RegExp(`\\b(${monthAlt})\\s+(\\d{1,2})(?:st|nd|rd|th)?,?\\s+(\\d{4})\\b`, 'gi');
|
|
162
|
+
for (let m; (m = re1.exec(text));) {
|
|
163
|
+
const mo = MONTHS[m[1].toLowerCase()];
|
|
164
|
+
const d = +m[2];
|
|
165
|
+
const y = +m[3];
|
|
166
|
+
if (mo == null || d < 1 || d > 31)
|
|
167
|
+
continue;
|
|
168
|
+
out.push({
|
|
169
|
+
phrase: m[0],
|
|
170
|
+
resolved_ms: Date.UTC(y, mo, d),
|
|
171
|
+
kind: 'absolute-date',
|
|
172
|
+
confidence: 0.95,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// "15 March 2024" / "15th of March, 2024"
|
|
176
|
+
const re2 = new RegExp(`\\b(\\d{1,2})(?:st|nd|rd|th)?\\s+(?:of\\s+)?(${monthAlt})(?:,?\\s+(\\d{4}))?\\b`, 'gi');
|
|
177
|
+
for (let m; (m = re2.exec(text));) {
|
|
178
|
+
const d = +m[1];
|
|
179
|
+
const mo = MONTHS[m[2].toLowerCase()];
|
|
180
|
+
const y = m[3] ? +m[3] : new Date().getUTCFullYear();
|
|
181
|
+
if (mo == null || d < 1 || d > 31)
|
|
182
|
+
continue;
|
|
183
|
+
out.push({
|
|
184
|
+
phrase: m[0],
|
|
185
|
+
resolved_ms: Date.UTC(y, mo, d),
|
|
186
|
+
kind: 'absolute-date',
|
|
187
|
+
confidence: m[3] ? 0.92 : 0.7,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
/** "March 2024", "in March 2024", "March of 2024". */
|
|
193
|
+
function extractAbsoluteMonths(text, _anchor) {
|
|
194
|
+
const out = [];
|
|
195
|
+
const monthAlt = Object.keys(MONTHS).join('|');
|
|
196
|
+
const re = new RegExp(`\\b(?:in\\s+|of\\s+)?(${monthAlt})(?:\\s+of)?\\s+(\\d{4})\\b`, 'gi');
|
|
197
|
+
for (let m; (m = re.exec(text));) {
|
|
198
|
+
const mo = MONTHS[m[1].toLowerCase()];
|
|
199
|
+
const y = +m[2];
|
|
200
|
+
out.push({
|
|
201
|
+
phrase: m[0],
|
|
202
|
+
resolved_ms: Date.UTC(y, mo, 1),
|
|
203
|
+
kind: 'absolute-month',
|
|
204
|
+
confidence: 0.9,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
}
|
|
209
|
+
/** "Q1 2024", "Q2 of 2024". */
|
|
210
|
+
function extractQuarters(text, _anchor) {
|
|
211
|
+
const out = [];
|
|
212
|
+
const re = /\bq([1-4])(?:\s+(?:of\s+)?(\d{4}))?\b/gi;
|
|
213
|
+
for (let m; (m = re.exec(text));) {
|
|
214
|
+
const q = +m[1];
|
|
215
|
+
const y = m[2] ? +m[2] : new Date().getUTCFullYear();
|
|
216
|
+
const month = (q - 1) * 3;
|
|
217
|
+
out.push({
|
|
218
|
+
phrase: m[0],
|
|
219
|
+
resolved_ms: Date.UTC(y, month, 1),
|
|
220
|
+
kind: 'quarter',
|
|
221
|
+
confidence: m[2] ? 0.9 : 0.65,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
/** "two weeks ago", "3 days ago", "a month ago". */
|
|
227
|
+
function extractRelativeNAgo(text, anchor) {
|
|
228
|
+
const out = [];
|
|
229
|
+
const unitAlt = Object.keys(RELATIVE_UNIT_MS).join('|');
|
|
230
|
+
const numAlt = Object.keys(NUMBER_WORDS).join('|');
|
|
231
|
+
const re = new RegExp(`\\b(\\d+|${numAlt})\\s+(${unitAlt})\\s+ago\\b`, 'gi');
|
|
232
|
+
for (let m; (m = re.exec(text));) {
|
|
233
|
+
const numStr = m[1].toLowerCase();
|
|
234
|
+
const n = NUMBER_WORDS[numStr] ?? +numStr;
|
|
235
|
+
if (!Number.isFinite(n))
|
|
236
|
+
continue;
|
|
237
|
+
const unitMs = RELATIVE_UNIT_MS[m[2].toLowerCase()];
|
|
238
|
+
if (unitMs == null)
|
|
239
|
+
continue;
|
|
240
|
+
const ms = anchor.getTime() - n * unitMs;
|
|
241
|
+
out.push({
|
|
242
|
+
phrase: m[0],
|
|
243
|
+
resolved_ms: ms,
|
|
244
|
+
kind: 'relative',
|
|
245
|
+
confidence: 0.85,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
250
|
+
/** "yesterday", "today", "tomorrow", "last week", "last month", "last March". */
|
|
251
|
+
function extractRelativeUnit(text, anchor) {
|
|
252
|
+
const out = [];
|
|
253
|
+
// yesterday / today / tomorrow
|
|
254
|
+
for (const m of text.matchAll(/\b(yesterday|today|tomorrow|tonight)\b/gi)) {
|
|
255
|
+
const word = m[1].toLowerCase();
|
|
256
|
+
const offset = word === 'yesterday' ? -1 : word === 'tomorrow' ? +1 : 0;
|
|
257
|
+
const d = new Date(anchor);
|
|
258
|
+
d.setUTCDate(d.getUTCDate() + offset);
|
|
259
|
+
d.setUTCHours(word === 'tonight' ? 20 : 12, 0, 0, 0);
|
|
260
|
+
out.push({
|
|
261
|
+
phrase: m[0],
|
|
262
|
+
resolved_ms: d.getTime(),
|
|
263
|
+
kind: 'relative',
|
|
264
|
+
confidence: 0.9,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
// last week / last month / last year / next week / etc.
|
|
268
|
+
for (const m of text.matchAll(/\b(last|next|this|previous|past)\s+(week|month|year)\b/gi)) {
|
|
269
|
+
const dir = m[1].toLowerCase();
|
|
270
|
+
const unit = m[2].toLowerCase();
|
|
271
|
+
const sign = dir === 'next' ? +1 : dir === 'this' ? 0 : -1;
|
|
272
|
+
const ms = RELATIVE_UNIT_MS[unit] ?? 0;
|
|
273
|
+
out.push({
|
|
274
|
+
phrase: m[0],
|
|
275
|
+
resolved_ms: anchor.getTime() + sign * ms,
|
|
276
|
+
kind: 'relative',
|
|
277
|
+
confidence: 0.8,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
// last March / next March / etc. — resolves to nearest March in that direction
|
|
281
|
+
const monthAlt = Object.keys(MONTHS).join('|');
|
|
282
|
+
const reMonth = new RegExp(`\\b(last|next|this|previous)\\s+(${monthAlt})\\b`, 'gi');
|
|
283
|
+
for (let m; (m = reMonth.exec(text));) {
|
|
284
|
+
const dir = m[1].toLowerCase();
|
|
285
|
+
const mo = MONTHS[m[2].toLowerCase()];
|
|
286
|
+
const y = anchor.getUTCFullYear();
|
|
287
|
+
const curMo = anchor.getUTCMonth();
|
|
288
|
+
let resolvedYear = y;
|
|
289
|
+
if (dir === 'last' || dir === 'previous') {
|
|
290
|
+
resolvedYear = mo < curMo ? y : y - 1;
|
|
291
|
+
}
|
|
292
|
+
else if (dir === 'next') {
|
|
293
|
+
resolvedYear = mo > curMo ? y : y + 1;
|
|
294
|
+
} // this March → current year
|
|
295
|
+
out.push({
|
|
296
|
+
phrase: m[0],
|
|
297
|
+
resolved_ms: Date.UTC(resolvedYear, mo, 1),
|
|
298
|
+
kind: 'relative',
|
|
299
|
+
confidence: 0.85,
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return out;
|
|
303
|
+
}
|
|
304
|
+
/** "Monday", "last Monday", "Tuesday" — anchored against `anchor`. */
|
|
305
|
+
function extractWeekdays(text, anchor) {
|
|
306
|
+
const out = [];
|
|
307
|
+
const dayAlt = Object.keys(WEEKDAYS).join('|');
|
|
308
|
+
// Only match standalone weekdays preceded by "last", "next", "this", or "on"
|
|
309
|
+
// to avoid false positives on every "Monday" mention.
|
|
310
|
+
const re = new RegExp(`\\b(?:(last|next|this|on)\\s+)?(${dayAlt})\\b`, 'gi');
|
|
311
|
+
for (let m; (m = re.exec(text));) {
|
|
312
|
+
const dir = (m[1] ?? '').toLowerCase();
|
|
313
|
+
if (!dir)
|
|
314
|
+
continue; // skip standalone "Monday" without context
|
|
315
|
+
const targetDay = WEEKDAYS[m[2].toLowerCase()];
|
|
316
|
+
const curDay = anchor.getUTCDay();
|
|
317
|
+
const diff = targetDay - curDay;
|
|
318
|
+
let offsetDays = dir === 'next' ? (diff <= 0 ? diff + 7 : diff) :
|
|
319
|
+
dir === 'last' ? (diff >= 0 ? diff - 7 : diff) :
|
|
320
|
+
diff; // "this Monday" / "on Monday"
|
|
321
|
+
const d = new Date(anchor);
|
|
322
|
+
d.setUTCDate(d.getUTCDate() + offsetDays);
|
|
323
|
+
d.setUTCHours(12, 0, 0, 0);
|
|
324
|
+
out.push({
|
|
325
|
+
phrase: m[0],
|
|
326
|
+
resolved_ms: d.getTime(),
|
|
327
|
+
kind: 'day-of-week',
|
|
328
|
+
confidence: 0.75,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
return out;
|
|
332
|
+
}
|
|
333
|
+
// ─── Query-side helpers ───────────────────────────────────────────────────
|
|
334
|
+
/**
|
|
335
|
+
* Returns the single most-likely time anchor from a question.
|
|
336
|
+
*
|
|
337
|
+
* "When did Sarah change jobs last March?" → the "last March" anchor.
|
|
338
|
+
* "How long ago did the meeting happen?" → null (no anchor present).
|
|
339
|
+
*
|
|
340
|
+
* Used by the benchmark adapter to bias retrieval toward memories near
|
|
341
|
+
* the query's time reference. If multiple anchors are present, prefers
|
|
342
|
+
* the most specific (highest confidence).
|
|
343
|
+
*/
|
|
344
|
+
export function extractQueryAnchor(query, now) {
|
|
345
|
+
const anchors = extractDateAnchors(query, now);
|
|
346
|
+
if (anchors.length === 0)
|
|
347
|
+
return null;
|
|
348
|
+
// Prefer highest confidence; break ties by latest in text.
|
|
349
|
+
return anchors.slice().sort((a, b) => b.confidence - a.confidence)[0];
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=date-anchors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-anchors.js","sourceRoot":"","sources":["../../src/lib/date-anchors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporal-intent classifier for queries.
|
|
3
|
+
*
|
|
4
|
+
* A query is "temporal" if answering it requires reasoning about WHEN
|
|
5
|
+
* something happened, not just WHAT. Examples:
|
|
6
|
+
*
|
|
7
|
+
* "When did Sarah change jobs?" ← yes (explicit "when")
|
|
8
|
+
* "How long ago was the meeting?" ← yes (duration)
|
|
9
|
+
* "What did Sarah do in March?" ← yes (month anchor)
|
|
10
|
+
* "Before or after Tuesday?" ← yes (relational)
|
|
11
|
+
* "What did Sarah say about hiking?" ← no (purely semantic)
|
|
12
|
+
*
|
|
13
|
+
* Temporal queries benefit from:
|
|
14
|
+
* - Tier 2: timestamp-aware retrieval ranking (boost time-proximate memories)
|
|
15
|
+
* - Tier 4: chronological re-sort + anchor-proximity re-rank
|
|
16
|
+
*
|
|
17
|
+
* Non-temporal queries skip the temporal machinery entirely.
|
|
18
|
+
*
|
|
19
|
+
* Returns a structured TemporalIntent with:
|
|
20
|
+
* - `isTemporal`: boolean gate
|
|
21
|
+
* - `kind`: what KIND of temporal (when / duration / ordering / range)
|
|
22
|
+
* - `anchor`: extracted query time reference, if any (via date-anchors.ts)
|
|
23
|
+
*
|
|
24
|
+
* Pure module — no I/O, no DB. Trivially unit-testable.
|
|
25
|
+
*/
|
|
26
|
+
import { extractQueryAnchor } from './date-anchors.js';
|
|
27
|
+
// Strong markers — presence flips isTemporal=true with high confidence.
|
|
28
|
+
const TRIGGER_PATTERNS = [
|
|
29
|
+
// "when did X happen", "when was Y"
|
|
30
|
+
{ re: /\bwhen\b/i, kind: 'when' },
|
|
31
|
+
// "how long ago", "how many days/weeks/months/years"
|
|
32
|
+
{ re: /\bhow\s+long\b/i, kind: 'duration' },
|
|
33
|
+
{ re: /\bhow\s+many\s+(?:days|weeks|months|years|hours|minutes)\b/i, kind: 'duration' },
|
|
34
|
+
{ re: /\bago\b/i, kind: 'duration' },
|
|
35
|
+
// ordering
|
|
36
|
+
{ re: /\bbefore\b/i, kind: 'ordering' },
|
|
37
|
+
{ re: /\bafter\b/i, kind: 'ordering' },
|
|
38
|
+
{ re: /\bprior\s+to\b/i, kind: 'ordering' },
|
|
39
|
+
{ re: /\bfirst\s+(?:time|did|was|met|said|asked)\b/i, kind: 'ordering' },
|
|
40
|
+
{ re: /\blast\s+(?:time|did|was|met|said|asked)\b/i, kind: 'ordering' },
|
|
41
|
+
{ re: /\bearliest\b/i, kind: 'ordering' },
|
|
42
|
+
{ re: /\blatest\b/i, kind: 'ordering' },
|
|
43
|
+
// range
|
|
44
|
+
{ re: /\bbetween\s+\w+\s+and\s+\w+\b/i, kind: 'range' },
|
|
45
|
+
{ re: /\bsince\s+(?:\w+|the)\b/i, kind: 'range' },
|
|
46
|
+
// explicit date/month mentions — weaker, only counts if no other signal yet
|
|
47
|
+
{ re: /\b(?:january|february|march|april|may|june|july|august|september|october|november|december)\b/i, kind: 'date-mention' },
|
|
48
|
+
{ re: /\b(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday)\b/i, kind: 'date-mention' },
|
|
49
|
+
{ re: /\b(?:yesterday|today|tomorrow|tonight)\b/i, kind: 'date-mention' },
|
|
50
|
+
];
|
|
51
|
+
export function classifyTemporal(query, now) {
|
|
52
|
+
if (!query) {
|
|
53
|
+
return { isTemporal: false, kind: null, anchor: null, triggers: [] };
|
|
54
|
+
}
|
|
55
|
+
const triggers = [];
|
|
56
|
+
let strongestKind = null;
|
|
57
|
+
for (const { re, kind } of TRIGGER_PATTERNS) {
|
|
58
|
+
const m = re.exec(query);
|
|
59
|
+
if (!m)
|
|
60
|
+
continue;
|
|
61
|
+
triggers.push(m[0].toLowerCase());
|
|
62
|
+
// Priority: when > ordering > duration > range > date-mention.
|
|
63
|
+
// Use first-match-wins by priority order in the array.
|
|
64
|
+
if (strongestKind === null)
|
|
65
|
+
strongestKind = kind;
|
|
66
|
+
}
|
|
67
|
+
const anchor = extractQueryAnchor(query, now);
|
|
68
|
+
return {
|
|
69
|
+
isTemporal: strongestKind !== null,
|
|
70
|
+
kind: strongestKind,
|
|
71
|
+
anchor,
|
|
72
|
+
triggers,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Convenience: just the boolean gate, for places that don't need
|
|
77
|
+
* the full classifier output.
|
|
78
|
+
*/
|
|
79
|
+
export function isTemporalQuery(query) {
|
|
80
|
+
return classifyTemporal(query).isTemporal;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Compute a proximity score [0..1] between a memory and a query anchor.
|
|
84
|
+
* 1.0 = same timestamp; decays with distance using a half-life schedule.
|
|
85
|
+
*
|
|
86
|
+
* Half-life is 30 days by default — most LoCoMo conversations span weeks,
|
|
87
|
+
* so memories within ~1 month of the query anchor get strong boosts.
|
|
88
|
+
*
|
|
89
|
+
* Used by Tier 4 re-rank.
|
|
90
|
+
*/
|
|
91
|
+
export function temporalProximityScore(memoryTs, queryAnchor, halfLifeMs = 30 * 24 * 60 * 60 * 1000) {
|
|
92
|
+
if (!memoryTs || !queryAnchor)
|
|
93
|
+
return 0;
|
|
94
|
+
const distMs = Math.abs(memoryTs - queryAnchor.resolved_ms);
|
|
95
|
+
// Exponential decay: score = 0.5^(dist/halfLife)
|
|
96
|
+
return Math.pow(0.5, distMs / halfLifeMs);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=temporal-intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temporal-intent.js","sourceRoot":"","sources":["../../src/lib/temporal-intent.ts"],"names":[],"mappings":"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"}
|