hippo-memory 1.38.3 → 1.38.9
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/api.d.ts +4 -14
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +22 -2
- package/dist/api.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +62 -62
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +7 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +15 -1
- package/dist/client.js.map +1 -1
- package/dist/consolidate.d.ts.map +1 -1
- package/dist/consolidate.js +11 -22
- package/dist/consolidate.js.map +1 -1
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +18 -3
- package/dist/db.js.map +1 -1
- package/dist/replay.d.ts +1 -1
- package/dist/replay.d.ts.map +1 -1
- package/dist/replay.js +5 -3
- package/dist/replay.js.map +1 -1
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +3 -1
- package/dist/search.js.map +1 -1
- package/dist/src/api.js +22 -2
- package/dist/src/api.js.map +1 -1
- package/dist/src/cli.js +62 -62
- package/dist/src/cli.js.map +1 -1
- package/dist/src/client.js +15 -1
- package/dist/src/client.js.map +1 -1
- package/dist/src/consolidate.js +11 -22
- package/dist/src/consolidate.js.map +1 -1
- package/dist/src/db.js +18 -3
- package/dist/src/db.js.map +1 -1
- package/dist/src/replay.js +5 -3
- package/dist/src/replay.js.map +1 -1
- package/dist/src/search.js +3 -1
- package/dist/src/search.js.map +1 -1
- package/dist/src/store.js +18 -6
- package/dist/src/store.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +18 -6
- package/dist/store.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -36,7 +36,6 @@ import { fileURLToPath } from 'node:url';
|
|
|
36
36
|
import { execFileSync, execSync, spawn } from 'child_process';
|
|
37
37
|
import { installJsonHooks, uninstallJsonHooks, resolveJsonHookPaths, detectInstalledTools, defaultSleepLogPath, ensureCodexWrapperInstalled, installCodexWrapper, isCodexWrapperInstalled, repairCodexWrapperIfInstalled, uninstallCodexWrapper, resolveCodexSessionTranscript, resolveCodexWrapperPaths, installOpencodePlugin, uninstallOpencodePlugin, resolveOpencodePluginPath, } from './hooks.js';
|
|
38
38
|
import { createMemory, calculateStrength, calculateRewardFactor, deriveHalfLife, resolveConfidence, computeSchemaFit, Layer, } from './memory.js';
|
|
39
|
-
import { resolveProjectIdentity } from './project-identity.js';
|
|
40
39
|
import { detectSecret } from './secret-detect.js';
|
|
41
40
|
import { getHippoRoot, isInitialized, initStore, writeEntry, readEntry, deleteEntry, loadAllEntries, loadSearchEntries, loadRecallSearchEntries, loadIndex, saveIndex, loadStats, updateStats, saveActiveTaskSnapshot, loadActiveTaskSnapshot, closeTaskSnapshotsForSession, clearActiveTaskSnapshot, appendSessionEvent, listSessionEvents, listMemoryConflicts, resolveConflict, saveSessionHandoff, loadLatestHandoff, loadHandoffById, RECALL_DEFAULT_DENY_SCOPES, } from './store.js';
|
|
42
41
|
import { rejectValue, unrejectValue, listRejectionsForTenant } from './reject-flow.js';
|
|
@@ -115,7 +114,7 @@ import { graphExpandRecall, MAX_HOPS, DEFAULT_MAX_NEIGHBORS } from './graph-reca
|
|
|
115
114
|
import { DEFAULT_GRAPH_STREAM_WEIGHT } from './graph-stream.js';
|
|
116
115
|
import { getReranker } from './rerankers/index.js';
|
|
117
116
|
import { computeSalience } from './salience.js';
|
|
118
|
-
import {
|
|
117
|
+
import { renderAmbientSummary } from './ambient.js';
|
|
119
118
|
import { validateOwner, isStrictOwnerEnv } from './owner-validation.js';
|
|
120
119
|
import { pruneAuditLog, parseOlderThanFlag } from './audit-prune.js';
|
|
121
120
|
import { listDlq, replayDlqEntry } from './connectors/slack/dlq.js';
|
|
@@ -2868,7 +2867,7 @@ function cmdCompactResume(hippoRoot, stdinText) {
|
|
|
2868
2867
|
* immediately. The child writes to the log file and survives TUI teardown;
|
|
2869
2868
|
* the next SessionStart reads the log via `hippo last-sleep`.
|
|
2870
2869
|
*/
|
|
2871
|
-
function cmdSessionEnd(hippoRoot, flags) {
|
|
2870
|
+
async function cmdSessionEnd(hippoRoot, flags) {
|
|
2872
2871
|
const logFile = typeof flags['log-file'] === 'string' ? flags['log-file'] : null;
|
|
2873
2872
|
// Read stdin synchronously. The SessionEnd hook payload carries
|
|
2874
2873
|
// `transcript_path` as JSON; we extract it here and pass it to the worker
|
|
@@ -2915,7 +2914,7 @@ function cmdSessionEnd(hippoRoot, flags) {
|
|
|
2915
2914
|
// --session-id (both are stdin-derived, argv-only for the child), so in
|
|
2916
2915
|
// this fallback capture auto-discovers the transcript and the DF1
|
|
2917
2916
|
// snapshot close no-ops — the ambient freshness bound is the backstop.
|
|
2918
|
-
cmdSessionEndWorker(hippoRoot, flags);
|
|
2917
|
+
await cmdSessionEndWorker(hippoRoot, flags);
|
|
2919
2918
|
return;
|
|
2920
2919
|
}
|
|
2921
2920
|
}
|
|
@@ -2924,9 +2923,9 @@ function cmdSessionEnd(hippoRoot, flags) {
|
|
|
2924
2923
|
* `__session-end-worker` subcommand (not user-facing). Failures in one stage
|
|
2925
2924
|
* do not block the other.
|
|
2926
2925
|
*/
|
|
2927
|
-
function cmdSessionEndWorker(hippoRoot, flags) {
|
|
2926
|
+
async function cmdSessionEndWorker(hippoRoot, flags) {
|
|
2928
2927
|
try {
|
|
2929
|
-
cmdSleep(hippoRoot, flags);
|
|
2928
|
+
await cmdSleep(hippoRoot, flags);
|
|
2930
2929
|
}
|
|
2931
2930
|
catch {
|
|
2932
2931
|
// sleep errors are already tee'd to the log file via cmdSleep's
|
|
@@ -3035,7 +3034,7 @@ function cmdCodexRun(hippoRoot, args) {
|
|
|
3035
3034
|
console.error(`Failed to launch Codex: ${err.message}`);
|
|
3036
3035
|
process.exit(1);
|
|
3037
3036
|
});
|
|
3038
|
-
child.on('exit', (code, signal) => {
|
|
3037
|
+
child.on('exit', async (code, signal) => {
|
|
3039
3038
|
const workerArgs = [
|
|
3040
3039
|
process.argv[1],
|
|
3041
3040
|
'__codex-session-end-worker',
|
|
@@ -3060,13 +3059,19 @@ function cmdCodexRun(hippoRoot, args) {
|
|
|
3060
3059
|
}
|
|
3061
3060
|
catch {
|
|
3062
3061
|
// Fall back to the inline path if the detached worker cannot be created.
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3062
|
+
// Awaited so the sleep write can't be killed by the exit calls below.
|
|
3063
|
+
try {
|
|
3064
|
+
await cmdCodexSessionEndWorker(hippoRoot, {
|
|
3065
|
+
'codex-home': path.dirname(historyPath),
|
|
3066
|
+
'history-path': historyPath,
|
|
3067
|
+
'start-offset': String(startOffsetBytes),
|
|
3068
|
+
'started-at': String(startedAtMs),
|
|
3069
|
+
'log-file': metadata.logFile,
|
|
3070
|
+
});
|
|
3071
|
+
}
|
|
3072
|
+
catch {
|
|
3073
|
+
// cmdCodexSessionEndWorker already fail-softs internally; this is belt-and-braces.
|
|
3074
|
+
}
|
|
3070
3075
|
}
|
|
3071
3076
|
if (signal) {
|
|
3072
3077
|
try {
|
|
@@ -3080,10 +3085,10 @@ function cmdCodexRun(hippoRoot, args) {
|
|
|
3080
3085
|
process.exit(code ?? 0);
|
|
3081
3086
|
});
|
|
3082
3087
|
}
|
|
3083
|
-
function cmdCodexSessionEndWorker(hippoRoot, flags) {
|
|
3088
|
+
async function cmdCodexSessionEndWorker(hippoRoot, flags) {
|
|
3084
3089
|
const logFile = typeof flags['log-file'] === 'string' ? flags['log-file'] : undefined;
|
|
3085
3090
|
try {
|
|
3086
|
-
cmdSleep(hippoRoot, logFile ? { 'log-file': logFile } : {});
|
|
3091
|
+
await cmdSleep(hippoRoot, logFile ? { 'log-file': logFile } : {});
|
|
3087
3092
|
}
|
|
3088
3093
|
catch {
|
|
3089
3094
|
// sleep errors are already written via cmdSleep
|
|
@@ -3314,6 +3319,8 @@ function cmdOutcome(hippoRoot, flags) {
|
|
|
3314
3319
|
}
|
|
3315
3320
|
console.log(`Applied ${good ? 'positive' : 'negative'} outcome to ${updated} memor${updated === 1 ? 'y' : 'ies'}`);
|
|
3316
3321
|
}
|
|
3322
|
+
// Shared between the forget dispatch and cmdForget so the message can't drift.
|
|
3323
|
+
const ARCHIVE_REASON_REQUIRED = 'hippo forget --archive requires --reason "<why>" (recorded on the archive).';
|
|
3317
3324
|
function cmdForget(hippoRoot, id, flags) {
|
|
3318
3325
|
requireInit(hippoRoot);
|
|
3319
3326
|
const ctx = {
|
|
@@ -3327,12 +3334,11 @@ function cmdForget(hippoRoot, id, flags) {
|
|
|
3327
3334
|
if (flags['archive'] === true) {
|
|
3328
3335
|
const reason = typeof flags['reason'] === 'string' ? flags['reason'] : null;
|
|
3329
3336
|
if (!reason) {
|
|
3330
|
-
console.error(
|
|
3337
|
+
console.error(ARCHIVE_REASON_REQUIRED);
|
|
3331
3338
|
process.exit(1);
|
|
3332
3339
|
}
|
|
3333
3340
|
try {
|
|
3334
3341
|
api.archiveRaw(ctx, id, reason);
|
|
3335
|
-
updateStats(hippoRoot, { forgotten: 1 });
|
|
3336
3342
|
console.log(`Archived ${id}`);
|
|
3337
3343
|
}
|
|
3338
3344
|
catch (err) {
|
|
@@ -3343,7 +3349,6 @@ function cmdForget(hippoRoot, id, flags) {
|
|
|
3343
3349
|
}
|
|
3344
3350
|
try {
|
|
3345
3351
|
api.forget(ctx, id);
|
|
3346
|
-
updateStats(hippoRoot, { forgotten: 1 });
|
|
3347
3352
|
console.log(`Forgot ${id}`);
|
|
3348
3353
|
}
|
|
3349
3354
|
catch (err) {
|
|
@@ -5590,30 +5595,8 @@ async function cmdContext(hippoRoot, args, flags, stdinText) {
|
|
|
5590
5595
|
printContextMarkdown(renderItems, result.tokens, framing);
|
|
5591
5596
|
}
|
|
5592
5597
|
printCrossProjectSection(crossEntries);
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
const ambientConfig = loadConfig(hippoRoot);
|
|
5596
|
-
if (ambientConfig.ambient.enabled && !pinnedOnly) {
|
|
5597
|
-
const tenantId = ctx.tenantId;
|
|
5598
|
-
const globalRoot = getGlobalRoot();
|
|
5599
|
-
const hasGlobalForAmbient = isInitialized(globalRoot);
|
|
5600
|
-
// v39: the landscape summary must reflect the same admission policy as
|
|
5601
|
-
// the injected entries - otherwise excluded rows leak back in as
|
|
5602
|
-
// aggregate signal (codex P2-13).
|
|
5603
|
-
const isolationOff = ambientConfig.contextProjectIsolation === false;
|
|
5604
|
-
const ambientCurrentName = resolveProjectIdentity(process.cwd()).name;
|
|
5605
|
-
const ambientAdmit = (e) => api.ambientAdmitEntry(e, ambientCurrentName, crossProject || isolationOff);
|
|
5606
|
-
const localForAmbient = isInitialized(hippoRoot)
|
|
5607
|
-
? loadAllEntries(hippoRoot, tenantId).filter(e => !e.superseded_by).filter(ambientAdmit)
|
|
5608
|
-
: [];
|
|
5609
|
-
const globalForAmbient = hasGlobalForAmbient
|
|
5610
|
-
? loadAllEntries(globalRoot, tenantId).filter(e => !e.superseded_by).filter(ambientAdmit)
|
|
5611
|
-
: [];
|
|
5612
|
-
const allForAmbient = [...localForAmbient, ...globalForAmbient];
|
|
5613
|
-
if (allForAmbient.length > 0) {
|
|
5614
|
-
const ambientState = computeAmbientState(allForAmbient);
|
|
5615
|
-
console.log(`\n${renderAmbientSummary(ambientState)}`);
|
|
5616
|
-
}
|
|
5598
|
+
if (result.ambientState) {
|
|
5599
|
+
console.log(`\n${renderAmbientSummary(result.ambientState)}`);
|
|
5617
5600
|
}
|
|
5618
5601
|
}
|
|
5619
5602
|
}
|
|
@@ -8130,8 +8113,11 @@ async function main() {
|
|
|
8130
8113
|
}
|
|
8131
8114
|
// Thin-client routing. When a server is up, simple `remember` calls go
|
|
8132
8115
|
// over HTTP so the daemon stays single-writer (footgun #2). Rich CLI
|
|
8133
|
-
// flags (--pin, --layer, --extract, --global
|
|
8134
|
-
//
|
|
8116
|
+
// flags (--pin, --layer, --extract, --global) still need the direct
|
|
8117
|
+
// path; we only intercept the minimal envelope. The salience gate is
|
|
8118
|
+
// NOT in richFlag and the route does not apply it, so a routed remember
|
|
8119
|
+
// stores what a direct one would skip. Measured 2026-09-07, tracked in
|
|
8120
|
+
// TODOS.md; do not read this list as covering salience.
|
|
8135
8121
|
const richFlag = flags['pin'] || flags['global'] || flags['extract'] || flags['force'] ||
|
|
8136
8122
|
flags['observed'] || flags['inferred'] || flags['verified'] ||
|
|
8137
8123
|
flags['layer'] !== undefined;
|
|
@@ -8247,10 +8233,10 @@ async function main() {
|
|
|
8247
8233
|
cmdLastSleep(flags);
|
|
8248
8234
|
break;
|
|
8249
8235
|
case 'session-end':
|
|
8250
|
-
cmdSessionEnd(hippoRoot, flags);
|
|
8236
|
+
await cmdSessionEnd(hippoRoot, flags);
|
|
8251
8237
|
break;
|
|
8252
8238
|
case '__session-end-worker':
|
|
8253
|
-
cmdSessionEndWorker(hippoRoot, flags);
|
|
8239
|
+
await cmdSessionEndWorker(hippoRoot, flags);
|
|
8254
8240
|
break;
|
|
8255
8241
|
case 'pre-compact': {
|
|
8256
8242
|
// Same TTY guard as `capture --last-session`: skip reading stdin when
|
|
@@ -8287,7 +8273,7 @@ async function main() {
|
|
|
8287
8273
|
cmdCodexRun(hippoRoot, args);
|
|
8288
8274
|
break;
|
|
8289
8275
|
case '__codex-session-end-worker':
|
|
8290
|
-
cmdCodexSessionEndWorker(hippoRoot, flags);
|
|
8276
|
+
await cmdCodexSessionEndWorker(hippoRoot, flags);
|
|
8291
8277
|
break;
|
|
8292
8278
|
case 'dedup':
|
|
8293
8279
|
cmdDedup(hippoRoot, flags);
|
|
@@ -8446,23 +8432,37 @@ async function main() {
|
|
|
8446
8432
|
console.error('Please provide a memory ID.');
|
|
8447
8433
|
process.exit(1);
|
|
8448
8434
|
}
|
|
8449
|
-
//
|
|
8450
|
-
//
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8435
|
+
// Archive has its own HTTP route (POST /v1/memories/:id/archive); route
|
|
8436
|
+
// both branches the same way the direct path does.
|
|
8437
|
+
const archive = flags['archive'] === true;
|
|
8438
|
+
const reason = typeof flags['reason'] === 'string' ? flags['reason'] : null;
|
|
8439
|
+
if (archive && !reason) {
|
|
8440
|
+
console.error(ARCHIVE_REASON_REQUIRED);
|
|
8441
|
+
process.exit(1);
|
|
8442
|
+
}
|
|
8443
|
+
const routed = await runViaServerIfAvailable(hippoRoot, async (info, apiKey) => {
|
|
8444
|
+
try {
|
|
8445
|
+
if (archive) {
|
|
8446
|
+
await client.archiveRaw(info.url, apiKey, id, reason);
|
|
8447
|
+
console.log(`Archived ${id}`);
|
|
8448
|
+
}
|
|
8449
|
+
else {
|
|
8455
8450
|
await client.forget(info.url, apiKey, id);
|
|
8456
8451
|
console.log(`Forgot ${id}`);
|
|
8457
8452
|
}
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8453
|
+
}
|
|
8454
|
+
catch (err) {
|
|
8455
|
+
// A server that died after the health probe is the caller's stale
|
|
8456
|
+
// pidfile fallback to handle, not an error to report to the user.
|
|
8457
|
+
if (client.isConnectionRefused(err))
|
|
8458
|
+
throw err;
|
|
8459
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
8460
|
+
console.error(archive ? `Could not archive ${id}: ${msg}` : msg);
|
|
8461
|
+
process.exit(1);
|
|
8462
|
+
}
|
|
8463
|
+
});
|
|
8464
|
+
if (routed)
|
|
8465
|
+
break;
|
|
8466
8466
|
cmdForget(hippoRoot, id, flags);
|
|
8467
8467
|
break;
|
|
8468
8468
|
}
|