hippo-memory 1.72.0 → 2.0.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 (259) hide show
  1. package/README.md +6 -4
  2. package/dist/agent-memories/apply.js +5 -5
  3. package/dist/api/assemble.js +2 -1
  4. package/dist/api/audit.d.ts +7 -7
  5. package/dist/api/audit.js +19 -17
  6. package/dist/api/auth.d.ts +5 -6
  7. package/dist/api/auth.js +28 -33
  8. package/dist/api/conflicts.js +1 -1
  9. package/dist/api/context-auto.js +4 -2
  10. package/dist/api/context-select.js +8 -20
  11. package/dist/api/context.js +12 -10
  12. package/dist/api/drill-down.js +2 -1
  13. package/dist/api/forget.d.ts +2 -2
  14. package/dist/api/forget.js +6 -7
  15. package/dist/api/graph.js +2 -1
  16. package/dist/api/learn.d.ts +1 -1
  17. package/dist/api/learn.js +45 -44
  18. package/dist/api/memories.d.ts +4 -2
  19. package/dist/api/memories.js +16 -5
  20. package/dist/api/objects.js +2 -1
  21. package/dist/api/outcome.d.ts +5 -5
  22. package/dist/api/outcome.js +16 -15
  23. package/dist/api/predictions.js +2 -1
  24. package/dist/api/promote.d.ts +3 -3
  25. package/dist/api/promote.js +25 -27
  26. package/dist/api/prompt-hook.d.ts +3 -1
  27. package/dist/api/prompt-hook.js +1 -0
  28. package/dist/api/quarantine.js +2 -1
  29. package/dist/api/recall-core.js +8 -3
  30. package/dist/api/recall-pipeline.js +17 -17
  31. package/dist/api/recall-types.d.ts +3 -1
  32. package/dist/api/recall.js +32 -29
  33. package/dist/api/remember-local.d.ts +5 -2
  34. package/dist/api/remember-local.js +14 -6
  35. package/dist/api/remember.d.ts +5 -2
  36. package/dist/api/remember.js +16 -14
  37. package/dist/api/session-end.d.ts +24 -0
  38. package/dist/api/session-end.js +31 -1
  39. package/dist/api/sleep-run.js +5 -4
  40. package/dist/api/sleep.js +4 -3
  41. package/dist/api/tokens.js +1 -1
  42. package/dist/api/types.d.ts +1 -7
  43. package/dist/capture/command.js +1 -1
  44. package/dist/capture/compaction-spool.d.ts +3 -5
  45. package/dist/capture/compaction-spool.js +41 -46
  46. package/dist/capture/session-end-caller.js +1 -1
  47. package/dist/capture/session-worker.js +19 -6
  48. package/dist/cli/audit.js +10 -10
  49. package/dist/cli/auth.js +4 -4
  50. package/dist/cli/client.d.ts +1 -2
  51. package/dist/cli/client.js +13 -13
  52. package/dist/cli/context.js +1 -1
  53. package/dist/cli/curate.d.ts +1 -1
  54. package/dist/cli/curate.js +9 -9
  55. package/dist/cli/decisions.js +4 -5
  56. package/dist/cli/hook-runtime.d.ts +3 -1
  57. package/dist/cli/hook-runtime.js +2 -2
  58. package/dist/cli/init.d.ts +1 -1
  59. package/dist/cli/init.js +9 -9
  60. package/dist/cli/object-verbs.d.ts +2 -2
  61. package/dist/cli/object-verbs.js +4 -4
  62. package/dist/cli/predictions.js +2 -3
  63. package/dist/cli/quality-repair-once.d.ts +1 -1
  64. package/dist/cli/quality-repair-once.js +2 -2
  65. package/dist/cli/refine-llm.js +2 -1
  66. package/dist/cli/remember.js +5 -5
  67. package/dist/cli/serve.js +9 -4
  68. package/dist/cli/session-hooks.d.ts +0 -4
  69. package/dist/cli/session-hooks.js +57 -66
  70. package/dist/cli/setup.d.ts +1 -1
  71. package/dist/cli/setup.js +2 -2
  72. package/dist/cli/shared.d.ts +1 -1
  73. package/dist/cli/shared.js +2 -2
  74. package/dist/cli/sleep.js +2 -2
  75. package/dist/cli/transfer.d.ts +3 -3
  76. package/dist/cli/transfer.js +34 -15
  77. package/dist/cli/usage.d.ts +1 -1
  78. package/dist/cli/usage.js +1 -1
  79. package/dist/cli/verb-row.d.ts +2 -0
  80. package/dist/cli/verbs/health.js +2 -0
  81. package/dist/cli/verbs/memory.js +43 -51
  82. package/dist/cli/verbs/objects.js +6 -3
  83. package/dist/cli/verbs/sessions.js +4 -2
  84. package/dist/cli.js +1 -2
  85. package/dist/connectors/dlq.js +2 -1
  86. package/dist/connectors/github/deletion.js +2 -1
  87. package/dist/connectors/github/ingest.js +2 -1
  88. package/dist/connectors/github/tenant-routing.js +2 -1
  89. package/dist/connectors/github/webhook.js +4 -2
  90. package/dist/connectors/ingest.js +2 -1
  91. package/dist/connectors/slack/deletion.js +2 -1
  92. package/dist/connectors/slack/ingest.js +2 -1
  93. package/dist/connectors/slack/tenant-routing.js +2 -1
  94. package/dist/consolidate/conflicts.js +1 -1
  95. package/dist/consolidate/dag.js +14 -9
  96. package/dist/consolidate/dedupe.js +1 -1
  97. package/dist/consolidate/memory-value.js +1 -1
  98. package/dist/consolidate/merge.js +6 -6
  99. package/dist/consolidate/sleep.js +1 -1
  100. package/dist/consolidate/traces.js +2 -2
  101. package/dist/core/config.js +15 -16
  102. package/dist/core/markdown.js +2 -2
  103. package/dist/core/memory.d.ts +4 -4
  104. package/dist/core/memory.js +10 -5
  105. package/dist/core/physics.d.ts +3 -1
  106. package/dist/core/physics.js +17 -2
  107. package/dist/core/project-identity.js +2 -1
  108. package/dist/core/search-types.d.ts +1 -1
  109. package/dist/dashboard/dashboard-actions.d.ts +2 -2
  110. package/dist/dashboard/dashboard-actions.js +5 -5
  111. package/dist/dashboard/dashboard-queries.js +2 -7
  112. package/dist/dashboard/dashboard-snapshot.js +1 -3
  113. package/dist/dashboard/dashboard.js +16 -5
  114. package/dist/db/connect.d.ts +2 -1
  115. package/dist/db/connect.js +2 -1
  116. package/dist/db/migrate.js +14 -7
  117. package/dist/db/migrations/v11.js +1 -0
  118. package/dist/db/migrations/v14.js +1 -0
  119. package/dist/db/physics-state.d.ts +0 -4
  120. package/dist/db/physics-state.js +5 -31
  121. package/dist/db/request-stores.d.ts +1 -0
  122. package/dist/db/request-stores.js +2 -1
  123. package/dist/db/vector-store.js +2 -1
  124. package/dist/doctor.d.ts +3 -0
  125. package/dist/doctor.js +7 -7
  126. package/dist/embeddings/local.js +2 -2
  127. package/dist/embeddings/provider.js +1 -10
  128. package/dist/entry/store-kit.d.ts +37 -0
  129. package/dist/entry/store-kit.js +25 -0
  130. package/dist/entry/testing.d.ts +6 -0
  131. package/dist/entry/testing.js +7 -0
  132. package/dist/eval/judgment.js +1 -1
  133. package/dist/hooks/json-hooks.js +6 -2
  134. package/dist/importers/core.js +3 -3
  135. package/dist/importers/vault.d.ts +1 -1
  136. package/dist/importers/vault.js +18 -18
  137. package/dist/index.d.ts +2 -2
  138. package/dist/index.js +1 -1
  139. package/dist/learn/autolearn.d.ts +6 -2
  140. package/dist/learn/autolearn.js +8 -6
  141. package/dist/learn/extract.js +1 -1
  142. package/dist/learn/invalidation.d.ts +2 -1
  143. package/dist/learn/invalidation.js +10 -5
  144. package/dist/mcp/memory-tools.d.ts +1 -1
  145. package/dist/mcp/memory-tools.js +6 -9
  146. package/dist/mcp/request.js +20 -19
  147. package/dist/mcp/stdio.js +13 -8
  148. package/dist/rerankers/cross-encoder.js +10 -3
  149. package/dist/search/embed-memories.d.ts +5 -2
  150. package/dist/search/embed-memories.js +40 -28
  151. package/dist/search/engine.d.ts +8 -0
  152. package/dist/search/engine.js +10 -0
  153. package/dist/search/vector.js +5 -5
  154. package/dist/server/auth.d.ts +1 -1
  155. package/dist/server/auth.js +7 -8
  156. package/dist/server/boot.d.ts +2 -1
  157. package/dist/server/boot.js +28 -19
  158. package/dist/server/client-ip.d.ts +9 -4
  159. package/dist/server/client-ip.js +35 -17
  160. package/dist/server/route-table.js +5 -6
  161. package/dist/server/routes/memories.js +4 -2
  162. package/dist/server/sleep-offload.js +3 -3
  163. package/dist/server/tls.d.ts +7 -2
  164. package/dist/server/tls.js +17 -5
  165. package/dist/server/types.d.ts +7 -2
  166. package/dist/server.d.ts +4 -41
  167. package/dist/server.js +3 -30
  168. package/dist/sharing/global-store.d.ts +4 -5
  169. package/dist/sharing/global-store.js +6 -11
  170. package/dist/sharing/global-sync.js +1 -1
  171. package/dist/sharing/search-both.js +9 -2
  172. package/dist/sharing/share.js +2 -4
  173. package/dist/store/ambient.js +2 -1
  174. package/dist/store/candidates.js +18 -8
  175. package/dist/store/cards.js +5 -4
  176. package/dist/store/compactions-record.js +8 -7
  177. package/dist/store/conflicts.d.ts +7 -1
  178. package/dist/store/conflicts.js +6 -5
  179. package/dist/store/connectors/dlq.js +2 -1
  180. package/dist/store/connectors/event-log.d.ts +13 -0
  181. package/dist/store/connectors/event-log.js +24 -0
  182. package/dist/store/connectors/github.js +6 -8
  183. package/dist/store/connectors/slack.js +6 -10
  184. package/dist/store/dashboard-reads.js +1 -0
  185. package/dist/store/delete-and-batch.js +5 -4
  186. package/dist/store/delivery-recorder.d.ts +2 -2
  187. package/dist/store/delivery-recorder.js +1 -6
  188. package/dist/store/descendant-page.js +2 -1
  189. package/dist/store/dormant.js +7 -3
  190. package/dist/store/entry-reads.d.ts +25 -3
  191. package/dist/store/entry-reads.js +43 -12
  192. package/dist/store/entry-row.js +9 -2
  193. package/dist/store/entry-writes.d.ts +10 -7
  194. package/dist/store/entry-writes.js +23 -11
  195. package/dist/store/goals.js +3 -2
  196. package/dist/store/graph-reads.js +5 -4
  197. package/dist/store/graph-view-rows.js +2 -1
  198. package/dist/store/half-life.js +2 -2
  199. package/dist/store/handoffs.d.ts +9 -3
  200. package/dist/store/handoffs.js +4 -3
  201. package/dist/store/index.d.ts +2 -2
  202. package/dist/store/index.js +1 -1
  203. package/dist/store/mirrors.js +9 -4
  204. package/dist/store/open.d.ts +2 -1
  205. package/dist/store/open.js +2 -1
  206. package/dist/store/port.d.ts +59 -3
  207. package/dist/store/quality-repair.js +1 -1
  208. package/dist/store/recall-trace.js +2 -1
  209. package/dist/store/rejected-values.js +14 -9
  210. package/dist/store/rows.js +2 -2
  211. package/dist/store/rule-sql.d.ts +2 -0
  212. package/dist/store/rule-sql.js +12 -6
  213. package/dist/store/search-rows.d.ts +5 -5
  214. package/dist/store/search-rows.js +9 -12
  215. package/dist/store/set-aside.js +1 -1
  216. package/dist/store/sqlite/connector-writes-group.js +3 -1
  217. package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
  218. package/dist/store/sqlite/entry-writes-group.js +1 -1
  219. package/dist/store/sqlite/held-connection.d.ts +2 -0
  220. package/dist/store/sqlite/held-connection.js +1 -1
  221. package/dist/store/sqlite/last-recall-group.d.ts +13 -0
  222. package/dist/store/sqlite/last-recall-group.js +57 -0
  223. package/dist/store/sqlite/local.d.ts +0 -17
  224. package/dist/store/sqlite/local.js +0 -31
  225. package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
  226. package/dist/store/sqlite/maintenance-groups.js +60 -0
  227. package/dist/store/sqlite/objects-group.js +14 -6
  228. package/dist/store/sqlite/store.d.ts +1 -8
  229. package/dist/store/sqlite/store.js +13 -24
  230. package/dist/store/summaries.d.ts +7 -0
  231. package/dist/store/summaries.js +49 -7
  232. package/dist/store/token-ledger-rows.js +3 -2
  233. package/dist/store/vector-index.js +5 -2
  234. package/dist/util/anthropic-messages.d.ts +3 -1
  235. package/dist/util/anthropic-messages.js +4 -2
  236. package/dist/util/atomic-write.d.ts +5 -2
  237. package/dist/util/atomic-write.js +12 -8
  238. package/dist/util/env.d.ts +10 -1
  239. package/dist/util/env.js +10 -1
  240. package/dist/util/format.d.ts +2 -0
  241. package/dist/util/format.js +4 -0
  242. package/dist/util/request-scope.d.ts +6 -2
  243. package/dist/util/request-scope.js +7 -3
  244. package/dist/util/spawn-argv.d.ts +9 -0
  245. package/dist/util/spawn-argv.js +57 -0
  246. package/dist/util/sql.d.ts +3 -0
  247. package/dist/util/sql.js +6 -0
  248. package/dist/util/vector-codec.d.ts +4 -0
  249. package/dist/util/vector-codec.js +15 -0
  250. package/dist/util/version.d.ts +1 -1
  251. package/dist/util/version.js +1 -1
  252. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  253. package/extensions/openclaw-plugin/package.json +1 -1
  254. package/openclaw.plugin.json +1 -1
  255. package/package.json +3 -1
  256. package/dist/api/on-store.d.ts +0 -16
  257. package/dist/api/on-store.js +0 -38
  258. package/dist/cli/lenient-id.d.ts +0 -2
  259. package/dist/cli/lenient-id.js +0 -13
