hippo-memory 1.61.0 → 1.62.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.
Files changed (57) hide show
  1. package/README.md +28 -53
  2. package/dist/agent-memories/apply.d.ts +1 -1
  3. package/dist/agent-memories/claude-code.d.ts +3 -1
  4. package/dist/agent-memories/claude-code.js +53 -9
  5. package/dist/agent-memories/sync.d.ts +3 -3
  6. package/dist/agent-memories/sync.js +14 -6
  7. package/dist/agent-memories/types.d.ts +0 -2
  8. package/dist/api/assemble.js +55 -54
  9. package/dist/api/context-select.d.ts +49 -0
  10. package/dist/api/context-select.js +344 -0
  11. package/dist/api/context.d.ts +2 -2
  12. package/dist/api/context.js +195 -522
  13. package/dist/api/drill-down.js +36 -33
  14. package/dist/api/promote.js +55 -66
  15. package/dist/api/recall.js +303 -438
  16. package/dist/api/sleep.js +203 -218
  17. package/dist/capture/compact.d.ts +1 -1
  18. package/dist/capture/compact.js +2 -2
  19. package/dist/cli/briefs.js +324 -306
  20. package/dist/cli/context.js +44 -34
  21. package/dist/cli/continuity.js +283 -271
  22. package/dist/cli/curate.js +35 -34
  23. package/dist/cli/decisions.js +333 -333
  24. package/dist/cli/explain.js +66 -60
  25. package/dist/cli/maintenance.js +62 -51
  26. package/dist/cli/playbooks.js +387 -370
  27. package/dist/cli/projects.js +8 -5
  28. package/dist/cli/recall.js +28 -43
  29. package/dist/cli/remember.js +113 -70
  30. package/dist/cli/session-hooks.js +100 -90
  31. package/dist/cli/setup.js +267 -246
  32. package/dist/cli/status.js +73 -64
  33. package/dist/cli/transfer.js +85 -99
  34. package/dist/compaction-record.d.ts +0 -2
  35. package/dist/compaction-record.js +1 -1
  36. package/dist/customer-notes.js +77 -68
  37. package/dist/dag.js +222 -186
  38. package/dist/decisions.js +93 -76
  39. package/dist/doctor.js +11 -7
  40. package/dist/goals.js +99 -86
  41. package/dist/incidents.js +45 -38
  42. package/dist/policies.js +85 -68
  43. package/dist/processes.js +87 -71
  44. package/dist/project-briefs.js +135 -108
  45. package/dist/project-merge.d.ts +12 -4
  46. package/dist/project-merge.js +130 -45
  47. package/dist/shared.d.ts +9 -0
  48. package/dist/shared.js +10 -8
  49. package/dist/skills.js +81 -65
  50. package/dist/store/search-rows.d.ts +2 -2
  51. package/dist/store/search-rows.js +15 -9
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.js +1 -1
  54. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  55. package/extensions/openclaw-plugin/package.json +1 -1
  56. package/openclaw.plugin.json +1 -1
  57. package/package.json +1 -1
