@hraness/wordcell 0.22.5 → 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 +56 -18
- package/dist/authoring.js +2 -2
- package/dist/{authority-3ga47syb.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 +3 -1
- package/dist/{index-bcknqxrq.js → index-0eacgvpv.js} +9 -1
- package/dist/{index-f75zmmdr.js → index-1er88ckw.js} +4 -4
- package/dist/{index-8v6k9h4r.js → index-1s8mc4hz.js} +1 -1
- package/dist/{index-de2w8crk.js → index-2fmnttca.js} +82 -15
- package/dist/{index-aer0jdrq.js → index-ahyhryb8.js} +1 -1
- package/dist/{index-f7fnww7a.js → index-b0khj0h5.js} +164 -9
- package/dist/{index-qdb8f8va.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-n57tewfr.js → index-fp732bgg.js} +2 -2
- package/dist/{index-zy7an84p.js → index-jvb7w0gg.js} +5 -2
- package/dist/{index-f984hw45.js → index-k86wepd8.js} +1 -1
- package/dist/{index-1r5rnkfr.js → index-mnq2wy34.js} +2 -2
- package/dist/{index-p96kb6t2.js → index-nn67kzwa.js} +1 -1
- package/dist/{index-fc4dr114.js → index-nwrehke7.js} +1 -1
- package/dist/{index-n9kwenpt.js → index-p70t8j13.js} +1 -1
- package/dist/{index-pz2b2x0y.js → index-pgtm2nhf.js} +1 -1
- package/dist/{index-054mb7d3.js → index-qfqjfxaa.js} +10 -9
- package/dist/{index-xzvcw9ga.js → index-r0m5taz2.js} +2 -2
- package/dist/{index-h2qn3y3f.js → index-r4qs6vq4.js} +4 -4
- package/dist/{index-gtwqye5a.js → index-tcaq1c7f.js} +4 -4
- package/dist/{index-42tb8qqp.js → index-tvd2sqrx.js} +7 -7
- package/dist/{index-8bgnhjgq.js → index-vtwbapjr.js} +3810 -159
- package/dist/{index-g5vsqmdy.js → index-xwxy71ew.js} +190 -4
- package/dist/index.js +15 -13
- 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-jf9v10j7.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 +11 -4
- package/skills/wordcell/AGENTS.md +1 -0
- package/skills/wordcell/SKILL.md +5 -3
- package/skills/wordcell/references/query.md +35 -1
- package/skills/wordcell/references/session-memory.md +207 -0
- 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 +571 -80
- 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 +9 -4
- package/src/import-supermemory.ts +1629 -0
- package/src/mcp-server.ts +415 -0
- package/src/mcp-tools.ts +1122 -0
- package/src/pdf/cli.ts +5 -4
- package/src/support-profile.ts +1 -1
- package/src/support.ts +3 -0
|
@@ -12,35 +12,46 @@ import {
|
|
|
12
12
|
localizeAssets,
|
|
13
13
|
scoreExtraction,
|
|
14
14
|
sniffImage
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-k86wepd8.js";
|
|
16
16
|
import {
|
|
17
17
|
adapterCapabilities,
|
|
18
18
|
inspectClipEnvironment,
|
|
19
19
|
renderAdapterCapabilities,
|
|
20
20
|
renderDoctorReport
|
|
21
|
-
} from "./index-
|
|
21
|
+
} from "./index-nwrehke7.js";
|
|
22
22
|
import {
|
|
23
23
|
cloneBrowserProfile
|
|
24
24
|
} from "./index-5n05se68.js";
|
|
25
25
|
import {
|
|
26
|
+
CONFIRM_LINE,
|
|
26
27
|
acquireBrowser,
|
|
27
28
|
acquireCookieHttp,
|
|
28
29
|
acquireCookieRecords,
|
|
29
30
|
acquireFile,
|
|
30
31
|
acquireHttp,
|
|
31
|
-
assertSafePersistentProfile
|
|
32
|
-
|
|
32
|
+
assertSafePersistentProfile,
|
|
33
|
+
cookiePermissionRecovery,
|
|
34
|
+
renderCookiePermissionNotice,
|
|
35
|
+
renderCookiePermissionRecovery,
|
|
36
|
+
setCookiePermissionReporter
|
|
37
|
+
} from "./index-xwxy71ew.js";
|
|
33
38
|
import {
|
|
34
39
|
CONTENT_REWRITE_TRUNCATION_WARNING,
|
|
35
40
|
buildClipMarkdown,
|
|
36
41
|
classifyPlatformUrl,
|
|
42
|
+
detectAudience,
|
|
37
43
|
parseBlueskyCapture,
|
|
38
44
|
parseHackerNewsCapture,
|
|
39
45
|
parseRedditCapture,
|
|
40
46
|
renderCapturedDocument,
|
|
47
|
+
renderFailure,
|
|
41
48
|
rewriteContentWithStatus,
|
|
42
|
-
|
|
43
|
-
|
|
49
|
+
sentence,
|
|
50
|
+
slugify,
|
|
51
|
+
stderrStyle,
|
|
52
|
+
terminalOutput,
|
|
53
|
+
writesToTerminal
|
|
54
|
+
} from "./index-cd75vky9.js";
|
|
44
55
|
import {
|
|
45
56
|
MAX_COOKIE_BYTES,
|
|
46
57
|
filterCookieProviderResult,
|
|
@@ -61,7 +72,7 @@ import {
|
|
|
61
72
|
captureUrl,
|
|
62
73
|
parseArguments,
|
|
63
74
|
usage
|
|
64
|
-
} from "./index-
|
|
75
|
+
} from "./index-byz4kzww.js";
|
|
65
76
|
import {
|
|
66
77
|
BoundedByteBuffer
|
|
67
78
|
} from "./index-gh719d91.js";
|
|
@@ -2359,10 +2370,10 @@ async function runCapture(rawOptions, dependencies = {}) {
|
|
|
2359
2370
|
}
|
|
2360
2371
|
|
|
2361
2372
|
// src/clip/cli.ts
|
|
2362
|
-
var defaultOutput = {
|
|
2373
|
+
var defaultOutput = terminalOutput({
|
|
2363
2374
|
stdout: (value) => process.stdout.write(value),
|
|
2364
2375
|
stderr: (value) => process.stderr.write(value)
|
|
2365
|
-
};
|
|
2376
|
+
});
|
|
2366
2377
|
function line(value) {
|
|
2367
2378
|
return value.endsWith(`
|
|
2368
2379
|
`) ? value : `${value}
|
|
@@ -2378,6 +2389,27 @@ function terminalSafeJson(value) {
|
|
|
2378
2389
|
return `${JSON.stringify(value, (_key, candidate) => typeof candidate === "string" ? sanitizeTerminalText(candidate) : candidate, 2)}
|
|
2379
2390
|
`;
|
|
2380
2391
|
}
|
|
2392
|
+
var CONFIRM_TIMEOUT_MS = 120000;
|
|
2393
|
+
async function confirmFromTerminal() {
|
|
2394
|
+
const reader = Bun.stdin.stream().getReader();
|
|
2395
|
+
let timer;
|
|
2396
|
+
try {
|
|
2397
|
+
const timeout = new Promise((resolve2) => {
|
|
2398
|
+
timer = setTimeout(() => resolve2("skip"), CONFIRM_TIMEOUT_MS);
|
|
2399
|
+
});
|
|
2400
|
+
const answer = reader.read().then(({ value }) => {
|
|
2401
|
+
const text = value === undefined ? "" : new TextDecoder().decode(value).trim().toLowerCase();
|
|
2402
|
+
return text === "s" || text === "skip" ? "skip" : "continue";
|
|
2403
|
+
});
|
|
2404
|
+
return await Promise.race([answer, timeout]);
|
|
2405
|
+
} finally {
|
|
2406
|
+
if (timer !== undefined)
|
|
2407
|
+
clearTimeout(timer);
|
|
2408
|
+
await reader.cancel().catch(() => {
|
|
2409
|
+
return;
|
|
2410
|
+
});
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2381
2413
|
function captureSummary(outcome) {
|
|
2382
2414
|
return {
|
|
2383
2415
|
ok: captureSucceeded(outcome),
|
|
@@ -2415,9 +2447,9 @@ async function diagnosticCommand(arguments_, output, inspectEnvironment) {
|
|
|
2415
2447
|
async function main(rawArguments = process.argv.slice(2), environment = process.env, output = defaultOutput, dependencies = {}, runtimeOptions = {}) {
|
|
2416
2448
|
const parsed = parseArguments(rawArguments, environment);
|
|
2417
2449
|
if (!parsed.ok) {
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2450
|
+
const first = rawArguments[0];
|
|
2451
|
+
const next = first === "doctor" || first === "adapters" || first === "inspect" ? `wordcell ${first} --help` : "wordcell clip --help";
|
|
2452
|
+
output.stderr(renderFailure(sentence(safe(parsed.message)), next, stderrStyle(environment, output)));
|
|
2421
2453
|
return 2;
|
|
2422
2454
|
}
|
|
2423
2455
|
const arguments_ = parsed.value;
|
|
@@ -2432,6 +2464,24 @@ ${sanitizeTerminalText(usage)}`);
|
|
|
2432
2464
|
output.stdout(arguments_.json ? terminalSafeJson({ schemaVersion: 1, adapters: adapterCapabilities }) : sanitizeTerminalText(renderAdapterCapabilities()));
|
|
2433
2465
|
return 0;
|
|
2434
2466
|
}
|
|
2467
|
+
const onTerminal = dependencies.stderrIsTerminal ?? writesToTerminal(output);
|
|
2468
|
+
const human = !arguments_.json && detectAudience(environment, onTerminal) === "human";
|
|
2469
|
+
let permissionFailure;
|
|
2470
|
+
setCookiePermissionReporter({
|
|
2471
|
+
notice: async (need) => {
|
|
2472
|
+
if (!human || arguments_.quiet)
|
|
2473
|
+
return "continue";
|
|
2474
|
+
output.stderr(renderCookiePermissionNotice(need, environment, stderrStyle(environment, output)));
|
|
2475
|
+
const confirm = dependencies.confirmPermission ?? (onTerminal && process.stdin.isTTY === true ? confirmFromTerminal : undefined);
|
|
2476
|
+
if (confirm === undefined)
|
|
2477
|
+
return "continue";
|
|
2478
|
+
output.stderr(CONFIRM_LINE);
|
|
2479
|
+
return await confirm();
|
|
2480
|
+
},
|
|
2481
|
+
failure: (failure) => {
|
|
2482
|
+
permissionFailure ??= failure;
|
|
2483
|
+
}
|
|
2484
|
+
});
|
|
2435
2485
|
if (!arguments_.quiet && !arguments_.json) {
|
|
2436
2486
|
const target = arguments_.currentTab ? "the current browser tab" : safe(arguments_.url?.href ?? "current");
|
|
2437
2487
|
output.stderr(`Capturing ${target} (${arguments_.mode}, ${arguments_.scope}) ...
|
|
@@ -2466,13 +2516,30 @@ ${sanitizeTerminalText(usage)}`);
|
|
|
2466
2516
|
}
|
|
2467
2517
|
return captureExitCode(outcome);
|
|
2468
2518
|
} catch (error) {
|
|
2469
|
-
const
|
|
2519
|
+
const raw = error instanceof Error ? error.message : String(error);
|
|
2520
|
+
const recovery = permissionFailure === undefined ? undefined : cookiePermissionRecovery(permissionFailure, environment);
|
|
2521
|
+
if (recovery !== undefined && raw.includes(recovery.message)) {
|
|
2522
|
+
if (arguments_.json) {
|
|
2523
|
+
output.stdout(terminalSafeJson({
|
|
2524
|
+
ok: false,
|
|
2525
|
+
error: recovery.message,
|
|
2526
|
+
code: recovery.code,
|
|
2527
|
+
next: recovery.next,
|
|
2528
|
+
permission: recovery.permission
|
|
2529
|
+
}));
|
|
2530
|
+
} else {
|
|
2531
|
+
output.stderr(renderCookiePermissionRecovery(recovery, stderrStyle(environment, output)));
|
|
2532
|
+
}
|
|
2533
|
+
return 1;
|
|
2534
|
+
}
|
|
2535
|
+
const message = safe(raw);
|
|
2470
2536
|
if (arguments_.json)
|
|
2471
2537
|
output.stdout(terminalSafeJson({ ok: false, error: message }));
|
|
2472
2538
|
else
|
|
2473
|
-
output.stderr(
|
|
2474
|
-
`);
|
|
2539
|
+
output.stderr(renderFailure(message, "wordcell doctor", stderrStyle(environment, output)));
|
|
2475
2540
|
return 1;
|
|
2541
|
+
} finally {
|
|
2542
|
+
setCookiePermissionReporter(undefined);
|
|
2476
2543
|
}
|
|
2477
2544
|
}
|
|
2478
2545
|
if (import.meta.main)
|
|
@@ -5,9 +5,10 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
isCanonicalNoteId,
|
|
7
7
|
isCanonicalRelationPredicate,
|
|
8
|
+
isMetadataNumber,
|
|
8
9
|
parseDocumentId,
|
|
9
10
|
parseQualifiedDocumentUri
|
|
10
|
-
} from "./index-
|
|
11
|
+
} from "./index-jvb7w0gg.js";
|
|
11
12
|
|
|
12
13
|
// src/authoring-model.ts
|
|
13
14
|
import { createHash } from "crypto";
|
|
@@ -462,13 +463,159 @@ function renderUpdatedNoteBody(snapshot, parts, body) {
|
|
|
462
463
|
const header = snapshot.content.slice(0, snapshot.content.length - parts.bodySuffix.length);
|
|
463
464
|
return `${header}${parts.newline}${parts.newline}${normalized}`;
|
|
464
465
|
}
|
|
465
|
-
|
|
466
|
+
var MAX_FRONTMATTER_FIELDS = 64;
|
|
467
|
+
var MAX_FRONTMATTER_LIST_ITEMS = 256;
|
|
468
|
+
var FRONTMATTER_FIELD_KEY = /^[a-z][a-z0-9_]{0,63}$/u;
|
|
469
|
+
var FRONTMATTER_MAP_KEY = /^[A-Za-z0-9_.:-]{1,64}$/u;
|
|
470
|
+
var RESERVED_FRONTMATTER_FIELDS = new Set([
|
|
471
|
+
"document_id",
|
|
472
|
+
"type",
|
|
473
|
+
"title",
|
|
474
|
+
"tags",
|
|
475
|
+
"relations"
|
|
476
|
+
]);
|
|
477
|
+
function validateFieldString(value, label) {
|
|
478
|
+
if (typeof value !== "string")
|
|
479
|
+
throw new TypeError(`frontmatter field ${label} must be a string`);
|
|
480
|
+
if (Buffer.from(value, "utf8").toString("utf8") !== value || /[\u0000-\u001f\u007f]/u.test(value)) {
|
|
481
|
+
throw new TypeError(`frontmatter field ${label} must be a single line of well-formed text`);
|
|
482
|
+
}
|
|
483
|
+
return value;
|
|
484
|
+
}
|
|
485
|
+
function validateFieldScalar(value, label) {
|
|
486
|
+
if (typeof value === "boolean")
|
|
487
|
+
return value;
|
|
488
|
+
if (typeof value === "number") {
|
|
489
|
+
if (!isMetadataNumber(value)) {
|
|
490
|
+
throw new TypeError(`frontmatter field ${label} must be a finite number and a safe integer when integral`);
|
|
491
|
+
}
|
|
492
|
+
return value;
|
|
493
|
+
}
|
|
494
|
+
return validateFieldString(value, label);
|
|
495
|
+
}
|
|
496
|
+
function validateFieldValue(value, key) {
|
|
497
|
+
if (Array.isArray(value)) {
|
|
498
|
+
if (value.length > MAX_FRONTMATTER_LIST_ITEMS) {
|
|
499
|
+
throw new TypeError(`frontmatter field ${key} has too many items`);
|
|
500
|
+
}
|
|
501
|
+
return value.map((item, index) => validateFieldString(item, `${key}[${index}]`));
|
|
502
|
+
}
|
|
503
|
+
if (typeof value === "object" && value !== null) {
|
|
504
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
505
|
+
throw new TypeError(`frontmatter field ${key} must be a plain map`);
|
|
506
|
+
}
|
|
507
|
+
const entries = Object.entries(value);
|
|
508
|
+
if (entries.length > MAX_FRONTMATTER_FIELDS) {
|
|
509
|
+
throw new TypeError(`frontmatter field ${key} has too many keys`);
|
|
510
|
+
}
|
|
511
|
+
const result = {};
|
|
512
|
+
for (const [nested, item] of entries) {
|
|
513
|
+
if (!FRONTMATTER_MAP_KEY.test(nested) || nested === "__proto__") {
|
|
514
|
+
throw new TypeError(`frontmatter field ${key} has an invalid key: ${JSON.stringify(nested)}`);
|
|
515
|
+
}
|
|
516
|
+
result[nested] = validateFieldScalar(item, `${key}.${nested}`);
|
|
517
|
+
}
|
|
518
|
+
return result;
|
|
519
|
+
}
|
|
520
|
+
return validateFieldScalar(value, key);
|
|
521
|
+
}
|
|
522
|
+
function validateFieldKey(key, allowTitle) {
|
|
523
|
+
if (!FRONTMATTER_FIELD_KEY.test(key)) {
|
|
524
|
+
throw new TypeError(`not a valid frontmatter field name: ${JSON.stringify(key)}`);
|
|
525
|
+
}
|
|
526
|
+
if (RESERVED_FRONTMATTER_FIELDS.has(key) && !(allowTitle && key === "title")) {
|
|
527
|
+
throw new TypeError(`frontmatter field ${key} is reserved`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
function validateFrontmatterFields(fields) {
|
|
531
|
+
if (fields === undefined)
|
|
532
|
+
return {};
|
|
533
|
+
const entries = Object.entries(fields);
|
|
534
|
+
if (entries.length > MAX_FRONTMATTER_FIELDS)
|
|
535
|
+
throw new TypeError("too many frontmatter fields");
|
|
536
|
+
const result = {};
|
|
537
|
+
for (const [key, value] of entries) {
|
|
538
|
+
validateFieldKey(key, false);
|
|
539
|
+
result[key] = validateFieldValue(value, key);
|
|
540
|
+
}
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
function validateFrontmatterFieldUpdates(fields) {
|
|
544
|
+
if (fields === undefined)
|
|
545
|
+
return {};
|
|
546
|
+
const entries = Object.entries(fields);
|
|
547
|
+
if (entries.length > MAX_FRONTMATTER_FIELDS)
|
|
548
|
+
throw new TypeError("too many frontmatter fields");
|
|
549
|
+
const result = {};
|
|
550
|
+
for (const [key, value] of entries) {
|
|
551
|
+
validateFieldKey(key, true);
|
|
552
|
+
if (key === "title") {
|
|
553
|
+
if (typeof value !== "string")
|
|
554
|
+
throw new TypeError("frontmatter field title must be a string");
|
|
555
|
+
result[key] = validateTitle(value);
|
|
556
|
+
} else {
|
|
557
|
+
result[key] = value === null ? null : validateFieldValue(value, key);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return result;
|
|
561
|
+
}
|
|
562
|
+
function canonicalJson(value) {
|
|
563
|
+
if (Array.isArray(value))
|
|
564
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
565
|
+
if (typeof value === "object" && value !== null) {
|
|
566
|
+
const keys = Object.keys(value).sort();
|
|
567
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
|
|
568
|
+
}
|
|
569
|
+
return JSON.stringify(value) ?? "undefined";
|
|
570
|
+
}
|
|
571
|
+
function topLevelValue(parts, key) {
|
|
572
|
+
const contents = parts.document.contents;
|
|
573
|
+
if (!isMap(contents) || !contents.has(key))
|
|
574
|
+
return;
|
|
575
|
+
const node = contents.get(key, true);
|
|
576
|
+
if (typeof node === "object" && node !== null && "toJSON" in node && typeof node.toJSON === "function") {
|
|
577
|
+
return node.toJSON();
|
|
578
|
+
}
|
|
579
|
+
return node;
|
|
580
|
+
}
|
|
581
|
+
function sameFrontmatterValue(present, requested) {
|
|
582
|
+
return canonicalJson(present) === canonicalJson(requested);
|
|
583
|
+
}
|
|
584
|
+
function renderUpdatedNoteBodyAndFields(snapshot, parts, body, fields) {
|
|
585
|
+
const updates = validateFrontmatterFieldUpdates(fields);
|
|
586
|
+
const bodyOnly = renderUpdatedNoteBody(snapshot, parts, body);
|
|
587
|
+
if (Object.keys(updates).length === 0)
|
|
588
|
+
return bodyOnly;
|
|
589
|
+
if (!parts.hadFrontmatter || !isMap(parts.document.contents)) {
|
|
590
|
+
throw new TypeError("frontmatter fields require a note with a frontmatter map");
|
|
591
|
+
}
|
|
592
|
+
const contents = parts.document.contents;
|
|
593
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
594
|
+
if (value === null) {
|
|
595
|
+
contents.delete(key);
|
|
596
|
+
} else if (!sameFrontmatterValue(topLevelValue(parts, key), value)) {
|
|
597
|
+
contents.set(key, parts.document.createNode(value));
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
const content = renderFrontmatter({
|
|
601
|
+
...parts,
|
|
602
|
+
bodySuffix: `${parts.newline}${parts.newline}${normalizedRequestedBody(body)}`
|
|
603
|
+
});
|
|
604
|
+
if (Buffer.byteLength(content, "utf8") > MAX_NOTE_BYTES) {
|
|
605
|
+
throw new RangeError("the note is too large for bounded authoring");
|
|
606
|
+
}
|
|
607
|
+
return content;
|
|
608
|
+
}
|
|
609
|
+
function renderCreatedNote(input, documentId, fields) {
|
|
466
610
|
const title = validateTitle(input.title);
|
|
467
611
|
const type = validateType(input.type);
|
|
468
612
|
const tags = validateTags(input.tags);
|
|
613
|
+
const extra = validateFrontmatterFields(fields);
|
|
469
614
|
const metadata = { document_id: documentId, type, title };
|
|
470
615
|
if (tags.length > 0)
|
|
471
616
|
metadata["tags"] = tags;
|
|
617
|
+
for (const [key, value] of Object.entries(extra))
|
|
618
|
+
metadata[key] = value;
|
|
472
619
|
const document = new Document(metadata, { schema: "core" });
|
|
473
620
|
const body = normalizedRequestedBody(input.body ?? `# ${title}
|
|
474
621
|
`);
|
|
@@ -517,8 +664,9 @@ function existingDocumentId(parts) {
|
|
|
517
664
|
return { kind: "invalid" };
|
|
518
665
|
}
|
|
519
666
|
}
|
|
520
|
-
function assertCompatibleCreate(snapshot, input, requestedDocumentId) {
|
|
667
|
+
function assertCompatibleCreate(snapshot, input, requestedDocumentId, fields) {
|
|
521
668
|
const parts = frontmatter(snapshot.content, snapshot.relativePath);
|
|
669
|
+
const requestedFields = validateFrontmatterFields(fields);
|
|
522
670
|
const requestedType = validateType(input.type);
|
|
523
671
|
const requestedTitle = validateTitle(input.title);
|
|
524
672
|
if (topLevelScalar(parts, "type") !== requestedType) {
|
|
@@ -535,6 +683,11 @@ function assertCompatibleCreate(snapshot, input, requestedDocumentId) {
|
|
|
535
683
|
if (input.body !== undefined && parts.bodySuffix !== `${parts.newline}${parts.newline}${normalizedRequestedBody(input.body)}`) {
|
|
536
684
|
throw new NoteAlreadyExistsError(snapshot.relativePath, "body differs");
|
|
537
685
|
}
|
|
686
|
+
for (const [key, value] of Object.entries(requestedFields)) {
|
|
687
|
+
if (!sameFrontmatterValue(topLevelValue(parts, key), value)) {
|
|
688
|
+
throw new NoteAlreadyExistsError(snapshot.relativePath, `${key} differs`);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
538
691
|
const existingId = existingDocumentId(parts);
|
|
539
692
|
if (requestedDocumentId !== undefined && (existingId.kind !== "valid" || existingId.documentId !== requestedDocumentId)) {
|
|
540
693
|
throw new NoteAlreadyExistsError(snapshot.relativePath, existingId.kind === "missing" ? "document_id is missing" : "document_id differs");
|
|
@@ -1125,10 +1278,11 @@ function installNote(platform, vault, id, content, expected, lock, dependencies)
|
|
|
1125
1278
|
}));
|
|
1126
1279
|
});
|
|
1127
1280
|
}
|
|
1128
|
-
function createNoteProgram(platform, root, input, options) {
|
|
1281
|
+
function createNoteProgram(platform, root, input, options, fields) {
|
|
1129
1282
|
return Effect2.gen(function* () {
|
|
1130
1283
|
const vault = yield* authoringNative(() => platform.resolveVault(root));
|
|
1131
1284
|
const id = yield* authoringSync(() => canonicalNoteId(input.id));
|
|
1285
|
+
const extra = yield* authoringSync(() => validateFrontmatterFields(fields));
|
|
1132
1286
|
const requestedDocumentId = yield* authoringSync(() => input.documentId === undefined ? undefined : parseDocumentId(input.documentId));
|
|
1133
1287
|
const expected = yield* authoringSync(() => checkedExpectedRevision(options));
|
|
1134
1288
|
const dependencies = yield* authoringSync(() => platform.dependenciesFor(options.dependencies));
|
|
@@ -1137,13 +1291,13 @@ function createNoteProgram(platform, root, input, options) {
|
|
|
1137
1291
|
const existing = yield* authoringNative(() => platform.readOptionalSnapshot(vault, id));
|
|
1138
1292
|
if (existing !== null) {
|
|
1139
1293
|
yield* authoringSync(() => assertExpected(existing, expected));
|
|
1140
|
-
const compatible = yield* authoringSync(() => assertCompatibleCreate(existing, input, requestedDocumentId));
|
|
1294
|
+
const compatible = yield* authoringSync(() => assertCompatibleCreate(existing, input, requestedDocumentId, extra));
|
|
1141
1295
|
return yield* authoringSync(() => noteResult(existing, compatible.relations, false, compatible.documentId));
|
|
1142
1296
|
}
|
|
1143
1297
|
if (expected !== undefined)
|
|
1144
1298
|
return yield* fail(new NoteRevisionConflictError(`${id}.md`, expected, null));
|
|
1145
1299
|
const documentId = yield* authoringSync(() => requestedDocumentId ?? parseDocumentId(dependencies.documentId()));
|
|
1146
|
-
const content = yield* authoringSync(() => renderCreatedNote(input, documentId));
|
|
1300
|
+
const content = yield* authoringSync(() => renderCreatedNote(input, documentId, extra));
|
|
1147
1301
|
const revision = yield* installNote(platform, vault, id, content, null, lock, dependencies);
|
|
1148
1302
|
return { changed: true, path: `${id}.md`, revision, relations: [], documentId };
|
|
1149
1303
|
}), (lock) => authoringNative(() => lock.release()));
|
|
@@ -1177,9 +1331,10 @@ function editNoteRelationProgram(platform, operation, root, sourceIdInput, predi
|
|
|
1177
1331
|
}), (lock) => authoringNative(() => lock.release()));
|
|
1178
1332
|
});
|
|
1179
1333
|
}
|
|
1180
|
-
function updateNoteBodyProgram(platform, root, idInput, body, options) {
|
|
1334
|
+
function updateNoteBodyProgram(platform, root, idInput, body, options, fields) {
|
|
1181
1335
|
return Effect2.gen(function* () {
|
|
1182
1336
|
const id = yield* authoringSync(() => canonicalNoteId(idInput));
|
|
1337
|
+
const updates = yield* authoringSync(() => validateFrontmatterFieldUpdates(fields));
|
|
1183
1338
|
const expected = yield* authoringSync(() => {
|
|
1184
1339
|
if (typeof options?.expectedRevision !== "string") {
|
|
1185
1340
|
throw new TypeError("expectedRevision is required for a note body update");
|
|
@@ -1198,7 +1353,7 @@ function updateNoteBodyProgram(platform, root, idInput, body, options) {
|
|
|
1198
1353
|
return yield* fail(new TypeError("the note has an invalid document_id"));
|
|
1199
1354
|
const documentId = identity.kind === "valid" ? identity.documentId : undefined;
|
|
1200
1355
|
const relations = yield* authoringSync(() => relationsFromParts(parts, source.relativePath));
|
|
1201
|
-
const content = yield* authoringSync(() =>
|
|
1356
|
+
const content = yield* authoringSync(() => renderUpdatedNoteBodyAndFields(source, parts, body, updates));
|
|
1202
1357
|
if (content === source.content)
|
|
1203
1358
|
return yield* authoringSync(() => noteResult(source, relations, false, documentId));
|
|
1204
1359
|
const revision = yield* installNote(platform, vault, id, content, source, lock, dependencies);
|
|
@@ -1237,4 +1392,4 @@ async function removeNoteRelation(root, sourceId, predicate, targetId, options =
|
|
|
1237
1392
|
return runAuthoring(editNoteRelationProgram(nativeAuthoringPlatform, "remove", root, sourceId, predicate, targetId, options));
|
|
1238
1393
|
}
|
|
1239
1394
|
|
|
1240
|
-
export { InvalidCanonicalNoteIdError, NoteRevisionConflictError, NoteAlreadyExistsError, NoteRecoveryRequiredError, canonicalNoteId, canonicalRelationTarget, normalizeRelationPredicate, noteRevision, listNoteRelations, createNote, createConceptNote, updateNoteBody, addNoteRelation, removeNoteRelation };
|
|
1395
|
+
export { MAX_NOTE_BYTES, NOTE_REVISION_PATTERN, InvalidCanonicalNoteIdError, NoteRevisionConflictError, NoteAlreadyExistsError, NoteRecoveryRequiredError, isErrno, sha256, revisionFor, canonicalNoteId, canonicalRelationTarget, normalizeRelationPredicate, frontmatter, relationsFromParts, renderUpdatedNoteBodyAndFields, renderCreatedNote, resolveVault, assertExactDirectoryEntry, assertSafeParent, nativeAuthoringPlatform, runAuthoring, createNoteProgram, updateNoteBodyProgram, noteRevision, listNoteRelations, createNote, createConceptNote, updateNoteBody, addNoteRelation, removeNoteRelation };
|
|
@@ -345,9 +345,12 @@ Capture options:
|
|
|
345
345
|
--scope auto|page|thread|comments Content scope (default: platform-aware)
|
|
346
346
|
--html <path|-> Parse saved/rendered HTML; - reads stdin
|
|
347
347
|
--browser-profile <name|path> Use a signed-in or persistent Chrome profile
|
|
348
|
+
(downloads read its cookies from the keychain)
|
|
348
349
|
--browser-live Attach to a live Chrome session
|
|
349
350
|
--cdp <loopback-port> Attach to a local CDP-capable browser
|
|
350
351
|
--cookie-source <browser> chrome|arc|brave|chromium|edge|firefox|safari
|
|
352
|
+
On a Mac, Chromium browsers ask for keychain
|
|
353
|
+
access; Safari needs Full Disk Access
|
|
351
354
|
--cookie-profile <name|path> Browser profile; Safari expects a Cookies.binarycookies path
|
|
352
355
|
--cookies-file <path> Cookie-Editor JSON/base64, Netscape, Cookie header, or cURL input
|
|
353
356
|
--media none|images|all Localize images or all supported media
|
|
@@ -3,6 +3,101 @@ import {
|
|
|
3
3
|
sanitizeTerminalText
|
|
4
4
|
} from "./index-1xxnjn0d.js";
|
|
5
5
|
|
|
6
|
+
// src/cli-style.ts
|
|
7
|
+
var UNICODE_SYMBOLS = {
|
|
8
|
+
ok: "\u2713",
|
|
9
|
+
fail: "\u2717",
|
|
10
|
+
warn: "\u26A0",
|
|
11
|
+
next: "\u2192",
|
|
12
|
+
on: "\u25CF",
|
|
13
|
+
off: "\u25CB",
|
|
14
|
+
skip: "\u2013",
|
|
15
|
+
progress: "\u21BB",
|
|
16
|
+
notice: "\uD83D\uDD10"
|
|
17
|
+
};
|
|
18
|
+
var ASCII_SYMBOLS = {
|
|
19
|
+
ok: "OK",
|
|
20
|
+
fail: "FAIL",
|
|
21
|
+
warn: "WARN",
|
|
22
|
+
next: "->",
|
|
23
|
+
on: "*",
|
|
24
|
+
off: "o",
|
|
25
|
+
skip: "-",
|
|
26
|
+
progress: "...",
|
|
27
|
+
notice: "NOTE"
|
|
28
|
+
};
|
|
29
|
+
var SYMBOL_COLORS = {
|
|
30
|
+
ok: "32",
|
|
31
|
+
fail: "31",
|
|
32
|
+
warn: "33",
|
|
33
|
+
next: "2",
|
|
34
|
+
on: "32",
|
|
35
|
+
skip: "2"
|
|
36
|
+
};
|
|
37
|
+
function nonEmpty(value) {
|
|
38
|
+
return value !== undefined && value !== "";
|
|
39
|
+
}
|
|
40
|
+
function prefersAscii(env) {
|
|
41
|
+
if (env.TERM === "dumb" || env.HRANESS_ASCII === "1")
|
|
42
|
+
return true;
|
|
43
|
+
const locale = [env.LC_ALL, env.LC_CTYPE, env.LANG].find(nonEmpty);
|
|
44
|
+
return locale === undefined || !/utf-?8/iu.test(locale);
|
|
45
|
+
}
|
|
46
|
+
function prefersColor(env, isTTY) {
|
|
47
|
+
if (env.FORCE_COLOR === "1")
|
|
48
|
+
return true;
|
|
49
|
+
if (nonEmpty(env.NO_COLOR))
|
|
50
|
+
return false;
|
|
51
|
+
return isTTY && env.TERM !== "dumb";
|
|
52
|
+
}
|
|
53
|
+
function terminalStyle(env, isTTY) {
|
|
54
|
+
return { ascii: prefersAscii(env), color: prefersColor(env, isTTY) };
|
|
55
|
+
}
|
|
56
|
+
function symbol(name, style) {
|
|
57
|
+
const glyph = style.ascii ? ASCII_SYMBOLS[name] : UNICODE_SYMBOLS[name];
|
|
58
|
+
const color = SYMBOL_COLORS[name];
|
|
59
|
+
return style.color && color !== undefined ? `\x1B[${color}m${glyph}\x1B[0m` : glyph;
|
|
60
|
+
}
|
|
61
|
+
var AGENT_MARKERS = [
|
|
62
|
+
"AI_AGENT",
|
|
63
|
+
"CLAUDECODE",
|
|
64
|
+
"CODEX_SANDBOX",
|
|
65
|
+
"CODEX_SANDBOX_NETWORK_DISABLED",
|
|
66
|
+
"CURSOR_AGENT",
|
|
67
|
+
"GEMINI_CLI"
|
|
68
|
+
];
|
|
69
|
+
function detectAudience(env, stderrIsTTY) {
|
|
70
|
+
const explicit = env.HRANESS_AUDIENCE;
|
|
71
|
+
if (explicit === "human" || explicit === "agent" || explicit === "quiet")
|
|
72
|
+
return explicit;
|
|
73
|
+
if (explicit === "off")
|
|
74
|
+
return "quiet";
|
|
75
|
+
if (AGENT_MARKERS.some((marker) => nonEmpty(env[marker])))
|
|
76
|
+
return "agent";
|
|
77
|
+
return stderrIsTTY ? "human" : "quiet";
|
|
78
|
+
}
|
|
79
|
+
function renderFailure(text, next, style) {
|
|
80
|
+
return `${symbol("fail", style)} ${text}
|
|
81
|
+
${symbol("next", style)} ${next}
|
|
82
|
+
`;
|
|
83
|
+
}
|
|
84
|
+
function sentence(message) {
|
|
85
|
+
const trimmed = message.trim();
|
|
86
|
+
const capitalized = /^[a-z]/u.test(trimmed) ? `${trimmed[0]?.toUpperCase() ?? ""}${trimmed.slice(1)}` : trimmed;
|
|
87
|
+
return /[.!?]$/u.test(capitalized) ? capitalized : `${capitalized}.`;
|
|
88
|
+
}
|
|
89
|
+
var terminalOutputs = new WeakSet;
|
|
90
|
+
function terminalOutput(output) {
|
|
91
|
+
terminalOutputs.add(output);
|
|
92
|
+
return output;
|
|
93
|
+
}
|
|
94
|
+
function stderrStyle(env, output) {
|
|
95
|
+
return terminalStyle(env, terminalOutputs.has(output) && process.stderr.isTTY === true);
|
|
96
|
+
}
|
|
97
|
+
function writesToTerminal(output) {
|
|
98
|
+
return terminalOutputs.has(output) && process.stderr.isTTY === true;
|
|
99
|
+
}
|
|
100
|
+
|
|
6
101
|
// src/clip/lib.ts
|
|
7
102
|
var articleMetadataLimits = {
|
|
8
103
|
title: 2048,
|
|
@@ -2043,4 +2138,4 @@ function renderCapturedDocument(document) {
|
|
|
2043
2138
|
return rewriteContent(markdown, new URL(document.sourceUrl), new Map, { remoteImages: "embed" });
|
|
2044
2139
|
}
|
|
2045
2140
|
|
|
2046
|
-
export { articleMetadataLimits, slugify, yamlString, resolveRemote, scanImageSources, CONTENT_REWRITE_TRUNCATION_WARNING, rewriteContentWithStatus, buildClipMarkdown, classifyPlatformUrl, parseHackerNewsCapture, parseRedditCapture, parseBlueskyCapture, renderCapturedDocument };
|
|
2141
|
+
export { terminalStyle, symbol, detectAudience, renderFailure, sentence, terminalOutput, stderrStyle, writesToTerminal, articleMetadataLimits, slugify, yamlString, resolveRemote, scanImageSources, CONTENT_REWRITE_TRUNCATION_WARNING, rewriteContentWithStatus, buildClipMarkdown, classifyPlatformUrl, parseHackerNewsCapture, parseRedditCapture, parseBlueskyCapture, renderCapturedDocument };
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
fuseRankedCandidates,
|
|
4
4
|
validateSearchQuery
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-ahyhryb8.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_NOTE_UTF8_BYTES,
|
|
8
8
|
MAX_SCANNED_NOTES,
|
|
9
9
|
MAX_VAULT_UTF8_BYTES,
|
|
10
10
|
VaultScanBudgetError,
|
|
11
11
|
scanVault
|
|
12
|
-
} from "./index-
|
|
12
|
+
} from "./index-1s8mc4hz.js";
|
|
13
13
|
|
|
14
14
|
// src/semantic.ts
|
|
15
15
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -303,12 +303,15 @@ class VaultAnalysisBudgetError extends RangeError {
|
|
|
303
303
|
function isMetadataObject(value) {
|
|
304
304
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
305
305
|
}
|
|
306
|
+
function isMetadataNumber(value) {
|
|
307
|
+
return Number.isFinite(value) && (!Number.isInteger(value) || Number.isSafeInteger(value));
|
|
308
|
+
}
|
|
306
309
|
function parsedMetadataValue(value, ancestors) {
|
|
307
310
|
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
308
311
|
return { ok: true, value };
|
|
309
312
|
}
|
|
310
313
|
if (typeof value === "number") {
|
|
311
|
-
return
|
|
314
|
+
return isMetadataNumber(value) ? { ok: true, value } : { ok: false };
|
|
312
315
|
}
|
|
313
316
|
if (typeof value !== "object" || ancestors.has(value))
|
|
314
317
|
return { ok: false };
|
|
@@ -1281,4 +1284,4 @@ function replaceCatalog(indexContent, catalog) {
|
|
|
1281
1284
|
return indexContent.slice(0, start) + catalog + indexContent.slice(end + catalogEnd.length);
|
|
1282
1285
|
}
|
|
1283
1286
|
|
|
1284
|
-
export { MAX_PORTFOLIO_NAME_BYTES, MAX_DOCUMENT_ID_BYTES, portfolioVaultIdentity, parseVaultKey, parseDocumentId, documentIdState, formatQualifiedDocumentUri, parseQualifiedDocumentUri, portfolioDocumentIdentity, catalogStart, catalogEnd, MAX_ANALYZED_NOTES, MAX_CONNECTION_OBSERVATIONS, MAX_MENTION_PAIRS, MAX_MENTIONS, VaultAnalysisBudgetError, metadataValueFromUnknown, isCanonicalRelationPredicate, isCanonicalNoteId, normalizeVaultPath, searchableMarkdown, wikiLinks, parseNote, lookupNote, analyzeVault, analyzeVaultComplete, renderCatalog, replaceCatalog };
|
|
1287
|
+
export { MAX_PORTFOLIO_NAME_BYTES, MAX_DOCUMENT_ID_BYTES, portfolioVaultIdentity, parseVaultKey, parseDocumentId, documentIdState, formatQualifiedDocumentUri, parseQualifiedDocumentUri, portfolioDocumentIdentity, catalogStart, catalogEnd, MAX_ANALYZED_NOTES, MAX_CONNECTION_OBSERVATIONS, MAX_MENTION_PAIRS, MAX_MENTIONS, VaultAnalysisBudgetError, isMetadataNumber, metadataValueFromUnknown, isCanonicalRelationPredicate, isCanonicalNoteId, normalizeVaultPath, searchableMarkdown, wikiLinks, parseNote, lookupNote, analyzeVault, analyzeVaultComplete, renderCatalog, replaceCatalog };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
MAX_SEARCH_RESULTS,
|
|
4
4
|
openKnowledgeBase
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-tvd2sqrx.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_EVALUATION_EVIDENCE_BYTES,
|
|
8
8
|
redactEvaluationMachinePaths
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./index-1gwbassd.js";
|
|
13
13
|
import {
|
|
14
14
|
scanVault
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-1s8mc4hz.js";
|
|
16
16
|
import {
|
|
17
17
|
MAX_REPOSITORY_MEMORY_DETAIL_LIMIT,
|
|
18
18
|
MAX_REPOSITORY_MEMORY_GROUP_LIMIT,
|