hippo-memory 1.51.0 → 1.52.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/README.md CHANGED
@@ -724,9 +724,9 @@ For Claude Code, it also adds:
724
724
  - a `SessionEnd` hook so `hippo sleep` runs automatically when the session exits
725
725
  - a `SessionStart` hook that prints the previous session's consolidation output
726
726
  - a `UserPromptSubmit` hook that runs `hippo context --pinned-only --include-recent 5 --format additional-context` every turn. It re-injects pinned memories (`hippo remember <text> --pin`) plus the last 5 writes, so fresh same-session lessons appear on the next prompt before you pin them. The block is rendered without live strength percentages, so it stays byte-identical while its memories do not change, and it is sent only when it changed since the session's last prompt: an unchanged block is skipped, resent every 10 skips (`pinnedInject.refreshTurns`, `0` never resends) and resent after compaction. `{"pinnedInject":{"skipUnchanged":false}}` sends it every turn as before. Opt out entirely with `{"pinnedInject":{"enabled":false}}` in `.hippo/config.json`.
727
- - a `PreCompact` hook that runs `hippo pre-compact` before the transcript gets summarized. It saves a working-state snapshot (task/summary/next step) and extracts durable memories from the tail, so mid-session compaction can't drop them.
727
+ - a `PreCompact` hook that runs `hippo pre-compact` before the transcript gets summarized. It saves a working-state snapshot (task/summary/next step) so mid-session compaction can't drop it; the `SessionEnd` hook still owns extracting durable memories.
728
728
  - a second `SessionStart` hook (matcher `compact`) that runs `hippo compact-resume`, printing that snapshot plus the recent session trail back into context right after compaction.
729
- - a `PostCompact` hook that runs `hippo post-compact`, which tells you what was saved ("Hippo saved your task snapshot and 2 new memories before compacting"). It prints nothing when nothing was saved.
729
+ - a `PostCompact` hook that runs `hippo post-compact`, which tells you what was saved ("Hippo saved your task snapshot before compacting."). It prints nothing when nothing was saved.
730
730
  - a `PostToolUseFailure` hook that runs `hippo capture-error`, which stores a failed tool call as an error memory. It skips interrupts, declined permissions and searches that found nothing, and stores a repeated failure once. It also logs every failure, stored or not, for `hippo failures`: the session, the tool and hashes of the error, never its text. A hash is not anonymous, since anyone who guesses an error's text can check it against the hash. The log keeps 90 days.
731
731
 
732
732
  To remove: `hippo hook uninstall claude-code`
package/dist/capture.d.ts CHANGED
@@ -106,16 +106,11 @@ export declare function sanitizeLogMessage(message: string): string;
106
106
  /** What one pre-compact run saved, reported to the user after compaction. */
107
107
  export interface PreCompactReport {
108
108
  snapshotSaved: boolean;
109
- captured: number;
110
109
  /** Claude Code session the run belonged to, when the payload named one. */
111
110
  sessionId: string | null;
112
111
  }
