clawvault 3.0.0 → 3.2.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 (291) hide show
  1. package/README.md +352 -20
  2. package/bin/clawvault.js +8 -2
  3. package/bin/command-registration.test.js +3 -1
  4. package/bin/command-runtime.js +9 -1
  5. package/bin/register-core-commands.js +23 -10
  6. package/bin/register-maintenance-commands.js +39 -3
  7. package/bin/register-query-commands.js +58 -29
  8. package/bin/register-task-commands.js +18 -1
  9. package/bin/register-task-commands.test.js +16 -0
  10. package/bin/register-vault-operations-commands.js +29 -1
  11. package/bin/register-workgraph-commands.js +1368 -0
  12. package/dashboard/lib/graph-diff.js +104 -0
  13. package/dashboard/lib/graph-diff.test.js +75 -0
  14. package/dashboard/lib/vault-parser.js +556 -0
  15. package/dashboard/lib/vault-parser.test.js +254 -0
  16. package/dashboard/public/app.js +796 -0
  17. package/dashboard/public/index.html +52 -0
  18. package/dashboard/public/styles.css +221 -0
  19. package/dashboard/server.js +374 -0
  20. package/dist/{chunk-F2JEUD4J.js → chunk-23YDQ3QU.js} +6 -8
  21. package/dist/{chunk-C7OK5WKP.js → chunk-2JQ3O2YL.js} +4 -4
  22. package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
  23. package/dist/chunk-2ZDO52B4.js +52 -0
  24. package/dist/{chunk-ZZA73MFY.js → chunk-33DOSHTA.js} +176 -36
  25. package/dist/chunk-33VSQP4J.js +37 -0
  26. package/dist/chunk-4BQTQMJP.js +93 -0
  27. package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
  28. package/dist/{chunk-62YTUT6J.js → chunk-4PY655YM.js} +15 -3
  29. package/dist/chunk-6FH3IULF.js +352 -0
  30. package/dist/{chunk-3NSBOUT3.js → chunk-77Q5CSPJ.js} +404 -80
  31. package/dist/{chunk-4VQTUVH7.js → chunk-7YZWHM36.js} +52 -26
  32. package/dist/chunk-BSJ6RIT7.js +447 -0
  33. package/dist/chunk-BUEW6IIK.js +364 -0
  34. package/dist/{chunk-WGRQ6HDV.js → chunk-CLJTREDS.js} +74 -14
  35. package/dist/chunk-EK6S23ZB.js +469 -0
  36. package/dist/{chunk-LNJA2UGL.js → chunk-ESFLMDRB.js} +9 -86
  37. package/dist/{chunk-H34S76MB.js → chunk-ESVS6K2B.js} +6 -6
  38. package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
  39. package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
  40. package/dist/{chunk-YKTA5JOJ.js → chunk-GAOWA7GR.js} +212 -46
  41. package/dist/chunk-GGA32J2R.js +784 -0
  42. package/dist/chunk-GNJL4YGR.js +79 -0
  43. package/dist/chunk-MDIH26GC.js +183 -0
  44. package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
  45. package/dist/chunk-MM6QGW3P.js +207 -0
  46. package/dist/{chunk-P5EPF6MB.js → chunk-MW5C6ZQA.js} +110 -13
  47. package/dist/chunk-NCKFNBHJ.js +257 -0
  48. package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
  49. package/dist/{chunk-42MXU7A6.js → chunk-P62WHA27.js} +58 -47
  50. package/dist/chunk-PBACDKKP.js +66 -0
  51. package/dist/{chunk-VGLOTGAS.js → chunk-QSHD36LH.js} +2 -2
  52. package/dist/{chunk-OZ7RIXTO.js → chunk-QSRRMEYM.js} +2 -2
  53. package/dist/chunk-QVEERJSP.js +152 -0
  54. package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
  55. package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
  56. package/dist/{chunk-SJSFRIYS.js → chunk-SLXOR3CC.js} +2 -2
  57. package/dist/chunk-SS4B7P7V.js +99 -0
  58. package/dist/{chunk-JY6FYXIT.js → chunk-STCQGCEQ.js} +6 -11
  59. package/dist/chunk-U4O6C46S.js +154 -0
  60. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  61. package/dist/chunk-VSL7KY3M.js +189 -0
  62. package/dist/{chunk-U55BGUAU.js → chunk-W4SPAEE7.js} +6 -6
  63. package/dist/chunk-WMGIIABP.js +15 -0
  64. package/dist/{chunk-3D6BCTP6.js → chunk-X3SPPUFG.js} +51 -39
  65. package/dist/{chunk-THRJVD4L.js → chunk-Y6VJKXGL.js} +1 -1
  66. package/dist/{chunk-ZVVFWOLW.js → chunk-ZN54U2OZ.js} +123 -10
  67. package/dist/cli/index.js +32 -25
  68. package/dist/commands/archive.js +3 -3
  69. package/dist/commands/backlog.js +3 -3
  70. package/dist/commands/blocked.js +3 -3
  71. package/dist/commands/canvas.d.ts +15 -0
  72. package/dist/commands/canvas.js +200 -0
  73. package/dist/commands/checkpoint.js +2 -2
  74. package/dist/commands/compat.js +2 -2
  75. package/dist/commands/context.js +8 -6
  76. package/dist/commands/doctor.d.ts +11 -7
  77. package/dist/commands/doctor.js +18 -16
  78. package/dist/commands/embed.js +5 -6
  79. package/dist/commands/entities.js +2 -2
  80. package/dist/commands/graph.js +4 -4
  81. package/dist/commands/inject.d.ts +1 -1
  82. package/dist/commands/inject.js +5 -6
  83. package/dist/commands/kanban.js +4 -4
  84. package/dist/commands/link.js +5 -5
  85. package/dist/commands/migrate-observations.js +4 -4
  86. package/dist/commands/observe.d.ts +0 -1
  87. package/dist/commands/observe.js +14 -13
  88. package/dist/commands/project.js +5 -5
  89. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  90. package/dist/commands/rebuild-embeddings.js +91 -0
  91. package/dist/commands/rebuild.js +12 -11
  92. package/dist/commands/recover.js +3 -3
  93. package/dist/commands/reflect.js +6 -7
  94. package/dist/commands/repair-session.js +1 -1
  95. package/dist/commands/replay.js +14 -14
  96. package/dist/commands/session-recap.js +1 -1
  97. package/dist/commands/setup.d.ts +2 -90
  98. package/dist/commands/setup.js +3 -21
  99. package/dist/commands/shell-init.js +1 -1
  100. package/dist/commands/sleep.d.ts +1 -1
  101. package/dist/commands/sleep.js +20 -19
  102. package/dist/commands/status.d.ts +2 -0
  103. package/dist/commands/status.js +57 -35
  104. package/dist/commands/sync-bd.d.ts +10 -0
  105. package/dist/commands/sync-bd.js +10 -0
  106. package/dist/commands/tailscale.js +3 -3
  107. package/dist/commands/task.js +4 -4
  108. package/dist/commands/template.js +2 -2
  109. package/dist/commands/wake.d.ts +1 -1
  110. package/dist/commands/wake.js +11 -10
  111. package/dist/commands/workgraph.d.ts +124 -0
  112. package/dist/commands/workgraph.js +38 -0
  113. package/dist/index.d.ts +337 -191
  114. package/dist/index.js +387 -118
  115. package/dist/{inject-Bzi5E-By.d.cts → inject-DYUrDqQO.d.ts} +3 -3
  116. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  117. package/dist/lib/auto-linker.js +2 -2
  118. package/dist/lib/canvas-layout.d.ts +100 -16
  119. package/dist/lib/canvas-layout.js +21 -78
  120. package/dist/lib/config.d.ts +27 -3
  121. package/dist/lib/config.js +4 -2
  122. package/dist/lib/entity-index.js +1 -1
  123. package/dist/lib/project-utils.js +4 -4
  124. package/dist/lib/session-repair.js +1 -1
  125. package/dist/lib/session-utils.js +1 -1
  126. package/dist/lib/tailscale.js +1 -1
  127. package/dist/lib/task-utils.js +3 -3
  128. package/dist/lib/template-engine.js +1 -1
  129. package/dist/lib/webdav.js +1 -1
  130. package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
  131. package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
  132. package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
  133. package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
  134. package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
  135. package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
  136. package/dist/openclaw-plugin.d.ts +8 -0
  137. package/dist/openclaw-plugin.js +14 -0
  138. package/dist/registry-BR4326o0.d.ts +30 -0
  139. package/dist/store-CA-6sKCJ.d.ts +34 -0
  140. package/dist/thread-B9LhXNU0.d.ts +41 -0
  141. package/dist/transformers.node-A2ZRORSQ.js +46775 -0
  142. package/dist/{types-Y2_Um2Ls.d.cts → types-BbWJoC1c.d.ts} +1 -44
  143. package/dist/workgraph/index.d.ts +5 -0
  144. package/dist/workgraph/index.js +23 -0
  145. package/dist/workgraph/ledger.d.ts +2 -0
  146. package/dist/workgraph/ledger.js +25 -0
  147. package/dist/workgraph/registry.d.ts +2 -0
  148. package/dist/workgraph/registry.js +19 -0
  149. package/dist/workgraph/store.d.ts +2 -0
  150. package/dist/workgraph/store.js +25 -0
  151. package/dist/workgraph/thread.d.ts +2 -0
  152. package/dist/workgraph/thread.js +25 -0
  153. package/dist/workgraph/types.d.ts +54 -0
  154. package/dist/workgraph/types.js +7 -0
  155. package/hooks/clawvault/HOOK.md +34 -4
  156. package/hooks/clawvault/handler.js +760 -78
  157. package/hooks/clawvault/handler.test.js +235 -79
  158. package/hooks/clawvault/openclaw.plugin.json +72 -0
  159. package/openclaw.plugin.json +65 -38
  160. package/package.json +15 -18
  161. package/dist/chunk-3RG5ZIWI.js +0 -10
  162. package/dist/chunk-6U6MK36V.js +0 -205
  163. package/dist/chunk-7R7O6STJ.js +0 -88
  164. package/dist/chunk-CMB7UL7C.js +0 -327
  165. package/dist/chunk-DEFFDRVP.js +0 -938
  166. package/dist/chunk-E7MFQB6D.js +0 -163
  167. package/dist/chunk-GAJV4IGR.js +0 -82
  168. package/dist/chunk-GQSLDZTS.js +0 -560
  169. package/dist/chunk-K234IDRJ.js +0 -1073
  170. package/dist/chunk-MFM6K7PU.js +0 -374
  171. package/dist/chunk-MXSSG3QU.js +0 -42
  172. package/dist/chunk-PAH27GSN.js +0 -108
  173. package/dist/cli/index.cjs +0 -10033
  174. package/dist/cli/index.d.cts +0 -5
  175. package/dist/commands/archive.cjs +0 -287
  176. package/dist/commands/archive.d.cts +0 -11
  177. package/dist/commands/backlog.cjs +0 -721
  178. package/dist/commands/backlog.d.cts +0 -53
  179. package/dist/commands/blocked.cjs +0 -204
  180. package/dist/commands/blocked.d.cts +0 -26
  181. package/dist/commands/checkpoint.cjs +0 -244
  182. package/dist/commands/checkpoint.d.cts +0 -41
  183. package/dist/commands/compat.cjs +0 -369
  184. package/dist/commands/compat.d.cts +0 -28
  185. package/dist/commands/context.cjs +0 -2989
  186. package/dist/commands/context.d.cts +0 -2
  187. package/dist/commands/doctor.cjs +0 -3062
  188. package/dist/commands/doctor.d.cts +0 -21
  189. package/dist/commands/embed.cjs +0 -232
  190. package/dist/commands/embed.d.cts +0 -17
  191. package/dist/commands/entities.cjs +0 -141
  192. package/dist/commands/entities.d.cts +0 -7
  193. package/dist/commands/graph.cjs +0 -501
  194. package/dist/commands/graph.d.cts +0 -21
  195. package/dist/commands/inject.cjs +0 -1636
  196. package/dist/commands/inject.d.cts +0 -2
  197. package/dist/commands/kanban.cjs +0 -884
  198. package/dist/commands/kanban.d.cts +0 -63
  199. package/dist/commands/link.cjs +0 -965
  200. package/dist/commands/link.d.cts +0 -11
  201. package/dist/commands/migrate-observations.cjs +0 -362
  202. package/dist/commands/migrate-observations.d.cts +0 -19
  203. package/dist/commands/observe.cjs +0 -4099
  204. package/dist/commands/observe.d.cts +0 -23
  205. package/dist/commands/project.cjs +0 -1341
  206. package/dist/commands/project.d.cts +0 -85
  207. package/dist/commands/rebuild.cjs +0 -3136
  208. package/dist/commands/rebuild.d.cts +0 -11
  209. package/dist/commands/recover.cjs +0 -361
  210. package/dist/commands/recover.d.cts +0 -38
  211. package/dist/commands/reflect.cjs +0 -1008
  212. package/dist/commands/reflect.d.cts +0 -11
  213. package/dist/commands/repair-session.cjs +0 -457
  214. package/dist/commands/repair-session.d.cts +0 -38
  215. package/dist/commands/replay.cjs +0 -4103
  216. package/dist/commands/replay.d.cts +0 -16
  217. package/dist/commands/session-recap.cjs +0 -353
  218. package/dist/commands/session-recap.d.cts +0 -27
  219. package/dist/commands/setup.cjs +0 -1345
  220. package/dist/commands/setup.d.cts +0 -100
  221. package/dist/commands/shell-init.cjs +0 -75
  222. package/dist/commands/shell-init.d.cts +0 -7
  223. package/dist/commands/sleep.cjs +0 -6028
  224. package/dist/commands/sleep.d.cts +0 -36
  225. package/dist/commands/status.cjs +0 -2736
  226. package/dist/commands/status.d.cts +0 -52
  227. package/dist/commands/tailscale.cjs +0 -1532
  228. package/dist/commands/tailscale.d.cts +0 -52
  229. package/dist/commands/task.cjs +0 -1236
  230. package/dist/commands/task.d.cts +0 -97
  231. package/dist/commands/template.cjs +0 -457
  232. package/dist/commands/template.d.cts +0 -36
  233. package/dist/commands/wake.cjs +0 -2626
  234. package/dist/commands/wake.d.cts +0 -22
  235. package/dist/context-BUGaWpyL.d.cts +0 -46
  236. package/dist/index.cjs +0 -14526
  237. package/dist/index.d.cts +0 -858
  238. package/dist/inject-Bzi5E-By.d.ts +0 -137
  239. package/dist/lib/auto-linker.cjs +0 -176
  240. package/dist/lib/auto-linker.d.cts +0 -26
  241. package/dist/lib/canvas-layout.cjs +0 -136
  242. package/dist/lib/canvas-layout.d.cts +0 -31
  243. package/dist/lib/config.cjs +0 -78
  244. package/dist/lib/config.d.cts +0 -11
  245. package/dist/lib/entity-index.cjs +0 -84
  246. package/dist/lib/entity-index.d.cts +0 -26
  247. package/dist/lib/project-utils.cjs +0 -864
  248. package/dist/lib/project-utils.d.cts +0 -97
  249. package/dist/lib/session-repair.cjs +0 -239
  250. package/dist/lib/session-repair.d.cts +0 -110
  251. package/dist/lib/session-utils.cjs +0 -209
  252. package/dist/lib/session-utils.d.cts +0 -63
  253. package/dist/lib/tailscale.cjs +0 -1183
  254. package/dist/lib/tailscale.d.cts +0 -225
  255. package/dist/lib/task-utils.cjs +0 -1137
  256. package/dist/lib/task-utils.d.cts +0 -208
  257. package/dist/lib/template-engine.cjs +0 -47
  258. package/dist/lib/template-engine.d.cts +0 -11
  259. package/dist/lib/webdav.cjs +0 -568
  260. package/dist/lib/webdav.d.cts +0 -109
  261. package/dist/plugin/index.cjs +0 -1907
  262. package/dist/plugin/index.d.cts +0 -36
  263. package/dist/plugin/index.d.ts +0 -36
  264. package/dist/plugin/index.js +0 -572
  265. package/dist/plugin/inject.cjs +0 -356
  266. package/dist/plugin/inject.d.cts +0 -54
  267. package/dist/plugin/inject.d.ts +0 -54
  268. package/dist/plugin/inject.js +0 -17
  269. package/dist/plugin/observe.cjs +0 -631
  270. package/dist/plugin/observe.d.cts +0 -39
  271. package/dist/plugin/observe.d.ts +0 -39
  272. package/dist/plugin/observe.js +0 -18
  273. package/dist/plugin/templates.cjs +0 -593
  274. package/dist/plugin/templates.d.cts +0 -52
  275. package/dist/plugin/templates.d.ts +0 -52
  276. package/dist/plugin/templates.js +0 -25
  277. package/dist/plugin/types.cjs +0 -18
  278. package/dist/plugin/types.d.cts +0 -209
  279. package/dist/plugin/types.d.ts +0 -209
  280. package/dist/plugin/types.js +0 -0
  281. package/dist/plugin/vault.cjs +0 -927
  282. package/dist/plugin/vault.d.cts +0 -68
  283. package/dist/plugin/vault.d.ts +0 -68
  284. package/dist/plugin/vault.js +0 -22
  285. package/dist/types-Y2_Um2Ls.d.ts +0 -205
  286. package/templates/memory-event.md +0 -67
  287. package/templates/party.md +0 -63
  288. package/templates/primitive-registry.yaml +0 -551
  289. package/templates/run.md +0 -68
  290. package/templates/trigger.md +0 -68
  291. package/templates/workspace.md +0 -50
