clawvault 2.1.2 → 2.2.1
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/bin/command-registration.test.js +6 -1
- package/bin/help-contract.test.js +2 -0
- package/bin/register-core-commands.js +14 -4
- package/bin/register-maintenance-commands.js +111 -0
- package/bin/register-query-commands.js +32 -1
- package/bin/register-session-lifecycle-commands.js +2 -0
- package/dist/{chunk-5MQB7B37.js → chunk-2HM7ZI4X.js} +268 -434
- package/dist/chunk-73P7XCQM.js +104 -0
- package/dist/{chunk-MIIXBNO3.js → chunk-FDJIZKCW.js} +12 -1
- package/dist/chunk-GJEGPO7U.js +49 -0
- package/dist/chunk-GQVYQCY5.js +396 -0
- package/dist/{chunk-TXO34J3O.js → chunk-H7JW4L7H.js} +1 -1
- package/dist/{chunk-TBVI4N53.js → chunk-I5X6J4FX.js} +120 -95
- package/dist/chunk-K6XHCUFL.js +123 -0
- package/dist/chunk-L6NB43WV.js +472 -0
- package/dist/{chunk-FEQ2CQ3Y.js → chunk-LB6P4CD5.js} +20 -7
- package/dist/chunk-MGDEINGP.js +99 -0
- package/dist/chunk-MQUJNOHK.js +58 -0
- package/dist/{chunk-QFBKWDYR.js → chunk-OTQW3OMC.js} +91 -12
- package/dist/chunk-P5EPF6MB.js +182 -0
- package/dist/chunk-VR5NE7PZ.js +45 -0
- package/dist/{chunk-PIJGYMQZ.js → chunk-W463YRED.js} +1 -1
- package/dist/chunk-WZI3OAE5.js +111 -0
- package/dist/chunk-Z2XBWN7A.js +247 -0
- package/dist/{chunk-O5V7SD5C.js → chunk-ZZA73MFY.js} +1 -1
- package/dist/commands/archive.d.ts +11 -0
- package/dist/commands/archive.js +11 -0
- package/dist/commands/context.d.ts +1 -1
- package/dist/commands/context.js +6 -4
- package/dist/commands/doctor.js +6 -6
- package/dist/commands/graph.js +2 -2
- package/dist/commands/link.js +1 -1
- package/dist/commands/migrate-observations.d.ts +19 -0
- package/dist/commands/migrate-observations.js +13 -0
- package/dist/commands/observe.js +5 -2
- package/dist/commands/rebuild.d.ts +11 -0
- package/dist/commands/rebuild.js +12 -0
- package/dist/commands/reflect.d.ts +11 -0
- package/dist/commands/reflect.js +13 -0
- package/dist/commands/replay.d.ts +16 -0
- package/dist/commands/replay.js +14 -0
- package/dist/commands/setup.js +2 -2
- package/dist/commands/sleep.d.ts +1 -0
- package/dist/commands/sleep.js +29 -6
- package/dist/commands/status.js +6 -6
- package/dist/commands/sync-bd.d.ts +10 -0
- package/dist/commands/sync-bd.js +9 -0
- package/dist/commands/wake.js +53 -35
- package/dist/{context-COo8oq1k.d.ts → context-BUGaWpyL.d.ts} +1 -0
- package/dist/index.d.ts +56 -20
- package/dist/index.js +67 -16
- package/hooks/clawvault/HOOK.md +3 -2
- package/hooks/clawvault/handler.js +51 -0
- package/hooks/clawvault/handler.test.js +20 -0
- package/package.json +2 -2
package/dist/commands/wake.js
CHANGED
|
@@ -4,18 +4,23 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
clearDirtyFlag
|
|
6
6
|
} from "../chunk-MZZJLQNQ.js";
|
|
7
|
+
import {
|
|
8
|
+
parseObservationMarkdown
|
|
9
|
+
} from "../chunk-K6XHCUFL.js";
|
|
10
|
+
import {
|
|
11
|
+
listObservationFiles
|
|
12
|
+
} from "../chunk-Z2XBWN7A.js";
|
|
7
13
|
import "../chunk-7ZRP733D.js";
|
|
8
14
|
import {
|
|
9
15
|
ClawVault
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-OTQW3OMC.js";
|
|
17
|
+
import "../chunk-FDJIZKCW.js";
|
|
18
|
+
import "../chunk-ZZA73MFY.js";
|
|
13
19
|
|
|
14
20
|
// src/commands/wake.ts
|
|
15
21
|
import * as fs from "fs";
|
|
16
22
|
import * as path from "path";
|
|
17
23
|
var DEFAULT_HANDOFF_LIMIT = 3;
|
|
18
|
-
var OBSERVATION_HIGHLIGHT_RE = /^(🔴|🟡)\s+(.+)$/u;
|
|
19
24
|
var MAX_WAKE_RED_OBSERVATIONS = 20;
|
|
20
25
|
var MAX_WAKE_YELLOW_OBSERVATIONS = 10;
|
|
21
26
|
var MAX_WAKE_OUTPUT_LINES = 100;
|
|
@@ -39,40 +44,48 @@ function buildWakeSummary(recovery, recap) {
|
|
|
39
44
|
}
|
|
40
45
|
return workSummary || "No recent work summary found.";
|
|
41
46
|
}
|
|
42
|
-
function formatDateKey(date) {
|
|
43
|
-
return date.toISOString().split("T")[0];
|
|
44
|
-
}
|
|
45
47
|
function readRecentObservationHighlights(vaultPath) {
|
|
46
48
|
const now = /* @__PURE__ */ new Date();
|
|
49
|
+
const today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
|
|
50
|
+
const fileByDate = new Map(
|
|
51
|
+
listObservationFiles(vaultPath, {
|
|
52
|
+
includeLegacy: true,
|
|
53
|
+
includeArchive: false,
|
|
54
|
+
dedupeByDate: true
|
|
55
|
+
}).map((entry) => [entry.date, entry.path])
|
|
56
|
+
);
|
|
47
57
|
const highlights = [];
|
|
48
58
|
for (let daysAgo = 0; daysAgo < 7; daysAgo++) {
|
|
49
|
-
const date = new Date(
|
|
50
|
-
date.
|
|
51
|
-
const dateKey =
|
|
52
|
-
const filePath =
|
|
53
|
-
if (!fs.existsSync(filePath)) continue;
|
|
59
|
+
const date = new Date(today);
|
|
60
|
+
date.setUTCDate(today.getUTCDate() - daysAgo);
|
|
61
|
+
const dateKey = date.toISOString().slice(0, 10);
|
|
62
|
+
const filePath = fileByDate.get(dateKey);
|
|
63
|
+
if (!filePath || !fs.existsSync(filePath)) continue;
|
|
54
64
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (!match?.[2]) continue;
|
|
65
|
+
const parsed = parseObservationMarkdown(content).filter((record) => record.importance >= 0.4);
|
|
66
|
+
const dayStructural = [];
|
|
67
|
+
const dayPotential = [];
|
|
68
|
+
for (const record of parsed) {
|
|
60
69
|
const item = {
|
|
61
70
|
date: dateKey,
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
type: record.type,
|
|
72
|
+
importance: record.importance,
|
|
73
|
+
text: record.content.trim()
|
|
64
74
|
};
|
|
65
|
-
if (
|
|
66
|
-
|
|
75
|
+
if (record.importance >= 0.8) {
|
|
76
|
+
dayStructural.push(item);
|
|
77
|
+
} else {
|
|
78
|
+
dayPotential.push(item);
|
|
79
|
+
}
|
|
67
80
|
}
|
|
68
81
|
if (daysAgo === 0) {
|
|
69
|
-
highlights.push(...
|
|
82
|
+
highlights.push(...dayStructural, ...dayPotential);
|
|
70
83
|
} else if (daysAgo === 1) {
|
|
71
|
-
highlights.push(...
|
|
84
|
+
highlights.push(...dayStructural, ...dayPotential.slice(0, 5));
|
|
72
85
|
} else if (daysAgo <= 3) {
|
|
73
|
-
highlights.push(...
|
|
86
|
+
highlights.push(...dayStructural);
|
|
74
87
|
} else {
|
|
75
|
-
highlights.push(...
|
|
88
|
+
highlights.push(...dayStructural.slice(0, 3));
|
|
76
89
|
}
|
|
77
90
|
}
|
|
78
91
|
return highlights;
|
|
@@ -88,16 +101,19 @@ function compareByRecency(left, right) {
|
|
|
88
101
|
if (left.date !== right.date) {
|
|
89
102
|
return right.date.localeCompare(left.date);
|
|
90
103
|
}
|
|
104
|
+
if (left.importance !== right.importance) {
|
|
105
|
+
return right.importance - left.importance;
|
|
106
|
+
}
|
|
91
107
|
return timeFromObservationText(right.text) - timeFromObservationText(left.text);
|
|
92
108
|
}
|
|
93
109
|
function formatRecentObservations(highlights) {
|
|
94
110
|
if (highlights.length === 0) {
|
|
95
|
-
return "_No
|
|
111
|
+
return "_No structural or potentially important observations from the recent window._";
|
|
96
112
|
}
|
|
97
113
|
const sorted = [...highlights].sort(compareByRecency);
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const visible = [...
|
|
114
|
+
const structural = sorted.filter((item) => item.importance >= 0.8).slice(0, MAX_WAKE_RED_OBSERVATIONS);
|
|
115
|
+
const potential = sorted.filter((item) => item.importance >= 0.4 && item.importance < 0.8).slice(0, MAX_WAKE_YELLOW_OBSERVATIONS);
|
|
116
|
+
const visible = [...structural, ...potential].sort(compareByRecency);
|
|
101
117
|
const omittedCount = Math.max(0, highlights.length - visible.length);
|
|
102
118
|
const byDate = /* @__PURE__ */ new Map();
|
|
103
119
|
for (const item of visible) {
|
|
@@ -116,7 +132,7 @@ function formatRecentObservations(highlights) {
|
|
|
116
132
|
if (lines.length >= bodyLineBudget) {
|
|
117
133
|
break;
|
|
118
134
|
}
|
|
119
|
-
lines.push(`- ${item.
|
|
135
|
+
lines.push(`- [${item.type}|i=${item.importance.toFixed(2)}] ${item.text}`);
|
|
120
136
|
}
|
|
121
137
|
if (lines.length < bodyLineBudget) {
|
|
122
138
|
lines.push("");
|
|
@@ -131,8 +147,8 @@ async function generateExecutiveSummary(recovery, recap, highlights) {
|
|
|
131
147
|
if (process.env.CLAWVAULT_NO_LLM || process.env.VITEST) return null;
|
|
132
148
|
const apiKey = process.env.GEMINI_API_KEY || process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY;
|
|
133
149
|
if (!apiKey) return null;
|
|
134
|
-
const
|
|
135
|
-
const
|
|
150
|
+
const structuralItems = highlights.filter((h) => h.importance >= 0.8).map((h) => h.text).slice(0, 10);
|
|
151
|
+
const potentialItems = highlights.filter((h) => h.importance >= 0.4 && h.importance < 0.8).map((h) => h.text).slice(0, 5);
|
|
136
152
|
const projects = recap.activeProjects.slice(0, 8);
|
|
137
153
|
const commitments = recap.pendingCommitments.slice(0, 5);
|
|
138
154
|
const lastWork = recovery.checkpoint?.workingOn || recap.recentHandoffs[0]?.workingOn?.join(", ") || "";
|
|
@@ -149,8 +165,8 @@ async function generateExecutiveSummary(recovery, recap, highlights) {
|
|
|
149
165
|
`Next steps: ${nextSteps || "(none)"}`,
|
|
150
166
|
`Active projects (${projects.length}): ${projects.join(", ") || "(none)"}`,
|
|
151
167
|
`Pending commitments: ${commitments.join(", ") || "(none)"}`,
|
|
152
|
-
`
|
|
153
|
-
`
|
|
168
|
+
`Structural observations: ${structuralItems.join(" | ") || "(none)"}`,
|
|
169
|
+
`Potential observations: ${potentialItems.join(" | ") || "(none)"}`,
|
|
154
170
|
"",
|
|
155
171
|
"Write the briefing now. Be concise."
|
|
156
172
|
].join("\n");
|
|
@@ -190,7 +206,9 @@ async function wake(options) {
|
|
|
190
206
|
const highlights = readRecentObservationHighlights(vaultPath);
|
|
191
207
|
const observations = formatRecentObservations(highlights);
|
|
192
208
|
const execSummary = options.noSummary ? null : await generateExecutiveSummary(recovery, recap, highlights);
|
|
193
|
-
const highlightSummaryItems = highlights.map(
|
|
209
|
+
const highlightSummaryItems = highlights.map(
|
|
210
|
+
(item) => `[${item.type}|i=${item.importance.toFixed(2)}] ${item.text}`
|
|
211
|
+
);
|
|
194
212
|
const wakeSummary = formatSummaryItems(highlightSummaryItems);
|
|
195
213
|
const baseSummary = buildWakeSummary(recovery, recap);
|
|
196
214
|
const fullBaseSummary = wakeSummary ? `${baseSummary} | ${wakeSummary}` : baseSummary;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,14 @@ export { f as DEFAULT_CATEGORIES, g as DEFAULT_CONFIG, h as MEMORY_TYPES, T as T
|
|
|
4
4
|
export { setupCommand } from './commands/setup.js';
|
|
5
5
|
export { CompatCheck, CompatCommandOptions, CompatReport, CompatStatus, checkOpenClawCompatibility, compatCommand, compatibilityExitCode } from './commands/compat.js';
|
|
6
6
|
export { GraphSummary, graphCommand, graphSummary } from './commands/graph.js';
|
|
7
|
-
export { C as ContextEntry, a as ContextFormat, b as ContextOptions, c as ContextProfile, d as ContextProfileInput, e as ContextProfileOption, f as ContextResult, R as ResolvedContextProfile, g as buildContext, h as contextCommand, i as formatContextMarkdown, j as inferContextProfile, n as normalizeContextProfileInput, r as registerContextCommand, k as resolveContextProfile } from './context-
|
|
7
|
+
export { C as ContextEntry, a as ContextFormat, b as ContextOptions, c as ContextProfile, d as ContextProfileInput, e as ContextProfileOption, f as ContextResult, R as ResolvedContextProfile, g as buildContext, h as contextCommand, i as formatContextMarkdown, j as inferContextProfile, n as normalizeContextProfileInput, r as registerContextCommand, k as resolveContextProfile } from './context-BUGaWpyL.js';
|
|
8
8
|
export { ObserveCommandOptions, observeCommand, registerObserveCommand } from './commands/observe.js';
|
|
9
|
+
export { ReflectCommandOptions, reflectCommand, registerReflectCommand } from './commands/reflect.js';
|
|
10
|
+
export { ArchiveCommandOptions, archiveCommand, registerArchiveCommand } from './commands/archive.js';
|
|
11
|
+
export { RebuildCommandOptions, rebuildCommand, registerRebuildCommand } from './commands/rebuild.js';
|
|
12
|
+
export { ReplayCommandOptions, registerReplayCommand, replayCommand } from './commands/replay.js';
|
|
13
|
+
export { MigrateObservationsOptions, MigrateObservationsResult, migrateObservations, migrateObservationsCommand, registerMigrateObservationsCommand } from './commands/migrate-observations.js';
|
|
14
|
+
export { SyncBdCommandOptions, registerSyncBdCommand, syncBdCommand } from './commands/sync-bd.js';
|
|
9
15
|
export { SessionRecapFormat, SessionRecapOptions, SessionRecapResult, SessionTurn, buildSessionRecap, formatSessionRecapMarkdown, sessionRecapCommand } from './commands/session-recap.js';
|
|
10
16
|
export { findNearestVaultPath, getVaultPath, resolveVaultPath } from './lib/config.js';
|
|
11
17
|
export { TemplateVariables, buildTemplateVariables, renderTemplate } from './lib/template-engine.js';
|
|
@@ -138,6 +144,7 @@ declare class ClawVault {
|
|
|
138
144
|
private slugify;
|
|
139
145
|
private saveIndex;
|
|
140
146
|
private createTemplates;
|
|
147
|
+
private createWelcomeNote;
|
|
141
148
|
private syncMemoryGraphIndex;
|
|
142
149
|
private generateReadme;
|
|
143
150
|
private getCategoryDescription;
|
|
@@ -337,21 +344,28 @@ interface ObserverOptions {
|
|
|
337
344
|
compressor?: ObserverCompressor;
|
|
338
345
|
reflector?: ObserverReflector;
|
|
339
346
|
now?: () => Date;
|
|
347
|
+
rawCapture?: boolean;
|
|
348
|
+
}
|
|
349
|
+
interface ObserverProcessOptions {
|
|
350
|
+
source?: string;
|
|
351
|
+
sessionKey?: string;
|
|
352
|
+
transcriptId?: string;
|
|
353
|
+
timestamp?: Date;
|
|
340
354
|
}
|
|
341
355
|
declare class Observer {
|
|
342
356
|
private readonly vaultPath;
|
|
343
|
-
private readonly observationsDir;
|
|
344
357
|
private readonly tokenThreshold;
|
|
345
358
|
private readonly reflectThreshold;
|
|
346
359
|
private readonly compressor;
|
|
347
360
|
private readonly reflector;
|
|
348
361
|
private readonly now;
|
|
362
|
+
private readonly rawCapture;
|
|
349
363
|
private readonly router;
|
|
350
364
|
private pendingMessages;
|
|
351
365
|
private observationsCache;
|
|
352
366
|
private lastRoutingSummary;
|
|
353
367
|
constructor(vaultPath: string, options?: ObserverOptions);
|
|
354
|
-
processMessages(messages: string[]): Promise<void>;
|
|
368
|
+
processMessages(messages: string[], options?: ObserverProcessOptions): Promise<void>;
|
|
355
369
|
/**
|
|
356
370
|
* Force-flush pending messages regardless of threshold.
|
|
357
371
|
* Call this on session end to capture everything.
|
|
@@ -362,17 +376,13 @@ declare class Observer {
|
|
|
362
376
|
}>;
|
|
363
377
|
getObservations(): string;
|
|
364
378
|
private estimateTokens;
|
|
365
|
-
private getObservationPath;
|
|
366
379
|
private readTodayObservations;
|
|
380
|
+
private readObservationForDate;
|
|
367
381
|
private readObservationFile;
|
|
368
382
|
private writeObservationFile;
|
|
369
|
-
private getObservationFiles;
|
|
370
|
-
private readObservationCorpus;
|
|
371
383
|
private deduplicateObservationMarkdown;
|
|
372
|
-
private
|
|
373
|
-
private
|
|
374
|
-
private normalizeObservationContent;
|
|
375
|
-
private reflectIfNeeded;
|
|
384
|
+
private persistRawMessages;
|
|
385
|
+
private sanitizeSource;
|
|
376
386
|
}
|
|
377
387
|
|
|
378
388
|
interface CompressorOptions {
|
|
@@ -401,18 +411,14 @@ declare class Compressor {
|
|
|
401
411
|
* Also fixes trailing word fragments fused after closing brackets.
|
|
402
412
|
*/
|
|
403
413
|
private sanitizeWikiLinks;
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
* Lines matching critical rules get upgraded to 🔴, notable rules to 🟡.
|
|
407
|
-
*/
|
|
408
|
-
private enforcePriorityRules;
|
|
414
|
+
private enforceImportanceRules;
|
|
415
|
+
private enforceImportanceForRecord;
|
|
409
416
|
private fallbackCompression;
|
|
410
417
|
private mergeObservations;
|
|
411
|
-
private
|
|
412
|
-
private normalizeObservationContent;
|
|
413
|
-
private parseSections;
|
|
418
|
+
private mergeRecord;
|
|
414
419
|
private renderSections;
|
|
415
|
-
private
|
|
420
|
+
private inferImportance;
|
|
421
|
+
private inferConfidence;
|
|
416
422
|
private isCriticalContent;
|
|
417
423
|
private isNotableContent;
|
|
418
424
|
private normalizeText;
|
|
@@ -420,6 +426,7 @@ declare class Compressor {
|
|
|
420
426
|
private extractTime;
|
|
421
427
|
private formatDate;
|
|
422
428
|
private formatTime;
|
|
429
|
+
private clamp01;
|
|
423
430
|
}
|
|
424
431
|
|
|
425
432
|
interface ReflectorOptions {
|
|
@@ -466,6 +473,35 @@ declare class SessionWatcher {
|
|
|
466
473
|
|
|
467
474
|
declare function parseSessionFile(filePath: string): string[];
|
|
468
475
|
|
|
476
|
+
interface ArchiveObservationsOptions {
|
|
477
|
+
olderThanDays?: number;
|
|
478
|
+
dryRun?: boolean;
|
|
479
|
+
now?: () => Date;
|
|
480
|
+
}
|
|
481
|
+
interface ArchiveObservationsResult {
|
|
482
|
+
scanned: number;
|
|
483
|
+
archived: number;
|
|
484
|
+
skipped: number;
|
|
485
|
+
dryRun: boolean;
|
|
486
|
+
archivedDates: string[];
|
|
487
|
+
}
|
|
488
|
+
declare function archiveObservations(vaultPath: string, options?: ArchiveObservationsOptions): ArchiveObservationsResult;
|
|
489
|
+
|
|
490
|
+
interface ReflectOptions {
|
|
491
|
+
vaultPath: string;
|
|
492
|
+
days?: number;
|
|
493
|
+
dryRun?: boolean;
|
|
494
|
+
now?: () => Date;
|
|
495
|
+
}
|
|
496
|
+
interface ReflectResult {
|
|
497
|
+
processedWeeks: number;
|
|
498
|
+
writtenWeeks: number;
|
|
499
|
+
dryRun: boolean;
|
|
500
|
+
files: string[];
|
|
501
|
+
archive: ArchiveObservationsResult | null;
|
|
502
|
+
}
|
|
503
|
+
declare function runReflection(options: ReflectOptions): Promise<ReflectResult>;
|
|
504
|
+
|
|
469
505
|
/**
|
|
470
506
|
* ClawVault 🐘 — An Elephant Never Forgets
|
|
471
507
|
*
|
|
@@ -495,4 +531,4 @@ declare function parseSessionFile(filePath: string): string[];
|
|
|
495
531
|
declare const VERSION: string;
|
|
496
532
|
declare function registerCommanderCommands(program: Command): Command;
|
|
497
533
|
|
|
498
|
-
export { Category, ClawVault, Compressor, type CompressorOptions, Document, HandoffDocument, MEMORY_GRAPH_SCHEMA_VERSION, type MemoryGraph, type MemoryGraphEdge, type MemoryGraphEdgeType, type MemoryGraphIndex, type MemoryGraphNode, type MemoryGraphNodeType, type MemoryGraphStats, MemoryType, Observer, type ObserverCompressor, type ObserverOptions, type ObserverReflector, QMD_INSTALL_COMMAND, QMD_INSTALL_URL, QmdUnavailableError, Reflector, type ReflectorOptions, SearchEngine, SearchOptions, SearchResult, SessionRecap, SessionWatcher, type SessionWatcherOptions, StoreOptions, SyncOptions, SyncResult, VERSION, VaultConfig, buildOrUpdateMemoryGraphIndex, createVault, extractTags, extractWikiLinks, findVault, getMemoryGraph, hasQmd, loadMemoryGraphIndex, parseSessionFile, qmdEmbed, qmdUpdate, registerCommanderCommands };
|
|
534
|
+
export { type ArchiveObservationsOptions, type ArchiveObservationsResult, Category, ClawVault, Compressor, type CompressorOptions, Document, HandoffDocument, MEMORY_GRAPH_SCHEMA_VERSION, type MemoryGraph, type MemoryGraphEdge, type MemoryGraphEdgeType, type MemoryGraphIndex, type MemoryGraphNode, type MemoryGraphNodeType, type MemoryGraphStats, MemoryType, Observer, type ObserverCompressor, type ObserverOptions, type ObserverReflector, QMD_INSTALL_COMMAND, QMD_INSTALL_URL, QmdUnavailableError, type ReflectOptions, type ReflectResult, Reflector, type ReflectorOptions, SearchEngine, SearchOptions, SearchResult, SessionRecap, SessionWatcher, type SessionWatcherOptions, StoreOptions, SyncOptions, SyncResult, VERSION, VaultConfig, archiveObservations, buildOrUpdateMemoryGraphIndex, createVault, extractTags, extractWikiLinks, findVault, getMemoryGraph, hasQmd, loadMemoryGraphIndex, parseSessionFile, qmdEmbed, qmdUpdate, registerCommanderCommands, runReflection };
|
package/dist/index.js
CHANGED
|
@@ -1,27 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildSessionRecap,
|
|
3
|
+
formatSessionRecapMarkdown,
|
|
4
|
+
sessionRecapCommand
|
|
5
|
+
} from "./chunk-ZKGY7WTT.js";
|
|
6
|
+
import {
|
|
7
|
+
setupCommand
|
|
8
|
+
} from "./chunk-W463YRED.js";
|
|
9
|
+
import {
|
|
10
|
+
registerSyncBdCommand,
|
|
11
|
+
syncBdCommand
|
|
12
|
+
} from "./chunk-MGDEINGP.js";
|
|
1
13
|
import {
|
|
2
14
|
buildTemplateVariables,
|
|
3
15
|
renderTemplate
|
|
4
16
|
} from "./chunk-7766SIJP.js";
|
|
17
|
+
import {
|
|
18
|
+
migrateObservations,
|
|
19
|
+
migrateObservationsCommand,
|
|
20
|
+
registerMigrateObservationsCommand
|
|
21
|
+
} from "./chunk-WZI3OAE5.js";
|
|
5
22
|
import {
|
|
6
23
|
SessionWatcher,
|
|
7
24
|
observeCommand,
|
|
8
25
|
registerObserveCommand
|
|
9
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-LB6P4CD5.js";
|
|
10
27
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
28
|
+
parseSessionFile
|
|
29
|
+
} from "./chunk-P5EPF6MB.js";
|
|
30
|
+
import {
|
|
31
|
+
rebuildCommand,
|
|
32
|
+
registerRebuildCommand
|
|
33
|
+
} from "./chunk-73P7XCQM.js";
|
|
34
|
+
import {
|
|
35
|
+
reflectCommand,
|
|
36
|
+
registerReflectCommand
|
|
37
|
+
} from "./chunk-GJEGPO7U.js";
|
|
15
38
|
import "./chunk-HRLWZGMA.js";
|
|
16
39
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
40
|
+
registerReplayCommand,
|
|
41
|
+
replayCommand
|
|
42
|
+
} from "./chunk-L6NB43WV.js";
|
|
19
43
|
import {
|
|
20
44
|
Compressor,
|
|
21
45
|
Observer,
|
|
22
|
-
Reflector
|
|
23
|
-
|
|
24
|
-
|
|
46
|
+
Reflector
|
|
47
|
+
} from "./chunk-2HM7ZI4X.js";
|
|
48
|
+
import {
|
|
49
|
+
runReflection
|
|
50
|
+
} from "./chunk-GQVYQCY5.js";
|
|
51
|
+
import {
|
|
52
|
+
archiveCommand,
|
|
53
|
+
registerArchiveCommand
|
|
54
|
+
} from "./chunk-VR5NE7PZ.js";
|
|
55
|
+
import {
|
|
56
|
+
archiveObservations
|
|
57
|
+
} from "./chunk-MQUJNOHK.js";
|
|
25
58
|
import {
|
|
26
59
|
buildContext,
|
|
27
60
|
contextCommand,
|
|
@@ -30,7 +63,9 @@ import {
|
|
|
30
63
|
normalizeContextProfileInput,
|
|
31
64
|
registerContextCommand,
|
|
32
65
|
resolveContextProfile
|
|
33
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-I5X6J4FX.js";
|
|
67
|
+
import "./chunk-K6XHCUFL.js";
|
|
68
|
+
import "./chunk-Z2XBWN7A.js";
|
|
34
69
|
import {
|
|
35
70
|
checkOpenClawCompatibility,
|
|
36
71
|
compatCommand,
|
|
@@ -40,7 +75,7 @@ import {
|
|
|
40
75
|
ClawVault,
|
|
41
76
|
createVault,
|
|
42
77
|
findVault
|
|
43
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-OTQW3OMC.js";
|
|
44
79
|
import {
|
|
45
80
|
DEFAULT_CATEGORIES,
|
|
46
81
|
DEFAULT_CONFIG,
|
|
@@ -55,17 +90,17 @@ import {
|
|
|
55
90
|
hasQmd,
|
|
56
91
|
qmdEmbed,
|
|
57
92
|
qmdUpdate
|
|
58
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-FDJIZKCW.js";
|
|
59
94
|
import {
|
|
60
95
|
graphCommand,
|
|
61
96
|
graphSummary
|
|
62
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-H7JW4L7H.js";
|
|
63
98
|
import {
|
|
64
99
|
MEMORY_GRAPH_SCHEMA_VERSION,
|
|
65
100
|
buildOrUpdateMemoryGraphIndex,
|
|
66
101
|
getMemoryGraph,
|
|
67
102
|
loadMemoryGraphIndex
|
|
68
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-ZZA73MFY.js";
|
|
69
104
|
import {
|
|
70
105
|
findNearestVaultPath,
|
|
71
106
|
getVaultPath,
|
|
@@ -87,6 +122,7 @@ var VERSION = readPackageVersion();
|
|
|
87
122
|
function registerCommanderCommands(program) {
|
|
88
123
|
registerContextCommand(program);
|
|
89
124
|
registerObserveCommand(program);
|
|
125
|
+
registerReflectCommand(program);
|
|
90
126
|
return program;
|
|
91
127
|
}
|
|
92
128
|
export {
|
|
@@ -105,6 +141,8 @@ export {
|
|
|
105
141
|
SessionWatcher,
|
|
106
142
|
TYPE_TO_CATEGORY,
|
|
107
143
|
VERSION,
|
|
144
|
+
archiveCommand,
|
|
145
|
+
archiveObservations,
|
|
108
146
|
buildContext,
|
|
109
147
|
buildOrUpdateMemoryGraphIndex,
|
|
110
148
|
buildSessionRecap,
|
|
@@ -127,17 +165,30 @@ export {
|
|
|
127
165
|
hasQmd,
|
|
128
166
|
inferContextProfile,
|
|
129
167
|
loadMemoryGraphIndex,
|
|
168
|
+
migrateObservations,
|
|
169
|
+
migrateObservationsCommand,
|
|
130
170
|
normalizeContextProfileInput,
|
|
131
171
|
observeCommand,
|
|
132
172
|
parseSessionFile,
|
|
133
173
|
qmdEmbed,
|
|
134
174
|
qmdUpdate,
|
|
175
|
+
rebuildCommand,
|
|
176
|
+
reflectCommand,
|
|
177
|
+
registerArchiveCommand,
|
|
135
178
|
registerCommanderCommands,
|
|
136
179
|
registerContextCommand,
|
|
180
|
+
registerMigrateObservationsCommand,
|
|
137
181
|
registerObserveCommand,
|
|
182
|
+
registerRebuildCommand,
|
|
183
|
+
registerReflectCommand,
|
|
184
|
+
registerReplayCommand,
|
|
185
|
+
registerSyncBdCommand,
|
|
138
186
|
renderTemplate,
|
|
187
|
+
replayCommand,
|
|
139
188
|
resolveContextProfile,
|
|
140
189
|
resolveVaultPath,
|
|
190
|
+
runReflection,
|
|
141
191
|
sessionRecapCommand,
|
|
142
|
-
setupCommand
|
|
192
|
+
setupCommand,
|
|
193
|
+
syncBdCommand
|
|
143
194
|
};
|
package/hooks/clawvault/HOOK.md
CHANGED
|
@@ -4,7 +4,7 @@ description: "Context resilience - recovery detection, auto-checkpoint, and sess
|
|
|
4
4
|
metadata:
|
|
5
5
|
openclaw:
|
|
6
6
|
emoji: "🐘"
|
|
7
|
-
events: ["gateway:startup", "gateway:heartbeat", "command:new", "session:start", "compaction:memoryFlush"]
|
|
7
|
+
events: ["gateway:startup", "gateway:heartbeat", "command:new", "session:start", "compaction:memoryFlush", "cron.weekly"]
|
|
8
8
|
requires:
|
|
9
9
|
bins: ["clawvault"]
|
|
10
10
|
---
|
|
@@ -18,6 +18,7 @@ Integrates ClawVault's context death resilience into OpenClaw:
|
|
|
18
18
|
- **On /new command**: Auto-checkpoints before session reset
|
|
19
19
|
- **On context compaction**: Forces incremental observation flush before context is lost
|
|
20
20
|
- **On session start**: Injects relevant vault context for the initial prompt
|
|
21
|
+
- **On weekly cron**: Runs `clawvault reflect` every Sunday midnight (UTC)
|
|
21
22
|
|
|
22
23
|
## Installation
|
|
23
24
|
|
|
@@ -63,7 +64,7 @@ Injection format:
|
|
|
63
64
|
|
|
64
65
|
### Event Compatibility
|
|
65
66
|
|
|
66
|
-
The hook accepts canonical OpenClaw events (`gateway:startup`, `gateway:heartbeat`, `command:new`, `session:start`, `compaction:memoryFlush`) and tolerates alias payload shapes (`event`, `eventName`, `name`, `hook`, `trigger`) to remain robust across runtime wrappers.
|
|
67
|
+
The hook accepts canonical OpenClaw events (`gateway:startup`, `gateway:heartbeat`, `command:new`, `session:start`, `compaction:memoryFlush`, `cron.weekly`) and tolerates alias payload shapes (`event`, `eventName`, `name`, `hook`, `trigger`) to remain robust across runtime wrappers.
|
|
67
68
|
|
|
68
69
|
## No Configuration Needed
|
|
69
70
|
|
|
@@ -544,6 +544,49 @@ function runActiveObservation(vaultPath, agentId, options = {}) {
|
|
|
544
544
|
return true;
|
|
545
545
|
}
|
|
546
546
|
|
|
547
|
+
function extractEventTimestamp(event) {
|
|
548
|
+
const candidates = [
|
|
549
|
+
event?.timestamp,
|
|
550
|
+
event?.scheduledAt,
|
|
551
|
+
event?.time,
|
|
552
|
+
event?.context?.timestamp,
|
|
553
|
+
event?.context?.scheduledAt
|
|
554
|
+
];
|
|
555
|
+
for (const candidate of candidates) {
|
|
556
|
+
if (!candidate) continue;
|
|
557
|
+
const parsed = new Date(candidate);
|
|
558
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
559
|
+
return parsed;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function isSundayMidnightUtc(date) {
|
|
566
|
+
return date.getUTCDay() === 0 && date.getUTCHours() === 0 && date.getUTCMinutes() === 0;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
async function handleWeeklyReflect(event) {
|
|
570
|
+
const vaultPath = findVaultPath();
|
|
571
|
+
if (!vaultPath) {
|
|
572
|
+
console.log('[clawvault] No vault found, skipping weekly reflection');
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
const timestamp = extractEventTimestamp(event) || new Date();
|
|
577
|
+
if (!isSundayMidnightUtc(timestamp)) {
|
|
578
|
+
console.log('[clawvault] Weekly reflect skipped (not Sunday midnight UTC)');
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
const result = runClawvault(['reflect', '-v', vaultPath], { timeoutMs: 120000 });
|
|
583
|
+
if (!result.success) {
|
|
584
|
+
console.warn('[clawvault] Weekly reflection failed');
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
console.log('[clawvault] Weekly reflection complete');
|
|
588
|
+
}
|
|
589
|
+
|
|
547
590
|
// Handle gateway startup - check for context death
|
|
548
591
|
async function handleStartup(event) {
|
|
549
592
|
const vaultPath = findVaultPath();
|
|
@@ -724,6 +767,14 @@ const handler = async (event) => {
|
|
|
724
767
|
return;
|
|
725
768
|
}
|
|
726
769
|
|
|
770
|
+
if (
|
|
771
|
+
eventMatches(event, 'cron', 'weekly')
|
|
772
|
+
|| eventIncludesToken(event, 'cron:weekly')
|
|
773
|
+
) {
|
|
774
|
+
await handleWeeklyReflect(event);
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
|
|
727
778
|
if (
|
|
728
779
|
eventMatches(event, 'gateway', 'heartbeat')
|
|
729
780
|
|| eventMatches(event, 'session', 'heartbeat')
|
|
@@ -240,4 +240,24 @@ describe('clawvault hook handler', () => {
|
|
|
240
240
|
|
|
241
241
|
fs.rmSync(vaultPath, { recursive: true, force: true });
|
|
242
242
|
});
|
|
243
|
+
|
|
244
|
+
it('runs weekly reflection on cron.weekly at Sunday midnight', async () => {
|
|
245
|
+
const vaultPath = makeVaultFixture();
|
|
246
|
+
process.env.CLAWVAULT_PATH = vaultPath;
|
|
247
|
+
execFileSyncMock.mockReturnValue('');
|
|
248
|
+
|
|
249
|
+
const handler = await loadHandler();
|
|
250
|
+
await handler({
|
|
251
|
+
eventName: 'cron.weekly',
|
|
252
|
+
timestamp: '2026-02-15T00:00:00.000Z'
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
expect(execFileSyncMock).toHaveBeenCalledWith(
|
|
256
|
+
'clawvault',
|
|
257
|
+
expect.arrayContaining(['reflect', '-v', vaultPath]),
|
|
258
|
+
expect.objectContaining({ shell: false })
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
fs.rmSync(vaultPath, { recursive: true, force: true });
|
|
262
|
+
});
|
|
243
263
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawvault",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
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",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
]
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
|
-
"build": "tsup src/index.ts src/commands/entities.ts src/commands/link.ts src/commands/checkpoint.ts src/commands/recover.ts src/commands/status.ts src/commands/template.ts src/commands/setup.ts src/commands/context.ts src/commands/observe.ts src/commands/session-recap.ts src/commands/wake.ts src/commands/sleep.ts src/commands/doctor.ts src/commands/compat.ts src/commands/graph.ts src/commands/shell-init.ts src/commands/repair-session.ts src/lib/entity-index.ts src/lib/auto-linker.ts src/lib/config.ts src/lib/template-engine.ts src/lib/session-utils.ts src/lib/session-repair.ts --format esm --dts --clean",
|
|
32
|
+
"build": "tsup src/index.ts src/commands/entities.ts src/commands/link.ts src/commands/checkpoint.ts src/commands/recover.ts src/commands/status.ts src/commands/template.ts src/commands/setup.ts src/commands/context.ts src/commands/observe.ts src/commands/reflect.ts src/commands/archive.ts src/commands/rebuild.ts src/commands/replay.ts src/commands/migrate-observations.ts src/commands/sync-bd.ts src/commands/session-recap.ts src/commands/wake.ts src/commands/sleep.ts src/commands/doctor.ts src/commands/compat.ts src/commands/graph.ts src/commands/shell-init.ts src/commands/repair-session.ts src/lib/entity-index.ts src/lib/auto-linker.ts src/lib/config.ts src/lib/template-engine.ts src/lib/session-utils.ts src/lib/session-repair.ts --format esm --dts --clean",
|
|
33
33
|
"dev": "tsup src/index.ts src/commands/*.ts src/lib/*.ts --format esm --dts --watch",
|
|
34
34
|
"lint": "eslint src",
|
|
35
35
|
"typecheck": "tsc --noEmit",
|