clawvault 2.6.0 → 3.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 (232) hide show
  1. package/bin/command-registration.test.js +1 -3
  2. package/bin/register-core-commands.js +10 -23
  3. package/bin/register-maintenance-commands.js +3 -20
  4. package/bin/register-query-commands.js +23 -0
  5. package/bin/register-task-commands.js +1 -18
  6. package/bin/register-task-commands.test.js +0 -16
  7. package/bin/register-vault-operations-commands.js +1 -29
  8. package/dist/{chunk-QVMXF7FY.js → chunk-3D6BCTP6.js} +39 -1
  9. package/dist/{chunk-R2MIW5G7.js → chunk-3DHXQHYG.js} +1 -1
  10. package/dist/{chunk-Q2J5YTUF.js → chunk-3NSBOUT3.js} +73 -36
  11. package/dist/chunk-3RG5ZIWI.js +10 -0
  12. package/dist/{chunk-AZYOKJYC.js → chunk-62YTUT6J.js} +2 -2
  13. package/dist/chunk-6U6MK36V.js +205 -0
  14. package/dist/{chunk-4QYGFWRM.js → chunk-7R7O6STJ.js} +4 -4
  15. package/dist/{chunk-VXEOHTSL.js → chunk-C7OK5WKP.js} +4 -4
  16. package/dist/chunk-CMB7UL7C.js +327 -0
  17. package/dist/chunk-DEFFDRVP.js +938 -0
  18. package/dist/{chunk-K3CDT7IH.js → chunk-E7MFQB6D.js} +61 -20
  19. package/dist/{chunk-ME37YNW3.js → chunk-F2JEUD4J.js} +6 -4
  20. package/dist/chunk-GAJV4IGR.js +82 -0
  21. package/dist/chunk-GQSLDZTS.js +560 -0
  22. package/dist/{chunk-4OXMU5S2.js → chunk-GUKMRGM7.js} +1 -1
  23. package/dist/{chunk-YOSEUUNB.js → chunk-H34S76MB.js} +6 -6
  24. package/dist/{chunk-4TE4JMLA.js → chunk-JY6FYXIT.js} +10 -5
  25. package/dist/chunk-K234IDRJ.js +1073 -0
  26. package/dist/{chunk-IEVLHNLU.js → chunk-LNJA2UGL.js} +86 -9
  27. package/dist/{chunk-MFAWT5O5.js → chunk-LYHGEHXG.js} +1 -0
  28. package/dist/chunk-MFM6K7PU.js +374 -0
  29. package/dist/{chunk-QWQ3TIKS.js → chunk-N2AXRYLC.js} +1 -1
  30. package/dist/chunk-PAH27GSN.js +108 -0
  31. package/dist/{chunk-OIWVQYQF.js → chunk-QBLMXKF2.js} +1 -1
  32. package/dist/{chunk-FHFUXL6G.js → chunk-QK3UCXWL.js} +2 -2
  33. package/dist/{chunk-2YDBJS7M.js → chunk-SJSFRIYS.js} +1 -1
  34. package/dist/{chunk-GSD4ALSI.js → chunk-U55BGUAU.js} +2 -2
  35. package/dist/{chunk-PBEE567J.js → chunk-VGLOTGAS.js} +1 -1
  36. package/dist/{chunk-F55HGNU4.js → chunk-WAZ3NLWL.js} +47 -0
  37. package/dist/{chunk-KL4NAOMO.js → chunk-WGRQ6HDV.js} +1 -1
  38. package/dist/{chunk-UEOUADMO.js → chunk-YKTA5JOJ.js} +13 -10
  39. package/dist/{chunk-XAVB4GB4.js → chunk-ZVVFWOLW.js} +4 -4
  40. package/dist/cli/index.cjs +10033 -0
  41. package/dist/cli/index.d.cts +5 -0
  42. package/dist/cli/index.js +20 -18
  43. package/dist/commands/archive.cjs +287 -0
  44. package/dist/commands/archive.d.cts +11 -0
  45. package/dist/commands/archive.js +1 -0
  46. package/dist/commands/backlog.cjs +721 -0
  47. package/dist/commands/backlog.d.cts +53 -0
  48. package/dist/commands/backlog.js +3 -2
  49. package/dist/commands/blocked.cjs +204 -0
  50. package/dist/commands/blocked.d.cts +26 -0
  51. package/dist/commands/blocked.js +3 -2
  52. package/dist/commands/checkpoint.cjs +244 -0
  53. package/dist/commands/checkpoint.d.cts +41 -0
  54. package/dist/commands/checkpoint.js +2 -1
  55. package/dist/commands/compat.cjs +369 -0
  56. package/dist/commands/compat.d.cts +28 -0
  57. package/dist/commands/compat.js +2 -1
  58. package/dist/commands/context.cjs +2989 -0
  59. package/dist/commands/context.d.cts +2 -0
  60. package/dist/commands/context.js +5 -4
  61. package/dist/commands/doctor.cjs +3062 -0
  62. package/dist/commands/doctor.d.cts +21 -0
  63. package/dist/commands/doctor.d.ts +6 -1
  64. package/dist/commands/doctor.js +13 -11
  65. package/dist/commands/embed.cjs +232 -0
  66. package/dist/commands/embed.d.cts +17 -0
  67. package/dist/commands/embed.js +5 -2
  68. package/dist/commands/entities.cjs +141 -0
  69. package/dist/commands/entities.d.cts +7 -0
  70. package/dist/commands/entities.js +1 -0
  71. package/dist/commands/graph.cjs +501 -0
  72. package/dist/commands/graph.d.cts +21 -0
  73. package/dist/commands/graph.js +1 -0
  74. package/dist/commands/inject.cjs +1636 -0
  75. package/dist/commands/inject.d.cts +2 -0
  76. package/dist/commands/inject.d.ts +1 -1
  77. package/dist/commands/inject.js +4 -2
  78. package/dist/commands/kanban.cjs +884 -0
  79. package/dist/commands/kanban.d.cts +63 -0
  80. package/dist/commands/kanban.js +4 -3
  81. package/dist/commands/link.cjs +965 -0
  82. package/dist/commands/link.d.cts +11 -0
  83. package/dist/commands/link.js +1 -0
  84. package/dist/commands/migrate-observations.cjs +362 -0
  85. package/dist/commands/migrate-observations.d.cts +19 -0
  86. package/dist/commands/migrate-observations.js +3 -2
  87. package/dist/commands/observe.cjs +4099 -0
  88. package/dist/commands/observe.d.cts +23 -0
  89. package/dist/commands/observe.d.ts +1 -0
  90. package/dist/commands/observe.js +11 -9
  91. package/dist/commands/project.cjs +1341 -0
  92. package/dist/commands/project.d.cts +85 -0
  93. package/dist/commands/project.js +5 -4
  94. package/dist/commands/rebuild.cjs +3136 -0
  95. package/dist/commands/rebuild.d.cts +11 -0
  96. package/dist/commands/rebuild.js +10 -8
  97. package/dist/commands/recover.cjs +361 -0
  98. package/dist/commands/recover.d.cts +38 -0
  99. package/dist/commands/recover.js +3 -2
  100. package/dist/commands/reflect.cjs +1008 -0
  101. package/dist/commands/reflect.d.cts +11 -0
  102. package/dist/commands/reflect.js +6 -4
  103. package/dist/commands/repair-session.cjs +457 -0
  104. package/dist/commands/repair-session.d.cts +38 -0
  105. package/dist/commands/repair-session.js +1 -0
  106. package/dist/commands/replay.cjs +4103 -0
  107. package/dist/commands/replay.d.cts +16 -0
  108. package/dist/commands/replay.js +12 -10
  109. package/dist/commands/session-recap.cjs +353 -0
  110. package/dist/commands/session-recap.d.cts +27 -0
  111. package/dist/commands/session-recap.js +1 -0
  112. package/dist/commands/setup.cjs +1345 -0
  113. package/dist/commands/setup.d.cts +100 -0
  114. package/dist/commands/setup.d.ts +90 -2
  115. package/dist/commands/setup.js +21 -2
  116. package/dist/commands/shell-init.cjs +75 -0
  117. package/dist/commands/shell-init.d.cts +7 -0
  118. package/dist/commands/shell-init.js +2 -0
  119. package/dist/commands/sleep.cjs +6028 -0
  120. package/dist/commands/sleep.d.cts +36 -0
  121. package/dist/commands/sleep.d.ts +1 -1
  122. package/dist/commands/sleep.js +17 -15
  123. package/dist/commands/status.cjs +2736 -0
  124. package/dist/commands/status.d.cts +52 -0
  125. package/dist/commands/status.js +12 -10
  126. package/dist/commands/tailscale.cjs +1532 -0
  127. package/dist/commands/tailscale.d.cts +52 -0
  128. package/dist/commands/tailscale.js +1 -0
  129. package/dist/commands/task.cjs +1236 -0
  130. package/dist/commands/task.d.cts +97 -0
  131. package/dist/commands/task.js +4 -3
  132. package/dist/commands/template.cjs +457 -0
  133. package/dist/commands/template.d.cts +36 -0
  134. package/dist/commands/template.js +2 -1
  135. package/dist/commands/wake.cjs +2626 -0
  136. package/dist/commands/wake.d.cts +22 -0
  137. package/dist/commands/wake.d.ts +1 -1
  138. package/dist/commands/wake.js +12 -11
  139. package/dist/context-BUGaWpyL.d.cts +46 -0
  140. package/dist/index.cjs +14526 -0
  141. package/dist/index.d.cts +858 -0
  142. package/dist/index.d.ts +192 -7
  143. package/dist/index.js +101 -75
  144. package/dist/{inject-x65KXWPk.d.ts → inject-Bzi5E-By.d.cts} +1 -1
  145. package/dist/inject-Bzi5E-By.d.ts +137 -0
  146. package/dist/lib/auto-linker.cjs +176 -0
  147. package/dist/lib/auto-linker.d.cts +26 -0
  148. package/dist/lib/auto-linker.js +1 -0
  149. package/dist/lib/canvas-layout.cjs +136 -0
  150. package/dist/lib/canvas-layout.d.cts +31 -0
  151. package/dist/lib/canvas-layout.d.ts +16 -100
  152. package/dist/lib/canvas-layout.js +78 -20
  153. package/dist/lib/config.cjs +78 -0
  154. package/dist/lib/config.d.cts +11 -0
  155. package/dist/lib/config.js +1 -0
  156. package/dist/lib/entity-index.cjs +84 -0
  157. package/dist/lib/entity-index.d.cts +26 -0
  158. package/dist/lib/entity-index.js +1 -0
  159. package/dist/lib/project-utils.cjs +864 -0
  160. package/dist/lib/project-utils.d.cts +97 -0
  161. package/dist/lib/project-utils.js +4 -3
  162. package/dist/lib/session-repair.cjs +239 -0
  163. package/dist/lib/session-repair.d.cts +110 -0
  164. package/dist/lib/session-repair.js +1 -0
  165. package/dist/lib/session-utils.cjs +209 -0
  166. package/dist/lib/session-utils.d.cts +63 -0
  167. package/dist/lib/session-utils.js +1 -0
  168. package/dist/lib/tailscale.cjs +1183 -0
  169. package/dist/lib/tailscale.d.cts +225 -0
  170. package/dist/lib/tailscale.js +1 -0
  171. package/dist/lib/task-utils.cjs +1137 -0
  172. package/dist/lib/task-utils.d.cts +208 -0
  173. package/dist/lib/task-utils.js +3 -2
  174. package/dist/lib/template-engine.cjs +47 -0
  175. package/dist/lib/template-engine.d.cts +11 -0
  176. package/dist/lib/template-engine.js +1 -0
  177. package/dist/lib/webdav.cjs +568 -0
  178. package/dist/lib/webdav.d.cts +109 -0
  179. package/dist/lib/webdav.js +1 -0
  180. package/dist/plugin/index.cjs +1907 -0
  181. package/dist/plugin/index.d.cts +36 -0
  182. package/dist/plugin/index.d.ts +36 -0
  183. package/dist/plugin/index.js +572 -0
  184. package/dist/plugin/inject.cjs +356 -0
  185. package/dist/plugin/inject.d.cts +54 -0
  186. package/dist/plugin/inject.d.ts +54 -0
  187. package/dist/plugin/inject.js +17 -0
  188. package/dist/plugin/observe.cjs +631 -0
  189. package/dist/plugin/observe.d.cts +39 -0
  190. package/dist/plugin/observe.d.ts +39 -0
  191. package/dist/plugin/observe.js +18 -0
  192. package/dist/plugin/templates.cjs +593 -0
  193. package/dist/plugin/templates.d.cts +52 -0
  194. package/dist/plugin/templates.d.ts +52 -0
  195. package/dist/plugin/templates.js +25 -0
  196. package/dist/plugin/types.cjs +18 -0
  197. package/dist/plugin/types.d.cts +209 -0
  198. package/dist/plugin/types.d.ts +209 -0
  199. package/dist/plugin/types.js +0 -0
  200. package/dist/plugin/vault.cjs +927 -0
  201. package/dist/plugin/vault.d.cts +68 -0
  202. package/dist/plugin/vault.d.ts +68 -0
  203. package/dist/plugin/vault.js +22 -0
  204. package/dist/{types-C74wgGL1.d.ts → types-Y2_Um2Ls.d.cts} +44 -1
  205. package/dist/types-Y2_Um2Ls.d.ts +205 -0
  206. package/hooks/clawvault/handler.js +70 -7
  207. package/hooks/clawvault/handler.test.js +91 -0
  208. package/openclaw.plugin.json +56 -0
  209. package/package.json +17 -7
  210. package/templates/memory-event.md +67 -0
  211. package/templates/party.md +63 -0
  212. package/templates/primitive-registry.yaml +551 -0
  213. package/templates/run.md +68 -0
  214. package/templates/trigger.md +68 -0
  215. package/templates/workspace.md +50 -0
  216. package/dashboard/lib/graph-diff.js +0 -104
  217. package/dashboard/lib/graph-diff.test.js +0 -75
  218. package/dashboard/lib/vault-parser.js +0 -556
  219. package/dashboard/lib/vault-parser.test.js +0 -254
  220. package/dashboard/public/app.js +0 -796
  221. package/dashboard/public/index.html +0 -52
  222. package/dashboard/public/styles.css +0 -221
  223. package/dashboard/server.js +0 -374
  224. package/dist/chunk-HA5M6KJB.js +0 -33
  225. package/dist/chunk-MAKNAHAW.js +0 -375
  226. package/dist/chunk-MDIH26GC.js +0 -183
  227. package/dist/chunk-MGDEINGP.js +0 -99
  228. package/dist/chunk-RVYA52PY.js +0 -363
  229. package/dist/commands/canvas.d.ts +0 -15
  230. package/dist/commands/canvas.js +0 -199
  231. package/dist/commands/sync-bd.d.ts +0 -10
  232. package/dist/commands/sync-bd.js +0 -9