@@ -57,31 +57,39 @@ export async function cmdExplain(hippoRoot, query, flags) {
57
57
  const results = dropHeldCopies(rank.results, (r) => r.entry);
58
58
  const candidates = rank.localEntries.length + rank.globalEntries.length;
59
59
  if (asJson) {
60
- const output = results.map((r, rank) => ({
61
- rank: rank + 1,
62
- id: r.entry.id,
63
- layer: r.entry.layer,
64
- confidence: confidenceFacets(r.entry).tier,
65
- aged_out: confidenceFacets(r.entry).agedOut,
66
- score: r.score,
67
- tokens: r.tokens,
68
- tags: r.entry.tags,
69
- content: r.entry.content,
70
- breakdown: r.breakdown,
71
- }));
72
- console.log(JSON.stringify({
73
- query,
74
- mode: modeUsed,
75
- candidates,
76
- returned: output.length,
77
- results: output,
78
- }));
60
+ printExplainJson(results, query, modeUsed, candidates);
79
61
  return;
80
62
  }
81
63
  if (results.length === 0) {
82
64
  console.log(`No memories matched "${query}" (scanned ${candidates}).`);
83
65
  return;
84
66
  }
67
+ printExplainTable(results, query, modeUsed, candidates);
68
+ results.forEach((r, i) => printExplainBreakdown(r, i));
69
+ console.log('Note: explain does not mark memories as retrieved (read-only).');
70
+ }
71
+ function printExplainJson(results, query, modeUsed, candidates) {
72
+ const output = results.map((r, rank) => ({
73
+ rank: rank + 1,
74
+ id: r.entry.id,
75
+ layer: r.entry.layer,
76
+ confidence: confidenceFacets(r.entry).tier,
77
+ aged_out: confidenceFacets(r.entry).agedOut,
78
+ score: r.score,
79
+ tokens: r.tokens,
80
+ tags: r.entry.tags,
81
+ content: r.entry.content,
82
+ breakdown: r.breakdown,
83
+ }));
84
+ console.log(JSON.stringify({
85
+ query,
86
+ mode: modeUsed,
87
+ candidates,
88
+ returned: output.length,
89
+ results: output,
90
+ }));
91
+ }
92
+ function printExplainTable(results, query, modeUsed, candidates) {
85
93
  console.log(`Query: "${query}"`);
86
94
  console.log(`Mode: ${modeUsed} candidates: ${candidates} returned: ${results.length}`);
87
95
  console.log();
@@ -95,49 +103,47 @@ export async function cmdExplain(hippoRoot, query, flags) {
95
103
  console.log(`${String(i + 1).padEnd(5)} ${fmt(r.score, 3).padEnd(7)} ${fmt(r.entry.strength).padEnd(9)} ${ageStr.padEnd(6)} ${r.entry.layer.padEnd(10)} ${r.entry.id.padEnd(17)} ${preview}`);
96
104
  }
97
105
  console.log();
98
- for (let i = 0; i < results.length; i++) {
99
- const r = results[i];
100
- const b = r.breakdown;
101
- console.log(`[${i + 1}] ${r.entry.id} composite=${fmt(r.score, 4)}`);
102
- if (!b) {
103
- console.log(' (no breakdown available)');
104
- console.log();
105
- continue;
106
- }
107
- if (b.mode === 'physics') {
108
- console.log(` mode: physics-gravity`);
109
- console.log(` cosine: ${fmt(b.cosine, 3)} (pre-amp baseline)`);
110
- console.log(` final: ${fmt(b.final, 4)} (post-amp, from physics scorer)`);
111
- }
112
- else {
113
- const matched = b.matchedTerms.length > 0 ? b.matchedTerms.join(', ') : '(none)';
114
- console.log(` mode: ${b.mode}${b.mode === 'hybrid-no-vec' ? ' (no cached doc vector — run `hippo embed`)' : ''}`);
115
- console.log(` BM25: raw=${fmt(r.bm25, 3)} normalized=${fmt(b.normBm25, 3)} weight=${fmt(b.bm25Weight, 2)} matched=[${matched}]`);
116
- console.log(` embedding: cosine=${fmt(b.cosine, 3)} weight=${fmt(b.embeddingWeight, 2)}`);
117
- console.log(` base: ${fmt(b.bm25Weight, 2)}*${fmt(b.normBm25, 3)} + ${fmt(b.embeddingWeight, 2)}*${fmt(b.cosine, 3)} = ${fmt(b.base, 4)}`);
118
- console.log(` strength: x${fmt(b.strengthMultiplier, 3)} (strength=${fmt(r.entry.strength, 3)})`);
119
- console.log(` recency: x${fmt(b.recencyMultiplier, 3)} (age=${b.ageDays}d)`);
120
- if (b.decisionBoost !== 1)
121
- console.log(` decision: x${fmt(b.decisionBoost, 2)} (tagged 'decision')`);
122
- if (b.scopeBoost !== 1)
123
- console.log(` scope: x${fmt(b.scopeBoost, 2)} (scope tag ${b.scopeBoost > 1 ? 'match' : 'mismatch'})`);
124
- if (b.pathBoost !== 1)
125
- console.log(` path: x${fmt(b.pathBoost, 3)} (cwd path tag overlap)`);
126
- if (b.sourceBump !== 1)
127
- console.log(` source: x${fmt(b.sourceBump, 2)} (local priority bump over global)`);
128
- if (b.outcomeBoost !== 1)
129
- console.log(` outcome: x${fmt(b.outcomeBoost, 3)} (user feedback: pos-neg = ${(r.entry.outcome_positive ?? 0) - (r.entry.outcome_negative ?? 0)})`);
130
- if (b.churnStaleMultiplier !== 1)
131
- console.log(` churn: x${fmt(b.churnStaleMultiplier, 2)} (tagged 'churn-stale')`);
132
- if (b.preMmrRank !== undefined && b.postMmrRank !== undefined && b.preMmrRank !== b.postMmrRank) {
133
- const arrow = b.postMmrRank < b.preMmrRank ? 'up' : 'down';
134
- console.log(` mmr: rank ${b.preMmrRank} -> ${b.postMmrRank} (diversity ${arrow})`);
135
- }
136
- console.log(` final: ${fmt(b.final, 4)}`);
137
- }
106
+ }
107
+ function printExplainBreakdown(r, i) {
108
+ const b = r.breakdown;
109
+ console.log(`[${i + 1}] ${r.entry.id} composite=${fmt(r.score, 4)}`);
110
+ if (!b) {
111
+ console.log(' (no breakdown available)');
138
112
  console.log();
113
+ return;
139
114
  }
140
- console.log('Note: explain does not mark memories as retrieved (read-only).');
115
+ if (b.mode === 'physics') {
116
+ console.log(` mode: physics-gravity`);
117
+ console.log(` cosine: ${fmt(b.cosine, 3)} (pre-amp baseline)`);
118
+ console.log(` final: ${fmt(b.final, 4)} (post-amp, from physics scorer)`);
119
+ }
120
+ else {
121
+ const matched = b.matchedTerms.length > 0 ? b.matchedTerms.join(', ') : '(none)';
122
+ console.log(` mode: ${b.mode}${b.mode === 'hybrid-no-vec' ? ' (no cached doc vector — run `hippo embed`)' : ''}`);
123
+ console.log(` BM25: raw=${fmt(r.bm25, 3)} normalized=${fmt(b.normBm25, 3)} weight=${fmt(b.bm25Weight, 2)} matched=[${matched}]`);
124
+ console.log(` embedding: cosine=${fmt(b.cosine, 3)} weight=${fmt(b.embeddingWeight, 2)}`);
125
+ console.log(` base: ${fmt(b.bm25Weight, 2)}*${fmt(b.normBm25, 3)} + ${fmt(b.embeddingWeight, 2)}*${fmt(b.cosine, 3)} = ${fmt(b.base, 4)}`);
126
+ console.log(` strength: x${fmt(b.strengthMultiplier, 3)} (strength=${fmt(r.entry.strength, 3)})`);
127
+ console.log(` recency: x${fmt(b.recencyMultiplier, 3)} (age=${b.ageDays}d)`);
128
+ if (b.decisionBoost !== 1)
129
+ console.log(` decision: x${fmt(b.decisionBoost, 2)} (tagged 'decision')`);
130
+ if (b.scopeBoost !== 1)
131
+ console.log(` scope: x${fmt(b.scopeBoost, 2)} (scope tag ${b.scopeBoost > 1 ? 'match' : 'mismatch'})`);
132
+ if (b.pathBoost !== 1)
133
+ console.log(` path: x${fmt(b.pathBoost, 3)} (cwd path tag overlap)`);
134
+ if (b.sourceBump !== 1)
135
+ console.log(` source: x${fmt(b.sourceBump, 2)} (local priority bump over global)`);
136
+ if (b.outcomeBoost !== 1)
137
+ console.log(` outcome: x${fmt(b.outcomeBoost, 3)} (user feedback: pos-neg = ${(r.entry.outcome_positive ?? 0) - (r.entry.outcome_negative ?? 0)})`);
138
+ if (b.churnStaleMultiplier !== 1)
139
+ console.log(` churn: x${fmt(b.churnStaleMultiplier, 2)} (tagged 'churn-stale')`);
140
+ if (b.preMmrRank !== undefined && b.postMmrRank !== undefined && b.preMmrRank !== b.postMmrRank) {
141
+ const arrow = b.postMmrRank < b.preMmrRank ? 'up' : 'down';
142
+ console.log(` mmr: rank ${b.preMmrRank} -> ${b.postMmrRank} (diversity ${arrow})`);
143
+ }
144
+ console.log(` final: ${fmt(b.final, 4)}`);
145
+ }
146
+ console.log();
141
147
  }
142
148
  export async function handleExplain({ hippoRoot, args, flags }) {
143
149
  const query = args.join(' ').trim();
@@ -102,34 +102,60 @@ export async function cmdEmbed(hippoRoot, flags) {
102
102
  // when no provider key is present (e.g. embedded earlier with a key that was
103
103
  // later removed). The provider-availability gate is deferred to the embed path.
104
104
  if (flags['reset-physics']) {
105
- const entries = loadAllEntries(root);
106
- const embIndex = loadEmbeddingIndex(root);
107
- const db = openHippoDb(root);
108
- try {
109
- const count = resetAllPhysicsState(db, entries, embIndex);
110
- console.log(`Reset physics state: ${count} particles re-initialized from embeddings.`);
111
- }
112
- finally {
113
- closeHippoDb(db);
114
- }
105
+ resetPhysics(root);
115
106
  return;
116
107
  }
117
108
  if (flags['status']) {
118
- const entries = loadAllEntries(root);
119
- const embIndex = loadEmbeddingIndex(root);
120
- const activeIds = new Set(entries.map((e) => e.id));
121
- const activeEmbedded = Object.keys(embIndex).filter((id) => activeIds.has(id)).length;
122
- const orphaned = Object.keys(embIndex).length - activeEmbedded;
123
- console.log(`Embedding status: ${activeEmbedded}/${entries.length} memories embedded`);
124
- if (orphaned > 0) {
125
- console.log(` ${orphaned} orphaned embeddings (run \`hippo embed\` to prune)`);
126
- }
127
- const missing = entries.filter((e) => !embIndex[e.id]);
128
- if (missing.length > 0) {
129
- console.log(` ${missing.length} memories need embedding (run \`hippo embed\` to embed them)`);
130
- }
109
+ printEmbedStatus(root);
110
+ return;
111
+ }
112
+ if (!embedProviderReady(root))
131
113
  return;
114
+ console.log('Embedding all memories (this may take a moment on first run to download model)...');
115
+ let count;
116
+ try {
117
+ count = await embedAll(root, resolveEmbeddingModel(root));
132
118
  }
119
+ catch (err) {
120
+ printError(`Embedding failed: ${err instanceof Error ? err.message : String(err)}`);
121
+ const partial = loadEmbeddingIndex(root);
122
+ printError(`Partial progress saved: ${Object.keys(partial).length} embeddings on disk. Re-run \`hippo embed\` to resume.`);
123
+ process.exitCode = 1;
124
+ return;
125
+ }
126
+ const entriesAfter = loadAllEntries(root);
127
+ const embIndexAfter = loadEmbeddingIndex(root);
128
+ console.log(`Done. ${count} new embeddings created. ${Object.keys(embIndexAfter).length}/${entriesAfter.length} total.`);
129
+ }
130
+ function resetPhysics(root) {
131
+ const entries = loadAllEntries(root);
132
+ const embIndex = loadEmbeddingIndex(root);
133
+ const db = openHippoDb(root);
134
+ try {
135
+ const count = resetAllPhysicsState(db, entries, embIndex);
136
+ console.log(`Reset physics state: ${count} particles re-initialized from embeddings.`);
137
+ }
138
+ finally {
139
+ closeHippoDb(db);
140
+ }
141
+ }
142
+ function printEmbedStatus(root) {
143
+ const entries = loadAllEntries(root);
144
+ const embIndex = loadEmbeddingIndex(root);
145
+ const activeIds = new Set(entries.map((e) => e.id));
146
+ const activeEmbedded = Object.keys(embIndex).filter((id) => activeIds.has(id)).length;
147
+ const orphaned = Object.keys(embIndex).length - activeEmbedded;
148
+ console.log(`Embedding status: ${activeEmbedded}/${entries.length} memories embedded`);
149
+ if (orphaned > 0) {
150
+ console.log(` ${orphaned} orphaned embeddings (run \`hippo embed\` to prune)`);
151
+ }
152
+ const missing = entries.filter((e) => !embIndex[e.id]);
153
+ if (missing.length > 0) {
154
+ console.log(` ${missing.length} memories need embedding (run \`hippo embed\` to embed them)`);
155
+ }
156
+ }
157
+ /** False, after saying why, when no usable provider exists. */
158
+ function embedProviderReady(root) {
133
159
  // Embedding (unlike status/reset) needs an available provider.
134
160
  const embedProvider = (() => {
135
161
  try {
@@ -142,38 +168,23 @@ export async function cmdEmbed(hippoRoot, flags) {
142
168
  })();
143
169
  if (!embedProvider) {
144
170
  process.exitCode = 1;
145
- return;
171
+ return false;
146
172
  }
147
- if (!embedProvider.isAvailable()) {
148
- if (loadConfig(root).embeddings.enabled === false) {
149
- console.log('Embeddings are disabled in config (embeddings.enabled = false). Set it to true or "auto" to enable.');
150
- return;
151
- }
152
- if (embedProvider.kind === 'local') {
153
- console.log('Embeddings not available. Install @huggingface/transformers to enable:');
154
- console.log(' npm install @huggingface/transformers');
155
- }
156
- else {
157
- printError(`Embedding provider '${embedProvider.kind}' is configured but ${embedProvider.keyEnv} is not set.`);
158
- printError(`Export ${embedProvider.keyEnv}, or set config.embeddings.provider back to 'local'.`);
159
- process.exitCode = 1;
160
- }
161
- return;
173
+ if (embedProvider.isAvailable())
174
+ return true;
175
+ if (loadConfig(root).embeddings.enabled === false) {
176
+ console.log('Embeddings are disabled in config (embeddings.enabled = false). Set it to true or "auto" to enable.');
177
+ return false;
162
178
  }
163
- console.log('Embedding all memories (this may take a moment on first run to download model)...');
164
- let count;
165
- try {
166
- count = await embedAll(root, resolveEmbeddingModel(root));
179
+ if (embedProvider.kind === 'local') {
180
+ console.log('Embeddings not available. Install @huggingface/transformers to enable:');
181
+ console.log(' npm install @huggingface/transformers');
167
182
  }
168
- catch (err) {
169
- printError(`Embedding failed: ${err instanceof Error ? err.message : String(err)}`);
170
- const partial = loadEmbeddingIndex(root);
171
- printError(`Partial progress saved: ${Object.keys(partial).length} embeddings on disk. Re-run \`hippo embed\` to resume.`);
183
+ else {
184
+ printError(`Embedding provider '${embedProvider.kind}' is configured but ${embedProvider.keyEnv} is not set.`);
185
+ printError(`Export ${embedProvider.keyEnv}, or set config.embeddings.provider back to 'local'.`);
172
186
  process.exitCode = 1;
173
- return;
174
187
  }
175
- const entriesAfter = loadAllEntries(root);
176
- const embIndexAfter = loadEmbeddingIndex(root);
177
- console.log(`Done. ${count} new embeddings created. ${Object.keys(embIndexAfter).length}/${entriesAfter.length} total.`);
188
+ return false;
178
189
  }
179
190
  //# sourceMappingURL=maintenance.js.map