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
@@ -86,16 +86,8 @@ async function renderContext(hippoRoot, args, flags, stdinText, rec) {
86
86
  if (!pinnedOnly) {
87
87
  requireInit(hippoRoot);
88
88
  }
89
- // The session id bounds the active-task-snapshot read: the stdin hook payload wins, then hostSessionId();
90
- // absent both, api.getContext applies the pure freshness bound.
91
- const payload = readHookPayload(stdinText);
92
- let payloadSessionId = payload.sessionId;
93
- const currentSessionId = payloadSessionId ?? hostSessionId();
94
- // A sub-agent's payload and env both carry its parent's session id, so it books no session and never skips a block.
95
- const subagent = isSubagentPayload(stdinText);
96
- const ledgerSessionId = subagent ? undefined : currentSessionId;
97
- if (subagent)
98
- payloadSessionId = undefined;
89
+ const session = resolveContextSession(stdinText);
90
+ const { currentSessionId, ledgerSessionId, payloadSessionId } = session;
99
91
  // The pilot arm is booked at the first hook call whatever the flags, so the holdout sees no budget or content branch.
100
92
  const resolvedTenant = resolveTenantId({});
101
93
  if (inPilotHoldout(hippoRoot, resolvedTenant, currentSessionId, payloadSessionId !== undefined)) {
@@ -112,38 +104,16 @@ async function renderContext(hippoRoot, args, flags, stdinText, rec) {
112
104
  if (!query && flags['auto']) {
113
105
  query = autoDetectContext();
114
106
  }
115
- // Scope detection uses cwd, so it is resolved here and passed in via opts.scope.
116
- const ctxExplicitScope = flags['scope'] !== undefined ? String(flags['scope']).trim() : null;
117
- const ctxActiveScope = ctxExplicitScope || detectScope();
118
107
  const ctx = {
119
108
  hippoRoot,
120
109
  tenantId: resolvedTenant,
121
110
  actor: api.adminActor('cli'),
122
111
  };
123
- // --cross-project re-includes other-project memories, rendered under their own section.
124
- const crossProject = flags['cross-project'] === true;
125
112
  const format = String(flags['format'] ?? 'markdown');
126
113
  const framing = String(flags['framing'] ?? 'observe');
127
- const opts = {
128
- q: query,
129
- budget,
130
- limit: parseLimitFlag(flags['limit']),
131
- pinnedOnly,
132
- scope: ctxActiveScope ?? undefined,
133
- includeRecent: parseCountFlag(flags['include-recent']),
134
- crossProject,
135
- currentSessionId,
136
- prompt: payload.prompt,
137
- // JSON is budgeted as the markdown it stands for, so one budget picks the same memories in every format.
138
- cost: contextCost(format === 'additional-context' ? 'additional-context' : 'markdown', framing),
139
- deliveryObserver: rec ?? undefined,
140
- };
114
+ const opts = buildContextOpts(flags, { query, budget, pinnedOnly, format, framing, session, rec });
141
115
  const result = await api.getContext(ctx, opts);
142
- const hasContextData = result.entries.length > 0 ||
143
- result.activeSnapshot ||
144
- result.sessionHandoff ||
145
- (result.recentEvents && result.recentEvents.length > 0);
146
- if (!hasContextData) {
116
+ if (!hasContextData(result)) {
147
117
  rec?.delivered({ state: 'empty' });
148
118
  return;
149
119
  }
@@ -158,6 +128,46 @@ async function renderContext(hippoRoot, args, flags, stdinText, rec) {
158
128
  renderContextMarkdown(view);
159
129
  }
160
130
  }
131
+ function resolveContextSession(stdinText) {
132
+ // The session id bounds the active-task-snapshot read: the stdin hook payload wins, then hostSessionId();
133
+ // absent both, api.getContext applies the pure freshness bound.
134
+ const payload = readHookPayload(stdinText);
135
+ let payloadSessionId = payload.sessionId;
136
+ const currentSessionId = payloadSessionId ?? hostSessionId();
137
+ // A sub-agent's payload and env both carry its parent's session id, so it books no session and never skips a block.
138
+ const subagent = isSubagentPayload(stdinText);
139
+ const ledgerSessionId = subagent ? undefined : currentSessionId;
140
+ if (subagent)
141
+ payloadSessionId = undefined;
142
+ return { currentSessionId, ledgerSessionId, payloadSessionId, prompt: payload.prompt };
143
+ }
144
+ function buildContextOpts(flags, input) {
145
+ // Scope detection uses cwd, so it is resolved here and passed in via opts.scope.
146
+ const ctxExplicitScope = flags['scope'] !== undefined ? String(flags['scope']).trim() : null;
147
+ const ctxActiveScope = ctxExplicitScope || detectScope();
148
+ // --cross-project re-includes other-project memories, rendered under their own section.
149
+ const crossProject = flags['cross-project'] === true;
150
+ return {
151
+ q: input.query,
152
+ budget: input.budget,
153
+ limit: parseLimitFlag(flags['limit']),
154
+ pinnedOnly: input.pinnedOnly,
155
+ scope: ctxActiveScope ?? undefined,
156
+ includeRecent: parseCountFlag(flags['include-recent']),
157
+ crossProject,
158
+ currentSessionId: input.session.currentSessionId,
159
+ prompt: input.session.prompt,
160
+ // JSON is budgeted as the markdown it stands for, so one budget picks the same memories in every format.
161
+ cost: contextCost(input.format === 'additional-context' ? 'additional-context' : 'markdown', input.framing),
162
+ deliveryObserver: input.rec ?? undefined,
163
+ };
164
+ }
165
+ function hasContextData(result) {
166
+ return Boolean(result.entries.length > 0 ||
167
+ result.activeSnapshot ||
168
+ result.sessionHandoff ||
169
+ (result.recentEvents && result.recentEvents.length > 0));
170
+ }
161
171
  function toRenderItems(entries) {
162
172
  return entries.map((r) => ({ entry: r.entry, score: r.score, tokens: r.tokens, isGlobal: r.isGlobal ?? false }));
163
173
  }