@@ -1,9 +1,9 @@
1
+ import {
2
+ Observer
3
+ } from "./chunk-3NSBOUT3.js";
1
4
  import {
2
5
  getSessionsDir
3
6
  } from "./chunk-HRLWZGMA.js";
4
- import {
5
- Observer
6
- } from "./chunk-Q2J5YTUF.js";
7
7
 
8
8
  // src/observer/active-session-observer.ts
9
9
  import * as fs from "fs";
@@ -18,6 +18,11 @@ 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
+ }
21
26
  function isFiniteNonNegative(value) {
22
27
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
23
28
  }
@@ -153,7 +158,12 @@ function getObserverStaleness(vaultPath, options = {}) {
153
158
  if (!sessionStat.isFile()) {
154
159
  continue;
155
160
  }
156
- if (cursor.lastFileSize >= sessionStat.size) {
161
+ const newBytes = sessionStat.size - cursor.lastFileSize;
162
+ if (newBytes <= 0) {
163
+ continue;
164
+ }
165
+ const processThreshold = getScaledObservationThresholdBytes(sessionStat.size);
166
+ if (newBytes < processThreshold) {
157
167
  continue;
158
168
  }
159
169
  staleCount += 1;
@@ -181,8 +191,32 @@ function loadSessionIndex(sessionsDir) {
181
191
  return {};
182
192
  }
183
193
  }
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
+ }
184
203
  function resolveTranscriptPath(sessionsDir, sessionId) {
185
- return path.join(sessionsDir, `${sessionId}.jsonl`);
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;
186
220
  }