113
- /**
114
- * The line shown to the user after compaction, or null when nothing was
115
- * saved. Without it the only sign was Claude Code's generic
116
- * "PreCompact [...] completed successfully".
117
- */
118
- export declare function preCompactMessage(report: Pick<PreCompactReport, 'snapshotSaved' | 'captured'>): string | null;
112
+ /** Line shown after compaction, or null when nothing was saved (Claude Code's own generic message is the fallback). */
113
+ export declare function preCompactMessage(report: Pick<PreCompactReport, 'snapshotSaved'>): string | null;
119
114
  /**
120
115
  * Where pre-compact leaves its report for `hippo post-compact`: next to the
121
116
  * pre-compact log, so both hooks find it from the same `--log-file`.
package/dist/capture.js CHANGED
@@ -21,7 +21,6 @@ import { defaultPreCompactLogPath } from './hooks.js';
21
21
  import { redactSecrets } from './secret-detect.js';
22
22
  import { RejectedValueError, checkRejectionGuard } from './rejection.js';
23
23
  import { openHippoDb, closeHippoDb } from './db.js';
24
- import { loadConfig } from './config.js';
25
24
  // Sentence-level patterns
26
25
  //
27
26
  // T1 (DF2): each pattern now carries TWO capture groups — group 1 is the
@@ -469,62 +468,6 @@ function isDuplicate(content, existing) {
469
468
  }
470
469
  return false;
471
470
  }
472
- /**
473
- * Write already-extracted items to the store, deduped against existing
474
- * tenant-scoped entries. Shared write path for `cmdCapture` (extracted from
475
- * raw text inline) and `cmdPreCompact` (extracted from a pre-computed tail
476
- * summary, no raw-text re-extraction). Mirrors the non-dry-run write loop in
477
- * `cmdCaptureCore`: same layer/source/confidence, same embed-if-configured,
478
- * fire-and-forget behaviour.
479
- *
480
- * Returns the fire-and-forget `embedMemory` promises alongside the counts
481
- * (review round X6) so a caller that must not exit before embeddings settle
482
- * — `cmdPreCompact`, which runs process.exit(0) right after — can await them
483
- * with a bounded timeout instead of racing a detached write.
484
- */
485
- function writeExtractedItems(hippoRoot, tenantId, extracted) {
486
- if (extracted.length === 0)
487
- return { captured: 0, skipped: 0, rejected: 0, embeds: [] };
488
- const existing = loadAllEntries(hippoRoot, tenantId);
489
- const embeds = [];
490
- let captured = 0;
491
- let skipped = 0;
492
- let rejected = 0;
493
- const baseHalfLifeDays = loadConfig(hippoRoot).defaultHalfLifeDays;
494
- for (const item of extracted) {
495
- if (isDuplicate(item.content, existing)) {
496
- skipped++;
497
- continue;
498
- }
499
- const entry = createMemory(item.content, {
500
- layer: Layer.Episodic,
501
- tags: item.tags,
502
- source: 'capture',
503
- confidence: 'observed',
504
- tenantId,
505
- baseHalfLifeDays,
506
- });
507
- // AT1 (plan §3 containment): a refusal is per-VALUE — one rejected
508
- // extraction must not abort the rest of this transcript's captures.
509
- try {
510
- writeEntry(hippoRoot, entry);
511
- }
512
- catch (err) {
513
- if (err instanceof RejectedValueError) {
514
- rejected++;
515
- continue;
516
- }
517
- throw err;
518
- }
519
- updateStats(hippoRoot, { remembered: 1 });
520
- existing.push(entry); // within-batch dedup
521
- if (isEmbeddingConfigured(hippoRoot)) {
522
- embeds.push(embedMemory(hippoRoot, entry).catch(() => { }));
523
- }
524
- captured++;
525
- }
526
- return { captured, skipped, rejected, embeds };
527
- }
528
471
  /**
529
472
  * Runtime shape guards used throughout this file wherever a value arrives
530
473
  * unparsed (JSONL transcript records, stdout/stderr write() chunks). Generic
@@ -557,7 +500,7 @@ function errorMessage(cause) {
557
500
  /** Leading markers of the command lines Claude Code writes with type 'user'. */
558
501
  const CLAUDE_CODE_COMMAND_PREFIXES = ['<local-command-', '<command-name>', '<command-message>', '<command-args>'];
559
502
  function isNonHumanUserLine(entry, content) {
560
- if (entry.isMeta === true || entry.isSidechain === true || entry.isCompactSummary === true)
503
+ if (entry.isMeta === true || entry.isSidechain === true || entry.isCompactSummary === true || entry.promptSource === 'system')
561
504
  return true;
562
505
  const head = content.trimStart();
563
506
  return CLAUDE_CODE_COMMAND_PREFIXES.some((p) => head.startsWith(p));
@@ -1121,20 +1064,11 @@ function isReadableFile(filePath) {
1121
1064
  return false;
1122
1065
  }
1123
1066
  }
1124
- /**
1125
- * The line shown to the user after compaction, or null when nothing was
1126
- * saved. Without it the only sign was Claude Code's generic
1127
- * "PreCompact [...] completed successfully".
1128
- */
1067
+ /** Line shown after compaction, or null when nothing was saved (Claude Code's own generic message is the fallback). */
1129
1068
  export function preCompactMessage(report) {
1130
- if (!report.snapshotSaved && report.captured === 0)
1069
+ if (!report.snapshotSaved)
1131
1070
  return null;
1132
- const parts = [];
1133
- if (report.snapshotSaved)
1134
- parts.push('your task snapshot');
1135
- if (report.captured > 0)
1136
- parts.push(`${report.captured} new memor${report.captured === 1 ? 'y' : 'ies'}`);
1137
- return `Hippo saved ${parts.join(' and ')} before compacting.${report.snapshotSaved ? ' The snapshot is restored into the new context.' : ''}`;
1071
+ return 'Hippo saved your task snapshot before compacting. The snapshot is restored into the new context.';
1138
1072
  }
