clawvault 3.1.0 → 3.2.1

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 (273) hide show
  1. package/README.md +422 -141
  2. package/bin/clawvault.js +10 -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 -28
  6. package/bin/register-maintenance-commands.js +39 -3
  7. package/bin/register-query-commands.js +58 -29
  8. package/bin/register-tailscale-commands.js +106 -0
  9. package/bin/register-task-commands.js +18 -1
  10. package/bin/register-task-commands.test.js +16 -0
  11. package/bin/register-vault-operations-commands.js +29 -1
  12. package/bin/register-workgraph-commands.js +451 -0
  13. package/dashboard/lib/graph-diff.js +104 -0
  14. package/dashboard/lib/graph-diff.test.js +75 -0
  15. package/dashboard/lib/vault-parser.js +556 -0
  16. package/dashboard/lib/vault-parser.test.js +254 -0
  17. package/dashboard/public/app.js +796 -0
  18. package/dashboard/public/index.html +52 -0
  19. package/dashboard/public/styles.css +221 -0
  20. package/dashboard/server.js +374 -0
  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-F2JEUD4J.js → chunk-4ITRXIVT.js} +5 -7
  24. package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
  25. package/dist/chunk-5PJ4STIC.js +465 -0
  26. package/dist/{chunk-62YTUT6J.js → chunk-AZYOKJYC.js} +2 -2
  27. package/dist/chunk-BSJ6RIT7.js +447 -0
  28. package/dist/chunk-ECRZL5XR.js +50 -0
  29. package/dist/chunk-ERNE2FZ5.js +189 -0
  30. package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
  31. package/dist/{chunk-VGLOTGAS.js → chunk-FAKNOB7Y.js} +2 -2
  32. package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
  33. package/dist/chunk-GNJL4YGR.js +79 -0
  34. package/dist/chunk-HR4KN6S2.js +152 -0
  35. package/dist/{chunk-OZ7RIXTO.js → chunk-IIOU45CK.js} +1 -1
  36. package/dist/chunk-IJBFGPCS.js +33 -0
  37. package/dist/chunk-IVRIKYFE.js +520 -0
  38. package/dist/chunk-K7PNYS45.js +93 -0
  39. package/dist/chunk-MDIH26GC.js +183 -0
  40. package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
  41. package/dist/{chunk-H34S76MB.js → chunk-MNPUYCHQ.js} +6 -6
  42. package/dist/chunk-NTOPJI7W.js +207 -0
  43. package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
  44. package/dist/chunk-PG56HX5T.js +154 -0
  45. package/dist/{chunk-LNJA2UGL.js → chunk-PI4WMLMG.js} +7 -84
  46. package/dist/chunk-QMHPQYUV.js +363 -0
  47. package/dist/{chunk-H62BP7RI.js → chunk-QPDDIHXE.js} +209 -43
  48. package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
  49. package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
  50. package/dist/{chunk-SJSFRIYS.js → chunk-S5OJEGFG.js} +2 -2
  51. package/dist/chunk-SS4B7P7V.js +99 -0
  52. package/dist/chunk-TIGW564L.js +628 -0
  53. package/dist/chunk-U67V476Y.js +35 -0
  54. package/dist/{chunk-JY6FYXIT.js → chunk-UCQAOZHW.js} +6 -11
  55. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  56. package/dist/chunk-WIOLLGAD.js +190 -0
  57. package/dist/{chunk-3WRJEKN4.js → chunk-WJVWINEM.js} +72 -8
  58. package/dist/chunk-WMGIIABP.js +15 -0
  59. package/dist/{chunk-33UGEQRT.js → chunk-X3SPPUFG.js} +151 -64
  60. package/dist/{chunk-3NSBOUT3.js → chunk-Y3TIJEBP.js} +314 -79
  61. package/dist/chunk-Y6VJKXGL.js +373 -0
  62. package/dist/{chunk-LI4O6NVK.js → chunk-YDWHS4LJ.js} +49 -9
  63. package/dist/{chunk-U55BGUAU.js → chunk-YNIPYN4F.js} +5 -5
  64. package/dist/chunk-YXQCA6B7.js +226 -0
  65. package/dist/cli/index.js +26 -22
  66. package/dist/commands/archive.js +3 -3
  67. package/dist/commands/backlog.js +3 -3
  68. package/dist/commands/blocked.js +3 -3
  69. package/dist/commands/canvas.d.ts +15 -0
  70. package/dist/commands/canvas.js +200 -0
  71. package/dist/commands/checkpoint.js +2 -2
  72. package/dist/commands/compat.js +2 -2
  73. package/dist/commands/context.js +7 -5
  74. package/dist/commands/doctor.d.ts +11 -7
  75. package/dist/commands/doctor.js +16 -14
  76. package/dist/commands/embed.js +5 -6
  77. package/dist/commands/entities.js +2 -2
  78. package/dist/commands/graph.js +3 -3
  79. package/dist/commands/inject.d.ts +1 -1
  80. package/dist/commands/inject.js +4 -5
  81. package/dist/commands/kanban.js +4 -4
  82. package/dist/commands/link.js +2 -2
  83. package/dist/commands/migrate-observations.js +4 -4
  84. package/dist/commands/observe.d.ts +0 -1
  85. package/dist/commands/observe.js +13 -12
  86. package/dist/commands/project.js +5 -5
  87. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  88. package/dist/commands/rebuild-embeddings.js +91 -0
  89. package/dist/commands/rebuild.js +12 -11
  90. package/dist/commands/recover.js +3 -3
  91. package/dist/commands/reflect.js +6 -7
  92. package/dist/commands/repair-session.js +1 -1
  93. package/dist/commands/replay.js +14 -14
  94. package/dist/commands/session-recap.js +1 -1
  95. package/dist/commands/setup.d.ts +2 -89
  96. package/dist/commands/setup.js +3 -21
  97. package/dist/commands/shell-init.js +1 -1
  98. package/dist/commands/sleep.d.ts +1 -1
  99. package/dist/commands/sleep.js +18 -17
  100. package/dist/commands/status.d.ts +2 -0
  101. package/dist/commands/status.js +40 -30
  102. package/dist/commands/sync-bd.d.ts +10 -0
  103. package/dist/commands/sync-bd.js +10 -0
  104. package/dist/commands/tailscale.d.ts +52 -0
  105. package/dist/commands/tailscale.js +26 -0
  106. package/dist/commands/task.js +4 -4
  107. package/dist/commands/template.js +2 -2
  108. package/dist/commands/wake.d.ts +1 -1
  109. package/dist/commands/wake.js +11 -10
  110. package/dist/index.d.ts +334 -191
  111. package/dist/index.js +432 -108
  112. package/dist/{inject-Bzi5E-By.d.ts → inject-DYUrDqQO.d.ts} +3 -3
  113. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  114. package/dist/lib/auto-linker.js +1 -1
  115. package/dist/lib/canvas-layout.d.ts +115 -0
  116. package/dist/lib/canvas-layout.js +35 -0
  117. package/dist/lib/config.d.ts +27 -3
  118. package/dist/lib/config.js +4 -2
  119. package/dist/lib/entity-index.js +1 -1
  120. package/dist/lib/project-utils.js +4 -4
  121. package/dist/lib/session-repair.js +1 -1
  122. package/dist/lib/session-utils.js +1 -1
  123. package/dist/lib/tailscale.d.ts +225 -0
  124. package/dist/lib/tailscale.js +50 -0
  125. package/dist/lib/task-utils.js +3 -3
  126. package/dist/lib/template-engine.js +1 -1
  127. package/dist/lib/webdav.d.ts +109 -0
  128. package/dist/lib/webdav.js +35 -0
  129. package/dist/plugin/index.d.ts +344 -28
  130. package/dist/plugin/index.js +3919 -227
  131. package/dist/registry-BR4326o0.d.ts +30 -0
  132. package/dist/store-CA-6sKCJ.d.ts +34 -0
  133. package/dist/thread-B9LhXNU0.d.ts +41 -0
  134. package/dist/{types-Y2_Um2Ls.d.ts → types-BbWJoC1c.d.ts} +1 -44
  135. package/dist/workgraph/index.d.ts +5 -0
  136. package/dist/workgraph/index.js +23 -0
  137. package/dist/workgraph/ledger.d.ts +2 -0
  138. package/dist/workgraph/ledger.js +25 -0
  139. package/dist/workgraph/registry.d.ts +2 -0
  140. package/dist/workgraph/registry.js +19 -0
  141. package/dist/workgraph/store.d.ts +2 -0
  142. package/dist/workgraph/store.js +25 -0
  143. package/dist/workgraph/thread.d.ts +2 -0
  144. package/dist/workgraph/thread.js +25 -0
  145. package/dist/workgraph/types.d.ts +54 -0
  146. package/dist/workgraph/types.js +7 -0
  147. package/hooks/clawvault/HOOK.md +113 -0
  148. package/hooks/clawvault/handler.js +1559 -0
  149. package/hooks/clawvault/handler.test.js +510 -0
  150. package/hooks/clawvault/openclaw.plugin.json +72 -0
  151. package/openclaw.plugin.json +235 -30
  152. package/package.json +20 -20
  153. package/dist/chunk-3RG5ZIWI.js +0 -10
  154. package/dist/chunk-3ZIH425O.js +0 -871
  155. package/dist/chunk-6U6MK36V.js +0 -205
  156. package/dist/chunk-CMB7UL7C.js +0 -327
  157. package/dist/chunk-D2H45LON.js +0 -1074
  158. package/dist/chunk-E7MFQB6D.js +0 -163
  159. package/dist/chunk-GQSLDZTS.js +0 -560
  160. package/dist/chunk-MFM6K7PU.js +0 -374
  161. package/dist/chunk-MXSSG3QU.js +0 -42
  162. package/dist/chunk-OCGVIN3L.js +0 -88
  163. package/dist/chunk-PAH27GSN.js +0 -108
  164. package/dist/chunk-YCUNCH2I.js +0 -78
  165. package/dist/cli/index.cjs +0 -8584
  166. package/dist/cli/index.d.cts +0 -5
  167. package/dist/commands/archive.cjs +0 -287
  168. package/dist/commands/archive.d.cts +0 -11
  169. package/dist/commands/backlog.cjs +0 -721
  170. package/dist/commands/backlog.d.cts +0 -53
  171. package/dist/commands/blocked.cjs +0 -204
  172. package/dist/commands/blocked.d.cts +0 -26
  173. package/dist/commands/checkpoint.cjs +0 -244
  174. package/dist/commands/checkpoint.d.cts +0 -41
  175. package/dist/commands/compat.cjs +0 -294
  176. package/dist/commands/compat.d.cts +0 -28
  177. package/dist/commands/context.cjs +0 -2990
  178. package/dist/commands/context.d.cts +0 -2
  179. package/dist/commands/doctor.cjs +0 -2986
  180. package/dist/commands/doctor.d.cts +0 -21
  181. package/dist/commands/embed.cjs +0 -232
  182. package/dist/commands/embed.d.cts +0 -17
  183. package/dist/commands/entities.cjs +0 -141
  184. package/dist/commands/entities.d.cts +0 -7
  185. package/dist/commands/graph.cjs +0 -501
  186. package/dist/commands/graph.d.cts +0 -21
  187. package/dist/commands/inject.cjs +0 -1636
  188. package/dist/commands/inject.d.cts +0 -2
  189. package/dist/commands/kanban.cjs +0 -884
  190. package/dist/commands/kanban.d.cts +0 -63
  191. package/dist/commands/link.cjs +0 -965
  192. package/dist/commands/link.d.cts +0 -11
  193. package/dist/commands/migrate-observations.cjs +0 -362
  194. package/dist/commands/migrate-observations.d.cts +0 -19
  195. package/dist/commands/observe.cjs +0 -4099
  196. package/dist/commands/observe.d.cts +0 -23
  197. package/dist/commands/project.cjs +0 -1341
  198. package/dist/commands/project.d.cts +0 -85
  199. package/dist/commands/rebuild.cjs +0 -3136
  200. package/dist/commands/rebuild.d.cts +0 -11
  201. package/dist/commands/recover.cjs +0 -361
  202. package/dist/commands/recover.d.cts +0 -38
  203. package/dist/commands/reflect.cjs +0 -1008
  204. package/dist/commands/reflect.d.cts +0 -11
  205. package/dist/commands/repair-session.cjs +0 -457
  206. package/dist/commands/repair-session.d.cts +0 -38
  207. package/dist/commands/replay.cjs +0 -4103
  208. package/dist/commands/replay.d.cts +0 -16
  209. package/dist/commands/session-recap.cjs +0 -353
  210. package/dist/commands/session-recap.d.cts +0 -27
  211. package/dist/commands/setup.cjs +0 -1278
  212. package/dist/commands/setup.d.cts +0 -99
  213. package/dist/commands/shell-init.cjs +0 -75
  214. package/dist/commands/shell-init.d.cts +0 -7
  215. package/dist/commands/sleep.cjs +0 -6029
  216. package/dist/commands/sleep.d.cts +0 -36
  217. package/dist/commands/status.cjs +0 -2737
  218. package/dist/commands/status.d.cts +0 -52
  219. package/dist/commands/task.cjs +0 -1236
  220. package/dist/commands/task.d.cts +0 -97
  221. package/dist/commands/template.cjs +0 -457
  222. package/dist/commands/template.d.cts +0 -36
  223. package/dist/commands/wake.cjs +0 -2627
  224. package/dist/commands/wake.d.cts +0 -22
  225. package/dist/context-BUGaWpyL.d.cts +0 -46
  226. package/dist/index.cjs +0 -12373
  227. package/dist/index.d.cts +0 -854
  228. package/dist/inject-Bzi5E-By.d.cts +0 -137
  229. package/dist/lib/auto-linker.cjs +0 -176
  230. package/dist/lib/auto-linker.d.cts +0 -26
  231. package/dist/lib/config.cjs +0 -78
  232. package/dist/lib/config.d.cts +0 -11
  233. package/dist/lib/entity-index.cjs +0 -84
  234. package/dist/lib/entity-index.d.cts +0 -26
  235. package/dist/lib/project-utils.cjs +0 -864
  236. package/dist/lib/project-utils.d.cts +0 -97
  237. package/dist/lib/session-repair.cjs +0 -239
  238. package/dist/lib/session-repair.d.cts +0 -110
  239. package/dist/lib/session-utils.cjs +0 -209
  240. package/dist/lib/session-utils.d.cts +0 -63
  241. package/dist/lib/task-utils.cjs +0 -1137
  242. package/dist/lib/task-utils.d.cts +0 -208
  243. package/dist/lib/template-engine.cjs +0 -47
  244. package/dist/lib/template-engine.d.cts +0 -11
  245. package/dist/plugin/index.cjs +0 -1907
  246. package/dist/plugin/index.d.cts +0 -36
  247. package/dist/plugin/inject.cjs +0 -356
  248. package/dist/plugin/inject.d.cts +0 -54
  249. package/dist/plugin/inject.d.ts +0 -54
  250. package/dist/plugin/inject.js +0 -17
  251. package/dist/plugin/observe.cjs +0 -631
  252. package/dist/plugin/observe.d.cts +0 -39
  253. package/dist/plugin/observe.d.ts +0 -39
  254. package/dist/plugin/observe.js +0 -18
  255. package/dist/plugin/templates.cjs +0 -593
  256. package/dist/plugin/templates.d.cts +0 -52
  257. package/dist/plugin/templates.d.ts +0 -52
  258. package/dist/plugin/templates.js +0 -25
  259. package/dist/plugin/types.cjs +0 -18
  260. package/dist/plugin/types.d.cts +0 -209
  261. package/dist/plugin/types.d.ts +0 -209
  262. package/dist/plugin/types.js +0 -0
  263. package/dist/plugin/vault.cjs +0 -927
  264. package/dist/plugin/vault.d.cts +0 -68
  265. package/dist/plugin/vault.d.ts +0 -68
  266. package/dist/plugin/vault.js +0 -22
  267. package/dist/types-Y2_Um2Ls.d.cts +0 -205
  268. package/templates/memory-event.md +0 -67
  269. package/templates/party.md +0 -63
  270. package/templates/primitive-registry.yaml +0 -551
  271. package/templates/run.md +0 -68
  272. package/templates/trigger.md +0 -68
  273. package/templates/workspace.md +0 -50
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Observer
3
- } from "./chunk-3NSBOUT3.js";
3
+ } from "./chunk-Y3TIJEBP.js";
4
4
  import {
5
5
  getSessionsDir
6
6
  } from "./chunk-HRLWZGMA.js";
