@hraness/wordcell 0.22.4 → 0.23.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/README.md +63 -22
- package/dist/authoring.js +2 -2
- package/dist/{authority-06eqhqam.js → authority-35cbvp1x.js} +2 -2
- package/dist/benchmark.js +3 -3
- package/dist/capture.js +6 -6
- package/dist/cli.js +26 -24
- package/dist/clip/acquire.js +3 -3
- package/dist/clip/args.js +1 -1
- package/dist/clip/cli.js +6 -6
- package/dist/clip/doctor.js +4 -4
- package/dist/evaluation-builder.js +10 -10
- package/dist/evaluation-kb.js +10 -10
- package/dist/graph-authority.js +4 -4
- package/dist/graph-percolation.js +6 -6
- package/dist/graph.js +5 -1
- package/dist/{index-bcknqxrq.js → index-0eacgvpv.js} +9 -1
- package/dist/{index-xv80vzfp.js → index-1er88ckw.js} +4 -4
- package/dist/{index-233z9wmn.js → index-1s8mc4hz.js} +13 -5
- package/dist/{index-de2w8crk.js → index-2fmnttca.js} +82 -15
- package/dist/{index-vnybgywh.js → index-ahyhryb8.js} +1 -1
- package/dist/{index-ecqpgr5y.js → index-b0khj0h5.js} +164 -9
- package/dist/{index-jk1sgx36.js → index-bdwcjvr4.js} +1 -1
- package/dist/{index-dfag79p7.js → index-byz4kzww.js} +3 -0
- package/dist/{index-hgve9rh2.js → index-cd75vky9.js} +96 -1
- package/dist/{index-rr9kzq4n.js → index-fp732bgg.js} +2 -2
- package/dist/{index-qbssx940.js → index-jvb7w0gg.js} +227 -9
- package/dist/{index-f984hw45.js → index-k86wepd8.js} +1 -1
- package/dist/{index-1k595z6v.js → index-mnq2wy34.js} +2 -2
- package/dist/{index-n386evxj.js → index-nn67kzwa.js} +1 -1
- package/dist/{index-fc4dr114.js → index-nwrehke7.js} +1 -1
- package/dist/{index-76dbn6pe.js → index-p70t8j13.js} +1 -1
- package/dist/{index-tf4wzjew.js → index-pgtm2nhf.js} +1 -1
- package/dist/{index-054mb7d3.js → index-qfqjfxaa.js} +10 -9
- package/dist/{index-pnt9wr59.js → index-r0m5taz2.js} +2 -2
- package/dist/{index-bqtqeak3.js → index-r4qs6vq4.js} +4 -4
- package/dist/{index-djrcc1yf.js → index-tcaq1c7f.js} +4 -4
- package/dist/{index-q7tbg07z.js → index-tvd2sqrx.js} +7 -7
- package/dist/{index-9h7zh0wt.js → index-vtwbapjr.js} +3814 -162
- package/dist/{index-g5vsqmdy.js → index-xwxy71ew.js} +190 -4
- package/dist/index.js +22 -14
- package/dist/pdf.js +3 -3
- package/dist/percolate.js +2 -2
- package/dist/portfolio.js +10 -10
- package/dist/publish.js +3 -3
- package/dist/sdk.js +9 -9
- package/dist/search.js +2 -2
- package/dist/semantic.js +4 -4
- package/dist/{support-m3t917ev.js → support-c8hy7qfa.js} +25 -23
- package/dist/url-intelligence.js +1 -1
- package/dist/workflows/decision-context.js +10 -10
- package/dist/workflows/index.js +10 -10
- package/package.json +12 -4
- package/skills/wordcell/AGENTS.md +1 -0
- package/skills/wordcell/SKILL.md +5 -3
- package/skills/wordcell/references/plan-structure.md +1 -1
- package/skills/wordcell/references/query.md +35 -1
- package/skills/wordcell/references/session-memory.md +207 -0
- package/skills/wordcell/references/url-platforms.md +1 -1
- package/src/authoring-import.ts +32 -0
- package/src/authoring-model.ts +185 -2
- package/src/authoring-program.ts +19 -7
- package/src/cli-help.ts +893 -0
- package/src/cli-intro.ts +1 -1
- package/src/cli-program.ts +575 -82
- package/src/cli-style.ts +132 -0
- package/src/clip/acquire.ts +20 -0
- package/src/clip/args.ts +3 -0
- package/src/clip/cli.ts +82 -5
- package/src/clip/cookie-permission.ts +241 -0
- package/src/clip/url-metadata-cli.ts +6 -5
- package/src/clip/url-metadata.ts +14 -0
- package/src/graph.ts +88 -13
- package/src/import-supermemory.ts +1629 -0
- package/src/mcp-server.ts +415 -0
- package/src/mcp-tools.ts +1122 -0
- package/src/mention-index.ts +194 -0
- package/src/pdf/cli.ts +5 -4
- package/src/support-profile.ts +1 -1
- package/src/support.ts +3 -0
- package/src/vault.ts +26 -2
package/src/graph.ts
CHANGED
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
type Node,
|
|
10
10
|
} from "yaml";
|
|
11
11
|
import { parseQualifiedDocumentUri, type QualifiedDocumentUri } from "./portfolio-identity.js";
|
|
12
|
+
import { cleanMentionBoundary, MentionIndexBudgetError, MentionMatcher, preflightMentionInput, type MentionIndexBudgetKind, type MentionIndexLimits } from "./mention-index.js";
|
|
13
|
+
export type { MentionIndexLimits } from "./mention-index.js";
|
|
12
14
|
|
|
13
15
|
export const catalogStart = "<!-- kb:catalog:start -->";
|
|
14
16
|
export const catalogEnd = "<!-- kb:catalog:end -->";
|
|
@@ -22,7 +24,8 @@ export type VaultAnalysisBudgetKind =
|
|
|
22
24
|
| "notes"
|
|
23
25
|
| "connection-observations"
|
|
24
26
|
| "mention-pairs"
|
|
25
|
-
| "mentions"
|
|
27
|
+
| "mentions"
|
|
28
|
+
| MentionIndexBudgetKind;
|
|
26
29
|
|
|
27
30
|
/** A stable failure for callers that need to distinguish bounded graph work. */
|
|
28
31
|
export class VaultAnalysisBudgetError extends RangeError {
|
|
@@ -214,6 +217,11 @@ export type AnalyzeVaultOptions = {
|
|
|
214
217
|
catalogNoteId?: string;
|
|
215
218
|
};
|
|
216
219
|
|
|
220
|
+
/** Complete discovery indexes phrases instead of enumerating every note pair. */
|
|
221
|
+
export type CompleteAnalyzeVaultOptions = AnalyzeVaultOptions & {
|
|
222
|
+
readonly mentionIndexLimits?: MentionIndexLimits;
|
|
223
|
+
};
|
|
224
|
+
|
|
217
225
|
export type VaultAnalysis = {
|
|
218
226
|
noteCount: number;
|
|
219
227
|
contextualLinks: readonly ResolvedLink[];
|
|
@@ -240,6 +248,14 @@ type MetadataParseResult =
|
|
|
240
248
|
| { readonly ok: true; readonly value: MetadataValue }
|
|
241
249
|
| { readonly ok: false };
|
|
242
250
|
|
|
251
|
+
/**
|
|
252
|
+
* The vault's number rule for frontmatter values: finite, and a safe integer
|
|
253
|
+
* when integral. Writers share it so every note they write reads back.
|
|
254
|
+
*/
|
|
255
|
+
export function isMetadataNumber(value: number): boolean {
|
|
256
|
+
return Number.isFinite(value) && (!Number.isInteger(value) || Number.isSafeInteger(value));
|
|
257
|
+
}
|
|
258
|
+
|
|
243
259
|
function parsedMetadataValue(
|
|
244
260
|
value: unknown,
|
|
245
261
|
ancestors: WeakSet<object>,
|
|
@@ -248,10 +264,7 @@ function parsedMetadataValue(
|
|
|
248
264
|
return { ok: true, value };
|
|
249
265
|
}
|
|
250
266
|
if (typeof value === "number") {
|
|
251
|
-
return
|
|
252
|
-
&& (!Number.isInteger(value) || Number.isSafeInteger(value))
|
|
253
|
-
? { ok: true, value }
|
|
254
|
-
: { ok: false };
|
|
267
|
+
return isMetadataNumber(value) ? { ok: true, value } : { ok: false };
|
|
255
268
|
}
|
|
256
269
|
if (typeof value !== "object" || ancestors.has(value)) return { ok: false };
|
|
257
270
|
|
|
@@ -1015,17 +1028,10 @@ function compareRelationIssues(left: RelationIssue, right: RelationIssue): numbe
|
|
|
1015
1028
|
|| targetComparison;
|
|
1016
1029
|
}
|
|
1017
1030
|
|
|
1018
|
-
const wordCharacter = (value: string): boolean => /[A-Za-z0-9]/.test(value);
|
|
1019
|
-
|
|
1020
1031
|
function phraseOffset(lowerHaystack: string, lowerPhrase: string): number {
|
|
1021
1032
|
let offset = lowerHaystack.indexOf(lowerPhrase);
|
|
1022
1033
|
while (offset !== -1) {
|
|
1023
|
-
|
|
1024
|
-
const afterIndex = offset + lowerPhrase.length;
|
|
1025
|
-
const after = afterIndex >= lowerHaystack.length ? "" : lowerHaystack[afterIndex] ?? "";
|
|
1026
|
-
const startsClean = !wordCharacter(lowerPhrase[0] ?? "") || !wordCharacter(before);
|
|
1027
|
-
const endsClean = !wordCharacter(lowerPhrase.at(-1) ?? "") || !wordCharacter(after);
|
|
1028
|
-
if (startsClean && endsClean) return offset;
|
|
1034
|
+
if (cleanMentionBoundary(lowerHaystack, lowerPhrase, offset)) return offset;
|
|
1029
1035
|
offset = lowerHaystack.indexOf(lowerPhrase, offset + 1);
|
|
1030
1036
|
}
|
|
1031
1037
|
return -1;
|
|
@@ -1093,6 +1099,33 @@ function checkedAnalysisLimit(
|
|
|
1093
1099
|
export function analyzeVault(
|
|
1094
1100
|
notes: readonly Note[],
|
|
1095
1101
|
options: AnalyzeVaultOptions = {},
|
|
1102
|
+
): VaultAnalysis {
|
|
1103
|
+
return analyzeVaultInternal(notes, options);
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Return the same complete graph using a finite phrase index. maxMentionPairs
|
|
1108
|
+
* counts matching source/target candidates; index work and repeated matches
|
|
1109
|
+
* have separate aggregate limits. Exhaustion always throws, never truncates.
|
|
1110
|
+
*/
|
|
1111
|
+
export function analyzeVaultComplete(
|
|
1112
|
+
notes: readonly Note[],
|
|
1113
|
+
options: CompleteAnalyzeVaultOptions = {},
|
|
1114
|
+
): VaultAnalysis {
|
|
1115
|
+
try {
|
|
1116
|
+
return analyzeVaultInternal(notes, options, options.mentionIndexLimits ?? {});
|
|
1117
|
+
} catch (error: unknown) {
|
|
1118
|
+
if (error instanceof MentionIndexBudgetError) {
|
|
1119
|
+
throw new VaultAnalysisBudgetError(error.kind, error.limit, error.message);
|
|
1120
|
+
}
|
|
1121
|
+
throw error;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
function analyzeVaultInternal(
|
|
1126
|
+
notes: readonly Note[],
|
|
1127
|
+
options: AnalyzeVaultOptions,
|
|
1128
|
+
mentionIndexLimits?: MentionIndexLimits,
|
|
1096
1129
|
): VaultAnalysis {
|
|
1097
1130
|
const maxNotes = checkedAnalysisLimit(
|
|
1098
1131
|
options.maxNotes,
|
|
@@ -1121,6 +1154,13 @@ export function analyzeVault(
|
|
|
1121
1154
|
`Vault analysis exceeds the ${maxNotes} note limit.`,
|
|
1122
1155
|
);
|
|
1123
1156
|
}
|
|
1157
|
+
const mentionInput = mentionIndexLimits === undefined ? undefined : preflightMentionInput((function* () {
|
|
1158
|
+
for (const note of notes) {
|
|
1159
|
+
yield note.searchableText;
|
|
1160
|
+
yield note.title;
|
|
1161
|
+
yield* note.aliases;
|
|
1162
|
+
}
|
|
1163
|
+
})(), mentionIndexLimits);
|
|
1124
1164
|
const catalogNoteId = withoutMarkdownExtension(
|
|
1125
1165
|
normalizeVaultPath(options.catalogNoteId ?? "index"),
|
|
1126
1166
|
);
|
|
@@ -1332,7 +1372,42 @@ export function analyzeVault(
|
|
|
1332
1372
|
: uniquePhrasesByTarget(suggestionNotes);
|
|
1333
1373
|
const mentions: MentionCandidate[] = [];
|
|
1334
1374
|
let mentionPairs = 0;
|
|
1375
|
+
const matcher = mentionIndexLimits === undefined ? undefined : new MentionMatcher(
|
|
1376
|
+
[...phrasesByTarget].flatMap(([targetId, phrases]) => phrases.map((phrase, rank) => ({ ...phrase, targetId, rank }))),
|
|
1377
|
+
mentionIndexLimits,
|
|
1378
|
+
mentionInput!.rawInputCodeUnits,
|
|
1379
|
+
mentionInput!.work,
|
|
1380
|
+
);
|
|
1381
|
+
const targetsById = new Map<string, { readonly note: Note; readonly order: number }[]>();
|
|
1382
|
+
if (matcher !== undefined) suggestionNotes.forEach((note, order) => {
|
|
1383
|
+
const targets = targetsById.get(note.id) ?? [];
|
|
1384
|
+
targets.push({ note, order });
|
|
1385
|
+
targetsById.set(note.id, targets);
|
|
1386
|
+
});
|
|
1335
1387
|
for (const source of suggestionNotes) {
|
|
1388
|
+
if (matcher !== undefined) {
|
|
1389
|
+
if (scopedMentionNotes.length === 0) continue;
|
|
1390
|
+
const found = matcher.scan(source.searchableText.toLocaleLowerCase("en-US"));
|
|
1391
|
+
const targets = [...found].flatMap(([id, match]) => (targetsById.get(id) ?? []).map((target) => ({ ...target, match })))
|
|
1392
|
+
.filter(({ note }) => source.id !== note.id && (options.mentionScope === undefined
|
|
1393
|
+
|| scopedMentionIds.has(source.id) || scopedMentionIds.has(note.id)))
|
|
1394
|
+
.sort((left, right) => left.order - right.order);
|
|
1395
|
+
let newlineOffsets: readonly number[] | undefined;
|
|
1396
|
+
for (const { note: target, match } of targets) {
|
|
1397
|
+
if (mentionPairs >= maxMentionPairs) throw new VaultAnalysisBudgetError(
|
|
1398
|
+
"mention-pairs", maxMentionPairs, `Vault analysis exceeds the ${maxMentionPairs} mention-pair limit.`,
|
|
1399
|
+
);
|
|
1400
|
+
mentionPairs += 1;
|
|
1401
|
+
if (linkedPairs.has(pairKey(source.id, target.id))) continue;
|
|
1402
|
+
if (mentions.length >= maxMentions) throw new VaultAnalysisBudgetError(
|
|
1403
|
+
"mentions", maxMentions, `Vault analysis exceeds the ${maxMentions} mention limit.`,
|
|
1404
|
+
);
|
|
1405
|
+
newlineOffsets ??= matcher.newlineOffsets(source.searchableText);
|
|
1406
|
+
mentions.push({ source: source.path, target: target.path, phrase: match.pattern.phrase,
|
|
1407
|
+
line: matcher.lineAt(newlineOffsets, match.offset) });
|
|
1408
|
+
}
|
|
1409
|
+
continue;
|
|
1410
|
+
}
|
|
1336
1411
|
const targets = options.mentionScope === undefined
|
|
1337
1412
|
|| scopedMentionIds.has(source.id)
|
|
1338
1413
|
? suggestionNotes
|