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.
- package/bin/command-registration.test.js +1 -3
- package/bin/register-core-commands.js +10 -23
- package/bin/register-maintenance-commands.js +3 -20
- package/bin/register-query-commands.js +23 -0
- package/bin/register-task-commands.js +1 -18
- package/bin/register-task-commands.test.js +0 -16
- package/bin/register-vault-operations-commands.js +1 -29
- package/dist/{chunk-QVMXF7FY.js → chunk-3D6BCTP6.js} +39 -1
- package/dist/{chunk-R2MIW5G7.js → chunk-3DHXQHYG.js} +1 -1
- package/dist/{chunk-Q2J5YTUF.js → chunk-3NSBOUT3.js} +73 -36
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/{chunk-AZYOKJYC.js → chunk-62YTUT6J.js} +2 -2
- package/dist/chunk-6U6MK36V.js +205 -0
- package/dist/{chunk-4QYGFWRM.js → chunk-7R7O6STJ.js} +4 -4
- package/dist/{chunk-VXEOHTSL.js → chunk-C7OK5WKP.js} +4 -4
- package/dist/chunk-CMB7UL7C.js +327 -0
- package/dist/chunk-DEFFDRVP.js +938 -0
- package/dist/{chunk-K3CDT7IH.js → chunk-E7MFQB6D.js} +61 -20
- package/dist/{chunk-ME37YNW3.js → chunk-F2JEUD4J.js} +6 -4
- package/dist/chunk-GAJV4IGR.js +82 -0
- package/dist/chunk-GQSLDZTS.js +560 -0
- package/dist/{chunk-4OXMU5S2.js → chunk-GUKMRGM7.js} +1 -1
- package/dist/{chunk-YOSEUUNB.js → chunk-H34S76MB.js} +6 -6
- package/dist/{chunk-4TE4JMLA.js → chunk-JY6FYXIT.js} +10 -5
- package/dist/chunk-K234IDRJ.js +1073 -0
- package/dist/{chunk-IEVLHNLU.js → chunk-LNJA2UGL.js} +86 -9
- package/dist/{chunk-MFAWT5O5.js → chunk-LYHGEHXG.js} +1 -0
- package/dist/chunk-MFM6K7PU.js +374 -0
- package/dist/{chunk-QWQ3TIKS.js → chunk-N2AXRYLC.js} +1 -1
- package/dist/chunk-PAH27GSN.js +108 -0
- package/dist/{chunk-OIWVQYQF.js → chunk-QBLMXKF2.js} +1 -1
- package/dist/{chunk-FHFUXL6G.js → chunk-QK3UCXWL.js} +2 -2
- package/dist/{chunk-2YDBJS7M.js → chunk-SJSFRIYS.js} +1 -1
- package/dist/{chunk-GSD4ALSI.js → chunk-U55BGUAU.js} +2 -2
- package/dist/{chunk-PBEE567J.js → chunk-VGLOTGAS.js} +1 -1
- package/dist/{chunk-F55HGNU4.js → chunk-WAZ3NLWL.js} +47 -0
- package/dist/{chunk-KL4NAOMO.js → chunk-WGRQ6HDV.js} +1 -1
- package/dist/{chunk-UEOUADMO.js → chunk-YKTA5JOJ.js} +13 -10
- package/dist/{chunk-XAVB4GB4.js → chunk-ZVVFWOLW.js} +4 -4
- package/dist/cli/index.cjs +10033 -0
- package/dist/cli/index.d.cts +5 -0
- package/dist/cli/index.js +20 -18
- package/dist/commands/archive.cjs +287 -0
- package/dist/commands/archive.d.cts +11 -0
- package/dist/commands/archive.js +1 -0
- package/dist/commands/backlog.cjs +721 -0
- package/dist/commands/backlog.d.cts +53 -0
- package/dist/commands/backlog.js +3 -2
- package/dist/commands/blocked.cjs +204 -0
- package/dist/commands/blocked.d.cts +26 -0
- package/dist/commands/blocked.js +3 -2
- package/dist/commands/checkpoint.cjs +244 -0
- package/dist/commands/checkpoint.d.cts +41 -0
- package/dist/commands/checkpoint.js +2 -1
- package/dist/commands/compat.cjs +369 -0
- package/dist/commands/compat.d.cts +28 -0
- package/dist/commands/compat.js +2 -1
- package/dist/commands/context.cjs +2989 -0
- package/dist/commands/context.d.cts +2 -0
- package/dist/commands/context.js +5 -4
- package/dist/commands/doctor.cjs +3062 -0
- package/dist/commands/doctor.d.cts +21 -0
- package/dist/commands/doctor.d.ts +6 -1
- package/dist/commands/doctor.js +13 -11
- package/dist/commands/embed.cjs +232 -0
- package/dist/commands/embed.d.cts +17 -0
- package/dist/commands/embed.js +5 -2
- package/dist/commands/entities.cjs +141 -0
- package/dist/commands/entities.d.cts +7 -0
- package/dist/commands/entities.js +1 -0
- package/dist/commands/graph.cjs +501 -0
- package/dist/commands/graph.d.cts +21 -0
- package/dist/commands/graph.js +1 -0
- package/dist/commands/inject.cjs +1636 -0
- package/dist/commands/inject.d.cts +2 -0
- package/dist/commands/inject.d.ts +1 -1
- package/dist/commands/inject.js +4 -2
- package/dist/commands/kanban.cjs +884 -0
- package/dist/commands/kanban.d.cts +63 -0
- package/dist/commands/kanban.js +4 -3
- package/dist/commands/link.cjs +965 -0
- package/dist/commands/link.d.cts +11 -0
- package/dist/commands/link.js +1 -0
- package/dist/commands/migrate-observations.cjs +362 -0
- package/dist/commands/migrate-observations.d.cts +19 -0
- package/dist/commands/migrate-observations.js +3 -2
- package/dist/commands/observe.cjs +4099 -0
- package/dist/commands/observe.d.cts +23 -0
- package/dist/commands/observe.d.ts +1 -0
- package/dist/commands/observe.js +11 -9
- package/dist/commands/project.cjs +1341 -0
- package/dist/commands/project.d.cts +85 -0
- package/dist/commands/project.js +5 -4
- package/dist/commands/rebuild.cjs +3136 -0
- package/dist/commands/rebuild.d.cts +11 -0
- package/dist/commands/rebuild.js +10 -8
- package/dist/commands/recover.cjs +361 -0
- package/dist/commands/recover.d.cts +38 -0
- package/dist/commands/recover.js +3 -2
- package/dist/commands/reflect.cjs +1008 -0
- package/dist/commands/reflect.d.cts +11 -0
- package/dist/commands/reflect.js +6 -4
- package/dist/commands/repair-session.cjs +457 -0
- package/dist/commands/repair-session.d.cts +38 -0
- package/dist/commands/repair-session.js +1 -0
- package/dist/commands/replay.cjs +4103 -0
- package/dist/commands/replay.d.cts +16 -0
- package/dist/commands/replay.js +12 -10
- package/dist/commands/session-recap.cjs +353 -0
- package/dist/commands/session-recap.d.cts +27 -0
- package/dist/commands/session-recap.js +1 -0
- package/dist/commands/setup.cjs +1345 -0
- package/dist/commands/setup.d.cts +100 -0
- package/dist/commands/setup.d.ts +90 -2
- package/dist/commands/setup.js +21 -2
- package/dist/commands/shell-init.cjs +75 -0
- package/dist/commands/shell-init.d.cts +7 -0
- package/dist/commands/shell-init.js +2 -0
- package/dist/commands/sleep.cjs +6028 -0
- package/dist/commands/sleep.d.cts +36 -0
- package/dist/commands/sleep.d.ts +1 -1
- package/dist/commands/sleep.js +17 -15
- package/dist/commands/status.cjs +2736 -0
- package/dist/commands/status.d.cts +52 -0
- package/dist/commands/status.js +12 -10
- package/dist/commands/tailscale.cjs +1532 -0
- package/dist/commands/tailscale.d.cts +52 -0
- package/dist/commands/tailscale.js +1 -0
- package/dist/commands/task.cjs +1236 -0
- package/dist/commands/task.d.cts +97 -0
- package/dist/commands/task.js +4 -3
- package/dist/commands/template.cjs +457 -0
- package/dist/commands/template.d.cts +36 -0
- package/dist/commands/template.js +2 -1
- package/dist/commands/wake.cjs +2626 -0
- package/dist/commands/wake.d.cts +22 -0
- package/dist/commands/wake.d.ts +1 -1
- package/dist/commands/wake.js +12 -11
- package/dist/context-BUGaWpyL.d.cts +46 -0
- package/dist/index.cjs +14526 -0
- package/dist/index.d.cts +858 -0
- package/dist/index.d.ts +192 -7
- package/dist/index.js +101 -75
- package/dist/{inject-x65KXWPk.d.ts → inject-Bzi5E-By.d.cts} +1 -1
- package/dist/inject-Bzi5E-By.d.ts +137 -0
- package/dist/lib/auto-linker.cjs +176 -0
- package/dist/lib/auto-linker.d.cts +26 -0
- package/dist/lib/auto-linker.js +1 -0
- package/dist/lib/canvas-layout.cjs +136 -0
- package/dist/lib/canvas-layout.d.cts +31 -0
- package/dist/lib/canvas-layout.d.ts +16 -100
- package/dist/lib/canvas-layout.js +78 -20
- package/dist/lib/config.cjs +78 -0
- package/dist/lib/config.d.cts +11 -0
- package/dist/lib/config.js +1 -0
- package/dist/lib/entity-index.cjs +84 -0
- package/dist/lib/entity-index.d.cts +26 -0
- package/dist/lib/entity-index.js +1 -0
- package/dist/lib/project-utils.cjs +864 -0
- package/dist/lib/project-utils.d.cts +97 -0
- package/dist/lib/project-utils.js +4 -3
- package/dist/lib/session-repair.cjs +239 -0
- package/dist/lib/session-repair.d.cts +110 -0
- package/dist/lib/session-repair.js +1 -0
- package/dist/lib/session-utils.cjs +209 -0
- package/dist/lib/session-utils.d.cts +63 -0
- package/dist/lib/session-utils.js +1 -0
- package/dist/lib/tailscale.cjs +1183 -0
- package/dist/lib/tailscale.d.cts +225 -0
- package/dist/lib/tailscale.js +1 -0
- package/dist/lib/task-utils.cjs +1137 -0
- package/dist/lib/task-utils.d.cts +208 -0
- package/dist/lib/task-utils.js +3 -2
- package/dist/lib/template-engine.cjs +47 -0
- package/dist/lib/template-engine.d.cts +11 -0
- package/dist/lib/template-engine.js +1 -0
- package/dist/lib/webdav.cjs +568 -0
- package/dist/lib/webdav.d.cts +109 -0
- package/dist/lib/webdav.js +1 -0
- package/dist/plugin/index.cjs +1907 -0
- package/dist/plugin/index.d.cts +36 -0
- package/dist/plugin/index.d.ts +36 -0
- package/dist/plugin/index.js +572 -0
- package/dist/plugin/inject.cjs +356 -0
- package/dist/plugin/inject.d.cts +54 -0
- package/dist/plugin/inject.d.ts +54 -0
- package/dist/plugin/inject.js +17 -0
- package/dist/plugin/observe.cjs +631 -0
- package/dist/plugin/observe.d.cts +39 -0
- package/dist/plugin/observe.d.ts +39 -0
- package/dist/plugin/observe.js +18 -0
- package/dist/plugin/templates.cjs +593 -0
- package/dist/plugin/templates.d.cts +52 -0
- package/dist/plugin/templates.d.ts +52 -0
- package/dist/plugin/templates.js +25 -0
- package/dist/plugin/types.cjs +18 -0
- package/dist/plugin/types.d.cts +209 -0
- package/dist/plugin/types.d.ts +209 -0
- package/dist/plugin/types.js +0 -0
- package/dist/plugin/vault.cjs +927 -0
- package/dist/plugin/vault.d.cts +68 -0
- package/dist/plugin/vault.d.ts +68 -0
- package/dist/plugin/vault.js +22 -0
- package/dist/{types-C74wgGL1.d.ts → types-Y2_Um2Ls.d.cts} +44 -1
- package/dist/types-Y2_Um2Ls.d.ts +205 -0
- package/hooks/clawvault/handler.js +70 -7
- package/hooks/clawvault/handler.test.js +91 -0
- package/openclaw.plugin.json +56 -0
- package/package.json +17 -7
- package/templates/memory-event.md +67 -0
- package/templates/party.md +63 -0
- package/templates/primitive-registry.yaml +551 -0
- package/templates/run.md +68 -0
- package/templates/trigger.md +68 -0
- package/templates/workspace.md +50 -0
- package/dashboard/lib/graph-diff.js +0 -104
- package/dashboard/lib/graph-diff.test.js +0 -75
- package/dashboard/lib/vault-parser.js +0 -556
- package/dashboard/lib/vault-parser.test.js +0 -254
- package/dashboard/public/app.js +0 -796
- package/dashboard/public/index.html +0 -52
- package/dashboard/public/styles.css +0 -221
- package/dashboard/server.js +0 -374
- package/dist/chunk-HA5M6KJB.js +0 -33
- package/dist/chunk-MAKNAHAW.js +0 -375
- package/dist/chunk-MDIH26GC.js +0 -183
- package/dist/chunk-MGDEINGP.js +0 -99
- package/dist/chunk-RVYA52PY.js +0 -363
- package/dist/commands/canvas.d.ts +0 -15
- package/dist/commands/canvas.js +0 -199
- package/dist/commands/sync-bd.d.ts +0 -10
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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);
|
|
@@ -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
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -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";
|