1139
1073
  /**
1140
1074
  * Where pre-compact leaves its report for `hippo post-compact`: next to the
@@ -1143,24 +1077,20 @@ export function preCompactMessage(report) {
1143
1077
  export function preCompactReportPath(logFile) {
1144
1078
  return path.join(path.dirname(logFile), 'pre-compact-last.json');
1145
1079
  }
1146
- /**
1147
- * Runs the PreCompact producer. Returns any `embedMemory` promises kicked
1148
- * off along the way (empty on every skip path) so `cmdPreCompact` can await
1149
- * them, bounded, before it exits (X6).
1150
- */
1080
+ /** Runs the PreCompact producer: saves a working-state snapshot into `report`. Never extracts memories; SessionEnd capture owns that. */
1151
1081
  function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1152
1082
  // X3: the PreCompact hook fires in every Claude Code project, including
1153
1083
  // ones that never ran `hippo init`, so gate before any store-opening call
1154
1084
  // (saveActiveTaskSnapshot etc. call initStore, which would create one).
1155
1085
  if (!isInitialized(hippoRoot)) {
1156
1086
  appendPreCompactLog(logFile, 'skip: store not initialized');
1157
- return [];
1087
+ return;
1158
1088
  }
1159
1089
  // Same hazard X4 guards below, different trigger: a read that timed out
1160
1090
  // must not reach auto-discovery either, or it snapshots another session.
1161
1091
  if (stdinTimedOut && (!stdinText || stdinText.trim() === '')) {
1162
1092
  appendPreCompactLog(logFile, 'skip: no PreCompact payload arrived before the stdin wait window closed');
1163
- return [];
1093
+ return;
1164
1094
  }
1165
1095
  // A true manual invocation has no stdin at all (TTY, or a non-TTY pipe
1166
1096
  // that yielded an empty read) — that's the ONLY case newest-transcript
@@ -1186,7 +1116,7 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1186
1116
  // `"transcript_path": null` (or the key missing entirely) — all fail
1187
1117
  // the string check. Log and skip; never fall through to auto-discovery.
1188
1118
  appendPreCompactLog(logFile, 'skip: malformed or incomplete PreCompact payload (missing string transcript_path)');
1189
- return [];
1119
+ return;
1190
1120
  }
1191
1121
  if ('session_id' in payload && isStringValue(payload.session_id))
1192
1122
  sessionId = payload.session_id;
@@ -1202,7 +1132,7 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1202
1132
  // this check could gate on, so containment buys no real isolation.
1203
1133
  if (payloadTranscriptPath !== null && !/\.jsonl$/i.test(payloadTranscriptPath)) {
1204
1134
  appendPreCompactLog(logFile, `skip: payload transcript_path is not a .jsonl file: ${payloadTranscriptPath}`);
1205
- return [];
1135
+ return;
1206
1136
  }
1207
1137
  // A payload transcript_path is EXCLUSIVE: never fall back to
1208
1138
  // newest-transcript auto-discovery when it's missing/unreadable. That
@@ -1217,7 +1147,7 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1217
1147
  }
1218
1148
  else {
1219
1149
  appendPreCompactLog(logFile, `skip: payload transcript_path unreadable: ${payloadTranscriptPath}`);
1220
- return [];
1150
+ return;
1221
1151
  }
1222
1152
  }
1223
1153
  else {
@@ -1225,7 +1155,7 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1225
1155
  }
1226
1156
  if (!transcriptPath) {
1227
1157
  appendPreCompactLog(logFile, 'skip: no transcript resolved');
1228
- return [];
1158
+ return;
1229
1159
  }
1230
1160
  let tail;
1231
1161
  try {
@@ -1248,22 +1178,18 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1248
1178
  }
1249
1179
  catch (err) {
1250
1180
  appendPreCompactLog(logFile, `skip: could not read transcript tail: ${errorMessage(err)}`);
1251
- return [];
1181
+ return;
1252
1182
  }
1253
1183
  const summaryFull = summariseTranscript(tail);