@@ -46,8 +46,6 @@ async function loadHandler() {
46
46
  afterEach(() => {
47
47
  vi.clearAllMocks();
48
48
  delete process.env.CLAWVAULT_PATH;
49
- delete process.env.OPENCLAW_MEMORY_PATH;
50
- delete process.env.OPENCLAW_VAULT_PATH;
51
49
  delete process.env.OPENCLAW_STATE_DIR;
52
50
  delete process.env.OPENCLAW_HOME;
53
51
  delete process.env.OPENCLAW_AGENT_ID;
@@ -107,28 +105,6 @@ describe('clawvault hook handler', () => {
107
105
  fs.rmSync(vaultPath, { recursive: true, force: true });
108
106
  });
109
107
 
110
- it('supports slash-prefixed command actions for /new', async () => {
111
- const vaultPath = makeVaultFixture();
112
- process.env.CLAWVAULT_PATH = vaultPath;
113
- execFileSyncMock.mockReturnValue('');
114
-
115
- const handler = await loadHandler();
116
- await handler({
117
- type: 'command',
118
- action: '/new',
119
- sessionKey: 'agent:clawdious:main',
120
- context: { commandSource: 'slash' }
121
- });
122
-
123
- expect(execFileSyncMock).toHaveBeenCalledWith(
124
- 'clawvault',
125
- expect.arrayContaining(['checkpoint', '--working-on']),
126
- expect.objectContaining({ shell: false })
127
- );
128
-
129
- fs.rmSync(vaultPath, { recursive: true, force: true });
130
- });
131
-
132
108
  it('injects recap and memory context on session start alias event', async () => {
133
109
  const vaultPath = makeVaultFixture();
134
110
  process.env.CLAWVAULT_PATH = vaultPath;
@@ -265,90 +241,270 @@ describe('clawvault hook handler', () => {
265
241
  fs.rmSync(vaultPath, { recursive: true, force: true });
266
242
  });
267
243
 
268
- it('supports compaction action separator variants', async () => {
244
+ it('runs weekly reflection on cron.weekly at Sunday midnight', async () => {
269
245
  const vaultPath = makeVaultFixture();
270
246
  process.env.CLAWVAULT_PATH = vaultPath;
271
247
  execFileSyncMock.mockReturnValue('');
272
248
 
273
249
  const handler = await loadHandler();
274
250
  await handler({
275
- type: 'compaction',
276
- action: 'memory_flush',
277
- sessionKey: 'agent:clawdious:main'
251
+ eventName: 'cron.weekly',
252
+ timestamp: '2026-02-15T00:00:00.000Z'
278
253
  });
279
254
 
280
255
  expect(execFileSyncMock).toHaveBeenCalledWith(
281
256
  'clawvault',
282
- expect.arrayContaining(['observe', '--cron', '--min-new', '1']),
257
+ expect.arrayContaining(['reflect', '-v', vaultPath]),
283
258
  expect.objectContaining({ shell: false })
284
259
  );
285
260
 
286
261
  fs.rmSync(vaultPath, { recursive: true, force: true });
287
262
  });
288
263
 
289
- it('discovers canonical ~/memory vault when env and cwd do not provide one', async () => {
290
- const fakeHome = fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-home-'));
291
- const vaultPath = path.join(fakeHome, 'memory');
292
- fs.mkdirSync(vaultPath, { recursive: true });
293
- fs.writeFileSync(path.join(vaultPath, '.clawvault.json'), JSON.stringify({ name: 'home' }), 'utf-8');
294
- const originalHome = process.env.HOME;
295
- const originalClawvaultPath = process.env.CLAWVAULT_PATH;
296
- const originalOpenclawMemory = process.env.OPENCLAW_MEMORY_PATH;
297
- const originalOpenclawVault = process.env.OPENCLAW_VAULT_PATH;
298
- process.env.HOME = fakeHome;
299
- delete process.env.CLAWVAULT_PATH;
300
- delete process.env.OPENCLAW_MEMORY_PATH;
301
- delete process.env.OPENCLAW_VAULT_PATH;
302
- // Mock cwd to a temp dir without a vault so walk-up doesn't find one
303
- const fakeCwd = fs.mkdtempSync(path.join(os.tmpdir(), 'clawvault-cwd-'));
304
- const originalCwd = process.cwd;
305
- process.cwd = () => fakeCwd;
306
- try {
307
- execFileSyncMock.mockReturnValue('');
308
-
309
- const handler = await loadHandler();
310
- await handler({
311
- eventName: 'compaction:memoryFlush',
312
- sessionKey: 'agent:main:main'
313
- });
314
-
315
- expect(execFileSyncMock).toHaveBeenCalledWith(
316
- 'clawvault',
317
- expect.arrayContaining(['observe', '--cron', '-v', vaultPath]),
318
- expect.objectContaining({ shell: false })
319
- );
320
- } finally {
321
- if (originalHome === undefined) {
322
- delete process.env.HOME;
323
- } else {
324
- process.env.HOME = originalHome;
264
+ it('uses vaultPath from plugin config when provided in event', async () => {
265
+ const vaultPath = makeVaultFixture();
266
+
267
+ execFileSyncMock.mockImplementation((_command, args) => {
268
+ if (args[0] === 'recover') {
269
+ return 'Clean startup';
325
270
  }
326
- if (originalClawvaultPath !== undefined) process.env.CLAWVAULT_PATH = originalClawvaultPath;
327
- if (originalOpenclawMemory !== undefined) process.env.OPENCLAW_MEMORY_PATH = originalOpenclawMemory;
328
- if (originalOpenclawVault !== undefined) process.env.OPENCLAW_VAULT_PATH = originalOpenclawVault;
329
- process.cwd = originalCwd;
330
- fs.rmSync(fakeHome, { recursive: true, force: true });
331
- fs.rmSync(fakeCwd, { recursive: true, force: true });
332
- }
271
+ return '';
272
+ });
273
+
274
+ const handler = await loadHandler();
275
+ const event = {
276
+ type: 'gateway',
277
+ action: 'startup',
278
+ pluginConfig: {
279
+ vaultPath
280
+ },
281
+ messages: []
282
+ };
283
+
284
+ await handler(event);
285
+
286
+ expect(execFileSyncMock).toHaveBeenCalledWith(
287
+ 'clawvault',
288
+ expect.arrayContaining(['recover', '--clear', '-v', vaultPath]),
289
+ expect.objectContaining({ shell: false })
290
+ );
291
+
292
+ fs.rmSync(vaultPath, { recursive: true, force: true });
333
293
  });
334
294
 
335
- it('runs weekly reflection on cron.weekly at Sunday midnight', async () => {
295
+ it('uses vaultPath from context.pluginConfig when provided', async () => {
336
296
  const vaultPath = makeVaultFixture();
337
- process.env.CLAWVAULT_PATH = vaultPath;
338
- execFileSyncMock.mockReturnValue('');
297
+
298
+ execFileSyncMock.mockImplementation((_command, args) => {
299
+ if (args[0] === 'recover') {
300
+ return 'Clean startup';
301
+ }
302
+ return '';
303
+ });
339
304
 
340
305
  const handler = await loadHandler();
341
- await handler({
342
- eventName: 'cron.weekly',
343
- timestamp: '2026-02-15T00:00:00.000Z'
306
+ const event = {
307
+ type: 'gateway',
308
+ action: 'startup',
309
+ context: {
310
+ pluginConfig: {
311
+ vaultPath
312
+ }
313
+ },
314
+ messages: []
315
+ };
316
+
317
+ await handler(event);
318
+
319
+ expect(execFileSyncMock).toHaveBeenCalledWith(
320
+ 'clawvault',
321
+ expect.arrayContaining(['recover', '--clear', '-v', vaultPath]),
322
+ expect.objectContaining({ shell: false })
323
+ );
324
+
325
+ fs.rmSync(vaultPath, { recursive: true, force: true });
326
+ });
327
+
328
+ it('uses vaultPath from OPENCLAW_PLUGIN_CLAWVAULT_VAULTPATH env var', async () => {
329
+ const vaultPath = makeVaultFixture();
330
+ process.env.OPENCLAW_PLUGIN_CLAWVAULT_VAULTPATH = vaultPath;
331
+
332
+ execFileSyncMock.mockImplementation((_command, args) => {
333
+ if (args[0] === 'recover') {
334
+ return 'Clean startup';
335
+ }
336
+ return '';
344
337
  });
345
338
 
339
+ const handler = await loadHandler();
340
+ const event = {
341
+ type: 'gateway',
342
+ action: 'startup',
343
+ messages: []
344
+ };
345
+
346
+ await handler(event);
347
+
346
348
  expect(execFileSyncMock).toHaveBeenCalledWith(
347
349
  'clawvault',
348
- expect.arrayContaining(['reflect', '-v', vaultPath]),
350
+ expect.arrayContaining(['recover', '--clear', '-v', vaultPath]),
349
351
  expect.objectContaining({ shell: false })
350
352
  );
351
353
 
354
+ delete process.env.OPENCLAW_PLUGIN_CLAWVAULT_VAULTPATH;
352
355
  fs.rmSync(vaultPath, { recursive: true, force: true });
353
356
  });
357
+
358
+ it('uses per-agent vault path from agentVaults config', async () => {
359
+ const agent1Vault = makeVaultFixture();
360
+ const agent2Vault = makeVaultFixture();
361
+ const fallbackVault = makeVaultFixture();
362
+
363
+ execFileSyncMock.mockImplementation((_command, args) => {
364
+ if (args[0] === 'recover') {
365
+ return 'Clean startup';
366
+ }
367
+ return '';
368
+ });
369
+
370
+ const handler = await loadHandler();
371
+ const event = {
372
+ type: 'gateway',
373
+ action: 'startup',
374
+ sessionKey: 'agent:agent1:main',
375
+ pluginConfig: {
376
+ vaultPath: fallbackVault,
377
+ agentVaults: {
378
+ agent1: agent1Vault,
379
+ agent2: agent2Vault
380
+ }
381
+ },
382
+ messages: []
383
+ };
384
+
385
+ await handler(event);
386
+
387
+ expect(execFileSyncMock).toHaveBeenCalledWith(
388
+ 'clawvault',
389
+ expect.arrayContaining(['recover', '--clear', '-v', agent1Vault]),
390
+ expect.objectContaining({ shell: false })
391
+ );
392
+
393
+ fs.rmSync(agent1Vault, { recursive: true, force: true });
394
+ fs.rmSync(agent2Vault, { recursive: true, force: true });
395
+ fs.rmSync(fallbackVault, { recursive: true, force: true });
396
+ });
397
+
398
+ it('falls back to vaultPath when agent not in agentVaults', async () => {
399
+ const agent1Vault = makeVaultFixture();
400
+ const fallbackVault = makeVaultFixture();
401
+
402
+ execFileSyncMock.mockImplementation((_command, args) => {
403
+ if (args[0] === 'recover') {
404
+ return 'Clean startup';
405
+ }
406
+ return '';
407
+ });
408
+
409
+ const handler = await loadHandler();
410
+ const event = {
411
+ type: 'gateway',
412
+ action: 'startup',
413
+ sessionKey: 'agent:unknown-agent:main',
414
+ pluginConfig: {
415
+ vaultPath: fallbackVault,
416
+ agentVaults: {
417
+ agent1: agent1Vault
418
+ }
419
+ },
420
+ messages: []
421
+ };
422
+
423
+ await handler(event);
424
+
425
+ expect(execFileSyncMock).toHaveBeenCalledWith(
426
+ 'clawvault',
427
+ expect.arrayContaining(['recover', '--clear', '-v', fallbackVault]),
428
+ expect.objectContaining({ shell: false })
429
+ );
430
+
431
+ fs.rmSync(agent1Vault, { recursive: true, force: true });
432
+ fs.rmSync(fallbackVault, { recursive: true, force: true });
433
+ });
434
+
435
+ it('uses agentVaults from context.pluginConfig', async () => {
436
+ const agent1Vault = makeVaultFixture();
437
+ const fallbackVault = makeVaultFixture();
438
+
439
+ execFileSyncMock.mockImplementation((_command, args) => {
440
+ if (args[0] === 'recover') {
441
+ return 'Clean startup';
442
+ }
443
+ return '';
444
+ });
445
+
446
+ const handler = await loadHandler();
447
+ const event = {
448
+ type: 'gateway',
449
+ action: 'startup',
450
+ sessionKey: 'agent:agent1:main',
451
+ context: {
452
+ pluginConfig: {
453
+ vaultPath: fallbackVault,
454
+ agentVaults: {
455
+ agent1: agent1Vault
456
+ }
457
+ }
458
+ },
459
+ messages: []
460
+ };
461
+
462
+ await handler(event);
463
+
464
+ expect(execFileSyncMock).toHaveBeenCalledWith(
465
+ 'clawvault',
466
+ expect.arrayContaining(['recover', '--clear', '-v', agent1Vault]),
467
+ expect.objectContaining({ shell: false })
468
+ );
469
+
470
+ fs.rmSync(agent1Vault, { recursive: true, force: true });
471
+ fs.rmSync(fallbackVault, { recursive: true, force: true });
472
+ });
473
+
474
+ it('uses OPENCLAW_AGENT_ID env var for agent resolution when session key not available', async () => {
475
+ const agent1Vault = makeVaultFixture();
476
+ const fallbackVault = makeVaultFixture();
477
+ process.env.OPENCLAW_AGENT_ID = 'agent1';
478
+
479
+ execFileSyncMock.mockImplementation((_command, args) => {
480
+ if (args[0] === 'recover') {
481
+ return 'Clean startup';
482
+ }
483
+ return '';
484
+ });
485
+
486
+ const handler = await loadHandler();
487
+ const event = {
488
+ type: 'gateway',
489
+ action: 'startup',
490
+ pluginConfig: {
491
+ vaultPath: fallbackVault,
492
+ agentVaults: {
493
+ agent1: agent1Vault
494
+ }
495
+ },
496
+ messages: []
497
+ };
498
+
499
+ await handler(event);
500
+
501
+ expect(execFileSyncMock).toHaveBeenCalledWith(
502
+ 'clawvault',
503
+ expect.arrayContaining(['recover', '--clear', '-v', agent1Vault]),
504
+ expect.objectContaining({ shell: false })
505
+ );
506
+
507
+ fs.rmSync(agent1Vault, { recursive: true, force: true });
508
+ fs.rmSync(fallbackVault, { recursive: true, force: true });
509
+ });
354
510
  });
@@ -0,0 +1,72 @@
1
+ {
2
+ "id": "clawvault",
3
+ "name": "ClawVault",
4
+ "version": "2.6.1",
5
+ "description": "Structured memory system for AI agents with context death resilience",
6
+ "kind": "memory",
7
+ "configSchema": {
8
+ "type": "object",
9
+ "properties": {
10
+ "vaultPath": {
11
+ "type": "string",
12
+ "description": "Path to the ClawVault vault directory. If not set, auto-discovered from CLAWVAULT_PATH or by walking up from cwd."
13
+ },
14
+ "autoCheckpoint": {
15
+ "type": "boolean",
16
+ "description": "Enable automatic checkpointing on session events",
17
+ "default": true
18
+ },
19
+ "contextProfile": {
20
+ "type": "string",
21
+ "enum": ["default", "planning", "incident", "handoff", "auto"],
22
+ "description": "Default context profile for session start injection",
23
+ "default": "auto"
24
+ },
25
+ "maxContextResults": {
26
+ "type": "integer",
27
+ "minimum": 1,
28
+ "maximum": 20,
29
+ "description": "Maximum number of context results to inject on session start",
30
+ "default": 4
31
+ },
32
+ "observeOnHeartbeat": {
33
+ "type": "boolean",
34
+ "description": "Enable observation threshold checks on gateway heartbeat",
35
+ "default": true
36
+ },
37
+ "weeklyReflection": {
38
+ "type": "boolean",
39
+ "description": "Enable weekly reflection on Sunday midnight UTC",
40
+ "default": true
41
+ }
42
+ },
43
+ "additionalProperties": false
44
+ },
45
+ "uiHints": {
46
+ "vaultPath": {
47
+ "label": "Vault Path",
48
+ "placeholder": "~/my-vault",
49
+ "description": "Path to your ClawVault memory vault"
50
+ },
51
+ "autoCheckpoint": {
52
+ "label": "Auto Checkpoint",
53
+ "description": "Automatically checkpoint before session resets"
54
+ },
55
+ "contextProfile": {
56
+ "label": "Context Profile",
57
+ "description": "Profile used for context injection at session start"
58
+ },
59
+ "maxContextResults": {
60
+ "label": "Max Context Results",
61
+ "description": "Number of vault memories to inject"
62
+ },
63
+ "observeOnHeartbeat": {
64
+ "label": "Observe on Heartbeat",
65
+ "description": "Check observation thresholds during heartbeat events"
66
+ },
67
+ "weeklyReflection": {
68
+ "label": "Weekly Reflection",
69
+ "description": "Run weekly reflection on Sunday midnight UTC"
70
+ }
71
+ }
72
+ }
@@ -1,56 +1,83 @@
1
1
  {
2
2
  "id": "clawvault",
3
- "kind": "memory",
4
- "uiHints": {
5
- "vaultPath": {
6
- "label": "Vault Path",
7
- "placeholder": "~/clawvault",
8
- "help": "Path to your ClawVault vault directory"
9
- },
10
- "collection": {
11
- "label": "QMD Collection",
12
- "placeholder": "clawvault",
13
- "help": "Name of the qmd search collection",
14
- "advanced": true
15
- },
16
- "autoRecall": {
17
- "label": "Auto-Recall",
18
- "help": "Automatically inject relevant memories before each agent turn"
19
- },
20
- "autoCapture": {
21
- "label": "Auto-Capture",
22
- "help": "Automatically observe and capture important information from conversations"
23
- },
24
- "recallLimit": {
25
- "label": "Recall Limit",
26
- "help": "Max memories to inject per turn (default: 5)",
27
- "advanced": true
28
- }
29
- },
3
+ "name": "ClawVault",
4
+ "version": "2.6.5",
5
+ "description": "Structured memory system for AI agents with context death resilience",
30
6
  "configSchema": {
31
7
  "type": "object",
32
- "additionalProperties": false,
33
8
  "properties": {
34
9
  "vaultPath": {
35
- "type": "string"
10
+ "type": "string",
11
+ "description": "Path to the ClawVault vault directory. If not set, auto-discovered from CLAWVAULT_PATH or by walking up from cwd. Used as fallback when agentVaults is not set or agent not found."
36
12
  },
37
- "collection": {
38
- "type": "string"
13
+ "agentVaults": {
14
+ "type": "object",
15
+ "description": "Mapping of agent names to vault paths. Allows each agent to have its own vault. Falls back to vaultPath if agent not found.",
16
+ "additionalProperties": {
17
+ "type": "string",
18
+ "description": "Path to the vault directory for this agent"
19
+ }
39
20
  },
40
- "autoRecall": {
21
+ "autoCheckpoint": {
41
22
  "type": "boolean",
23
+ "description": "Enable automatic checkpointing on session events",
42
24
  "default": true
43
25
  },
44
- "autoCapture": {
45
- "type": "boolean",
46
- "default": true
26
+ "contextProfile": {
27
+ "type": "string",
28
+ "enum": ["default", "planning", "incident", "handoff", "auto"],
29
+ "description": "Default context profile for session start injection",
30
+ "default": "auto"
47
31
  },
48
- "recallLimit": {
49
- "type": "number",
32
+ "maxContextResults": {
33
+ "type": "integer",
50
34
  "minimum": 1,
51
35
  "maximum": 20,
52
- "default": 5
36
+ "description": "Maximum number of context results to inject on session start",
37
+ "default": 4
38
+ },
39
+ "observeOnHeartbeat": {
40
+ "type": "boolean",
41
+ "description": "Enable observation threshold checks on gateway heartbeat",
42
+ "default": true
43
+ },
44
+ "weeklyReflection": {
45
+ "type": "boolean",
46
+ "description": "Enable weekly reflection on Sunday midnight UTC",
47
+ "default": true
53
48
  }
49
+ },
50
+ "additionalProperties": false
51
+ },
52
+ "uiHints": {
53
+ "vaultPath": {
54
+ "label": "Vault Path",
55
+ "placeholder": "~/my-vault",
56
+ "description": "Path to your ClawVault memory vault (fallback when agentVaults not set)"
57
+ },
58
+ "agentVaults": {
59
+ "label": "Agent Vaults",
60
+ "description": "Per-agent vault paths (e.g., {\"agent1\": \"/path/to/vault1\", \"agent2\": \"/path/to/vault2\"})"
61
+ },
62
+ "autoCheckpoint": {
63
+ "label": "Auto Checkpoint",
64
+ "description": "Automatically checkpoint before session resets"
65
+ },
66
+ "contextProfile": {
67
+ "label": "Context Profile",
68
+ "description": "Profile used for context injection at session start"
69
+ },
70
+ "maxContextResults": {
71
+ "label": "Max Context Results",
72
+ "description": "Number of vault memories to inject"
73
+ },
74
+ "observeOnHeartbeat": {
75
+ "label": "Observe on Heartbeat",
76
+ "description": "Check observation thresholds during heartbeat events"
77
+ },
78
+ "weeklyReflection": {
79
+ "label": "Weekly Reflection",
80
+ "description": "Run weekly reflection on Sunday midnight UTC"
54
81
  }
55
82
  }
56
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawvault",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "Structured memory system for AI agents \u2014 typed storage, knowledge graph, context profiles, canvas dashboards, neural graph themes, and Obsidian-native task views. An elephant never forgets. \ud83d\udc18",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -11,11 +11,6 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "require": "./dist/index.cjs"
14
- },
15
- "./plugin": {
16
- "types": "./dist/plugin/index.d.ts",
17
- "import": "./dist/plugin/index.js",
18
- "require": "./dist/plugin/index.cjs"
19
14
  }
20
15
  },
21
16
  "bin": {
@@ -24,23 +19,27 @@
24
19
  "files": [
25
20
  "dist",
26
21
  "bin",
22
+ "dashboard",
27
23
  "templates",
28
24
  "hooks",
29
25
  "openclaw.plugin.json"
30
26
  ],
31
27
  "openclaw": {
28
+ "plugin": "./openclaw.plugin.json",
29
+ "extensions": [
30
+ "./dist/openclaw-plugin.js"
31
+ ],
32
32
  "hooks": [
33
33
  "./hooks/clawvault"
34
- ],
35
- "plugin": "./openclaw.plugin.json"
34
+ ]
36
35
  },
37
36
  "scripts": {
38
- "build": "tsup src/commands/archive.ts src/commands/backlog.ts src/commands/blocked.ts src/commands/checkpoint.ts src/commands/compat.ts src/commands/context.ts src/commands/doctor.ts src/commands/embed.ts src/commands/entities.ts src/commands/graph.ts src/commands/inject.ts src/commands/kanban.ts src/commands/link.ts src/commands/migrate-observations.ts src/commands/observe.ts src/commands/project.ts src/commands/rebuild.ts src/commands/recover.ts src/commands/reflect.ts src/commands/repair-session.ts src/commands/replay.ts src/commands/session-recap.ts src/commands/setup.ts src/commands/shell-init.ts src/commands/sleep.ts src/commands/status.ts src/commands/tailscale.ts src/commands/task.ts src/commands/template.ts src/commands/wake.ts src/cli/index.ts src/index.ts src/lib/auto-linker.ts src/lib/canvas-layout.ts src/lib/config.ts src/lib/entity-index.ts src/lib/project-utils.ts src/lib/session-repair.ts src/lib/session-utils.ts src/lib/tailscale.ts src/lib/task-utils.ts src/lib/template-engine.ts src/lib/webdav.ts src/plugin/index.ts src/plugin/types.ts src/plugin/vault.ts src/plugin/observe.ts src/plugin/inject.ts src/plugin/templates.ts --format esm,cjs --dts --clean",
37
+ "build": "tsup src/commands/archive.ts src/commands/backlog.ts src/commands/blocked.ts src/commands/canvas.ts src/commands/checkpoint.ts src/commands/compat.ts src/commands/context.ts src/commands/doctor.ts src/commands/embed.ts src/commands/entities.ts src/commands/graph.ts src/commands/inject.ts src/commands/kanban.ts src/commands/link.ts src/commands/migrate-observations.ts src/commands/observe.ts src/commands/project.ts src/commands/rebuild.ts src/commands/rebuild-embeddings.ts src/commands/recover.ts src/commands/reflect.ts src/commands/repair-session.ts src/commands/replay.ts src/commands/session-recap.ts src/commands/setup.ts src/commands/shell-init.ts src/commands/sleep.ts src/commands/status.ts src/commands/sync-bd.ts src/commands/tailscale.ts src/commands/task.ts src/commands/template.ts src/commands/wake.ts src/commands/workgraph.ts src/cli/index.ts src/index.ts src/openclaw-plugin.ts src/lib/auto-linker.ts src/lib/canvas-layout.ts src/lib/config.ts src/lib/entity-index.ts src/lib/project-utils.ts src/lib/session-repair.ts src/lib/session-utils.ts src/lib/tailscale.ts src/lib/task-utils.ts src/lib/template-engine.ts src/lib/webdav.ts src/workgraph/index.ts src/workgraph/types.ts src/workgraph/registry.ts src/workgraph/ledger.ts src/workgraph/store.ts src/workgraph/thread.ts --format esm --dts --clean",
39
38
  "dev": "tsup src/index.ts src/commands/*.ts src/lib/*.ts --format esm --dts --watch",
40
39
  "lint": "eslint src",
41
40
  "typecheck": "tsc --noEmit",
42
- "test": "vitest run",
43
- "ci": "npm run typecheck && npm test && npm run build",
41
+ "test": "npm run build && vitest run",
42
+ "ci": "npm run typecheck && npm test",
44
43
  "prepublishOnly": "npm run build"
45
44
  },
46
45
  "keywords": [
@@ -71,7 +70,6 @@
71
70
  "node": ">=18"
72
71
  },
73
72
  "dependencies": {
74
- "@sinclair/typebox": "^0.34.48",
75
73
  "chalk": "^5.3.0",
76
74
  "chokidar": "^5.0.0",
77
75
  "commander": "^12.0.0",
@@ -80,7 +78,8 @@
80
78
  "glob": "^10.3.10",
81
79
  "gray-matter": "^4.0.3",
82
80
  "natural": "^6.10.4",
83
- "ws": "^8.19.0"
81
+ "ws": "^8.19.0",
82
+ "yaml": "^2.8.2"
84
83
  },
85
84
  "peerDependencies": {
86
85
  "qmd": "*"
@@ -91,14 +90,12 @@
91
90
  }
92
91
  },
93
92
  "devDependencies": {
93
+ "@huggingface/transformers": "^3.8.1",
94
94
  "@types/node": "^20.11.0",
95
95
  "ajv": "^8.17.1",
96
96
  "puppeteer": "^24.37.2",
97
97
  "tsup": "^8.0.1",
98
98
  "typescript": "^5.3.3",
99
99
  "vitest": "^1.2.0"
100
- },
101
- "workspaces": [
102
- "packages/*"
103
- ]
104
- }
100
+ }
101
+ }
@@ -1,10 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- export {
9
- __require
10
- };