187
221
  function discoverSessionDescriptors(sessionsDir, fallbackAgentId) {
188
222
  const descriptors = [];
@@ -259,6 +293,21 @@ function normalizeRole(role) {
259
293
  }
260
294
  return role.trim().toLowerCase();
261
295
  }
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
+ }
262
311
  function parseOpenClawJsonLine(line) {
263
312
  if (!line.trim()) {
264
313
  return "";
@@ -275,14 +324,38 @@ function parseOpenClawJsonLine(line) {
275
324
  const entry = parsed;
276
325
  if ("role" in entry && "content" in entry) {
277
326
  const role = normalizeRole(entry.role);
278
- const content = extractContentText(entry.content);
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
+ }
279
340
  if (!content) return "";
280
341
  return role ? `${role}: ${content}` : content;
281
342
  }
282
343
  if (entry.type === "message" && entry.message && typeof entry.message === "object") {
283
344
  const message = entry.message;
284
345
  const role = normalizeRole(message.role);
285
- const content = extractContentText(message.content);
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
+ }
286
359
  if (!content) return "";
287
360
  return role ? `${role}: ${content}` : content;
288
361
  }
@@ -445,7 +518,9 @@ async function observeActiveSessions(options, dependencies = {}) {
445
518
  const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
446
519
  const cursors = loadObserveCursorStore(vaultPath);
447
520
  const descriptors = discoverSessionDescriptors(sessionsDir, agentId);
448
- const candidates = selectCandidates(descriptors, cursors, options.minNewBytes);
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;
449
524
  if (dryRun || candidates.length === 0) {
450
525
  return {
451
526
  agentId,
@@ -475,7 +550,9 @@ async function observeActiveSessions(options, dependencies = {}) {
475
550
  let observedNewBytes = 0;
476
551
  const routedCounts = {};
477
552
  const failedSessions = [];
478
- for (const candidate of candidates) {
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)`);
479
556
  try {
480
557
  const observer = observerFactory(vaultPath, observerOptions);
481
558
  const { messages, nextOffset } = await readIncrementalMessages(candidate.filePath, candidate.startOffset);
@@ -295,6 +295,7 @@ export {
295
295
  normalizeTemplateName,
296
296
  buildTemplateIndex,
297
297
  parseTemplateDefinition,
298
+ loadTemplateDefinition,
298
299
  loadSchemaTemplateDefinition,
299
300
  listTemplateDefinitions,
300
301
  renderDocumentFromTemplate
@@ -0,0 +1,374 @@
1
+ import {
2
+ classifyText,
3
+ generateFrontmatter,
4
+ getSchema,
5
+ serializeFrontmatter,
6
+ validateFrontmatter
7
+ } from "./chunk-GQSLDZTS.js";
8
+ import {
9
+ __require
10
+ } from "./chunk-3RG5ZIWI.js";
11
+
12
+ // src/plugin/vault.ts
13
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync } from "fs";
14
+ import { join } from "path";
15
+ function writeVaultFile(vaultPath, options) {
16
+ const errors = [];
17
+ const primitiveType = options.primitiveType ?? classifyText(options.content ?? options.title ?? "").primitiveType;
18
+ const schema = getSchema(primitiveType);
19
+ const frontmatter = generateFrontmatter(primitiveType, {
20
+ title: options.title,
21
+ extraFields: options.extraFields,
22
+ source: options.source,
23
+ sessionId: options.sessionId
24
+ });
25
+ const validation = validateFrontmatter(primitiveType, frontmatter);
26
+ if (!validation.valid) {
27
+ errors.push(...validation.errors);
28
+ }
29
+ const directory = options.directory ?? getDefaultDirectory(vaultPath, primitiveType);
30
+ if (!existsSync(directory)) {
31
+ mkdirSync(directory, { recursive: true });
32
+ }
33
+ const filename = options.filename ?? generateFilename(primitiveType, options.title, frontmatter);
34
+ const filePath = join(directory, filename);
35
+ const fileExists = existsSync(filePath);
36
+ if (fileExists && !options.overwrite) {
37
+ return updateVaultFile(filePath, frontmatter, options.content, primitiveType, errors);
38
+ }
39
+ const fileContent = buildFileContent(frontmatter, options.content, schema);
40
+ try {
41
+ writeFileSync(filePath, fileContent, "utf-8");
42
+ return {
43
+ success: errors.length === 0,
44
+ path: filePath,
45
+ primitiveType,
46
+ errors,
47
+ created: true,
48
+ updated: false
49
+ };
50
+ } catch (err) {
51
+ errors.push(`Failed to write file: ${String(err)}`);
52
+ return {
53
+ success: false,
54
+ path: filePath,
55
+ primitiveType,
56
+ errors,
57
+ created: false,
58
+ updated: false
59
+ };
60
+ }
61
+ }
62
+ function updateVaultFile(filePath, newFrontmatter, newContent, primitiveType, errors) {
63
+ try {
64
+ const existingContent = readFileSync(filePath, "utf-8");
65
+ const parsed = parseExistingFile(existingContent);
66
+ if (!parsed) {
67
+ errors.push("Failed to parse existing file");
68
+ return {
69
+ success: false,
70
+ path: filePath,
71
+ primitiveType,
72
+ errors,
73
+ created: false,
74
+ updated: false
75
+ };
76
+ }
77
+ const mergedFrontmatter = {
78
+ ...parsed.frontmatter,
79
+ ...newFrontmatter,
80
+ updated: (/* @__PURE__ */ new Date()).toISOString()
81
+ };
82
+ if (parsed.frontmatter.created) {
83
+ mergedFrontmatter.created = parsed.frontmatter.created;
84
+ }
85
+ const content = newContent ?? parsed.body;
86
+ const schema = getSchema(primitiveType);
87
+ const fileContent = buildFileContent(mergedFrontmatter, content, schema);
88
+ writeFileSync(filePath, fileContent, "utf-8");
89
+ return {
90
+ success: errors.length === 0,
91
+ path: filePath,
92
+ primitiveType,
93
+ errors,
94
+ created: false,
95
+ updated: true
96
+ };
97
+ } catch (err) {
98
+ errors.push(`Failed to update file: ${String(err)}`);
99
+ return {
100
+ success: false,
101
+ path: filePath,
102
+ primitiveType,
103
+ errors,
104
+ created: false,
105
+ updated: false
106
+ };
107
+ }
108
+ }
109
+ function parseExistingFile(content) {
110
+ const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
111
+ if (!match) return null;
112
+ try {
113
+ const frontmatter = parseSimpleYaml(match[1]);
114
+ return { frontmatter, body: match[2] };
115
+ } catch {
116
+ return null;
117
+ }
118
+ }
119
+ function parseSimpleYaml(yaml) {
120
+ const result = {};
121
+ const lines = yaml.split("\n");
122
+ for (const line of lines) {
123
+ if (!line.trim() || line.trim().startsWith("#")) continue;
124
+ const colonIndex = line.indexOf(":");
125
+ if (colonIndex === -1) continue;
126
+ const key = line.slice(0, colonIndex).trim();
127
+ const valueStr = line.slice(colonIndex + 1).trim();
128
+ if (valueStr === "" || valueStr.startsWith("|") || valueStr.startsWith(">")) continue;
129
+ result[key] = parseYamlValue(valueStr);
130
+ }
131
+ return result;
132
+ }
133
+ function parseYamlValue(value) {
134
+ if (value === "" || value === "null" || value === "~") return null;
135
+ if (value === "true") return true;
136
+ if (value === "false") return false;
137
+ if (/^-?\d+$/.test(value)) return parseInt(value, 10);
138
+ if (/^-?\d+\.\d+$/.test(value)) return parseFloat(value);
139
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
140
+ return value.slice(1, -1);
141
+ }
142
+ return value;
143
+ }
144
+ function getDefaultDirectory(vaultPath, primitiveType) {
145
+ const directoryMap = {
146
+ task: "tasks",
147
+ project: "projects",
148
+ decision: "decisions",
149
+ person: "people",
150
+ lesson: "lessons",
151
+ trigger: "triggers",
152
+ run: "runs",
153
+ checkpoint: "checkpoints",
154
+ handoff: "handoffs",
155
+ "daily-note": "daily",
156
+ daily: "daily",
157
+ party: "parties",
158
+ workspace: "workspaces",
159
+ memory_event: "memory"
160
+ };
161
+ const subdir = directoryMap[primitiveType] ?? "notes";
162
+ return join(vaultPath, subdir);
163
+ }
164
+ function generateFilename(primitiveType, title, frontmatter) {
165
+ const now = /* @__PURE__ */ new Date();
166
+ const dateStr = now.toISOString().split("T")[0];
167
+ const timeStr = now.toISOString().slice(11, 19).replace(/:/g, "");
168
+ if (title) {
169
+ const slug = slugify(title);
170
+ return `${dateStr}-${slug}.md`;
171
+ }
172
+ switch (primitiveType) {
173
+ case "daily-note":
174
+ case "daily":
175
+ return `${dateStr}.md`;
176
+ case "memory_event":
177
+ return `${dateStr}-${timeStr}.md`;
178
+ case "run":
179
+ return `run-${dateStr}-${timeStr}.md`;
180
+ case "checkpoint":
181
+ return `checkpoint-${dateStr}-${timeStr}.md`;
182
+ case "handoff":
183
+ return `handoff-${dateStr}-${timeStr}.md`;
184
+ default:
185
+ return `${primitiveType}-${dateStr}-${timeStr}.md`;
186
+ }
187
+ }
188
+ function slugify(text) {
189
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
190
+ }
191
+ function buildFileContent(frontmatter, content, schema) {
192
+ const parts = [];
193
+ parts.push(serializeFrontmatter(frontmatter));
194
+ parts.push("");
195
+ const title = frontmatter.title || frontmatter.summary;
196
+ if (title) {
197
+ parts.push(`# ${title}`);
198
+ parts.push("");
199
+ }
200
+ if (content) {
201
+ parts.push(content);
202
+ } else if (schema?.bodyTemplate) {
203
+ let body = schema.bodyTemplate;
204
+ body = body.replace(/\{\{title\}\}/g, String(title || "Untitled"));
205
+ body = body.replace(/\{\{date\}\}/g, (/* @__PURE__ */ new Date()).toISOString().split("T")[0]);
206
+ body = body.replace(/\{\{datetime\}\}/g, (/* @__PURE__ */ new Date()).toISOString());
207
+ body = body.replace(/\{\{links_line\}\}/g, "");
208
+ body = body.replace(/\{\{content\}\}/g, "");
209
+ parts.push(body.trim());
210
+ }
211
+ return parts.join("\n");
212
+ }
213
+ function writeObservation(vaultPath, observation, options = {}) {
214
+ return writeVaultFile(vaultPath, {
215
+ primitiveType: observation.primitiveType,
216
+ title: observation.text.slice(0, 80),
217
+ content: observation.text,
218
+ extraFields: {
219
+ type: observation.primitiveType === "memory_event" ? observation.category : observation.primitiveType,
220
+ confidence: observation.confidence,
221
+ tags: observation.tags,
222
+ observed_at: observation.extractedAt.toISOString()
223
+ },
224
+ source: options.source ?? "openclaw",
225
+ sessionId: options.sessionId
226
+ });
227
+ }
228
+ function writeObservations(vaultPath, observations, options = {}) {
229
+ return observations.map((obs) => writeObservation(vaultPath, obs, options));
230
+ }
231
+ function appendToLedger(vaultPath, entry) {
232
+ const dateStr = entry.timestamp.toISOString().slice(0, 10);
233
+ const ledgerDir = join(vaultPath, "ledger");
234
+ if (!existsSync(ledgerDir)) {
235
+ mkdirSync(ledgerDir, { recursive: true });
236
+ }
237
+ const ledgerFile = join(ledgerDir, `${dateStr}.md`);
238
+ const timeStr = entry.timestamp.toISOString().slice(11, 19);
239
+ const parts = [`[${timeStr}]`];
240
+ if (entry.category) parts.push(`[${entry.category}]`);
241
+ if (entry.actor) parts.push(`(${entry.actor})`);
242
+ parts.push(entry.content);
243
+ const line = `
244
+ - ${parts.join(" ")}`;
245
+ if (!existsSync(ledgerFile)) {
246
+ const frontmatter = serializeFrontmatter({
247
+ type: "ledger",
248
+ date: dateStr,
249
+ created: entry.timestamp.toISOString()
250
+ });
251
+ writeFileSync(ledgerFile, `${frontmatter}
252
+
253
+ # Observation Ledger \u2014 ${dateStr}
254
+ ${line}`, "utf-8");
255
+ } else {
256
+ appendFileSync(ledgerFile, line, "utf-8");
257
+ }
258
+ }
259
+ function appendObservationToLedger(vaultPath, observation, actor) {
260
+ appendToLedger(vaultPath, {
261
+ timestamp: observation.extractedAt,
262
+ category: observation.category,
263
+ actor,
264
+ content: observation.text,
265
+ primitiveType: observation.primitiveType,
266
+ tags: observation.tags
267
+ });
268
+ }
269
+ function batchWriteObservations(vaultPath, observations, options = {}) {
270
+ const results = [];
271
+ let successful = 0;
272
+ let failed = 0;
273
+ const writeLedger = options.writeLedger ?? true;
274
+ const writeFiles = options.writeFiles ?? false;
275
+ for (const observation of observations) {
276
+ if (writeLedger) {
277
+ try {
278
+ appendObservationToLedger(vaultPath, observation, options.actor);
279
+ } catch {
280
+ }
281
+ }
282
+ if (writeFiles) {
283
+ const result = writeObservation(vaultPath, observation, {
284
+ source: options.source,
285
+ sessionId: options.sessionId
286
+ });
287
+ results.push(result);
288
+ if (result.success) {
289
+ successful++;
290
+ } else {
291
+ failed++;
292
+ }
293
+ } else {
294
+ successful++;
295
+ results.push({
296
+ success: true,
297
+ path: join(vaultPath, "ledger", `${observation.extractedAt.toISOString().slice(0, 10)}.md`),
298
+ primitiveType: observation.primitiveType,
299
+ errors: [],
300
+ created: false,
301
+ updated: true
302
+ });
303
+ }
304
+ }
305
+ return {
306
+ total: observations.length,
307
+ successful,
308
+ failed,
309
+ results
310
+ };
311
+ }
312
+ function ensureVaultStructure(vaultPath) {
313
+ const directories = [
314
+ "tasks",
315
+ "projects",
316
+ "decisions",
317
+ "people",
318
+ "lessons",
319
+ "memory",
320
+ "ledger",
321
+ "daily"
322
+ ];
323
+ for (const dir of directories) {
324
+ const fullPath = join(vaultPath, dir);
325
+ if (!existsSync(fullPath)) {
326
+ mkdirSync(fullPath, { recursive: true });
327
+ }
328
+ }
329
+ }
330
+ function getVaultStats(vaultPath) {
331
+ const directories = [];
332
+ const primitiveTypes = {};
333
+ let fileCount = 0;
334
+ const { readdirSync, statSync } = __require("fs");
335
+ function scanDir(dir, depth = 0) {
336
+ if (depth > 2) return;
337
+ try {
338
+ const entries = readdirSync(dir, { withFileTypes: true });
339
+ for (const entry of entries) {
340
+ if (entry.name.startsWith(".") || entry.name.startsWith("_")) continue;
341
+ const fullPath = join(dir, entry.name);
342
+ if (entry.isDirectory()) {
343
+ directories.push(fullPath.replace(vaultPath + "/", ""));
344
+ scanDir(fullPath, depth + 1);
345
+ } else if (entry.name.endsWith(".md")) {
346
+ fileCount++;
347
+ try {
348
+ const content = readFileSync(fullPath, "utf-8");
349
+ const match = content.match(/^---\n[\s\S]*?type:\s*(\S+)/);
350
+ if (match) {
351
+ const type = match[1];
352
+ primitiveTypes[type] = (primitiveTypes[type] ?? 0) + 1;
353
+ }
354
+ } catch {
355
+ }
356
+ }
357
+ }
358
+ } catch {
359
+ }
360
+ }
361
+ scanDir(vaultPath);
362
+ return { directories, fileCount, primitiveTypes };
363
+ }
364
+
365
+ export {
366
+ writeVaultFile,
367
+ writeObservation,
368
+ writeObservations,
369
+ appendToLedger,
370
+ appendObservationToLedger,
371
+ batchWriteObservations,
372
+ ensureVaultStructure,
373
+ getVaultStats
374
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  loadSchemaTemplateDefinition,
3
3
  renderDocumentFromTemplate
4
- } from "./chunk-MFAWT5O5.js";
4
+ } from "./chunk-LYHGEHXG.js";
5
5
 
6
6
  // src/lib/task-utils.ts
7
7
  import * as fs2 from "fs";
@@ -0,0 +1,108 @@
1
+ // src/lib/claude-credentials.ts
2
+ import { execFileSync } from "child_process";
3
+ import { existsSync, readFileSync, writeFileSync } from "fs";
4
+ import { homedir } from "os";
5
+ import { join } from "path";
6
+ var CLAUDE_CODE_SERVICE = "Claude Code-credentials";
7
+ var CLAUDE_CODE_ACCOUNT = "Claude Code";
8
+ var OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
9
+ var TOKEN_REFRESH_URL = "https://console.anthropic.com/v1/oauth/token";
10
+ var EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
11
+ function readClaudeCliCredentials(opts) {
12
+ if (process.platform === "darwin") {
13
+ try {
14
+ const raw = execFileSync(
15
+ "security",
16
+ ["find-generic-password", "-s", CLAUDE_CODE_SERVICE, "-w"],
17
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }
18
+ ).trim();
19
+ const parsed = parseCredentialsJson(raw);
20
+ if (parsed) return parsed;
21
+ } catch {
22
+ }
23
+ }
24
+ const home = opts?.homeDir ?? homedir();
25
+ const credFile = join(home, ".claude", ".credentials.json");
26
+ if (!existsSync(credFile)) {
27
+ return null;
28
+ }
29
+ try {
30
+ const raw = readFileSync(credFile, "utf8");
31
+ return parseCredentialsJson(raw);
32
+ } catch {
33
+ return null;
34
+ }
35
+ }
36
+ function parseCredentialsJson(raw) {
37
+ try {
38
+ const parsed = JSON.parse(raw);
39
+ const oauth = parsed.claudeAiOauth;
40
+ if (oauth && typeof oauth.accessToken === "string" && typeof oauth.refreshToken === "string" && typeof oauth.expiresAt === "number") {
41
+ return {
42
+ accessToken: oauth.accessToken,
43
+ refreshToken: oauth.refreshToken,
44
+ expiresAt: oauth.expiresAt
45
+ };
46
+ }
47
+ } catch {
48
+ }
49
+ return null;
50
+ }
51
+ async function refreshClaudeOAuthToken(refreshToken, fetchImpl) {
52
+ const f = fetchImpl ?? fetch;
53
+ const response = await f(TOKEN_REFRESH_URL, {
54
+ method: "POST",
55
+ headers: { "content-type": "application/json" },
56
+ body: JSON.stringify({
57
+ grant_type: "refresh_token",
58
+ client_id: OAUTH_CLIENT_ID,
59
+ refresh_token: refreshToken
60
+ })
61
+ });
62
+ if (!response.ok) {
63
+ throw new Error(`OAuth token refresh failed (${response.status})`);
64
+ }
65
+ const data = await response.json();
66
+ return {
67
+ accessToken: data.access_token,
68
+ refreshToken: data.refresh_token,
69
+ expiresAt: Date.now() + data.expires_in * 1e3
70
+ };
71
+ }
72
+ function writeClaudeCliCredentials(cred, opts) {
73
+ const payload = JSON.stringify({ claudeAiOauth: cred });
74
+ if (process.platform === "darwin") {
75
+ try {
76
+ execFileSync(
77
+ "security",
78
+ ["add-generic-password", "-U", "-s", CLAUDE_CODE_SERVICE, "-a", CLAUDE_CODE_ACCOUNT, "-w", payload],
79
+ { stdio: "ignore" }
80
+ );
81
+ return;
82
+ } catch {
83
+ }
84
+ }
85
+ const home = opts?.homeDir ?? homedir();
86
+ const credFile = join(home, ".claude", ".credentials.json");
87
+ writeFileSync(credFile, payload, "utf8");
88
+ }
89
+ async function resolveClaudeOAuthToken(opts) {
90
+ const cred = readClaudeCliCredentials(opts);
91
+ if (!cred) {
92
+ return null;
93
+ }
94
+ if (cred.expiresAt < Date.now() + EXPIRY_BUFFER_MS) {
95
+ try {
96
+ const refreshed = await refreshClaudeOAuthToken(cred.refreshToken, opts?.fetchImpl);
97
+ writeClaudeCliCredentials(refreshed, opts);
98
+ return refreshed.accessToken;
99
+ } catch {
100
+ return cred.accessToken;
101
+ }
102
+ }
103
+ return cred.accessToken;
104
+ }
105
+
106
+ export {
107
+ resolveClaudeOAuthToken
108
+ };
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  checkDirtyDeath,
6
6
  clearDirtyFlag
7
- } from "./chunk-F55HGNU4.js";
7
+ } from "./chunk-WAZ3NLWL.js";
8
8
 