1254
- // CX5 (codex round 2): extraction runs over REDACTED text — extracted
1255
- // items become durable memories and must never carry raw secrets any more
1256
- // than the snapshot fields may. (The pre-existing SessionEnd capture path
1257
- // is deliberately unchanged.)
1184
+ // Snapshot fields must never carry raw secrets, same rule X9 applies below to task/next_step.
1258
1185
  const scrubbedSummary = redactSecrets(summaryFull);
1259
- const extracted = extractFromText(scrubbedSummary);
1260
1186
  const rawTask = lastPlainUserMessage(tail);
1261
1187
  const rawNextStep = lastAssistantTextBlock(tail);
1262
- // Full skip only when EVERY derived field is empty and nothing was
1263
- // extracted — never clobber a user-authored active snapshot with junk.
1264
- if (!rawTask.trim() && !summaryFull.trim() && !rawNextStep.trim() && extracted.length === 0) {
1265
- appendPreCompactLog(logFile, 'skip: empty summary and no extracted items');
1266
- return [];
1188
+ // Full skip only when every derived field is empty: never clobber a
1189
+ // user-authored active snapshot with junk.
1190
+ if (!rawTask.trim() && !summaryFull.trim() && !rawNextStep.trim()) {
1191
+ appendPreCompactLog(logFile, 'skip: empty summary');
1192
+ return;
1267
1193
  }
1268
1194
  const tenantId = resolveTenantId({});
1269
1195
  // Per-field merge (X1): a tool-heavy tail whose only user turns are
@@ -1309,10 +1235,8 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1309
1235
  const nextStep = scrubbedNextStep.trim()
1310
1236
  ? truncateCodePointSafe(scrubbedNextStep, PRE_COMPACT_NEXT_STEP_CAP)
1311
1237
  : (fallback?.next_step ?? '');
1312
- // Snapshot writes FIRST: a capture-extraction failure below must never
1313
- // lose the headline artifact. The reverse order would risk it. All-empty
1314
- // fields (cross-session tail with nothing derivable) skip the write so a
1315
- // foreign session's junk never displaces the owning session's snapshot.
1238
+ // All-empty fields (cross-session tail with nothing derivable) skip the
1239
+ // write so a foreign session's junk never displaces the owning snapshot.
1316
1240
  if (!task && !summary && !nextStep) {
1317
1241
  appendPreCompactLog(logFile, 'skip: no snapshot content for this session (nothing derivable; fallback blocked or empty)');
1318
1242
  }
@@ -1332,25 +1256,7 @@ function runPreCompact(hippoRoot, stdinText, stdinTimedOut, logFile, report) {
1332
1256
  appendPreCompactLog(logFile, `snapshot save failed: ${errorMessage(err)}`);
1333
1257
  }
1334
1258
  }
1335
- // Capture extraction SECOND, own try/catch: a failure here self-heals at
1336
- // the next SessionEnd capture (existing dedup absorbs the overlap).
1337
- try {
1338
- const { captured, skipped, rejected, embeds } = writeExtractedItems(hippoRoot, tenantId, extracted);
1339
- report.captured = captured;
1340
- appendPreCompactLog(logFile, `capture: ${captured} items captured, ${skipped} skipped` +
1341
- (rejected > 0 ? `, ${rejected} rejected` : ''));
1342
- return embeds;
1343
- }
1344
- catch (err) {
1345
- appendPreCompactLog(logFile, `capture failed: ${errorMessage(err)}`);
1346
- return [];
1347
- }
1348
1259
  }
1349
- // X6: bound how long cmdPreCompact will wait for fire-and-forget embeddings
1350
- // to settle before it exits. PreCompact runs under a hook timeout (30s in
1351
- // the installer) — 3s leaves ample headroom while still giving embeddings a
1352
- // real chance to finish instead of racing process.exit(0) unconditionally.
1353
- const EMBED_SETTLE_TIMEOUT_MS = 3000;
1354
1260
  /**
1355
1261
  * PreCompact hook entry point. Exit code 2 on PreCompact BLOCKS compaction,
1356
1262
  * so this verb must exit 0 on every path — malformed stdin, missing
@@ -1360,29 +1266,17 @@ const EMBED_SETTLE_TIMEOUT_MS = 3000;
1360
1266
  */
