clawvault 1.9.2 → 1.9.3
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-S3TOK4VI.js → chunk-AVPHNEDB.js} +42 -58
- package/dist/{chunk-PBLNXOPM.js → chunk-EQ2AZVBX.js} +118 -8
- package/dist/{chunk-P3KFRS2W.js → chunk-JATU7JVY.js} +33 -3
- package/dist/commands/context.js +1 -1
- package/dist/commands/observe.js +2 -2
- package/dist/commands/sleep.js +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +3 -3
- package/package.json +1 -1
|
@@ -58,33 +58,6 @@ function estimateTokens(text) {
|
|
|
58
58
|
}
|
|
59
59
|
return Math.ceil(text.length / 4);
|
|
60
60
|
}
|
|
61
|
-
function fitWithinBudget(items, budget) {
|
|
62
|
-
if (!Number.isFinite(budget) || budget <= 0) {
|
|
63
|
-
return [];
|
|
64
|
-
}
|
|
65
|
-
const sorted = items.map((item, index) => ({ ...item, index })).sort((a, b) => {
|
|
66
|
-
if (a.priority !== b.priority) {
|
|
67
|
-
return a.priority - b.priority;
|
|
68
|
-
}
|
|
69
|
-
return a.index - b.index;
|
|
70
|
-
});
|
|
71
|
-
let remaining = Math.floor(budget);
|
|
72
|
-
const fitted = [];
|
|
73
|
-
for (const item of sorted) {
|
|
74
|
-
if (!item.text.trim()) {
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
const cost = estimateTokens(item.text);
|
|
78
|
-
if (cost <= remaining) {
|
|
79
|
-
fitted.push({ text: item.text, source: item.source });
|
|
80
|
-
remaining -= cost;
|
|
81
|
-
}
|
|
82
|
-
if (remaining <= 0) {
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return fitted;
|
|
87
|
-
}
|
|
88
61
|
|
|
89
62
|
// src/commands/context.ts
|
|
90
63
|
var DEFAULT_LIMIT = 5;
|
|
@@ -223,12 +196,8 @@ async function buildDailyContextItems(vault) {
|
|
|
223
196
|
}
|
|
224
197
|
const relativePath = path2.relative(vault.getPath(), document.path).split(path2.sep).join("/");
|
|
225
198
|
const snippet = estimateSnippet(document.content);
|
|
226
|
-
const sourceId = `daily:${date}:${relativePath}`;
|
|
227
199
|
items.push({
|
|
228
200
|
priority: 2,
|
|
229
|
-
source: sourceId,
|
|
230
|
-
text: `${date}
|
|
231
|
-
${snippet}`,
|
|
232
201
|
entry: {
|
|
233
202
|
title: `Daily note ${date}`,
|
|
234
203
|
path: relativePath,
|
|
@@ -247,17 +216,13 @@ function buildObservationContextItems(vaultPath) {
|
|
|
247
216
|
const observationMarkdown = readObservations(vaultPath, OBSERVATION_LOOKBACK_DAYS);
|
|
248
217
|
const parsed = parseObservationLines(observationMarkdown);
|
|
249
218
|
const items = [];
|
|
250
|
-
for (const
|
|
219
|
+
for (const observation of parsed) {
|
|
251
220
|
const priority = observationPriorityToRank(observation.priority);
|
|
252
221
|
const modifiedDate = asDate(observation.date, /* @__PURE__ */ new Date());
|
|
253
222
|
const date = observation.date || modifiedDate.toISOString().slice(0, 10);
|
|
254
223
|
const snippet = estimateSnippet(observation.content);
|
|
255
|
-
const sourceId = `observation:${priority}:${date}:${index}`;
|
|
256
224
|
items.push({
|
|
257
225
|
priority,
|
|
258
|
-
source: sourceId,
|
|
259
|
-
text: `${observation.priority} ${date}
|
|
260
|
-
${snippet}`,
|
|
261
226
|
entry: {
|
|
262
227
|
title: `${observation.priority} observation (${date})`,
|
|
263
228
|
path: `observations/${date}.md`,
|
|
@@ -273,7 +238,7 @@ ${snippet}`,
|
|
|
273
238
|
return items;
|
|
274
239
|
}
|
|
275
240
|
function buildSearchContextItems(vault, results) {
|
|
276
|
-
return results.map((result
|
|
241
|
+
return results.map((result) => {
|
|
277
242
|
const relativePath = path2.relative(vault.getPath(), result.document.path).split(path2.sep).join("/");
|
|
278
243
|
const entry = {
|
|
279
244
|
title: result.document.title,
|
|
@@ -287,34 +252,53 @@ function buildSearchContextItems(vault, results) {
|
|
|
287
252
|
};
|
|
288
253
|
return {
|
|
289
254
|
priority: 3,
|
|
290
|
-
source: `search:${index}:${entry.path}`,
|
|
291
|
-
text: `${entry.title}
|
|
292
|
-
${entry.snippet}`,
|
|
293
255
|
entry
|
|
294
256
|
};
|
|
295
257
|
});
|
|
296
258
|
}
|
|
297
|
-
function
|
|
259
|
+
function renderEntryBlock(entry) {
|
|
260
|
+
return `### ${entry.title} (${entry.source}, score: ${entry.score.toFixed(2)}, ${entry.age})
|
|
261
|
+
${entry.snippet}
|
|
262
|
+
|
|
263
|
+
`;
|
|
264
|
+
}
|
|
265
|
+
function truncateToBudget(text, budget) {
|
|
266
|
+
if (!Number.isFinite(budget) || budget <= 0) {
|
|
267
|
+
return "";
|
|
268
|
+
}
|
|
269
|
+
const maxChars = Math.max(0, Math.floor(budget) * 4);
|
|
270
|
+
if (text.length <= maxChars) {
|
|
271
|
+
return text;
|
|
272
|
+
}
|
|
273
|
+
return text.slice(0, maxChars).trimEnd();
|
|
274
|
+
}
|
|
275
|
+
function applyTokenBudget(items, task, budget) {
|
|
276
|
+
const fullContext = items.map((item) => item.entry);
|
|
277
|
+
const fullMarkdown = formatContextMarkdown(task, fullContext);
|
|
298
278
|
if (budget === void 0) {
|
|
299
|
-
return
|
|
279
|
+
return { context: fullContext, markdown: fullMarkdown };
|
|
300
280
|
}
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
})),
|
|
307
|
-
budget
|
|
308
|
-
);
|
|
309
|
-
const bySource = new Map(items.map((item) => [item.source, item.entry]));
|
|
281
|
+
const normalizedBudget = Math.max(1, Math.floor(budget));
|
|
282
|
+
const header = `## Relevant Context for: ${task}
|
|
283
|
+
|
|
284
|
+
`;
|
|
285
|
+
let remaining = normalizedBudget - estimateTokens(header);
|
|
310
286
|
const selectedEntries = [];
|
|
311
|
-
for (const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
287
|
+
for (const item of [...items].sort((a, b) => a.priority - b.priority)) {
|
|
288
|
+
if (remaining <= 0) {
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
const cost = estimateTokens(renderEntryBlock(item.entry));
|
|
292
|
+
if (cost <= remaining) {
|
|
293
|
+
selectedEntries.push(item.entry);
|
|
294
|
+
remaining -= cost;
|
|
315
295
|
}
|
|
316
296
|
}
|
|
317
|
-
|
|
297
|
+
const markdown = truncateToBudget(formatContextMarkdown(task, selectedEntries), normalizedBudget);
|
|
298
|
+
return {
|
|
299
|
+
context: selectedEntries,
|
|
300
|
+
markdown
|
|
301
|
+
};
|
|
318
302
|
}
|
|
319
303
|
async function buildContext(task, options) {
|
|
320
304
|
const normalizedTask = task.trim();
|
|
@@ -343,12 +327,12 @@ async function buildContext(task, options) {
|
|
|
343
327
|
...yellowObservations,
|
|
344
328
|
...greenObservations
|
|
345
329
|
];
|
|
346
|
-
const context = applyTokenBudget(ordered, options.budget);
|
|
330
|
+
const { context, markdown } = applyTokenBudget(ordered, normalizedTask, options.budget);
|
|
347
331
|
return {
|
|
348
332
|
task: normalizedTask,
|
|
349
333
|
generated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
350
334
|
context,
|
|
351
|
-
markdown
|
|
335
|
+
markdown
|
|
352
336
|
};
|
|
353
337
|
}
|
|
354
338
|
async function contextCommand(task, options) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/observer/compressor.ts
|
|
2
2
|
var DATE_HEADING_RE = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
|
|
3
3
|
var OBSERVATION_LINE_RE = /^(🔴|🟡|🟢)\s+(.+)$/u;
|
|
4
|
-
var CRITICAL_RE =
|
|
4
|
+
var CRITICAL_RE = /(?:\b(?:decision|decided|chose|selected)\s*:|\bdecid(?:e|ed|ing|ion)\b|\berror\b|\bfail(?:ed|ure)?\b|\bprefer(?:ence)?\b|\bblock(?:ed|er)?\b|\bmust\b|\brequired?\b|\burgent\b)/i;
|
|
5
5
|
var NOTABLE_RE = /\b(context|pattern|architecture|approach|trade[- ]?off|milestone|notable)\b/i;
|
|
6
6
|
var Compressor = class {
|
|
7
7
|
model;
|
|
@@ -191,13 +191,40 @@ ${cleaned}`;
|
|
|
191
191
|
if (existingSections.size === 0) {
|
|
192
192
|
return this.renderSections(incomingSections);
|
|
193
193
|
}
|
|
194
|
+
for (const [date, lines] of existingSections.entries()) {
|
|
195
|
+
existingSections.set(date, this.deduplicateObservationLines(lines));
|
|
196
|
+
}
|
|
194
197
|
for (const [date, lines] of incomingSections.entries()) {
|
|
195
|
-
const current = existingSections.get(date) ?? [];
|
|
196
|
-
current.
|
|
198
|
+
const current = this.deduplicateObservationLines(existingSections.get(date) ?? []);
|
|
199
|
+
const seen = new Set(current.map((line) => this.normalizeObservationContent(line.content)));
|
|
200
|
+
for (const line of lines) {
|
|
201
|
+
const normalized = this.normalizeObservationContent(line.content);
|
|
202
|
+
if (!normalized || seen.has(normalized)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
seen.add(normalized);
|
|
206
|
+
current.push(line);
|
|
207
|
+
}
|
|
197
208
|
existingSections.set(date, current);
|
|
198
209
|
}
|
|
199
210
|
return this.renderSections(existingSections);
|
|
200
211
|
}
|
|
212
|
+
deduplicateObservationLines(lines) {
|
|
213
|
+
const deduped = [];
|
|
214
|
+
const seen = /* @__PURE__ */ new Set();
|
|
215
|
+
for (const line of lines) {
|
|
216
|
+
const normalized = this.normalizeObservationContent(line.content);
|
|
217
|
+
if (!normalized || seen.has(normalized)) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
seen.add(normalized);
|
|
221
|
+
deduped.push(line);
|
|
222
|
+
}
|
|
223
|
+
return deduped;
|
|
224
|
+
}
|
|
225
|
+
normalizeObservationContent(content) {
|
|
226
|
+
return content.replace(/^\d{2}:\d{2}\s+/, "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
227
|
+
}
|
|
201
228
|
parseSections(markdown) {
|
|
202
229
|
const sections = /* @__PURE__ */ new Map();
|
|
203
230
|
let currentDate = null;
|
|
@@ -398,7 +425,10 @@ var CATEGORY_PATTERNS = [
|
|
|
398
425
|
category: "people",
|
|
399
426
|
patterns: [
|
|
400
427
|
/\b(said|asked|told|mentioned|emailed|called|messaged|met with)\b/i,
|
|
401
|
-
/\b(client|partner|team|colleague|contact)\b/i
|
|
428
|
+
/\b(client|partner|team|colleague|contact)\b/i,
|
|
429
|
+
/\b(?:Pedro|Justin|Maria|Sarah|[A-Z][a-z]+ (?:said|asked|told|mentioned))\b/,
|
|
430
|
+
/\b(?:talked to|met with)\s+[A-Z][a-z]+\b/i,
|
|
431
|
+
/\b[A-Z][a-z]+\s+from\b/
|
|
402
432
|
]
|
|
403
433
|
},
|
|
404
434
|
{
|
|
@@ -503,6 +533,8 @@ ${entry}
|
|
|
503
533
|
};
|
|
504
534
|
|
|
505
535
|
// src/observer/observer.ts
|
|
536
|
+
var DATE_HEADING_RE4 = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
|
|
537
|
+
var OBSERVATION_LINE_RE4 = /^(🔴|🟡|🟢)\s+(.+)$/u;
|
|
506
538
|
var Observer = class {
|
|
507
539
|
vaultPath;
|
|
508
540
|
observationsDir;
|
|
@@ -538,9 +570,14 @@ var Observer = class {
|
|
|
538
570
|
return;
|
|
539
571
|
}
|
|
540
572
|
const todayPath = this.getObservationPath(this.now());
|
|
541
|
-
const
|
|
542
|
-
const
|
|
573
|
+
const existingRaw = this.readObservationFile(todayPath);
|
|
574
|
+
const existing = this.deduplicateObservationMarkdown(existingRaw);
|
|
575
|
+
if (existingRaw.trim() !== existing) {
|
|
576
|
+
this.writeObservationFile(todayPath, existing);
|
|
577
|
+
}
|
|
578
|
+
const compressedRaw = (await this.compressor.compress(this.pendingMessages, existing)).trim();
|
|
543
579
|
this.pendingMessages = [];
|
|
580
|
+
const compressed = this.deduplicateObservationMarkdown(compressedRaw);
|
|
544
581
|
if (!compressed) {
|
|
545
582
|
return;
|
|
546
583
|
}
|
|
@@ -561,9 +598,14 @@ var Observer = class {
|
|
|
561
598
|
return { observations: this.observationsCache, routingSummary: this.lastRoutingSummary };
|
|
562
599
|
}
|
|
563
600
|
const todayPath = this.getObservationPath(this.now());
|
|
564
|
-
const
|
|
565
|
-
const
|
|
601
|
+
const existingRaw = this.readObservationFile(todayPath);
|
|
602
|
+
const existing = this.deduplicateObservationMarkdown(existingRaw);
|
|
603
|
+
if (existingRaw.trim() !== existing) {
|
|
604
|
+
this.writeObservationFile(todayPath, existing);
|
|
605
|
+
}
|
|
606
|
+
const compressedRaw = (await this.compressor.compress(this.pendingMessages, existing)).trim();
|
|
566
607
|
this.pendingMessages = [];
|
|
608
|
+
const compressed = this.deduplicateObservationMarkdown(compressedRaw);
|
|
567
609
|
if (compressed) {
|
|
568
610
|
this.writeObservationFile(todayPath, compressed);
|
|
569
611
|
this.observationsCache = compressed;
|
|
@@ -612,6 +654,74 @@ var Observer = class {
|
|
|
612
654
|
}
|
|
613
655
|
return files.map((filePath) => this.readObservationFile(filePath)).filter(Boolean).join("\n\n");
|
|
614
656
|
}
|
|
657
|
+
deduplicateObservationMarkdown(markdown) {
|
|
658
|
+
const parsed = this.parseSections(markdown);
|
|
659
|
+
if (parsed.size === 0) {
|
|
660
|
+
return markdown.trim();
|
|
661
|
+
}
|
|
662
|
+
for (const [date, lines] of parsed.entries()) {
|
|
663
|
+
const seen = /* @__PURE__ */ new Set();
|
|
664
|
+
const deduped = [];
|
|
665
|
+
for (const line of lines) {
|
|
666
|
+
const normalized = this.normalizeObservationContent(line.content);
|
|
667
|
+
if (!normalized || seen.has(normalized)) {
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
seen.add(normalized);
|
|
671
|
+
deduped.push(line);
|
|
672
|
+
}
|
|
673
|
+
parsed.set(date, deduped);
|
|
674
|
+
}
|
|
675
|
+
return this.renderSections(parsed);
|
|
676
|
+
}
|
|
677
|
+
parseSections(markdown) {
|
|
678
|
+
const sections = /* @__PURE__ */ new Map();
|
|
679
|
+
let currentDate = null;
|
|
680
|
+
for (const rawLine of markdown.split(/\r?\n/)) {
|
|
681
|
+
const dateMatch = rawLine.match(DATE_HEADING_RE4);
|
|
682
|
+
if (dateMatch) {
|
|
683
|
+
currentDate = dateMatch[1];
|
|
684
|
+
if (!sections.has(currentDate)) {
|
|
685
|
+
sections.set(currentDate, []);
|
|
686
|
+
}
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
if (!currentDate) {
|
|
690
|
+
continue;
|
|
691
|
+
}
|
|
692
|
+
const lineMatch = rawLine.match(OBSERVATION_LINE_RE4);
|
|
693
|
+
if (!lineMatch) {
|
|
694
|
+
continue;
|
|
695
|
+
}
|
|
696
|
+
const current = sections.get(currentDate) ?? [];
|
|
697
|
+
current.push({
|
|
698
|
+
priority: lineMatch[1],
|
|
699
|
+
content: lineMatch[2].trim()
|
|
700
|
+
});
|
|
701
|
+
sections.set(currentDate, current);
|
|
702
|
+
}
|
|
703
|
+
return sections;
|
|
704
|
+
}
|
|
705
|
+
renderSections(sections) {
|
|
706
|
+
const chunks = [];
|
|
707
|
+
const dates = [...sections.keys()].sort((a, b) => a.localeCompare(b));
|
|
708
|
+
for (const date of dates) {
|
|
709
|
+
const lines = sections.get(date) ?? [];
|
|
710
|
+
if (lines.length === 0) {
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
chunks.push(`## ${date}`);
|
|
714
|
+
chunks.push("");
|
|
715
|
+
for (const line of lines) {
|
|
716
|
+
chunks.push(`${line.priority} ${line.content}`);
|
|
717
|
+
}
|
|
718
|
+
chunks.push("");
|
|
719
|
+
}
|
|
720
|
+
return chunks.join("\n").trim();
|
|
721
|
+
}
|
|
722
|
+
normalizeObservationContent(content) {
|
|
723
|
+
return content.replace(/^\d{2}:\d{2}\s+/, "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
724
|
+
}
|
|
615
725
|
async reflectIfNeeded() {
|
|
616
726
|
const corpus = this.readObservationCorpus();
|
|
617
727
|
if (this.estimateTokens(corpus) < this.reflectThreshold) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Observer,
|
|
3
3
|
parseSessionFile
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EQ2AZVBX.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/observe.ts
|
|
7
7
|
import * as fs2 from "fs";
|
|
@@ -16,13 +16,17 @@ var SessionWatcher = class {
|
|
|
16
16
|
watchPath;
|
|
17
17
|
observer;
|
|
18
18
|
ignoreInitial;
|
|
19
|
+
debounceMs;
|
|
19
20
|
watcher = null;
|
|
20
21
|
fileOffsets = /* @__PURE__ */ new Map();
|
|
22
|
+
pendingPaths = /* @__PURE__ */ new Set();
|
|
23
|
+
debounceTimer = null;
|
|
21
24
|
processingQueue = Promise.resolve();
|
|
22
25
|
constructor(watchPath, observer, options = {}) {
|
|
23
26
|
this.watchPath = path.resolve(watchPath);
|
|
24
27
|
this.observer = observer;
|
|
25
28
|
this.ignoreInitial = options.ignoreInitial ?? false;
|
|
29
|
+
this.debounceMs = options.debounceMs ?? 500;
|
|
26
30
|
}
|
|
27
31
|
async start() {
|
|
28
32
|
if (!fs.existsSync(this.watchPath)) {
|
|
@@ -37,18 +41,44 @@ var SessionWatcher = class {
|
|
|
37
41
|
}
|
|
38
42
|
});
|
|
39
43
|
const enqueue = (changedPath) => {
|
|
40
|
-
this.
|
|
44
|
+
this.pendingPaths.add(path.resolve(changedPath));
|
|
45
|
+
this.scheduleDrain();
|
|
41
46
|
};
|
|
42
47
|
this.watcher.on("add", enqueue);
|
|
43
48
|
this.watcher.on("change", enqueue);
|
|
44
49
|
this.watcher.on("unlink", (deletedPath) => {
|
|
45
|
-
|
|
50
|
+
const resolved = path.resolve(deletedPath);
|
|
51
|
+
this.fileOffsets.delete(resolved);
|
|
52
|
+
this.pendingPaths.delete(resolved);
|
|
53
|
+
});
|
|
54
|
+
await new Promise((resolve3, reject) => {
|
|
55
|
+
this.watcher?.once("ready", () => resolve3());
|
|
56
|
+
this.watcher?.once("error", (error) => reject(error));
|
|
46
57
|
});
|
|
47
58
|
}
|
|
48
59
|
async stop() {
|
|
60
|
+
if (this.debounceTimer) {
|
|
61
|
+
clearTimeout(this.debounceTimer);
|
|
62
|
+
this.debounceTimer = null;
|
|
63
|
+
}
|
|
64
|
+
this.pendingPaths.clear();
|
|
65
|
+
await this.processingQueue.catch(() => void 0);
|
|
49
66
|
await this.watcher?.close();
|
|
50
67
|
this.watcher = null;
|
|
51
68
|
}
|
|
69
|
+
scheduleDrain() {
|
|
70
|
+
if (this.debounceTimer) {
|
|
71
|
+
clearTimeout(this.debounceTimer);
|
|
72
|
+
}
|
|
73
|
+
this.debounceTimer = setTimeout(() => {
|
|
74
|
+
this.debounceTimer = null;
|
|
75
|
+
const nextPaths = [...this.pendingPaths];
|
|
76
|
+
this.pendingPaths.clear();
|
|
77
|
+
for (const changedPath of nextPaths) {
|
|
78
|
+
this.processingQueue = this.processingQueue.then(() => this.consumeFile(changedPath)).catch(() => void 0);
|
|
79
|
+
}
|
|
80
|
+
}, this.debounceMs);
|
|
81
|
+
}
|
|
52
82
|
async consumeFile(filePath) {
|
|
53
83
|
const resolved = path.resolve(filePath);
|
|
54
84
|
if (!fs.existsSync(resolved)) {
|
package/dist/commands/context.js
CHANGED
package/dist/commands/observe.js
CHANGED
package/dist/commands/sleep.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -307,6 +307,10 @@ declare class Observer {
|
|
|
307
307
|
private writeObservationFile;
|
|
308
308
|
private getObservationFiles;
|
|
309
309
|
private readObservationCorpus;
|
|
310
|
+
private deduplicateObservationMarkdown;
|
|
311
|
+
private parseSections;
|
|
312
|
+
private renderSections;
|
|
313
|
+
private normalizeObservationContent;
|
|
310
314
|
private reflectIfNeeded;
|
|
311
315
|
}
|
|
312
316
|
|
|
@@ -329,6 +333,8 @@ declare class Compressor {
|
|
|
329
333
|
private normalizeLlmOutput;
|
|
330
334
|
private fallbackCompression;
|
|
331
335
|
private mergeObservations;
|
|
336
|
+
private deduplicateObservationLines;
|
|
337
|
+
private normalizeObservationContent;
|
|
332
338
|
private parseSections;
|
|
333
339
|
private renderSections;
|
|
334
340
|
private inferPriority;
|
|
@@ -356,17 +362,22 @@ declare class Reflector {
|
|
|
356
362
|
|
|
357
363
|
interface SessionWatcherOptions {
|
|
358
364
|
ignoreInitial?: boolean;
|
|
365
|
+
debounceMs?: number;
|
|
359
366
|
}
|
|
360
367
|
declare class SessionWatcher {
|
|
361
368
|
private readonly watchPath;
|
|
362
369
|
private readonly observer;
|
|
363
370
|
private readonly ignoreInitial;
|
|
371
|
+
private readonly debounceMs;
|
|
364
372
|
private watcher;
|
|
365
373
|
private fileOffsets;
|
|
374
|
+
private pendingPaths;
|
|
375
|
+
private debounceTimer;
|
|
366
376
|
private processingQueue;
|
|
367
377
|
constructor(watchPath: string, observer: Observer, options?: SessionWatcherOptions);
|
|
368
378
|
start(): Promise<void>;
|
|
369
379
|
stop(): Promise<void>;
|
|
380
|
+
private scheduleDrain;
|
|
370
381
|
private consumeFile;
|
|
371
382
|
}
|
|
372
383
|
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
contextCommand,
|
|
17
17
|
formatContextMarkdown,
|
|
18
18
|
registerContextCommand
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-AVPHNEDB.js";
|
|
20
20
|
import {
|
|
21
21
|
ClawVault,
|
|
22
22
|
createVault,
|
|
@@ -41,13 +41,13 @@ import {
|
|
|
41
41
|
SessionWatcher,
|
|
42
42
|
observeCommand,
|
|
43
43
|
registerObserveCommand
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-JATU7JVY.js";
|
|
45
45
|
import {
|
|
46
46
|
Compressor,
|
|
47
47
|
Observer,
|
|
48
48
|
Reflector,
|
|
49
49
|
parseSessionFile
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-EQ2AZVBX.js";
|
|
51
51
|
|
|
52
52
|
// src/index.ts
|
|
53
53
|
import * as fs from "fs";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawvault",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
4
4
|
"description": "ClawVault™ - 🐘 An elephant never forgets. Structured memory for OpenClaw agents. Context death resilience, Obsidian-compatible markdown, local semantic search.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|