9
9
  // src/commands/recover.ts
10
10
  import * as fs from "fs";
@@ -3,7 +3,7 @@ var DATE_HEADING_RE = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
3
3
  var SCORED_LINE_RE = /^(?:-\s*)?\[(decision|preference|fact|commitment|task|todo|commitment-unresolved|milestone|lesson|relationship|project)\|c=(0(?:\.\d+)?|1(?:\.0+)?)\|i=(0(?:\.\d+)?|1(?:\.0+)?)\]\s+(.+)$/i;
4
4
  var EMOJI_LINE_RE = /^(?:-\s*)?(🔴|🟡|🟢)\s+(\d{2}:\d{2})?\s*(.+)$/u;
5
5
  var DECISION_RE = /\b(decis(?:ion|ions)?|decid(?:e|ed|ing)|chose|selected|opted|went with|picked)\b/i;
6
- var PREFERENCE_RE = /\b(prefer(?:ence|s|red)?|likes?|dislikes?|default to|always use|never use)\b/i;
6
+ var PREFERENCE_RE = /\b(prefer(?:ence|s|red)?|likes?|dislikes?|default to|always use|never use|enjoys?|loves?|favou?rite|fan of|interested in|go-to|tend(?:s)? to use|passionate about|hobby|hobbies|(?:I|my|our)\s+(?:own|have|use|got|bought|drive|wear|eat|drink|cook|play|watch|read|listen)|(?:I(?:'m| am))\s+(?:a |an |into |allergic|vegetarian|vegan|gluten|lactose|trying to|learning)|usually|every (?:morning|evening|night|day|week)|routine)\b/i;
7
7
  var COMMITMENT_RE = /\b(commit(?:ment|ted)?|promised|deadline|due|scheduled|will deliver|agreed to)\b/i;
8
8
  var TODO_RE = /(?:\btodo:\s*|\bwe need to\b|\bdon't forget(?: to)?\b|\bremember to\b|\bmake sure to\b)/i;
9
9
  var COMMITMENT_TASK_RE = /\b(?:i'?ll|i will|let me|(?:i'?m\s+)?going to|plan to|should)\b/i;
@@ -33,10 +33,10 @@ function inferObservationType(content) {
33
33
  if (DECISION_RE.test(content)) return "decision";
34
34
  if (UNRESOLVED_RE.test(content)) return "commitment-unresolved";
35
35
  if (TODO_RE.test(content)) return "todo";
36
+ if (PREFERENCE_RE.test(content)) return "preference";
36
37
  if (COMMITMENT_TASK_RE.test(content) || DEADLINE_RE.test(content)) return "task";
37
38
  if (COMMITMENT_RE.test(content)) return "commitment";
38
39
  if (MILESTONE_RE.test(content)) return "milestone";
39
- if (PREFERENCE_RE.test(content)) return "preference";
40
40
  if (LESSON_RE.test(content)) return "lesson";
41
41
  if (RELATIONSHIP_RE.test(content)) return "relationship";
42
42
  if (PROJECT_RE.test(content)) return "project";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runReflection
3
- } from "./chunk-YOSEUUNB.js";
3
+ } from "./chunk-H34S76MB.js";
4
4
  import {
5
5
  resolveVaultPath
6
6
  } from "./chunk-MXSSG3QU.js";