@@ -7,7 +7,6 @@ import { nonEmptyStringFlag, flagIsTrue, stringFlag } from './flag-values.js';
7
7
  import { requireInit } from './shared.js';
8
8
  import { cliApiContext } from './api-context.js';
9
9
  import { closeObject, foundOrExit, idArgOrExit, listObjects, printLifecycleTail } from './object-verbs.js';
10
- import { parseObjectId } from './lenient-id.js';
11
10
  import { errorMessage } from '../util/log.js';
12
11
  import { CliExit } from './exit.js';
13
12
  const DECISION = { cmd: 'decide', noun: 'Decision', idLabel: 'decision' };
@@ -27,7 +26,7 @@ function decideList(hippoRoot, tenantId, flags) {
27
26
  });
28
27
  }
29
28
  function decideGet(hippoRoot, tenantId, args) {
30
- const id = idArgOrExit(args, 'Usage: hippo decide get <id>', DECISION.idLabel, parseObjectId);
29
+ const id = idArgOrExit(args, 'Usage: hippo decide get <id>', DECISION.idLabel);
31
30
  const decision = foundOrExit(decisionsModule.loadDecisionById(hippoRoot, tenantId, id), DECISION.noun, id);
32
31
  console.log(`Decision #${decision.id}`);
33
32
  console.log(` status: ${decision.status}`);
@@ -37,7 +36,7 @@ function decideGet(hippoRoot, tenantId, args) {
37
36
  printLifecycleTail(decision);
38
37
  }
39
38
  function decideClose(hippoRoot, tenantId, args) {
40
- closeObject(args, DECISION, (id) => decisionsModule.closeDecision(hippoRoot, tenantId, id), parseObjectId);
39
+ closeObject(args, DECISION, (id) => decisionsModule.closeDecision(hippoRoot, tenantId, id));
41
40
  }
42
41
  export async function handleDecide({ hippoRoot, tenantId, args, flags }) {
43
42
  requireInit(hippoRoot);
@@ -83,7 +82,7 @@ async function decideCreate(hippoRoot, tenantId, decisionText, flags) {
83
82
  extraTags: decisionPathTags,
84
83
  });
85
84
  if (oldEntry)
86
- weakenSupersededMemory(hippoRoot, oldEntry, supersedesMemId);
85
+ weakenOrWarn(hippoRoot, oldEntry, supersedesMemId);
87
86
  console.log(`Decision recorded: #${created.id}`);
88
87
  if (created.memoryId)
89
88
  console.log(` memory: ${created.memoryId}`);
@@ -97,7 +96,7 @@ function exitWithDecideUsage() {
97
96
  printError(' hippo decide close <id>');
98
97
  throw new CliExit(1);
99
98
  }
100
- function weakenSupersededMemory(hippoRoot, oldEntry, supersedesMemId) {
99
+ function weakenOrWarn(hippoRoot, oldEntry, supersedesMemId) {
101
100
  // Best-effort and last: saveDecision already committed. Failing here would make a retry find no active
102
101
  // decision for the old memory and create a duplicate active successor, so warn instead.
103
102
  try {
@@ -25,5 +25,7 @@ export declare function payloadCwdRoot(hippoRoot: string, stdinText: string | un
25
25
  * work with one warning, exit 0. */
26
26
  export declare function runHookWithStores<T>(fn: () => T | Promise<T>): Promise<T | undefined>;
27
27
  /** Whether this session sits in the pilot's holdout arm; off at rate 0 and with no session id. */
28
- export declare function inPilotHoldout(hippoRoot: string, tenantId: string, sessionId: string | undefined, write: boolean): boolean;
28
+ export declare function inPilotHoldout(hippoRoot: string, tenantId: string, sessionId: string | undefined, opts: {
29
+ write: boolean;
30
+ }): boolean;
29
31
  //# sourceMappingURL=hook-runtime.d.ts.map
@@ -106,7 +106,7 @@ export async function runHookWithStores(fn) {
106
106
  }
107
107
  }
108
108
  /** Whether this session sits in the pilot's holdout arm; off at rate 0 and with no session id. */
109
- export function inPilotHoldout(hippoRoot, tenantId, sessionId, write) {
110
- return sessionPilotArm(hippoRoot, tenantId, sessionId, write) === 'holdout';
109
+ export function inPilotHoldout(hippoRoot, tenantId, sessionId, opts) {
110
+ return sessionPilotArm(hippoRoot, tenantId, sessionId, opts.write) === 'holdout';
111
111
  }
112
112
  //# sourceMappingURL=hook-runtime.js.map
@@ -1,3 +1,3 @@
1
1
  import { type CommandContext } from './flag-values.js';
2
- export declare function handleInit({ hippoRoot, tenantId, flags }: CommandContext): void;
2
+ export declare function handleInit({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
3
3
  //# sourceMappingURL=init.d.ts.map
package/dist/cli/init.js CHANGED
@@ -68,12 +68,12 @@ function initScannedRepo(repo, tenantId, globalRoot) {
68
68
  return alreadyExists;
69
69
  }
70
70
  /** Seeds one scanned repo from git history and its agents' notes, unless --no-learn. */
71
- function learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport) {
71
+ async function learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport) {
72
72
  const repoHippo = path.join(repo, '.hippo');
73
73
  let added = 0;
74
74
  let lowInfo = 0;
75
75
  if (learn && isGitRepo(repo)) {
76
- const result = learnFromRepo(repoHippo, tenantId, repo, seedDays, path.basename(repo));
76
+ const result = await learnFromRepo(repoHippo, tenantId, repo, seedDays, path.basename(repo));
77
77
  added = result.added;
78
78
  lowInfo = result.lowInfo;
79
79
  }
@@ -102,7 +102,7 @@ function printScanSummary(repoCount, totalLessons, totalLowInfo) {
102
102
  (totalLowInfo > 0 ? `, ${totalLowInfo} low-information subject(s) dropped` : '') +
103
103
  '.');
104
104
  }
105
- function cmdInitScan(scanDir, tenantId, flags) {
105
+ async function cmdInitScan(scanDir, tenantId, flags) {
106
106
  const resolved = path.resolve(scanDir);
107
107
  console.log(`Scanning ${resolved} for git repositories...\n`);
108
108
  const repos = scanForGitRepos(resolved);
@@ -121,7 +121,7 @@ function cmdInitScan(scanDir, tenantId, flags) {
121
121
  const learn = !flags['no-learn'];
122
122
  for (const repo of repos) {
123
123
  const alreadyExists = initScannedRepo(repo, tenantId, globalRoot);
124
- const { added, lowInfo } = learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport);
124
+ const { added, lowInfo } = await learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport);
125
125
  totalLessons += added;
126
126
  totalLowInfo += lowInfo;
127
127
  const status = alreadyExists ? 'existing' : 'new';
@@ -153,12 +153,12 @@ function initGlobalOnly(flags) {
153
153
  if (!flags['no-learn'])
154
154
  printAgentImport(importUserMemories(globalRoot, { machine: currentMachine() }));
155
155
  }
156
- function seedFromGitHistory(hippoRoot, tenantId) {
156
+ async function seedFromGitHistory(hippoRoot, tenantId) {
157
157
  if (!isGitRepo(process.cwd()))
158
158
  return;
159
159
  const seedDays = 30;
160
160
  console.log(`\n Seeding memories from last ${seedDays} days of git history...`);
161
- const { added, skipped } = learnFromRepo(hippoRoot, tenantId, process.cwd(), seedDays);
161
+ const { added, skipped } = await learnFromRepo(hippoRoot, tenantId, process.cwd(), seedDays);
162
162
  if (added > 0) {
163
163
  console.log(` Learned ${added} lessons from git (${skipped} duplicates skipped).`);
164
164
  }
@@ -166,11 +166,11 @@ function seedFromGitHistory(hippoRoot, tenantId) {
166
166
  console.log(` No matching commits found in git history.`);
167
167
  }
168
168
  }
169
- export function handleInit({ hippoRoot, tenantId, flags }) {
169
+ export async function handleInit({ hippoRoot, tenantId, flags }) {
170
170
  // Handle --scan mode
171
171
  if (flags['scan']) {
172
172
  const scanDir = stringFlag(flags, 'scan') ?? os.homedir();
173
- cmdInitScan(scanDir, tenantId, flags);
173
+ await cmdInitScan(scanDir, tenantId, flags);
174
174
  return;
175
175
  }
176
176
  if (flags['global']) {
@@ -199,7 +199,7 @@ export function handleInit({ hippoRoot, tenantId, flags }) {
199
199
  const learn = !flags['no-learn'] && !skipLearnOnSharedStore(hippoRoot);
200
200
  // Seed with git history on first init (unless --no-learn)
201
201
  if (!alreadyExists && learn && !flags['global'])
202
- seedFromGitHistory(hippoRoot, tenantId);
202
+ await seedFromGitHistory(hippoRoot, tenantId);
203
203
  // Every run, not only the first: an agent's notes change between inits.
204
204
  if (learn)
205
205
  printAgentImport(importForStore(hippoRoot, { machine: currentMachine() }));
@@ -14,7 +14,7 @@ export interface ObjectListSpec<O, S extends string> {
14
14
  }
15
15
  export declare function listObjects<O, S extends string>(flags: CliFlags, spec: ObjectListSpec<O, S>): void;
16
16
  /** The `<id>` after the subcommand; prints `usage` and exits 1 when it is missing. */
17
- export declare function idArgOrExit(args: string[], usage: string, label: string, parseId?: (raw: string, label: string) => number): number;
17
+ export declare function idArgOrExit(args: string[], usage: string, label: string): number;
18
18
  export declare function foundOrExit<O>(found: O | null | undefined, noun: string, id: number): O;
19
19
  /** How a kind is named in usage lines (`cmd`), in messages (`noun`) and in the invalid-id error (`idLabel`). */
20
20
  export interface ObjectNames {
@@ -25,7 +25,7 @@ export interface ObjectNames {
25
25
  /** `hippo <cmd> close <id>` for a kind whose close call returns the closed row. */
26
26
  export declare function closeObject(args: string[], names: ObjectNames, close: (id: number) => {
27
27
  id: number;
28
- }, parseId?: (raw: string, label: string) => number): void;
28
+ }): void;
29
29
  interface LifecycleTail {
30
30
  readonly changeSummary?: string | null;
31
31
  readonly supersededBy: number | null;
@@ -29,13 +29,13 @@ export function listObjects(flags, spec) {
29
29
  spec.printRow(o);
30
30
  }
31
31
  /** The `<id>` after the subcommand; prints `usage` and exits 1 when it is missing. */
32
- export function idArgOrExit(args, usage, label, parseId = parsePositiveId) {
32
+ export function idArgOrExit(args, usage, label) {
33
33
  const idRaw = args[1];
34
34
  if (!idRaw) {
35
35
  printError(usage);
36
36
  throw new CliExit(1);
37
37
  }
38
- return parseId(idRaw, label);
38
+ return parsePositiveId(idRaw, label);
39
39
  }
40
40
  export function foundOrExit(found, noun, id) {
41
41
  if (!found) {
@@ -45,8 +45,8 @@ export function foundOrExit(found, noun, id) {
45
45
  return found;
46
46
  }
47
47
  /** `hippo <cmd> close <id>` for a kind whose close call returns the closed row. */
48
- export function closeObject(args, names, close, parseId = parsePositiveId) {
49
- const id = idArgOrExit(args, `Usage: hippo ${names.cmd} close <id>`, names.idLabel, parseId);
48
+ export function closeObject(args, names, close) {
49
+ const id = idArgOrExit(args, `Usage: hippo ${names.cmd} close <id>`, names.idLabel);
50
50
  console.log(`${names.noun} #${close(id).id} closed.`);
51
51
  }
52
52
  /** The detail lines every `get` ends with. */
@@ -6,12 +6,11 @@ import { printError } from './output.js';
6
6
  import { parseListLimit, stringFlag } from './flag-values.js';
7
7
  import { requireInit } from './shared.js';
8
8
  import { foundOrExit, idArgOrExit, requireStatus } from './object-verbs.js';
9
- import { parseObjectId } from './lenient-id.js';
10
9
  import { CliExit } from './exit.js';
11
10
  const BASERATE_DECIMALS = 3;
12
11
  const PREDICTION_NOUN = 'Prediction';
13
12
  async function predictClose(ctx, args, flags) {
14
- const id = idArgOrExit(args, 'Usage: hippo predict close <id> --state <closed|closed-unknown> [--actual <v>] [--note "..."]', 'prediction', parseObjectId);
13
+ const id = idArgOrExit(args, 'Usage: hippo predict close <id> --state <closed|closed-unknown> [--actual <v>] [--note "..."]', 'prediction');
15
14
  const stateRaw = (stringFlag(flags, 'state') ?? '').trim();
16
15
  // SAFETY: Set.has only compares by value, so a string outside the closure states is a plain miss.
17
16
  if (!VALID_CLOSURE_STATES.has(stateRaw) || stateRaw === 'open') {
@@ -77,7 +76,7 @@ async function predictList(ctx, flags) {
77
76
  }
78
77
  }
79
78
  async function predictShow(ctx, args) {
80
- const id = idArgOrExit(args, 'Usage: hippo predict show <id>', 'prediction', parseObjectId);
79
+ const id = idArgOrExit(args, 'Usage: hippo predict show <id>', 'prediction');
81
80
  const pred = foundOrExit(await predictionsApi.predictionById(ctx, id), PREDICTION_NOUN, id);
82
81
  console.log(`Prediction #${pred.id}`);
83
82
  console.log(` class: ${pred.classTag}`);
@@ -1,3 +1,3 @@
1
1
  /** Fault-isolated like the project tag repair: a failure warns, leaves the store unmarked and runs again next time. */
2
- export declare function repairQualityOnceAt(root: string, tenantId: string): void;
2
+ export declare function repairQualityOnceAt(root: string, tenantId: string): Promise<void>;
3
3
  //# sourceMappingURL=quality-repair-once.d.ts.map
@@ -5,9 +5,9 @@ import { getGlobalRoot } from '../sharing/global-store.js';
5
5
  import { repairMemoryQualityOnce } from '../api/audit.js';
6
6
  import { cliApiContext } from './api-context.js';
7
7
  /** Fault-isolated like the project tag repair: a failure warns, leaves the store unmarked and runs again next time. */
8
- export function repairQualityOnceAt(root, tenantId) {
8
+ export async function repairQualityOnceAt(root, tenantId) {
9
9
  try {
10
- const result = repairMemoryQualityOnce(cliApiContext(root, tenantId));
10
+ const result = await repairMemoryQualityOnce(cliApiContext(root, tenantId));
11
11
  if (result === null)
12
12
  return;
13
13
  if (!result.supported) {
@@ -61,6 +61,7 @@ function describeRefineFailure(failure) {
61
61
  case 'request': return `refine: request failed: ${failure.message}`;
62
62
  case 'http': return `refine: API answered HTTP ${failure.status}${failure.detail ? `: ${failure.detail}` : ''}`;
63
63
  case 'unreadable': return `refine: unreadable response: ${failure.message}`;
64
+ case 'empty': return 'refine: response held no text';
64
65
  }
65
66
  }
66
67
  function isConsolidated(entry) {
@@ -121,7 +122,7 @@ async function refineOneEntry(ctx, reach, entry, opts, result) {
121
122
  result.details.push({ id: entry.id, status: 'refined', reason: 'dry-run (no write)' });
122
123
  return;
123
124
  }
124
- storeRefinement(cliApiContext(ctx.hippoRoot, entry.tenantId), entry, refined);
125
+ storeRefinement(cliApiContext(ctx.hippoRoot, entry.tenant_id), entry, refined);
125
126
  result.refined++;
126
127
  result.details.push({ id: entry.id, status: 'refined' });
127
128
  }
@@ -97,7 +97,7 @@ async function cmdRemember(hippoRoot, tenantId, text, flags) {
97
97
  const { requested: requestedTags, all: allTags } = rememberTags(flags, process.cwd());
98
98
  const envelope = parseRememberEnvelope(flags);
99
99
  const ctx = cliApiContext(targetRoot, tenantId);
100
- const outcome = api.rememberLocally(ctx, {
100
+ const outcome = await api.rememberLocally(ctx, {
101
101
  content: text,
102
102
  kind: envelope.kind,
103
103
  scope: envelope.scope ?? undefined,
@@ -173,7 +173,7 @@ async function cmdSupersede(hippoRoot, tenantId, oldId, newContent, flags) {
173
173
  };
174
174
  let newId;
175
175
  try {
176
- ({ newId } = api.supersede(cliApiContext(hippoRoot, tenantId), oldId, newContent, overrides));
176
+ ({ newId } = await api.supersede(cliApiContext(hippoRoot, tenantId), oldId, newContent, overrides));
177
177
  }
178
178
  catch (err) {
179
179
  if (err instanceof NotFoundError)
@@ -205,7 +205,7 @@ function traceTags(flags) {
205
205
  ? [String(rawTags)]
206
206
  : [];
207
207
  }
208
- function cmdTraceRecord(hippoRoot, tenantId, flags) {
208
+ async function cmdTraceRecord(hippoRoot, tenantId, flags) {
209
209
  requireInit(hippoRoot);
210
210
  const task = String(flags['task'] ?? '').trim();
211
211
  const stepsJson = String(flags['steps'] ?? '').trim();
@@ -227,7 +227,7 @@ function cmdTraceRecord(hippoRoot, tenantId, flags) {
227
227
  steps,
228
228
  outcome,
229
229
  });
230
- const { id } = api.remember(cliApiContext(hippoRoot, tenantId), {
230
+ const { id } = await api.remember(cliApiContext(hippoRoot, tenantId), {
231
231
  content,
232
232
  tags,
233
233
  local: {
@@ -427,7 +427,7 @@ export async function handleSupersede({ hippoRoot, tenantId, args, flags }) {
427
427
  export async function handleTrace({ hippoRoot, tenantId, args, flags }) {
428
428
  const sub = args[0] ? String(args[0]) : '';
429
429
  if (sub === 'record') {
430
- cmdTraceRecord(hippoRoot, tenantId, flags);
430
+ await cmdTraceRecord(hippoRoot, tenantId, flags);
431
431
  return;
432
432
  }
433
433
  if (!sub) {
package/dist/cli/serve.js CHANGED
@@ -1,10 +1,10 @@
1
1
  // Long-running verbs: `hippo dashboard`, `hippo mcp` and `hippo serve`.
2
2
  import { installCrashHandlers } from '../util/crash-handlers.js';
3
- import { envAllowKeylessLocal, envPort, envRequireAuth, envTlsCert, envTlsKey } from '../util/env.js';
3
+ import { envAllowKeylessLocal, envKeylessLocalRole, envPort, envRequireAuth, envTlsCert, envTlsKey } from '../util/env.js';
4
4
  import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import { printError } from './output.js';
7
- import { stringFlagOrExit, stringFlag, numberFlag } from './flag-values.js';
7
+ import { flagIsTrue, stringFlagOrExit, stringFlag, numberFlag } from './flag-values.js';
8
8
  import { requireInit } from './shared.js';
9
9
  import { errorMessage } from '../util/log.js';
10
10
  import { CliExit } from './exit.js';
@@ -52,7 +52,10 @@ function keyRuleLine() {
52
52
  if (envRequireAuth())
53
53
  return 'every request needs an API key (HIPPO_REQUIRE_AUTH=1)';
54
54
  if (envAllowKeylessLocal()) {
55
- return 'requests from this machine need no API key and act as host admin (HIPPO_ALLOW_KEYLESS_LOCAL=1); unset it to require a key on every request';
55
+ const role = envKeylessLocalRole() === 'admin'
56
+ ? 'act as host admin (HIPPO_ALLOW_KEYLESS_LOCAL=1, HIPPO_KEYLESS_LOCAL_ROLE=admin)'
57
+ : 'act as a member (HIPPO_ALLOW_KEYLESS_LOCAL=1; HIPPO_KEYLESS_LOCAL_ROLE=admin opens sleep and the quarantine routes)';
58
+ return `requests from this machine need no API key and ${role}; unset HIPPO_ALLOW_KEYLESS_LOCAL to require a key on every request`;
56
59
  }
57
60
  return 'every request needs an API key: mint one with `hippo auth create` and send it as "Authorization: Bearer <key>" ' +
58
61
  '(the hippo CLI reads HIPPO_API_KEY). To let requests from this machine in without a key, start with HIPPO_ALLOW_KEYLESS_LOCAL=1';
@@ -68,7 +71,9 @@ export async function handleServe({ hippoRoot, flags }) {
68
71
  const host = stringFlag(flags, 'host') ?? DEFAULT_SERVER_HOST;
69
72
  const tls = readTlsFiles(flags);
70
73
  const { serve } = await import('../server.js');
71
- const handle = await serve({ hippoRoot, port, host, handleSignals: true, tls });
74
+ // Unset rather than false without the flag, so HIPPO_ALLOW_CLEARTEXT=1 still applies.
75
+ const allowCleartext = flagIsTrue(flags, 'allow-cleartext') || undefined;
76
+ const handle = await serve({ hippoRoot, port, host, handleSignals: true, tls, allowCleartext });
72
77
  console.log(`hippo serve listening on ${handle.url} (pid ${process.pid})`);
73
78
  console.log(keyRuleLine());
74
79
  console.log(`pidfile: ${path.join(hippoRoot, 'server.pid')}`);
@@ -3,10 +3,6 @@ import { type CliFlags, type CommandContext } from './flag-values.js';
3
3
  * The child logs to a file that the next SessionStart reads via `hippo last-sleep`. */
4
4
  export declare function handleSessionEnd({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
5
5
  export declare function handleSessionEndWorker({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
6
- /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
7
- export declare function quoteCmdArg(arg: string): string;
8
- /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
9
- export declare function cmdShimArgs(shimPath: string, forwardArgs: readonly string[]): string[];
10
6
  export declare function handleCodexRun({ hippoRoot, tenantId, args }: CommandContext): void;
11
7
  export declare function cmdCodexSessionEndWorker(hippoRoot: string, tenantId: string, flags: CliFlags): Promise<void>;
12
8
  export declare function handleCodexSessionEndWorker({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
@@ -21,9 +21,10 @@ import { isStringValue, readSessionEnd, readVscodeStop } from '../core/capture-c
21
21
  import { loadConfig } from '../core/config.js';
22
22
  import { autoSleepDue } from '../api/auto-sleep.js';
23
23
  import { COMPACTION_DB_WAIT_MS } from '../core/compaction-timing.js';
24
- import { bookSessionRereads, closeEndedSession, compactResumeBlock } from '../api/session-end.js';
24
+ import { compactResumeBlock, sessionEndWork as runSessionEnd } from '../api/session-end.js';
25
25
  import { normaliseHookPayload, readHookStdin, readStdinBounded } from './stdin.js';
26
26
  import { errorMessage, log } from '../util/log.js';
27
+ import { cmdShimArgs } from '../util/spawn-argv.js';
27
28
  import { bookLedgerTurn } from '../api/ledger-db.js';
28
29
  import { flushDeliveryRecorder, startDeliveryRecorder, startToolFailureRecorder } from '../api/prompt-hook.js';
29
30
  import { printError } from './output.js';
@@ -52,7 +53,7 @@ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
52
53
  });
53
54
  }
54
55
  // A compaction follows a prompt or SessionStart that booked the arm, so this only reads it.
55
- if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, false)) {
56
+ if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, { write: false })) {
56
57
  suppressOutput = true;
57
58
  rec?.disabled();
58
59
  }
@@ -75,8 +76,7 @@ function restoreCompactSnapshot(hippoRoot, tenantId, payloadSessionId, rec) {
75
76
  return;
76
77
  // Printed in one write so the ledger books exactly the text the model is handed.
77
78
  console.log(text);
78
- rec?.delivered({ state: 'sent', emittedText: `${text}
79
- ` });
79
+ rec?.delivered({ state: 'sent', emittedText: `${text}\n` });
80
80
  bookLedgerTurn(hippoRoot, {
81
81
  uses: [{
82
82
  tenantId, sessionId: payloadSessionId, surface: 'compact_resume', event: 'inject', items: 1, tokens: estimateTokens(text),
@@ -111,20 +111,15 @@ export async function handleSessionEnd({ hippoRoot, tenantId, flags }) {
111
111
  const named = input?.transcriptPath ?? null;
112
112
  const transcriptPath = (named !== null && fs.existsSync(named) ? named : null)
113
113
  ?? (runtime === 'copilot' && sessionId ? copilotTranscriptFor(sessionId) : null);
114
+ const worker = { logFile, transcriptPath, sessionId, turn };
114
115
  try {
115
- spawnSessionEndWorker(sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn));
116
+ spawnSessionEndWorker(sessionEndWorkerArgs(worker));
116
117
  }
117
118
  catch (err) {
118
119
  log.debug(`session-end: the worker did not spawn, running inline: ${errorMessage(err)}`);
119
120
  // Inline is the last resort, handed what the child's argv would have carried.
120
- if (logFile)
121
- flags['log-file'] = logFile;
122
- if (transcriptPath)
123
- flags['transcript'] = transcriptPath;
124
- if (sessionId)
125
- flags['session-id'] = sessionId;
126
121
  try {
127
- await cmdSessionEndWorker(root, tenantId, flags);
122
+ await cmdSessionEndWorker(root, tenantId, inlineWorkerFlags(flags, worker));
128
123
  }
129
124
  finally {
130
125
  await runHookWithStores(() => flushDeliveryRecorder(rec));
@@ -142,7 +137,8 @@ function sessionEndInput(stdinText, timedOut, runtime) {
142
137
  log.debug(`session-end: ${receipt.reason}`);
143
138
  return null;
144
139
  }
145
- function sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn) {
140
+ function sessionEndWorkerArgs(o) {
141
+ const { logFile, transcriptPath, sessionId, turn } = o;
146
142
  const workerArgs = [process.argv[1], '__session-end-worker'];
147
143
  if (logFile)
148
144
  workerArgs.push('--log-file', logFile);
@@ -154,6 +150,26 @@ function sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn) {
154
150
  workerArgs.push('--turn');
155
151
  return workerArgs;
156
152
  }
153
+ /** The flags the detached worker would parse from its argv, so the inline run sees what the child would have; the hook's own flags fill the gaps. */
154
+ function inlineWorkerFlags(flags, w) {
155
+ const out = {};
156
+ const keep = (name, value) => {
157
+ if (value)
158
+ out[name] = value;
159
+ };
160
+ keep('log-file', w.logFile ?? flags['log-file']);
161
+ keep('transcript', w.transcriptPath ?? flags['transcript']);
162
+ keep('session-id', w.sessionId ?? flags['session-id']);
163
+ if (flagIsTrue(flags, 'turn'))
164
+ out['turn'] = true;
165
+ if (flagIsTrue(flags, 'dry-run'))
166
+ out['dry-run'] = true;
167
+ if (flagIsTrue(flags, 'no-learn'))
168
+ out['no-learn'] = true;
169
+ if (flagIsTrue(flags, 'no-share'))
170
+ out['no-share'] = true;
171
+ return out;
172
+ }
157
173
  function spawnSessionEndWorker(workerArgs) {
158
174
  const child = spawn(process.execPath, workerArgs, {
159
175
  detached: true,
@@ -176,48 +192,37 @@ async function cmdSessionEndWorker(hippoRoot, tenantId, flags) {
176
192
  export function handleSessionEndWorker({ hippoRoot, tenantId, flags }) {
177
193
  return cmdSessionEndWorker(hippoRoot, tenantId, flags);
178
194
  }
179
- async function sessionEndWork(hippoRoot, tenantId, flags, mode) {
195
+ function sessionEndWork(hippoRoot, tenantId, flags, mode) {
180
196
  const transcriptPath = stringFlag(flags, 'transcript');
181
- const closeLogFile = stringFlag(flags, 'log-file') ?? null;
182
- const closeSessionId = stringFlag(flags, 'session-id') ?? null;
183
- const rereadLog = await bookSessionRereads(cliApiContext(hippoRoot, tenantId), transcriptPath, closeSessionId)
184
- .catch((err) => [`re-read count failed: ${errorMessage(err)}`]);
185
- // Sleep starts the log file afresh, so the lines go in after it; on exit too, in case sleep exits the process.
186
- const flushRereadLog = () => { for (const line of rereadLog.splice(0))
187
- appendSessionEndCloseLog(closeLogFile, line); };
188
- process.once('exit', flushRereadLog);
189
- // Like the other hooks: project store, else global; a folder with neither must not get one made.
190
- const store = hookStoreRoot(hippoRoot);
191
- if (!isInitialized(store)) {
192
- appendSessionEndCloseLog(closeLogFile, 'skip: no hippo store for this folder or globally', { startFresh: true });
193
- flushRereadLog();
194
- return;
195
- }
196
- if (mode === 'turn' && closeSessionId)
197
- await sleepIfDue(hippoRoot, tenantId, flags, closeLogFile, transcriptPath, closeSessionId);
198
- else
199
- await sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
200
- flushRereadLog();
201
- const digestLog = (message) => appendSessionEndCloseLog(closeLogFile, message);
202
- const scan = transcriptPath ? readSessionScan(transcriptPath, digestLog) : null;
203
- const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
204
- if (mode === 'turn')
205
- captureNewTurns(transcriptPath, closeSessionId, scan, capture, digestLog);
206
- else
207
- capture(scan?.turns);
208
- recordSessionDigest(hippoRoot, scan, {
209
- key: closeSessionId || path.basename(transcriptPath ?? '', '.jsonl'),
197
+ const logFile = stringFlag(flags, 'log-file') ?? null;
198
+ const sessionId = stringFlag(flags, 'session-id') ?? null;
199
+ return runSessionEnd({
200
+ mode,
201
+ hippoRoot,
210
202
  tenantId,
211
- log: digestLog,
212
- });
213
- // Only this session's snapshot, and only after sleep and capture.
214
- const closeLog = (line) => appendSessionEndCloseLog(closeLogFile, line);
215
- closeEndedSession(cliApiContext(store, tenantId), {
216
- sessionId: closeSessionId,
217
- turn: mode === 'turn',
218
- workingState: () => (transcriptPath ? transcriptWorkingState(transcriptPath, closeLog) : null),
203
+ sessionId,
204
+ transcriptPath,
205
+ contextFor: (root) => cliApiContext(root, tenantId),
206
+ storeRoot: () => hookStoreRoot(hippoRoot),
207
+ log: (line, opts) => appendSessionEndCloseLog(logFile, line, opts),
208
+ sleep: () => (mode === 'turn' && sessionId
209
+ ? sleepIfDue(hippoRoot, tenantId, flags, logFile, transcriptPath, sessionId)
210
+ : sleepProjectStore(hippoRoot, tenantId, flags, logFile, transcriptPath)),
211
+ readScan: (log) => (transcriptPath ? readSessionScan(transcriptPath, log) : null),
212
+ capture: (store, scan) => {
213
+ const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
214
+ if (mode === 'turn')
215
+ captureNewTurns(transcriptPath, sessionId, scan, capture, (line) => appendSessionEndCloseLog(logFile, line));
216
+ else
217
+ capture(scan?.turns);
218
+ },
219
+ digest: (scan, log) => recordSessionDigest(hippoRoot, scan, {
220
+ key: sessionId || path.basename(transcriptPath ?? '', '.jsonl'),
221
+ tenantId,
222
+ log,
223
+ }),
224
+ workingState: (log) => (transcriptPath ? transcriptWorkingState(transcriptPath, log) : null),
219
225
  evidence: () => collectHandoffEvidence(process.cwd(), 'unknown'),
220
- log: closeLog,
221
226
  });
222
227
  }
223
228
  async function sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath) {
@@ -304,20 +309,6 @@ function loadCodexWrapperMetadata() {
304
309
  // SAFETY: the file is the one installCodexWrapper wrote; handleCodexRun reads only logFile and realCodexPath from it.
305
310
  return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
306
311
  }
307
- /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
308
- export function quoteCmdArg(arg) {
309
- if (arg.length === 0)
310
- return '""';
311
- if (!/[ \t"&()^<>|%!]/.test(arg))
312
- return arg;
313
- return `"${arg.replace(/"/g, '""').replace(/%/g, '"^%"')}"`;
314
- }
315
- /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
316
- export function cmdShimArgs(shimPath, forwardArgs) {
317
- const command = `"${shimPath}"${forwardArgs.length > 0 ? ` ${forwardArgs.map(quoteCmdArg).join(' ')}` : ''}`;
318
- // The line is already quoted for cmd.exe, so Node must not quote it again; /s strips the outer pair.
319
- return ['/d', '/v:off', '/s', '/c', `"${command}"`];
320
- }
321
312
  function spawnRealCodex(realCodexPath, forwardArgs, cwd) {
322
313
  const ext = path.extname(realCodexPath).toLowerCase();
323
314
  if (process.platform === 'win32' && ext === '.ps1') {
@@ -1,5 +1,5 @@
1
1
  import { type CommandContext } from './flag-values.js';
2
2
  export declare function handleHook({ args }: CommandContext): void;
3
3
  export declare function handleSetup({ flags }: CommandContext): void;
4
- export declare function handleDailyRunner({ tenantId }: CommandContext): void;
4
+ export declare function handleDailyRunner({ tenantId }: CommandContext): Promise<void>;
5
5
  //# sourceMappingURL=setup.d.ts.map
package/dist/cli/setup.js CHANGED
@@ -486,14 +486,14 @@ function dailyStepFailure(err, timeoutMs) {
486
486
  return `timed out after ${timeoutMs} ms and was stopped`;
487
487
  return errorMessage(err);
488
488
  }
489
- export function handleDailyRunner({ tenantId }) {
489
+ export async function handleDailyRunner({ tenantId }) {
490
490
  const globalRoot = getGlobalRoot();
491
491
  // No workspace sleep ever opens the global store, yet hooks in folders without a store compact into it.
492
492
  if (isInitialized(globalRoot)) {
493
493
  const finished = replayCompactionsAt(globalRoot, (message) => log.warn(`compaction replay: ${message}`));
494
494
  if (finished > 0)
495
495
  console.log(`Finished saving ${finished} compaction${finished === 1 ? '' : 's'} left over in the global store.`);
496
- repairQualityOnceAt(globalRoot, tenantId);
496
+ await repairQualityOnceAt(globalRoot, tenantId);
497
497
  }
498
498
  printAgentImport(importUserMemories(globalRoot, { machine: currentMachine() }), '');
499
499
  const workspaces = listRegisteredWorkspaces(globalRoot);
@@ -17,7 +17,7 @@ interface LearnFromRepoResult {
17
17
  skipped: number;
18
18
  lowInfo: number;
19
19
  }
20
- export declare function learnFromRepo(hippoRoot: string, tenantId: string, repoPath: string, days: number, label?: string): LearnFromRepoResult;
20
+ export declare function learnFromRepo(hippoRoot: string, tenantId: string, repoPath: string, days: number, label?: string): Promise<LearnFromRepoResult>;
21
21
  export declare function resolveAuthRoot(hippoRoot: string, flags: CliFlags): string;
22
22
  export {};
23
23
  //# sourceMappingURL=shared.d.ts.map
@@ -83,9 +83,9 @@ export function skipLearnOnSharedStore(hippoRoot) {
83
83
  console.log("Shared store: skipped learning from this account's git commits and coding agents' own memories.");
84
84
  return true;
85
85
  }
86
- export function learnFromRepo(hippoRoot, tenantId, repoPath, days, label) {
86
+ export async function learnFromRepo(hippoRoot, tenantId, repoPath, days, label) {
87
87
  const prefix = label ? `[${label}] ` : '';
88
- const result = learn(cliApiContext(hippoRoot, tenantId), { repoPath, days, profile: CLI_LEARN });
88
+ const result = await learn(cliApiContext(hippoRoot, tenantId), { repoPath, days, profile: CLI_LEARN });
89
89
  if (result.status === 'not-a-repo') {
90
90
  console.log(`${prefix}No git history found (or not a git repository).`);
91
91
  return { added: 0, skipped: 0, lowInfo: 0 };
package/dist/cli/sleep.js CHANGED
@@ -80,7 +80,7 @@ async function cmdSleepCore(hippoRoot, tenantId, flags) {
80
80
  else if (learn) {
81
81
  const config = loadConfig(hippoRoot);
82
82
  if (config.autoLearnOnSleep && isGitRepo(process.cwd())) {
83
- const { added } = learnFromRepo(hippoRoot, tenantId, process.cwd(), 1);
83
+ const { added } = await learnFromRepo(hippoRoot, tenantId, process.cwd(), 1);
84
84
  if (added > 0)
85
85
  console.log(`Auto-learned ${added} lessons from today's git commits.`);
86
86
  }
@@ -101,7 +101,7 @@ async function cmdSleepCore(hippoRoot, tenantId, flags) {
101
101
  if (finished > 0)
102
102
  console.log(`Finished saving ${finished} compaction${finished === 1 ? '' : 's'} left over from earlier sessions.`);
103
103
  repairProjectTagsOnce(hippoRoot, tenantId);
104
- repairQualityOnceAt(hippoRoot, tenantId);
104
+ await repairQualityOnceAt(hippoRoot, tenantId);
105
105
  }
106
106
  // Phase 2-6: Pure-storage pipeline (consolidate + dedup + audit + share + ambient).
107
107
  const ctx = cliApiContext(hippoRoot, tenantId);
@@ -1,8 +1,8 @@
1
1
  import { type CommandContext } from './flag-values.js';
2
- export declare function handleLearn({ hippoRoot, tenantId, flags }: CommandContext): void;
3
- export declare function handleImport({ hippoRoot, tenantId, args, flags }: CommandContext): void;
2
+ export declare function handleLearn({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
3
+ export declare function handleImport({ hippoRoot, tenantId, args, flags }: CommandContext): Promise<void>;
4
4
  export declare function handleSync({ hippoRoot, flags }: CommandContext): void;
5
- export declare function handleWatch({ hippoRoot, tenantId, args }: CommandContext): Promise<void>;
5
+ export declare function handleWatch({ hippoRoot, tenantId, args, flags }: CommandContext): Promise<void>;
6
6
  export declare function handlePromote({ hippoRoot, tenantId, args }: CommandContext): Promise<void>;
7
7
  export declare function handleShare({ hippoRoot, tenantId, args, flags }: CommandContext): Promise<void>;
8
8
  export declare function handlePeers({ tenantId, flags }: CommandContext): void;