1361
1267
  export async function cmdPreCompact(hippoRoot, options) {
1362
1268
  const logFile = options.logFile ?? defaultPreCompactLogPath();
1363
- let embeds = [];
1364
- const report = { snapshotSaved: false, captured: 0, sessionId: null };
1269
+ const report = { snapshotSaved: false, sessionId: null };
1365
1270
  try {
1366
- embeds = runPreCompact(hippoRoot, options.stdinText, options.stdinTimedOut ?? false, logFile, report);
1271
+ runPreCompact(hippoRoot, options.stdinText, options.stdinTimedOut ?? false, logFile, report);
1367
1272
  }
1368
1273
  catch (err) {
1369
1274
  appendPreCompactLog(logFile, `pre-compact failed: ${errorMessage(err)}`);
1370
1275
  }
1371
- if (embeds.length > 0) {
1372
- let timer;
1373
- const timeout = new Promise((resolve) => {
1374
- timer = setTimeout(() => resolve('timeout'), EMBED_SETTLE_TIMEOUT_MS);
1375
- timer.unref?.();
1376
- });
1377
- const settled = Promise.allSettled(embeds).then(() => 'settled');
1378
- const outcome = await Promise.race([settled, timeout]);
1379
- clearTimeout(timer);
1380
- appendPreCompactLog(logFile, outcome === 'settled' ? 'embeddings settled' : 'embeddings timeout');
1381
- }
1382
1276
  // Nothing goes to stdout: Claude Code passes PreCompact stdout to the
1383
1277
  // summarising model as extra instructions. The PostCompact hook
1384
1278
  // (`hippo post-compact`) tells the user instead, from this report.
1385
- if (report.snapshotSaved || report.captured > 0) {
1279
+ if (report.snapshotSaved) {
1386
1280
  try {
1387
1281
  fs.writeFileSync(preCompactReportPath(logFile), JSON.stringify({ ...report, at: new Date().toISOString() }));
1388
1282
  }
@@ -1431,7 +1325,6 @@ export function postCompactMessage(stdinText, logFile = defaultPreCompactLogPath
1431
1325
  return null;
1432
1326
  return preCompactMessage({
1433
1327
  snapshotSaved: 'snapshotSaved' in report && report.snapshotSaved === true,
1434
- captured: 'captured' in report && Number.isInteger(report.captured) ? Number(report.captured) : 0,
1435
1328
  });
1436
1329
  }
1437
1330
  catch {
package/dist/cli.js CHANGED
@@ -41,7 +41,7 @@ import { execFileSync, execSync, spawn } from 'child_process';
41
41
  import { installJsonHooks, uninstallJsonHooks, resolveJsonHookPaths, detectInstalledTools, defaultSleepLogPath, ensureCodexWrapperInstalled, installCodexWrapper, isCodexWrapperInstalled, repairCodexWrapperIfInstalled, uninstallCodexWrapper, resolveCodexSessionTranscript, resolveCodexWrapperPaths, installOpencodePlugin, uninstallOpencodePlugin, resolveOpencodePluginPath, } from './hooks.js';
42
42
  import { createMemory, calculateStrength, calculateRewardFactor, deriveHalfLife, resolveConfidence, confidenceFacets, confidenceLabel, computeSchemaFit, Layer, } from './memory.js';
43
43
  import { detectSecret } from './secret-detect.js';
44
- import { getHippoRoot, isInitialized, initStore, writeEntry, strengthenRetrieved, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadRecallSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, closeTaskSnapshotsForSession, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, stampHandoffOutcome, writeSessionEndHandoff, createCard, loadCard, listCards, loadCardRuns, claimCard, heartbeatCard, blockCard, reviewCard, completeCard, reclaimExpiredCards, addCardComment, } from './store.js';
44
+ import { getHippoRoot, isInitialized, initStore, writeEntry, strengthenRetrieved, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadRecallSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, closeTaskSnapshotsForSession, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, stampHandoffOutcome, writeSessionEndHandoff, createCard, loadCard, listCards, loadCardRuns, claimCard, heartbeatCard, blockCard, reviewCard, completeCard, reclaimExpiredCards, addCardComment, } from './store.js';
45
45
  import { rejectValue, unrejectValue, listRejectionsForTenant } from './reject-flow.js';
46
46
  import { RejectedValueError } from './rejection.js';
47
47
  import { isHandoffOutcome, formatHandoffEvidenceLine } from './handoff.js';
@@ -2935,6 +2935,8 @@ function cmdLastSleep(flags) {
2935
2935
  // X8: session-event content is capped at print time only — the shared
2936
2936
  // printSessionEvents stays untouched for every other caller.
2937
2937
  const COMPACT_RESUME_EVENT_CONTENT_CAP = 400;
2938
+ // A snapshot older than this was not written for this compaction (pre-compact skipped), so restoring it is stale, not a resume.
2939
+ const COMPACT_RESUME_MAX_AGE_MS = 15 * 60_000;
2938
2940
  function cmdCompactResume(hippoRoot, stdinText, stdinTimedOut) {
2939
2941
  try {
2940
2942
  // X3: gate on the non-exiting isInitialized check before any
@@ -2985,7 +2987,7 @@ function cmdCompactResume(hippoRoot, stdinText, stdinTimedOut) {
2985
2987
  }
2986
2988
  if (!suppressOutput) {
2987
2989
  const tenantId = resolveTenantId({});
2988
- const snapshot = loadActiveTaskSnapshot(hippoRoot, tenantId);
2990
+ const snapshot = loadFreshActiveTaskSnapshot(hippoRoot, tenantId, { maxAgeMs: COMPACT_RESUME_MAX_AGE_MS });
2989
2991
  // X5: concurrent sessions must not cross-restore. Only suppress when
2990
2992
  // BOTH ids are present and differ — either side missing, or a manual
2991
2993
  // invocation with no payload session_id, still prints.
@@ -8953,7 +8955,7 @@ Commands:
8953
8955
  last-sleep Print the last 'hippo sleep --log-file' output and clear it
8954
8956
  --path <p> Log path (default: ~/.hippo/logs/last-sleep.log)
8955
8957
  --keep Print without clearing
8956
- pre-compact PreCompact hook: snapshot + capture the tail before compaction
8958
+ pre-compact PreCompact hook: save a working-state snapshot before compaction
8957
8959
  --log-file <p> Diagnostic log path (default: ~/.hippo/logs/pre-compact.log)
8958
8960
  compact-resume SessionStart(compact) hook: re-print the snapshot + session trail
8959
8961
  post-compact PostCompact hook: tell the user what pre-compact saved
package/dist/version.d.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  * an ESM `import` can resolve cleanly, and a hardcoded constant survives
17
17
  * any packager that drops .json files.
18
18
  */
19
- export declare const PACKAGE_VERSION = "1.51.0";
19
+ export declare const PACKAGE_VERSION = "1.52.0";
20
20
  /** Compares plain x.y.z versions, positive if a > b; tags throw so the rollback guard never misfires silently. */
21
21
  export declare function compareSemver(a: string, b: string): number;
22
22
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -16,7 +16,7 @@
16
16
  * an ESM `import` can resolve cleanly, and a hardcoded constant survives
17
17
  * any packager that drops .json files.
18
18
  */
19
- export const PACKAGE_VERSION = '1.51.0';
19
+ export const PACKAGE_VERSION = '1.52.0';
20
20
  /** Compares plain x.y.z versions, positive if a > b; tags throw so the rollback guard never misfires silently. */
21
21
  export function compareSemver(a, b) {
22
22
  const parse = (v) => {
@@ -2,7 +2,7 @@
2
2
  "id": "hippo-memory",
3
3
  "name": "Hippo Memory",
4
4
  "description": "Biologically-inspired memory for AI agents. Decay by default, retrieval strengthening, sleep consolidation.",
5
- "version": "1.51.0",
5
+ "version": "1.52.0",
6
6
 
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-memory",
3
- "version": "1.51.0",
3
+ "version": "1.52.0",
4
4
  "type": "module",
5
5
  "description": "Hippo Memory plugin for OpenClaw - biologically-inspired agent memory",
6
6
  "main": "index.ts",
@@ -2,7 +2,7 @@
2
2
  "id": "hippo-memory",
3
3
  "name": "Hippo Memory",
4
4
  "description": "Biologically-inspired memory for AI agents. Decay by default, retrieval strengthening, sleep consolidation.",
5
- "version": "1.51.0",
5
+ "version": "1.52.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-memory",
3
- "version": "1.51.0",
3
+ "version": "1.52.0",
4
4
  "description": "Biologically-inspired memory for AI agents. Zero runtime deps, SQLite, MCP server, and an opt-in hosted TypeSafe Jev reranker. Decay, retrieval strengthening, consolidation.",
5
5
  "mcpName": "io.github.kitfunso/hippo-memory",
6
6
  "type": "module",