@monoes/monomindcli 2.14.0 → 2.14.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.
- package/.claude/skills/monodesign/scripts/context.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +2 -2
- package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +2 -2
- package/.claude/skills/monodesign/scripts/live-browser.js +1 -1
- package/bin/cli.js +21 -1
- package/bin/mcp-server.js +21 -1
- package/dist/src/capabilities/cap-documents.d.ts.map +1 -1
- package/dist/src/capabilities/cap-documents.js +23 -0
- package/dist/src/capabilities/cap-documents.js.map +1 -1
- package/dist/src/commands/doc-filters.d.ts +19 -0
- package/dist/src/commands/doc-filters.d.ts.map +1 -0
- package/dist/src/commands/doc-filters.js +58 -0
- package/dist/src/commands/doc-filters.js.map +1 -0
- package/dist/src/commands/doc-library.d.ts +21 -0
- package/dist/src/commands/doc-library.d.ts.map +1 -0
- package/dist/src/commands/doc-library.js +390 -0
- package/dist/src/commands/doc-library.js.map +1 -0
- package/dist/src/commands/doc-list.d.ts +9 -0
- package/dist/src/commands/doc-list.d.ts.map +1 -0
- package/dist/src/commands/doc-list.js +99 -0
- package/dist/src/commands/doc-list.js.map +1 -0
- package/dist/src/commands/doc.d.ts.map +1 -1
- package/dist/src/commands/doc.js +49 -37
- package/dist/src/commands/doc.js.map +1 -1
- package/dist/src/knowledge/capture-envelope.d.ts +80 -0
- package/dist/src/knowledge/capture-envelope.d.ts.map +1 -0
- package/dist/src/knowledge/capture-envelope.js +165 -0
- package/dist/src/knowledge/capture-envelope.js.map +1 -0
- package/dist/src/knowledge/capture-text.d.ts +23 -0
- package/dist/src/knowledge/capture-text.d.ts.map +1 -0
- package/dist/src/knowledge/capture-text.js +49 -0
- package/dist/src/knowledge/capture-text.js.map +1 -0
- package/dist/src/knowledge/citation.d.ts +121 -0
- package/dist/src/knowledge/citation.d.ts.map +1 -0
- package/dist/src/knowledge/citation.js +252 -0
- package/dist/src/knowledge/citation.js.map +1 -0
- package/dist/src/knowledge/document-pipeline.d.ts +60 -0
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +188 -4
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/knowledge/html-extract.d.ts +43 -0
- package/dist/src/knowledge/html-extract.d.ts.map +1 -0
- package/dist/src/knowledge/html-extract.js +286 -0
- package/dist/src/knowledge/html-extract.js.map +1 -0
- package/dist/src/knowledge/html-tags.d.ts +30 -0
- package/dist/src/knowledge/html-tags.d.ts.map +1 -0
- package/dist/src/knowledge/html-tags.js +229 -0
- package/dist/src/knowledge/html-tags.js.map +1 -0
- package/dist/src/knowledge/library.d.ts +106 -0
- package/dist/src/knowledge/library.d.ts.map +1 -0
- package/dist/src/knowledge/library.js +195 -0
- package/dist/src/knowledge/library.js.map +1 -0
- package/dist/src/knowledge/mhtml.d.ts +60 -0
- package/dist/src/knowledge/mhtml.d.ts.map +1 -0
- package/dist/src/knowledge/mhtml.js +154 -0
- package/dist/src/knowledge/mhtml.js.map +1 -0
- package/dist/src/knowledge/related.d.ts +58 -0
- package/dist/src/knowledge/related.d.ts.map +1 -0
- package/dist/src/knowledge/related.js +222 -0
- package/dist/src/knowledge/related.js.map +1 -0
- package/dist/src/knowledge/section-diff.d.ts +48 -0
- package/dist/src/knowledge/section-diff.d.ts.map +1 -0
- package/dist/src/knowledge/section-diff.js +151 -0
- package/dist/src/knowledge/section-diff.js.map +1 -0
- package/dist/src/knowledge/watch.d.ts +92 -0
- package/dist/src/knowledge/watch.d.ts.map +1 -0
- package/dist/src/knowledge/watch.js +221 -0
- package/dist/src/knowledge/watch.js.map +1 -0
- package/dist/src/mcp-server.d.ts.map +1 -1
- package/dist/src/mcp-server.js +44 -87
- package/dist/src/mcp-server.js.map +1 -1
- package/dist/src/mcp-tools/browser-instrument-tools.d.ts +35 -0
- package/dist/src/mcp-tools/browser-instrument-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/browser-instrument-tools.js +359 -0
- package/dist/src/mcp-tools/browser-instrument-tools.js.map +1 -0
- package/dist/src/mcp-tools/browser-metrics.d.ts +42 -0
- package/dist/src/mcp-tools/browser-metrics.d.ts.map +1 -0
- package/dist/src/mcp-tools/browser-metrics.js +91 -0
- package/dist/src/mcp-tools/browser-metrics.js.map +1 -0
- package/dist/src/mcp-tools/browser-profile-tools.d.ts +16 -0
- package/dist/src/mcp-tools/browser-profile-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/browser-profile-tools.js +324 -0
- package/dist/src/mcp-tools/browser-profile-tools.js.map +1 -0
- package/dist/src/mcp-tools/browser-session.d.ts +68 -0
- package/dist/src/mcp-tools/browser-session.d.ts.map +1 -0
- package/dist/src/mcp-tools/browser-session.js +224 -0
- package/dist/src/mcp-tools/browser-session.js.map +1 -0
- package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/browser-tools.js +10 -176
- package/dist/src/mcp-tools/browser-tools.js.map +1 -1
- package/dist/src/mcp-tools/capture-resource-read.d.ts +115 -0
- package/dist/src/mcp-tools/capture-resource-read.d.ts.map +1 -0
- package/dist/src/mcp-tools/capture-resource-read.js +296 -0
- package/dist/src/mcp-tools/capture-resource-read.js.map +1 -0
- package/dist/src/mcp-tools/capture-resource-tools.d.ts +22 -0
- package/dist/src/mcp-tools/capture-resource-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/capture-resource-tools.js +182 -0
- package/dist/src/mcp-tools/capture-resource-tools.js.map +1 -0
- package/dist/src/mcp-tools/capture-resources.d.ts +142 -0
- package/dist/src/mcp-tools/capture-resources.d.ts.map +1 -0
- package/dist/src/mcp-tools/capture-resources.js +289 -0
- package/dist/src/mcp-tools/capture-resources.js.map +1 -0
- package/dist/src/mcp-tools/index.d.ts +3 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +6 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/knowledge-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/knowledge-tools.js +9 -1
- package/dist/src/mcp-tools/knowledge-tools.js.map +1 -1
- package/dist/src/mcp-tools/resource-router.d.ts +86 -0
- package/dist/src/mcp-tools/resource-router.d.ts.map +1 -0
- package/dist/src/mcp-tools/resource-router.js +181 -0
- package/dist/src/mcp-tools/resource-router.js.map +1 -0
- package/dist/src/memory/memory-bridge.js +1 -1
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/orgrt/session-ledger.d.ts +7 -0
- package/dist/src/orgrt/session-ledger.d.ts.map +1 -1
- package/dist/src/orgrt/session-ledger.js +15 -0
- package/dist/src/orgrt/session-ledger.js.map +1 -1
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +21 -8
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Related-at-save (RCL-03) — "3 things in your brain relate to this".
|
|
3
|
+
*
|
|
4
|
+
* The extension calls this on EVERY capture, while the user watches. That
|
|
5
|
+
* single fact sets every design decision here:
|
|
6
|
+
*
|
|
7
|
+
* - it never throws. An empty store, a missing embedder, a URL that was
|
|
8
|
+
* never captured — all of them are an empty list, because a capture must
|
|
9
|
+
* not fail because the sidebar had nothing to say;
|
|
10
|
+
* - it is bounded. The vector pass races a timeout (default 2s) and the
|
|
11
|
+
* cheap signals — same URL, same site, read straight off the metadata log —
|
|
12
|
+
* are computed first, so a slow or absent embedder degrades to a fast
|
|
13
|
+
* answer instead of no answer;
|
|
14
|
+
* - the target itself is never in its own results, by path AND by canonical
|
|
15
|
+
* URL, so a re-capture does not "relate" to the version it replaced.
|
|
16
|
+
*
|
|
17
|
+
* Three signals, combined: exact URL (the same page, captured before),
|
|
18
|
+
* same site, and vector similarity over the chunks already embedded.
|
|
19
|
+
*
|
|
20
|
+
* @module v1/cli/knowledge/related
|
|
21
|
+
*/
|
|
22
|
+
import * as fs from 'node:fs';
|
|
23
|
+
import * as path from 'node:path';
|
|
24
|
+
import { captureIdentityUrl, readCaptureProvenance } from './capture-envelope.js';
|
|
25
|
+
import { passageQuote } from './citation.js';
|
|
26
|
+
import { documentCapturedAt, documentSite } from './library.js';
|
|
27
|
+
const DEFAULT_LIMIT = 3;
|
|
28
|
+
const DEFAULT_TIMEOUT_MS = 2000;
|
|
29
|
+
const DEFAULT_MIN_SCORE = 0.25;
|
|
30
|
+
const QUERY_CHARS = 1200;
|
|
31
|
+
const SAME_URL_SCORE = 1;
|
|
32
|
+
/** Ceiling for everything that is not literally the same page. */
|
|
33
|
+
const NEAR_SCORE_CAP = 0.95;
|
|
34
|
+
const SAME_SITE_SCORE = 0.45;
|
|
35
|
+
const BOTH_SIGNALS_BONUS = 0.1;
|
|
36
|
+
const EXCERPT_CHARS = 200;
|
|
37
|
+
function stripFragment(url) {
|
|
38
|
+
const hash = url.indexOf('#');
|
|
39
|
+
return (hash === -1 ? url : url.slice(0, hash)).trim();
|
|
40
|
+
}
|
|
41
|
+
function looksLikeUrl(target) {
|
|
42
|
+
return /^https?:\/\//i.test(target.trim());
|
|
43
|
+
}
|
|
44
|
+
function hostOf(url) {
|
|
45
|
+
if (!url)
|
|
46
|
+
return undefined;
|
|
47
|
+
try {
|
|
48
|
+
return new URL(url).hostname.toLowerCase().replace(/^www\./, '');
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Words a URL alone gives us — the fallback query when there is no text. */
|
|
55
|
+
function urlWords(url) {
|
|
56
|
+
try {
|
|
57
|
+
const u = new URL(url);
|
|
58
|
+
return [u.hostname.replace(/^www\./, ''), ...u.pathname.split(/[/\-_.]+/)]
|
|
59
|
+
.filter((w) => w && !/^\d+$/.test(w) && w.length > 1)
|
|
60
|
+
.join(' ');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return url;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function queryText(record, target, provided) {
|
|
67
|
+
if (provided?.trim())
|
|
68
|
+
return provided.slice(0, QUERY_CHARS);
|
|
69
|
+
const parts = [];
|
|
70
|
+
if (record?.provenance?.title)
|
|
71
|
+
parts.push(record.provenance.title);
|
|
72
|
+
if (record && fs.existsSync(record.filePath)) {
|
|
73
|
+
try {
|
|
74
|
+
const { extractText } = await import('../capabilities/cap-documents.js');
|
|
75
|
+
const stat = fs.statSync(record.filePath);
|
|
76
|
+
const text = await extractText({
|
|
77
|
+
path: record.filePath,
|
|
78
|
+
absolutePath: record.filePath,
|
|
79
|
+
extension: path.extname(record.filePath).toLowerCase(),
|
|
80
|
+
size: stat.size,
|
|
81
|
+
modified: stat.mtime,
|
|
82
|
+
created: stat.birthtime,
|
|
83
|
+
});
|
|
84
|
+
if (text)
|
|
85
|
+
parts.push(text.slice(0, QUERY_CHARS));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* fall through to the URL words */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!parts.length)
|
|
92
|
+
parts.push(urlWords(looksLikeUrl(target) ? target : path.basename(target)));
|
|
93
|
+
return parts.join('\n').slice(0, QUERY_CHARS);
|
|
94
|
+
}
|
|
95
|
+
/** Resolve the vector pass or give up on time — whichever comes first. */
|
|
96
|
+
function withTimeout(work, ms, fallback) {
|
|
97
|
+
return new Promise((resolve) => {
|
|
98
|
+
const timer = setTimeout(() => resolve(fallback), ms);
|
|
99
|
+
work
|
|
100
|
+
.then((value) => {
|
|
101
|
+
clearTimeout(timer);
|
|
102
|
+
resolve(value);
|
|
103
|
+
})
|
|
104
|
+
.catch(() => {
|
|
105
|
+
clearTimeout(timer);
|
|
106
|
+
resolve(fallback);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The documents most related to `target` (a URL, a docId, or an indexed path).
|
|
112
|
+
*
|
|
113
|
+
* Safe to call on every capture: bounded, and empty rather than thrown on any
|
|
114
|
+
* failure.
|
|
115
|
+
*/
|
|
116
|
+
export async function relatedDocuments(target, opts = {}) {
|
|
117
|
+
try {
|
|
118
|
+
const pipeline = await import('./document-pipeline.js');
|
|
119
|
+
const scope = opts.scope;
|
|
120
|
+
const rootDir = opts.rootDir ?? pipeline.getKnowledgeRoot(scope ?? 'shared');
|
|
121
|
+
const limit = opts.limit ?? DEFAULT_LIMIT;
|
|
122
|
+
const self = pipeline.findDocumentRecord(rootDir, target, scope);
|
|
123
|
+
// A capture that has been written but not yet ingested is the case this
|
|
124
|
+
// story exists for: the extension has the directory on disk and wants to
|
|
125
|
+
// know what it relates to BEFORE the ingest finishes. Its identity comes
|
|
126
|
+
// from the envelope's own meta.json.
|
|
127
|
+
const pending = !self && !looksLikeUrl(target) ? readCaptureProvenance(target) : null;
|
|
128
|
+
const selfUrl = self?.canonicalUrl ??
|
|
129
|
+
(looksLikeUrl(target) ? stripFragment(target) : captureIdentityUrl(pending));
|
|
130
|
+
const selfSite = hostOf(selfUrl);
|
|
131
|
+
const selfPaths = new Set([self?.filePath, looksLikeUrl(target) ? undefined : path.resolve(target)].filter((p) => !!p));
|
|
132
|
+
// Excluding by URL is right when the target IS that page — an indexed
|
|
133
|
+
// document, or a caller asking about the URL itself. It is wrong for a
|
|
134
|
+
// capture still sitting in the inbox: there the earlier capture of the
|
|
135
|
+
// same page is the single most related thing in the brain.
|
|
136
|
+
const excludeByUrl = !!self || looksLikeUrl(target);
|
|
137
|
+
const isSelf = (doc) => selfPaths.has(doc.filePath) || (excludeByUrl && !!selfUrl && doc.canonicalUrl === selfUrl);
|
|
138
|
+
const docs = pipeline.listDocuments(rootDir, scope).filter((d) => !isSelf(d));
|
|
139
|
+
const byPath = new Map(docs.map((d) => [d.filePath, d]));
|
|
140
|
+
const scored = new Map();
|
|
141
|
+
const put = (doc, reason, score, extra = {}) => {
|
|
142
|
+
const existing = scored.get(doc.filePath);
|
|
143
|
+
if (existing) {
|
|
144
|
+
if (!existing.reasons.includes(reason))
|
|
145
|
+
existing.reasons.push(reason);
|
|
146
|
+
// Agreeing signals compound, but only the same page itself reaches 1 —
|
|
147
|
+
// otherwise a same-site neighbour that also embeds well would tie with
|
|
148
|
+
// the earlier capture of this very page and win on sort order.
|
|
149
|
+
const cap = existing.reasons.includes('same-url') ? SAME_URL_SCORE : NEAR_SCORE_CAP;
|
|
150
|
+
existing.score = Math.min(cap, Math.max(existing.score, score) + BOTH_SIGNALS_BONUS);
|
|
151
|
+
Object.assign(existing, extra);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const url = doc.canonicalUrl ?? doc.provenance?.canonicalUrl ?? doc.provenance?.url;
|
|
155
|
+
scored.set(doc.filePath, {
|
|
156
|
+
filePath: doc.filePath,
|
|
157
|
+
scope: doc.scope,
|
|
158
|
+
title: doc.provenance?.title ?? path.basename(doc.filePath),
|
|
159
|
+
...(url ? { url } : {}),
|
|
160
|
+
...(documentSite(doc) ? { site: documentSite(doc) } : {}),
|
|
161
|
+
score,
|
|
162
|
+
reasons: [reason],
|
|
163
|
+
...(documentCapturedAt(doc) ? { capturedAt: documentCapturedAt(doc) } : {}),
|
|
164
|
+
...extra,
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
// 1 + 2 — the cheap signals, straight off the metadata log.
|
|
168
|
+
for (const doc of docs) {
|
|
169
|
+
const url = doc.canonicalUrl ?? doc.provenance?.canonicalUrl;
|
|
170
|
+
if (selfUrl && url && stripFragment(url) === selfUrl)
|
|
171
|
+
put(doc, 'same-url', SAME_URL_SCORE);
|
|
172
|
+
else if (selfSite && documentSite(doc) === selfSite)
|
|
173
|
+
put(doc, 'same-site', SAME_SITE_SCORE);
|
|
174
|
+
}
|
|
175
|
+
// 3 — similarity, bounded. A store with no embeddings comes back empty
|
|
176
|
+
// here and the metadata signals still stand.
|
|
177
|
+
// For a not-yet-ingested capture the text to compare against is the file
|
|
178
|
+
// the caller pointed at, read through the same extraction the ingest uses.
|
|
179
|
+
const queryRecord = self ?? (pending ? { filePath: path.resolve(target), provenance: pending } : undefined);
|
|
180
|
+
const query = await queryText(queryRecord, target, opts.text);
|
|
181
|
+
if (query.trim()) {
|
|
182
|
+
const hits = await withTimeout(pipeline.searchKnowledge(query, {
|
|
183
|
+
scope: scope ?? 'shared',
|
|
184
|
+
rootDir,
|
|
185
|
+
limit: Math.max(limit * 6, 12),
|
|
186
|
+
minScore: opts.minScore ?? DEFAULT_MIN_SCORE,
|
|
187
|
+
store: opts.store ?? 'all',
|
|
188
|
+
}), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS, []);
|
|
189
|
+
const best = new Map();
|
|
190
|
+
for (const hit of hits) {
|
|
191
|
+
if (!hit.filePath || selfPaths.has(hit.filePath))
|
|
192
|
+
continue;
|
|
193
|
+
const current = best.get(hit.filePath);
|
|
194
|
+
if (!current || hit.similarity > current.similarity)
|
|
195
|
+
best.set(hit.filePath, hit);
|
|
196
|
+
}
|
|
197
|
+
for (const [filePath, hit] of best) {
|
|
198
|
+
const doc = byPath.get(filePath);
|
|
199
|
+
if (!doc || isSelf(doc))
|
|
200
|
+
continue;
|
|
201
|
+
put(doc, 'similar', Math.min(1, hit.similarity), {
|
|
202
|
+
excerpt: passageQuote(hit.text ?? '', EXCERPT_CHARS),
|
|
203
|
+
chunkIndex: hit.chunkIndex,
|
|
204
|
+
...(hit.anchor ? { anchor: hit.anchor } : {}),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return [...scored.values()]
|
|
209
|
+
.sort((a, b) => b.score - a.score || (b.capturedAt ?? '').localeCompare(a.capturedAt ?? ''))
|
|
210
|
+
.slice(0, limit);
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
// Called on every capture: an unexpected failure is "nothing related",
|
|
214
|
+
// never a broken save. It is still a bug when it is one of ours, so it is
|
|
215
|
+
// visible under DEBUG rather than only in an empty sidebar.
|
|
216
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG) {
|
|
217
|
+
console.error(`[relatedDocuments] ${target}:`, err);
|
|
218
|
+
}
|
|
219
|
+
return [];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=related.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"related.js","sourceRoot":"","sources":["../../../src/knowledge/related.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic diff between two versions of a captured page (RCL-08).
|
|
3
|
+
*
|
|
4
|
+
* A character diff of a re-captured page is noise: the byline date moved, an
|
|
5
|
+
* ad slot re-rendered, the markdown re-wrapped. What a watcher actually wants
|
|
6
|
+
* to be told is WHICH SECTIONS changed and roughly how much — "Pricing gained
|
|
7
|
+
* a paragraph, Changelog got three new entries, everything else is the same".
|
|
8
|
+
*
|
|
9
|
+
* So the unit here is the markdown section (heading + body), keyed by its
|
|
10
|
+
* full heading path, and the measure is words and sentences rather than
|
|
11
|
+
* characters. Sentences are also what gives a change its sample line: the
|
|
12
|
+
* first sentence that is in the new version and was not in the old one is the
|
|
13
|
+
* most useful single thing to print.
|
|
14
|
+
*
|
|
15
|
+
* No dependency, no LLM: heading paths and sentence sets are enough to say
|
|
16
|
+
* what moved.
|
|
17
|
+
*
|
|
18
|
+
* @module v1/cli/knowledge/section-diff
|
|
19
|
+
*/
|
|
20
|
+
export interface Section {
|
|
21
|
+
/** Full heading path, e.g. `Pricing > Enterprise`. `(intro)` for text
|
|
22
|
+
* before the first heading. */
|
|
23
|
+
key: string;
|
|
24
|
+
heading: string;
|
|
25
|
+
level: number;
|
|
26
|
+
body: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SectionChange {
|
|
29
|
+
key: string;
|
|
30
|
+
addedWords: number;
|
|
31
|
+
removedWords: number;
|
|
32
|
+
/** First sentence present in the new version and absent from the old. */
|
|
33
|
+
sample?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface SectionDiff {
|
|
36
|
+
added: string[];
|
|
37
|
+
removed: string[];
|
|
38
|
+
changed: SectionChange[];
|
|
39
|
+
unchanged: number;
|
|
40
|
+
/** One line, ready to print or to put in a notification. */
|
|
41
|
+
summary: string;
|
|
42
|
+
}
|
|
43
|
+
/** Split markdown into sections keyed by heading path. Duplicate paths get a
|
|
44
|
+
* `#2` suffix so two "Notes" sections never collapse into one. */
|
|
45
|
+
export declare function splitSections(text: string): Section[];
|
|
46
|
+
/** What changed between two versions of the same page. */
|
|
47
|
+
export declare function diffSections(oldText: string, newText: string): SectionDiff;
|
|
48
|
+
//# sourceMappingURL=section-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-diff.d.ts","sourceRoot":"","sources":["../../../src/knowledge/section-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,WAAW,OAAO;IACtB;oCACgC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD;mEACmE;AACnE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAmCrD;AA2DD,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAgC1E"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic diff between two versions of a captured page (RCL-08).
|
|
3
|
+
*
|
|
4
|
+
* A character diff of a re-captured page is noise: the byline date moved, an
|
|
5
|
+
* ad slot re-rendered, the markdown re-wrapped. What a watcher actually wants
|
|
6
|
+
* to be told is WHICH SECTIONS changed and roughly how much — "Pricing gained
|
|
7
|
+
* a paragraph, Changelog got three new entries, everything else is the same".
|
|
8
|
+
*
|
|
9
|
+
* So the unit here is the markdown section (heading + body), keyed by its
|
|
10
|
+
* full heading path, and the measure is words and sentences rather than
|
|
11
|
+
* characters. Sentences are also what gives a change its sample line: the
|
|
12
|
+
* first sentence that is in the new version and was not in the old one is the
|
|
13
|
+
* most useful single thing to print.
|
|
14
|
+
*
|
|
15
|
+
* No dependency, no LLM: heading paths and sentence sets are enough to say
|
|
16
|
+
* what moved.
|
|
17
|
+
*
|
|
18
|
+
* @module v1/cli/knowledge/section-diff
|
|
19
|
+
*/
|
|
20
|
+
const HEADING_RE = /^(#{1,6})\s+(.+?)\s*#*\s*$/;
|
|
21
|
+
const INTRO_KEY = '(intro)';
|
|
22
|
+
/** Split markdown into sections keyed by heading path. Duplicate paths get a
|
|
23
|
+
* `#2` suffix so two "Notes" sections never collapse into one. */
|
|
24
|
+
export function splitSections(text) {
|
|
25
|
+
const lines = String(text ?? '').split('\n');
|
|
26
|
+
const stack = [];
|
|
27
|
+
const sections = [];
|
|
28
|
+
const seen = new Map();
|
|
29
|
+
let current = { key: INTRO_KEY, heading: INTRO_KEY, level: 0, body: '' };
|
|
30
|
+
const buffer = [];
|
|
31
|
+
const flush = () => {
|
|
32
|
+
current.body = buffer.join('\n').trim();
|
|
33
|
+
buffer.length = 0;
|
|
34
|
+
if (current.key !== INTRO_KEY || current.body)
|
|
35
|
+
sections.push(current);
|
|
36
|
+
};
|
|
37
|
+
let inFence = false;
|
|
38
|
+
for (const line of lines) {
|
|
39
|
+
if (/^\s{0,3}(`{3,}|~{3,})/.test(line))
|
|
40
|
+
inFence = !inFence;
|
|
41
|
+
const m = inFence ? null : HEADING_RE.exec(line);
|
|
42
|
+
if (!m) {
|
|
43
|
+
buffer.push(line);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
flush();
|
|
47
|
+
const level = m[1].length;
|
|
48
|
+
const heading = m[2].trim();
|
|
49
|
+
stack.length = Math.max(0, level - 1);
|
|
50
|
+
stack[level - 1] = heading;
|
|
51
|
+
let key = stack.filter(Boolean).join(' > ');
|
|
52
|
+
const n = (seen.get(key) ?? 0) + 1;
|
|
53
|
+
seen.set(key, n);
|
|
54
|
+
if (n > 1)
|
|
55
|
+
key = `${key} #${n}`;
|
|
56
|
+
current = { key, heading, level, body: '' };
|
|
57
|
+
}
|
|
58
|
+
flush();
|
|
59
|
+
return sections;
|
|
60
|
+
}
|
|
61
|
+
function words(text) {
|
|
62
|
+
return text.toLowerCase().match(/[\p{L}\p{N}][\p{L}\p{N}'’-]*/gu) ?? [];
|
|
63
|
+
}
|
|
64
|
+
function sentences(text) {
|
|
65
|
+
return text
|
|
66
|
+
.replace(/\s+/g, ' ')
|
|
67
|
+
.split(/(?<=[.!?])\s+/)
|
|
68
|
+
.map((s) => s.trim())
|
|
69
|
+
.filter((s) => s.length > 0);
|
|
70
|
+
}
|
|
71
|
+
/** Multiset difference: how many words the new body has that the old did not
|
|
72
|
+
* (and vice versa), so re-ordering a paragraph does not read as a rewrite. */
|
|
73
|
+
function wordDelta(oldBody, newBody) {
|
|
74
|
+
const counts = new Map();
|
|
75
|
+
for (const w of words(oldBody))
|
|
76
|
+
counts.set(w, (counts.get(w) ?? 0) + 1);
|
|
77
|
+
let added = 0;
|
|
78
|
+
for (const w of words(newBody)) {
|
|
79
|
+
const have = counts.get(w) ?? 0;
|
|
80
|
+
if (have > 0)
|
|
81
|
+
counts.set(w, have - 1);
|
|
82
|
+
else
|
|
83
|
+
added++;
|
|
84
|
+
}
|
|
85
|
+
let removed = 0;
|
|
86
|
+
for (const n of counts.values())
|
|
87
|
+
removed += n;
|
|
88
|
+
return { added, removed };
|
|
89
|
+
}
|
|
90
|
+
const SAMPLE_MAX = 160;
|
|
91
|
+
function firstNewSentence(oldBody, newBody) {
|
|
92
|
+
const before = new Set(sentences(oldBody));
|
|
93
|
+
for (const s of sentences(newBody)) {
|
|
94
|
+
if (before.has(s))
|
|
95
|
+
continue;
|
|
96
|
+
return s.length > SAMPLE_MAX ? `${s.slice(0, SAMPLE_MAX - 1)}…` : s;
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const SUMMARY_SECTIONS = 3;
|
|
101
|
+
function renderSummary(diff) {
|
|
102
|
+
const parts = [];
|
|
103
|
+
if (diff.changed.length)
|
|
104
|
+
parts.push(`${diff.changed.length} section(s) changed`);
|
|
105
|
+
if (diff.added.length)
|
|
106
|
+
parts.push(`${diff.added.length} added`);
|
|
107
|
+
if (diff.removed.length)
|
|
108
|
+
parts.push(`${diff.removed.length} removed`);
|
|
109
|
+
if (!parts.length)
|
|
110
|
+
return 'text changed, but no section did — formatting only';
|
|
111
|
+
const detail = [
|
|
112
|
+
...diff.changed
|
|
113
|
+
.slice(0, SUMMARY_SECTIONS)
|
|
114
|
+
.map((c) => `${c.key} (+${c.addedWords}/-${c.removedWords} words)`),
|
|
115
|
+
...diff.added.slice(0, SUMMARY_SECTIONS).map((k) => `+${k}`),
|
|
116
|
+
...diff.removed.slice(0, SUMMARY_SECTIONS).map((k) => `-${k}`),
|
|
117
|
+
];
|
|
118
|
+
return detail.length ? `${parts.join(', ')} — ${detail.join('; ')}` : parts.join(', ');
|
|
119
|
+
}
|
|
120
|
+
/** What changed between two versions of the same page. */
|
|
121
|
+
export function diffSections(oldText, newText) {
|
|
122
|
+
const before = new Map(splitSections(oldText).map((s) => [s.key, s]));
|
|
123
|
+
const after = new Map(splitSections(newText).map((s) => [s.key, s]));
|
|
124
|
+
const added = [];
|
|
125
|
+
const changed = [];
|
|
126
|
+
let unchanged = 0;
|
|
127
|
+
for (const [key, section] of after) {
|
|
128
|
+
const previous = before.get(key);
|
|
129
|
+
if (!previous) {
|
|
130
|
+
added.push(key);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (previous.body.replace(/\s+/g, ' ').trim() === section.body.replace(/\s+/g, ' ').trim()) {
|
|
134
|
+
unchanged++;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const delta = wordDelta(previous.body, section.body);
|
|
138
|
+
changed.push({
|
|
139
|
+
key,
|
|
140
|
+
addedWords: delta.added,
|
|
141
|
+
removedWords: delta.removed,
|
|
142
|
+
...(firstNewSentence(previous.body, section.body)
|
|
143
|
+
? { sample: firstNewSentence(previous.body, section.body) }
|
|
144
|
+
: {}),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
const removed = [...before.keys()].filter((k) => !after.has(k));
|
|
148
|
+
const diff = { added, removed, changed, unchanged };
|
|
149
|
+
return { ...diff, summary: renderSummary(diff) };
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=section-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-diff.js","sourceRoot":"","sources":["../../../src/knowledge/section-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA4BH,MAAM,UAAU,GAAG,4BAA4B,CAAC;AAChD,MAAM,SAAS,GAAG,SAAS,CAAC;AAE5B;mEACmE;AACnE,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,IAAI,OAAO,GAAY,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAClF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxE,CAAC,CAAC;IAEF,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QAC3D,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QACD,KAAK,EAAE,CAAC;QACR,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1B,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5B,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACtC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;QAC3B,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACjB,IAAI,CAAC,GAAG,CAAC;YAAE,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAC9C,CAAC;IACD,KAAK,EAAE,CAAC;IACR,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,KAAK,CAAC,IAAY;IACzB,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,gCAAgC,CAAC,IAAI,EAAE,CAAC;AAC1E,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI;SACR,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,KAAK,CAAC,eAAe,CAAC;SACtB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED;+EAC+E;AAC/E,SAAS,SAAS,CAAC,OAAe,EAAE,OAAe;IACjD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC;QAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,IAAI,GAAG,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;;YACjC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,IAAI,CAAC,CAAC;IAC9C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,SAAS,gBAAgB,CAAC,OAAe,EAAE,OAAe;IACxD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,SAAS;QAC5B,OAAO,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,SAAS,aAAa,CAAC,IAAkC;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,qBAAqB,CAAC,CAAC;IACjF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;IAChE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;IACtE,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,oDAAoD,CAAC;IAC/E,MAAM,MAAM,GAAG;QACb,GAAG,IAAI,CAAC,OAAO;aACZ,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC;aAC1B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,YAAY,SAAS,CAAC;QACrE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5D,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;KAC/D,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzF,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,OAAe;IAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAErE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,KAAK,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3F,SAAS,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC;YACX,GAAG;YACH,UAAU,EAAE,KAAK,CAAC,KAAK;YACvB,YAAY,EAAE,KAAK,CAAC,OAAO;YAC3B,GAAG,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;gBAC/C,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC3D,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;IACL,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhE,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IACpD,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Watch a captured page for change (RCL-08).
|
|
3
|
+
*
|
|
4
|
+
* WHAT THIS IS NOT: a scheduler, a daemon, or a fetcher. `checkWatches` is
|
|
5
|
+
* invoked by something else — mono-agent's scheduler drives it — and it does
|
|
6
|
+
* not touch the network. It re-reads what the pipeline already stored and
|
|
7
|
+
* compares content hashes, which is exactly the versioning RCL-06 put there.
|
|
8
|
+
* A re-capture is what makes a page "change"; this reports it.
|
|
9
|
+
*
|
|
10
|
+
* The watch list is a small JSON file next to the metadata log, keyed by the
|
|
11
|
+
* page's identity URL (or, for a local file, its path). Writes go through a
|
|
12
|
+
* temp file and a rename so a crashed check cannot leave a half-written list.
|
|
13
|
+
*
|
|
14
|
+
* @module v1/cli/knowledge/watch
|
|
15
|
+
*/
|
|
16
|
+
import { type SectionDiff } from './section-diff.js';
|
|
17
|
+
export declare const WATCH_FILE = "watches.json";
|
|
18
|
+
export declare const DEFAULT_INTERVAL_SECONDS = 86400;
|
|
19
|
+
export interface WatchEntry {
|
|
20
|
+
/** Identity: the capture's canonical URL, or an indexed file path. */
|
|
21
|
+
url: string;
|
|
22
|
+
scope: string;
|
|
23
|
+
intervalSeconds: number;
|
|
24
|
+
/** Content hash last seen by a check — the baseline the next one compares to. */
|
|
25
|
+
lastHash?: string;
|
|
26
|
+
lastCheckedAt?: string;
|
|
27
|
+
lastChangedAt?: string;
|
|
28
|
+
addedAt: string;
|
|
29
|
+
label?: string;
|
|
30
|
+
}
|
|
31
|
+
export type WatchStatus = 'changed' | 'unchanged' | 'new' | 'missing' | 'not-due';
|
|
32
|
+
export interface WatchCheck {
|
|
33
|
+
url: string;
|
|
34
|
+
scope: string;
|
|
35
|
+
status: WatchStatus;
|
|
36
|
+
checkedAt: string;
|
|
37
|
+
filePath?: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
previousHash?: string;
|
|
40
|
+
currentHash?: string;
|
|
41
|
+
version?: number;
|
|
42
|
+
capturedAt?: string;
|
|
43
|
+
/** Present on `changed`, unless the previous version's file is gone. */
|
|
44
|
+
diff?: SectionDiff;
|
|
45
|
+
/** Why a change could not be summarized, when it could not. */
|
|
46
|
+
note?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface WatchCheckReport {
|
|
49
|
+
checked: number;
|
|
50
|
+
changed: number;
|
|
51
|
+
skipped: number;
|
|
52
|
+
results: WatchCheck[];
|
|
53
|
+
}
|
|
54
|
+
export declare function listWatches(rootDir: string): WatchEntry[];
|
|
55
|
+
/** `30m`, `6h`, `2d`, or bare seconds. Throws on a typo — a watch that
|
|
56
|
+
* silently defaulted to daily would look like it was working. */
|
|
57
|
+
export declare function parseInterval(value: string | number | undefined): number;
|
|
58
|
+
export interface AddWatchOptions {
|
|
59
|
+
interval?: string | number;
|
|
60
|
+
scope?: string;
|
|
61
|
+
label?: string;
|
|
62
|
+
now?: Date;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Watch `target` (a URL, a docId or an indexed path).
|
|
66
|
+
*
|
|
67
|
+
* The baseline is seeded from what is indexed RIGHT NOW, so the first check
|
|
68
|
+
* after adding reports nothing — a watch exists to catch the NEXT change, not
|
|
69
|
+
* to re-announce the capture that created it. Re-adding an existing watch
|
|
70
|
+
* updates its interval and label and keeps the baseline.
|
|
71
|
+
*/
|
|
72
|
+
export declare function addWatch(rootDir: string, target: string, opts?: AddWatchOptions): Promise<WatchEntry>;
|
|
73
|
+
/** Stop watching. Matches the stored identity URL, a docId, or a path. */
|
|
74
|
+
export declare function removeWatch(rootDir: string, target: string, scope?: string): boolean;
|
|
75
|
+
export interface CheckWatchesOptions {
|
|
76
|
+
scope?: string;
|
|
77
|
+
/** Check every watch regardless of its interval. */
|
|
78
|
+
force?: boolean;
|
|
79
|
+
/** Report without updating the stored baselines. */
|
|
80
|
+
dryRun?: boolean;
|
|
81
|
+
now?: Date;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Which watched pages have changed since the last check.
|
|
85
|
+
*
|
|
86
|
+
* Reads only what is already indexed: a page "changes" when a new capture of
|
|
87
|
+
* it was ingested under a new content hash. Each change carries a section-level
|
|
88
|
+
* summary (`diffSections`) built from the previous version's own archived
|
|
89
|
+
* file, or a note saying why it could not be built.
|
|
90
|
+
*/
|
|
91
|
+
export declare function checkWatches(rootDir: string, opts?: CheckWatchesOptions): Promise<WatchCheckReport>;
|
|
92
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/knowledge/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEnE,eAAO,MAAM,UAAU,iBAAiB,CAAC;AACzC,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;AAElF,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAQD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,EAAE,CAWzD;AAaD;kEACkE;AAClE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAQxE;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,UAAU,CAAC,CA8BrB;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CASpF;AAID,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AA2BD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CA8E3B"}
|