@@ -18,11 +18,6 @@ var AGENT_ID_RE = /^[a-zA-Z0-9_-]{1,100}$/;
18
18
  var SESSION_ID_RE = /^[a-zA-Z0-9._-]{1,200}$/;
19
19
  var CURSOR_FILE_NAME = "observe-cursors.json";
20
20
  var STALE_CURSOR_THRESHOLD_MS = 12 * 60 * 60 * 1e3;
21
- function formatBytes(bytes) {
22
- if (bytes >= ONE_MIB) return `${(bytes / ONE_MIB).toFixed(1)}MB`;
23
- if (bytes >= ONE_KIB) return `${Math.round(bytes / ONE_KIB)}KB`;
24
- return `${bytes}B`;
25
- }
26
21
  function isFiniteNonNegative(value) {
27
22
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
28
23
  }
@@ -158,12 +153,7 @@ function getObserverStaleness(vaultPath, options = {}) {
158
153
  if (!sessionStat.isFile()) {
159
154
  continue;
160
155
  }
161
- const newBytes = sessionStat.size - cursor.lastFileSize;
162
- if (newBytes <= 0) {
163
- continue;
164
- }
165
- const processThreshold = getScaledObservationThresholdBytes(sessionStat.size);
166
- if (newBytes < processThreshold) {
156
+ if (cursor.lastFileSize >= sessionStat.size) {
167
157
  continue;
168
158
  }
169
159
  staleCount += 1;
@@ -191,32 +181,8 @@ function loadSessionIndex(sessionsDir) {
191
181
  return {};
192
182
  }
193
183
  }
194
- function findMostRecentResetFile(sessionsDir, sessionId) {
195
- const prefix = `${sessionId}.jsonl.reset.`;
196
- try {
197
- const files = fs.readdirSync(sessionsDir).filter((f) => f.startsWith(prefix)).sort().reverse();
198
- return files.length > 0 ? path.join(sessionsDir, files[0]) : null;
199
- } catch {
200
- return null;
201
- }
202
- }
203
184
  function resolveTranscriptPath(sessionsDir, sessionId) {
204
- const mainPath = path.join(sessionsDir, `${sessionId}.jsonl`);
205
- try {
206
- const stat = fs.statSync(mainPath);
207
- if (stat.size < 100) {
208
- const resetFile = findMostRecentResetFile(sessionsDir, sessionId);
209
- if (resetFile) {
210
- return resetFile;
211
- }
212
- }
213
- } catch {
214
- const resetFile = findMostRecentResetFile(sessionsDir, sessionId);
215
- if (resetFile) {
216
- return resetFile;
217
- }
218
- }
219
- return mainPath;
185
+ return path.join(sessionsDir, `${sessionId}.jsonl`);
220
186
  }
221
187
  function discoverSessionDescriptors(sessionsDir, fallbackAgentId) {
222
188
  const descriptors = [];
@@ -293,21 +259,6 @@ function normalizeRole(role) {
293
259
  }
294
260
  return role.trim().toLowerCase();
295
261
  }
296
- function summarizeContentArray(content) {
297
- const parts = [];
298
- for (const block of content) {
299
- if (!block || typeof block !== "object") continue;
300
- const b = block;
301
- if (b.type === "text" && typeof b.text === "string") {
302
- const text = normalizeWhitespace(b.text);
303
- if (text) parts.push(text);
304
- } else if (b.type === "toolCall") {
305
- const toolName = typeof b.name === "string" ? b.name : "tool";
306
- parts.push(`[tool: ${toolName}]`);
307
- }
308
- }
309
- return parts.join(" ");
310
- }
311
262
  function parseOpenClawJsonLine(line) {
312
263
  if (!line.trim()) {
313
264
  return "";
@@ -324,38 +275,14 @@ function parseOpenClawJsonLine(line) {
324
275
  const entry = parsed;
325
276
  if ("role" in entry && "content" in entry) {
326
277
  const role = normalizeRole(entry.role);
327
- if (role === "system") return "";
328
- if (role === "toolresult") {
329
- const output = extractContentText(entry.content);
330
- const preview = output.slice(0, 80) || "ok";
331
- return `[tool_result \u2192 ${preview}]`;
332
- }
333
- const raw = entry.content;
334
- let content;
335
- if (Array.isArray(raw)) {
336
- content = summarizeContentArray(raw);
337
- } else {
338
- content = extractContentText(raw);
339
- }
278
+ const content = extractContentText(entry.content);
340
279
  if (!content) return "";
341
280
  return role ? `${role}: ${content}` : content;
342
281
  }
343
282
  if (entry.type === "message" && entry.message && typeof entry.message === "object") {
344
283
  const message = entry.message;
345
284
  const role = normalizeRole(message.role);
346
- if (role === "system") return "";
347
- if (role === "toolresult") {
348
- const output = extractContentText(message.content);
349
- const preview = output.slice(0, 80) || "ok";
350
- return `[tool_result \u2192 ${preview}]`;
351
- }
352
- const raw = message.content;
353
- let content;
354
- if (Array.isArray(raw)) {
355
- content = summarizeContentArray(raw);
356
- } else {
357
- content = extractContentText(raw);
358
- }
285
+ const content = extractContentText(message.content);
359
286
  if (!content) return "";
360
287
  return role ? `${role}: ${content}` : content;
361
288
  }
@@ -518,9 +445,7 @@ async function observeActiveSessions(options, dependencies = {}) {
518
445
  const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
519
446
  const cursors = loadObserveCursorStore(vaultPath);
520
447
  const descriptors = discoverSessionDescriptors(sessionsDir, agentId);
521
- const allCandidates = selectCandidates(descriptors, cursors, options.minNewBytes);
522
- allCandidates.sort((a, b) => b.newBytes - a.newBytes);
523
- const candidates = options.maxSessions != null && options.maxSessions > 0 ? allCandidates.slice(0, options.maxSessions) : allCandidates;
448
+ const candidates = selectCandidates(descriptors, cursors, options.minNewBytes);
524
449
  if (dryRun || candidates.length === 0) {
525
450
  return {
526
451
  agentId,
@@ -550,9 +475,7 @@ async function observeActiveSessions(options, dependencies = {}) {
550
475
  let observedNewBytes = 0;
551
476
  const routedCounts = {};
552
477
  const failedSessions = [];
553
- for (let i = 0; i < candidates.length; i += 1) {
554
- const candidate = candidates[i];
555
- console.log(`[observer] processing session ${i + 1}/${candidates.length}: ${candidate.sessionKey} (${formatBytes(candidate.newBytes)} new)`);
478
+ for (const candidate of candidates) {
556
479
  try {
557
480
  const observer = observerFactory(vaultPath, observerOptions);
558
481
  const { messages, nextOffset } = await readIncrementalMessages(candidate.filePath, candidate.startOffset);
@@ -0,0 +1,363 @@
1
+ import {
2
+ hasQmd,
3
+ withQmdIndexArgs
4
+ } from "./chunk-5PJ4STIC.js";
5
+ import {
6
+ DEFAULT_CATEGORIES
7
+ } from "./chunk-2CDEETQN.js";
8
+
9
+ // src/commands/setup.ts
10
+ import * as fs from "fs";
11
+ import * as os from "os";
12
+ import * as path from "path";
13
+ import { execFileSync } from "child_process";
14
+ var CONFIG_FILE = ".clawvault.json";
15
+ function resolveVaultTarget(vaultOverride) {
16
+ if (vaultOverride) {
17
+ const vaultPath = path.resolve(vaultOverride);
18
+ return { vaultPath, source: "--vault flag", existed: fs.existsSync(vaultPath) };
19
+ }
20
+ const envPath = process.env.CLAWVAULT_PATH?.trim();
21
+ const home = os.homedir();
22
+ if (envPath) {
23
+ const vaultPath = path.resolve(envPath);
24
+ return { vaultPath, source: "CLAWVAULT_PATH", existed: fs.existsSync(vaultPath) };
25
+ }
26
+ const candidates = [
27
+ { vaultPath: path.join(home, ".openclaw", "workspace", "memory"), source: "OpenClaw default" },
28
+ { vaultPath: path.resolve(process.cwd(), "memory"), source: "./memory" },
29
+ { vaultPath: path.join(home, "memory"), source: "~/memory" }
30
+ ];
31
+ for (const candidate of candidates) {
32
+ if (fs.existsSync(candidate.vaultPath)) {
33
+ return { ...candidate, existed: true };
34
+ }
35
+ }
36
+ const fallback = candidates[0];
37
+ return { ...fallback, existed: false };
38
+ }
39
+ function ensureVaultStructure(vaultPath) {
40
+ fs.mkdirSync(vaultPath, { recursive: true });
41
+ for (const category of DEFAULT_CATEGORIES) {
42
+ fs.mkdirSync(path.join(vaultPath, category), { recursive: true });
43
+ }
44
+ const configPath = path.join(vaultPath, CONFIG_FILE);
45
+ if (fs.existsSync(configPath)) return false;
46
+ const now = (/* @__PURE__ */ new Date()).toISOString();
47
+ const name = path.basename(vaultPath);
48
+ const meta = {
49
+ name,
50
+ version: "1.0.0",
51
+ created: now,
52
+ lastUpdated: now,
53
+ categories: DEFAULT_CATEGORIES,
54
+ documentCount: 0,
55
+ qmdCollection: name,
56
+ qmdRoot: vaultPath
57
+ };
58
+ fs.writeFileSync(configPath, JSON.stringify(meta, null, 2));
59
+ return true;
60
+ }
61
+ function writeBases(vaultPath, force) {
62
+ const basesFiles = {
63
+ "all-tasks.base": `filters:
64
+ and:
65
+ - file.inFolder("tasks")
66
+ - status != "done"
67
+ formulas:
68
+ age: (now() - file.ctime).days
69
+ status_icon: if(status == "blocked", "\u{1F534}", if(status == "in-progress", "\u{1F528}", if(status == "open", "\u26AA", "\u2705")))
70
+ views:
71
+ - type: table
72
+ name: All Active Tasks
73
+ groupBy:
74
+ property: status
75
+ direction: ASC
76
+ order:
77
+ - formula.status_icon
78
+ - file.name
79
+ - status
80
+ - owner
81
+ - project
82
+ - priority
83
+ - blocked_by
84
+ - formula.age
85
+ - type: cards
86
+ name: Task Board
87
+ groupBy:
88
+ property: status
89
+ direction: ASC
90
+ order:
91
+ - file.name
92
+ - owner
93
+ - project
94
+ - priority`,
95
+ "blocked.base": `filters:
96
+ and:
97
+ - file.inFolder("tasks")
98
+ - status == "blocked"
99
+ formulas:
100
+ days_blocked: (now() - file.ctime).days
101
+ views:
102
+ - type: table
103
+ name: Blocked Tasks
104
+ order:
105
+ - file.name
106
+ - owner
107
+ - project
108
+ - blocked_by
109
+ - formula.days_blocked
110
+ - priority`,
111
+ "by-project.base": `filters:
112
+ and:
113
+ - file.inFolder("tasks")
114
+ - status != "done"
115
+ formulas:
116
+ status_icon: if(status == "blocked", "\u{1F534}", if(status == "in-progress", "\u{1F528}", "\u26AA"))
117
+ views:
118
+ - type: table
119
+ name: By Project
120
+ groupBy:
121
+ property: project
122
+ direction: ASC
123
+ order:
124
+ - formula.status_icon
125
+ - file.name
126
+ - status
127
+ - owner
128
+ - priority
129
+ - type: cards
130
+ name: Project Cards
131
+ groupBy:
132
+ property: project
133
+ direction: ASC
134
+ order:
135
+ - file.name
136
+ - owner
137
+ - status`,
138
+ "by-owner.base": `filters:
139
+ and:
140
+ - file.inFolder("tasks")
141
+ - status != "done"
142
+ views:
143
+ - type: table
144
+ name: By Owner
145
+ groupBy:
146
+ property: owner
147
+ direction: ASC
148
+ order:
149
+ - file.name
150
+ - status
151
+ - project
152
+ - priority`,
153
+ "backlog.base": `filters:
154
+ and:
155
+ - file.inFolder("backlog")
156
+ views:
157
+ - type: table
158
+ name: Backlog
159
+ order:
160
+ - file.name
161
+ - source
162
+ - project
163
+ - file.ctime`
164
+ };
165
+ let written = 0;
166
+ for (const [filename, content] of Object.entries(basesFiles)) {
167
+ const filePath = path.join(vaultPath, filename);
168
+ if (force || !fs.existsSync(filePath)) {
169
+ fs.writeFileSync(filePath, content);
170
+ written++;
171
+ }
172
+ }
173
+ return written;
174
+ }
175
+ var NEURAL_GRAPH_CSS = `/* ClawVault Graph Colors \u2014 Neural Neural Style */
176
+ /* Auto-generated by \`clawvault setup --theme neural\` */
177
+
178
+ body.theme-dark .graph-view .graph-view-container { background-color: #0a0a0a; }
179
+
180
+ body.theme-dark .graph-view .node.tag-person circle { fill: #00b4d8 !important; }
181
+ body.theme-dark .graph-view .node.tag-project circle { fill: #2d6a4f !important; }
182
+ body.theme-dark .graph-view .node.tag-decision circle { fill: #e8590c !important; }
183
+ body.theme-dark .graph-view .node.tag-lesson circle { fill: #fcc419 !important; }
184
+ body.theme-dark .graph-view .node.tag-commitment circle { fill: #e03131 !important; }
185
+ body.theme-dark .graph-view .node.tag-task circle { fill: #22b8cf !important; }
186
+ body.theme-dark .graph-view .node.tag-observation circle { fill: #7950f2 !important; }
187
+ body.theme-dark .graph-view .node.tag-handoff circle { fill: #845ef7 !important; }
188
+ body.theme-dark .graph-view .node.tag-daily circle { fill: #495057 !important; }
189
+
190
+ body.theme-dark .graph-view .node.is-focused circle {
191
+ fill: #e8a430 !important; stroke: #e8a430 !important;
192
+ stroke-width: 3px; filter: drop-shadow(0 0 6px #e8a430);
193
+ }
194
+
195
+ body.theme-dark .graph-view .link { stroke: rgba(45, 200, 120, 0.15) !important; }
196
+ body.theme-dark .graph-view .link.is-focused { stroke: rgba(45, 200, 120, 0.6) !important; }
197
+ body.theme-dark .graph-view .node text { fill: #c1c2c5 !important; font-size: 0.8em; }
198
+ `;
199
+ var MINIMAL_GRAPH_CSS = `/* ClawVault Graph Colors \u2014 Minimal */
200
+ /* Auto-generated by \`clawvault setup --theme minimal\` */
201
+
202
+ body.theme-dark .graph-view .node.tag-person circle { fill: #4a90e8 !important; }
203
+ body.theme-dark .graph-view .node.tag-project circle { fill: #4ae85d !important; }
204
+ body.theme-dark .graph-view .node.tag-decision circle { fill: #e85d4a !important; }
205
+ body.theme-dark .graph-view .node.tag-lesson circle { fill: #9b59b6 !important; }
206
+ body.theme-dark .graph-view .node.tag-task circle { fill: #e8a430 !important; }
207
+ `;
208
+ var NEURAL_COLOR_GROUPS = [
209
+ { query: "path:people", color: { a: 1, rgb: 47316 } },
210
+ { query: "path:projects", color: { a: 1, rgb: 2976335 } },
211
+ { query: "path:decisions", color: { a: 1, rgb: 15227916 } },
212
+ { query: "path:lessons", color: { a: 1, rgb: 16565273 } },
213
+ { query: "path:tasks", color: { a: 1, rgb: 2275535 } },
214
+ { query: "path:commitments", color: { a: 1, rgb: 14680369 } },
215
+ { query: "path:backlog", color: { a: 1, rgb: 9806262 } },
216
+ { query: "path:inbox", color: { a: 1, rgb: 15964178 } },
217
+ { query: "path:handoffs", color: { a: 1, rgb: 8675063 } },
218
+ { query: "path:ledger", color: { a: 1, rgb: 7950066 } }
219
+ ];
220
+ var MINIMAL_COLOR_GROUPS = [
221
+ { query: "path:people", color: { a: 1, rgb: 4886760 } },
222
+ { query: "path:projects", color: { a: 1, rgb: 4909149 } },
223
+ { query: "path:decisions", color: { a: 1, rgb: 15228234 } },
224
+ { query: "path:lessons", color: { a: 1, rgb: 10181046 } },
225
+ { query: "path:tasks", color: { a: 1, rgb: 15246384 } }
226
+ ];
227
+ function writeGraphColors(vaultPath, theme, force) {
228
+ const obsidianDir = path.join(vaultPath, ".obsidian");
229
+ if (!fs.existsSync(obsidianDir)) {
230
+ return false;
231
+ }
232
+ const snippetsDir = path.join(obsidianDir, "snippets");
233
+ fs.mkdirSync(snippetsDir, { recursive: true });
234
+ const snippetName = "clawvault-graph";
235
+ const snippetPath = path.join(snippetsDir, `${snippetName}.css`);
236
+ if (!force && fs.existsSync(snippetPath)) {
237
+ return false;
238
+ }
239
+ const css = theme === "neural" ? NEURAL_GRAPH_CSS : MINIMAL_GRAPH_CSS;
240
+ fs.writeFileSync(snippetPath, css);
241
+ const appearancePath = path.join(obsidianDir, "appearance.json");
242
+ let appearance = {};
243
+ if (fs.existsSync(appearancePath)) {
244
+ try {
245
+ appearance = JSON.parse(fs.readFileSync(appearancePath, "utf-8"));
246
+ } catch {
247
+ }
248
+ }
249
+ const snippets = appearance.enabledCssSnippets || [];
250
+ if (!snippets.includes(snippetName)) {
251
+ snippets.push(snippetName);
252
+ appearance.enabledCssSnippets = snippets;
253
+ fs.writeFileSync(appearancePath, JSON.stringify(appearance, null, 2));
254
+ }
255
+ const graphPath = path.join(obsidianDir, "graph.json");
256
+ let graphConfig = {};
257
+ if (fs.existsSync(graphPath)) {
258
+ try {
259
+ graphConfig = JSON.parse(fs.readFileSync(graphPath, "utf-8"));
260
+ } catch {
261
+ }
262
+ }
263
+ graphConfig.colorGroups = theme === "neural" ? NEURAL_COLOR_GROUPS : MINIMAL_COLOR_GROUPS;
264
+ if (theme === "neural") {
265
+ graphConfig.showTags = false;
266
+ graphConfig.showAttachments = false;
267
+ graphConfig.nodeSizeMultiplier = 1.2;
268
+ graphConfig.lineSizeMultiplier = 0.8;
269
+ graphConfig.textFadeMultiplier = 0;
270
+ graphConfig.repelStrength = 10;
271
+ graphConfig.linkDistance = 250;
272
+ graphConfig.centerStrength = 0.5;
273
+ }
274
+ fs.writeFileSync(graphPath, JSON.stringify(graphConfig, null, 2));
275
+ return true;
276
+ }
277
+ function getQmdConfig(vaultPath) {
278
+ const configPath = path.join(vaultPath, CONFIG_FILE);
279
+ if (fs.existsSync(configPath)) {
280
+ try {
281
+ const meta = JSON.parse(fs.readFileSync(configPath, "utf-8"));
282
+ return {
283
+ collection: meta.qmdCollection || meta.name || path.basename(vaultPath),
284
+ root: meta.qmdRoot || vaultPath
285
+ };
286
+ } catch {
287
+ return { collection: path.basename(vaultPath), root: vaultPath };
288
+ }
289
+ }
290
+ return { collection: path.basename(vaultPath), root: vaultPath };
291
+ }
292
+ async function setupCommand(options = {}) {
293
+ const target = resolveVaultTarget(options.vault);
294
+ if (target.existed && !fs.statSync(target.vaultPath).isDirectory()) {
295
+ throw new Error(`Vault path is not a directory: ${target.vaultPath}`);
296
+ }
297
+ if (!target.existed) fs.mkdirSync(target.vaultPath, { recursive: true });
298
+ console.log(`${target.existed ? "Found" : "Created"} vault path (${target.source}): ${target.vaultPath}`);
299
+ const initialized = ensureVaultStructure(target.vaultPath);
300
+ console.log(initialized ? "\u2713 Initialized vault structure." : "\u2713 Vault structure already present.");
301
+ const force = options.force ?? false;
302
+ const theme = options.theme ?? "neural";
303
+ const explicitFlags = options.graphColors !== void 0 || options.bases !== void 0 || options.canvas !== void 0;
304
+ const doGraphColors = explicitFlags ? options.graphColors !== false : true;
305
+ const doBases = explicitFlags ? options.bases !== false : true;
306
+ const doCanvas = explicitFlags ? options.canvas !== void 0 && options.canvas !== false : false;
307
+ if (doGraphColors && theme !== "none") {
308
+ const wrote = writeGraphColors(target.vaultPath, theme, force);
309
+ if (wrote) {
310
+ console.log(`\u2713 Graph colors configured (${theme} theme)`);
311
+ } else {
312
+ const obsidianDir = path.join(target.vaultPath, ".obsidian");
313
+ if (!fs.existsSync(obsidianDir)) {
314
+ console.log("\u2298 No .obsidian directory \u2014 skipping graph colors (not an Obsidian vault)");
315
+ } else {
316
+ console.log("\u2298 Graph colors already exist (use --force to overwrite)");
317
+ }
318
+ }
319
+ } else if (doGraphColors && theme === "none") {
320
+ console.log("\u2298 Graph colors skipped (--theme none)");
321
+ }
322
+ if (doBases) {
323
+ const count = writeBases(target.vaultPath, force);
324
+ if (count > 0) {
325
+ console.log(`\u2713 Created ${count} Obsidian Bases view${count > 1 ? "s" : ""}`);
326
+ } else {
327
+ console.log("\u2298 Bases views already exist (use --force to overwrite)");
328
+ }
329
+ }
330
+ if (doCanvas) {
331
+ try {
332
+ const { canvasCommand } = await import("./commands/canvas.js");
333
+ await canvasCommand(target.vaultPath);
334
+ } catch (err) {
335
+ console.log(`\u26A0 Canvas generation failed: ${err instanceof Error ? err.message : String(err)}`);
336
+ }
337
+ }
338
+ if (hasQmd()) {
339
+ const { collection, root } = getQmdConfig(target.vaultPath);
340
+ try {
341
+ execFileSync("qmd", withQmdIndexArgs(["collection", "add", root, "--name", collection, "--mask", "**/*.md"], options.qmdIndexName), {
342
+ stdio: "ignore"
343
+ });
344
+ console.log(`\u2713 qmd collection ready: ${collection}`);
345
+ } catch {
346
+ console.log("\u2298 qmd collection already exists.");
347
+ }
348
+ } else {
349
+ console.log("\u2298 qmd not found \u2014 skipping semantic search setup.");
350
+ }
351
+ console.log("\nTip: add this to your shell config:");
352
+ console.log(` export CLAWVAULT_PATH="${target.vaultPath}"`);
353
+ console.log("\nCustomize further:");
354
+ console.log(" clawvault setup --theme neural # Neural neural graph colors");
355
+ console.log(" clawvault setup --theme minimal # Subtle category colors");
356
+ console.log(" clawvault setup --canvas # Generate vault status canvas");
357
+ console.log(" clawvault setup --no-bases --no-graph-colors # Structure only");
358
+ console.log(" clawvault setup --force # Overwrite existing configs");
359
+ }
360
+
361
+ export {
362
+ setupCommand
363
+ };