@hraness/wordcell 0.23.0 → 0.24.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/README.md +29 -16
- package/dist/authoring.js +2 -1
- package/dist/cli.js +10 -9
- package/dist/clip/jobs.js +5 -1
- package/dist/evaluation-builder.js +5 -4
- package/dist/evaluation-kb.js +5 -4
- package/dist/graph-authority.js +2 -1
- package/dist/graph-percolation.js +3 -2
- package/dist/{index-1er88ckw.js → index-3gc2yk4k.js} +10 -5
- package/dist/{index-mnq2wy34.js → index-59bcxqee.js} +1 -1
- package/dist/{index-p70t8j13.js → index-7drercgk.js} +1 -1
- package/dist/{index-tcaq1c7f.js → index-e26mdwxz.js} +1 -1
- package/dist/{index-r4qs6vq4.js → index-hz2wyggk.js} +1 -1
- package/dist/{index-vtwbapjr.js → index-jqkkb4fr.js} +72 -12
- package/dist/{index-tvd2sqrx.js → index-mcpppwbq.js} +439 -4
- package/dist/index-qkesh4c6.js +7 -0
- package/dist/{index-b0khj0h5.js → index-qt2zwza8.js} +6 -1
- package/dist/{index-0eacgvpv.js → index-t0fh8a1q.js} +7 -3
- package/dist/index.js +6 -5
- package/dist/portfolio.js +5 -4
- package/dist/sdk.js +4 -3
- package/dist/{support-c8hy7qfa.js → support-07jpt1z4.js} +9 -8
- package/dist/url-intelligence.js +2 -1
- package/dist/workflows/decision-context.js +5 -4
- package/dist/workflows/index.js +5 -4
- package/package.json +12 -8
- package/skills/wordcell/SKILL.md +1 -1
- package/skills/wordcell/references/publish.md +2 -1
- package/skills/wordcell/references/query.md +17 -3
- package/src/authoring-platform.ts +3 -0
- package/src/cli-help.ts +1 -0
- package/src/cli-program.ts +41 -3
- package/src/clip/jobs.ts +2 -1
- package/src/clip/metadata-search-tool/Cargo.lock +2 -0
- package/src/clip/metadata-search-tool/Cargo.toml +2 -0
- package/src/clip/metadata-search-tool/runner.ts +4 -1
- package/src/clip/metadata-search-tool/src/duckduckgo.rs +534 -0
- package/src/clip/metadata-search-tool/src/main.rs +31 -18
- package/src/clip/metadata-search.ts +4 -2
- package/src/clip/url-metadata.ts +2 -1
- package/src/directory-sync.ts +9 -0
- package/src/graph-authority.ts +5 -2
- package/src/mcp-tools.ts +17 -1
- package/src/sdk.ts +149 -1
- package/src/selected-passage.ts +409 -0
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
parseArguments as parseArguments2,
|
|
4
4
|
parseUrlMetadataArguments
|
|
5
|
-
} from "./index-
|
|
6
|
-
import"./index-
|
|
5
|
+
} from "./index-jqkkb4fr.js";
|
|
6
|
+
import"./index-t0fh8a1q.js";
|
|
7
7
|
import {
|
|
8
8
|
parsePdfArguments
|
|
9
9
|
} from "./index-qfqjfxaa.js";
|
|
10
|
-
import"./index-
|
|
10
|
+
import"./index-hz2wyggk.js";
|
|
11
11
|
import"./index-j4zgmzjr.js";
|
|
12
12
|
import"./index-2fmnttca.js";
|
|
13
13
|
import"./index-6jcz0m1c.js";
|
|
@@ -28,16 +28,16 @@ import"./index-mxxxytys.js";
|
|
|
28
28
|
import"./index-23z4zxgg.js";
|
|
29
29
|
import"./index-pj501bh1.js";
|
|
30
30
|
import"./index-9rf81m0p.js";
|
|
31
|
-
import"./index-
|
|
32
|
-
import"./index-
|
|
31
|
+
import"./index-59bcxqee.js";
|
|
32
|
+
import"./index-mcpppwbq.js";
|
|
33
33
|
import"./index-adx6khj5.js";
|
|
34
34
|
import"./index-fp732bgg.js";
|
|
35
35
|
import"./index-4j3tt0c3.js";
|
|
36
36
|
import"./index-j70m75wd.js";
|
|
37
37
|
import"./index-b88v3vtm.js";
|
|
38
|
-
import"./index-
|
|
38
|
+
import"./index-e26mdwxz.js";
|
|
39
39
|
import"./index-bdwcjvr4.js";
|
|
40
|
-
import"./index-
|
|
40
|
+
import"./index-3gc2yk4k.js";
|
|
41
41
|
import"./index-pgtm2nhf.js";
|
|
42
42
|
import"./index-1gwbassd.js";
|
|
43
43
|
import"./index-ahyhryb8.js";
|
|
@@ -53,8 +53,9 @@ import"./index-23m6bbjt.js";
|
|
|
53
53
|
import"./index-hya40gb2.js";
|
|
54
54
|
import"./index-5vwpzb5a.js";
|
|
55
55
|
import"./index-x3fthpsc.js";
|
|
56
|
-
import"./index-
|
|
56
|
+
import"./index-qt2zwza8.js";
|
|
57
57
|
import"./index-3rm7cz6h.js";
|
|
58
|
+
import"./index-qkesh4c6.js";
|
|
58
59
|
import"./index-jvb7w0gg.js";
|
|
59
60
|
import"./index-z1w83f81.js";
|
|
60
61
|
|
package/dist/url-intelligence.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
readUrlMetadataDocument,
|
|
11
11
|
renderUrlMetadataDocument,
|
|
12
12
|
writeUrlMetadataDocument
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-t0fh8a1q.js";
|
|
14
14
|
import {
|
|
15
15
|
ARCHIVE_TODAY_HOSTS,
|
|
16
16
|
ArchiveTodayFailure,
|
|
@@ -28,6 +28,7 @@ import"./index-e5fbsywq.js";
|
|
|
28
28
|
import"./index-gh719d91.js";
|
|
29
29
|
import"./index-mxxxytys.js";
|
|
30
30
|
import"./index-1xxnjn0d.js";
|
|
31
|
+
import"./index-qkesh4c6.js";
|
|
31
32
|
import"./index-z1w83f81.js";
|
|
32
33
|
|
|
33
34
|
// src/url-intelligence.ts
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
decisionContextWorkflow
|
|
4
|
-
} from "../index-
|
|
4
|
+
} from "../index-7drercgk.js";
|
|
5
5
|
import"../index-h170byqw.js";
|
|
6
|
-
import"../index-
|
|
6
|
+
import"../index-mcpppwbq.js";
|
|
7
7
|
import"../index-adx6khj5.js";
|
|
8
8
|
import"../index-fp732bgg.js";
|
|
9
9
|
import"../index-4j3tt0c3.js";
|
|
10
10
|
import"../index-j70m75wd.js";
|
|
11
|
-
import"../index-
|
|
11
|
+
import"../index-e26mdwxz.js";
|
|
12
12
|
import"../index-bdwcjvr4.js";
|
|
13
|
-
import"../index-
|
|
13
|
+
import"../index-3gc2yk4k.js";
|
|
14
14
|
import"../index-pgtm2nhf.js";
|
|
15
15
|
import"../index-1gwbassd.js";
|
|
16
16
|
import"../index-ahyhryb8.js";
|
|
@@ -21,6 +21,7 @@ import"../index-48pz4jpc.js";
|
|
|
21
21
|
import"../index-06c9ctr6.js";
|
|
22
22
|
import"../index-5vwpzb5a.js";
|
|
23
23
|
import"../index-3rm7cz6h.js";
|
|
24
|
+
import"../index-qkesh4c6.js";
|
|
24
25
|
import"../index-jvb7w0gg.js";
|
|
25
26
|
import"../index-z1w83f81.js";
|
|
26
27
|
export {
|
package/dist/workflows/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
decisionContextWorkflow
|
|
4
|
-
} from "../index-
|
|
4
|
+
} from "../index-7drercgk.js";
|
|
5
5
|
import {
|
|
6
6
|
explainChangeWorkflow
|
|
7
7
|
} from "../index-e4fagfjz.js";
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
planRadarWorkflow
|
|
10
10
|
} from "../index-rdd5f7jj.js";
|
|
11
11
|
import"../index-h170byqw.js";
|
|
12
|
-
import"../index-
|
|
12
|
+
import"../index-mcpppwbq.js";
|
|
13
13
|
import"../index-adx6khj5.js";
|
|
14
14
|
import"../index-fp732bgg.js";
|
|
15
15
|
import"../index-4j3tt0c3.js";
|
|
16
16
|
import"../index-j70m75wd.js";
|
|
17
|
-
import"../index-
|
|
17
|
+
import"../index-e26mdwxz.js";
|
|
18
18
|
import"../index-bdwcjvr4.js";
|
|
19
|
-
import"../index-
|
|
19
|
+
import"../index-3gc2yk4k.js";
|
|
20
20
|
import"../index-pgtm2nhf.js";
|
|
21
21
|
import"../index-1gwbassd.js";
|
|
22
22
|
import"../index-ahyhryb8.js";
|
|
@@ -27,6 +27,7 @@ import"../index-48pz4jpc.js";
|
|
|
27
27
|
import"../index-06c9ctr6.js";
|
|
28
28
|
import"../index-5vwpzb5a.js";
|
|
29
29
|
import"../index-3rm7cz6h.js";
|
|
30
|
+
import"../index-qkesh4c6.js";
|
|
30
31
|
import"../index-jvb7w0gg.js";
|
|
31
32
|
import"../index-z1w83f81.js";
|
|
32
33
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hraness/wordcell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"description": "Wordcell keeps decisions, plans, and sources as Markdown beside your code, so coding agents can find them from the file they are about to change.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -368,6 +368,7 @@
|
|
|
368
368
|
"src/clip/metadata-search-tool/Cargo.lock",
|
|
369
369
|
"src/clip/metadata-search-tool/runner.ts",
|
|
370
370
|
"src/clip/metadata-search-tool/src/main.rs",
|
|
371
|
+
"src/clip/metadata-search-tool/src/duckduckgo.rs",
|
|
371
372
|
"src/git.ts",
|
|
372
373
|
"src/evaluation-analysis-v2.ts",
|
|
373
374
|
"src/evaluation-builder.ts",
|
|
@@ -437,6 +438,7 @@
|
|
|
437
438
|
"src/semantic.ts",
|
|
438
439
|
"src/serve.ts",
|
|
439
440
|
"src/sdk.ts",
|
|
441
|
+
"src/selected-passage.ts",
|
|
440
442
|
"src/source-inbox.ts",
|
|
441
443
|
"src/untrusted-content.ts",
|
|
442
444
|
"src/vault.ts",
|
|
@@ -467,13 +469,14 @@
|
|
|
467
469
|
"src/oh/validation.ts",
|
|
468
470
|
"assets/agent-skill.svg",
|
|
469
471
|
"src/support.ts",
|
|
470
|
-
"src/support-profile.ts"
|
|
472
|
+
"src/support-profile.ts",
|
|
473
|
+
"src/directory-sync.ts"
|
|
471
474
|
],
|
|
472
475
|
"scripts": {
|
|
473
|
-
"kb:refresh": "bunx --bun github
|
|
474
|
-
"kb:check:lane": "bunx --bun github
|
|
475
|
-
"kb:check": "bunx --bun github
|
|
476
|
-
"kb:catalog": "bunx --bun github
|
|
476
|
+
"kb:refresh": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell refresh --root kb",
|
|
477
|
+
"kb:check:lane": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell check --root kb --no-catalog",
|
|
478
|
+
"kb:check": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell check --root kb && bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell agents check --root kb --repo .",
|
|
479
|
+
"kb:catalog": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell catalog --root kb",
|
|
477
480
|
"build": "bun -e 'await (await import(\"node:fs/promises\")).rm(\"./dist\", { recursive: true, force: true })' && bun build ./src/index.ts ./src/publish.ts ./src/publish-model.ts ./src/publish-search.ts ./src/agent-context.ts ./src/agent-guide-audit.ts ./src/attachments.ts ./src/authoring.ts ./src/benchmark.ts ./src/clip/browser-profiles.ts ./src/capture.ts ./src/cli.ts ./src/clip/acquire.ts ./src/clip/args.ts ./src/clip/bounded-byte-buffer.ts ./src/clip/bundle-reader.ts ./src/clip/cli.ts ./src/clip/cookies.ts ./src/clip/doctor.ts ./src/clip/jobs.ts ./src/clip/network.ts ./src/clip/network-proxy.ts ./src/clip/persist.ts ./src/clip/refresh.ts ./src/clip/terminal.ts ./src/evaluation.ts ./src/evaluation-builder.ts ./src/evaluation-kb.ts ./src/git.ts ./src/graph.ts ./src/graph-percolation.ts ./src/graph-authority.ts ./src/navigation.ts ./src/pdf.ts ./src/percolate.ts ./src/portfolio.ts ./src/query.ts ./src/rerank.ts ./src/rerank-typesafe.ts ./src/repository-memory.ts ./src/sdk.ts ./src/search.ts ./src/search-rules.ts ./src/semantic.ts ./src/source-inbox.ts ./src/untrusted-content.ts ./src/url-intelligence.ts ./src/workflow.ts ./src/workflows/index.ts ./src/workflows/decision-context.ts ./src/workflows/explain-change.ts ./src/workflows/plan-radar.ts ./src/clip/defuddle-worker.ts --outdir ./dist --root ./src --target bun --format esm --splitting --packages external && bun build ./src/publish-reader/reader.ts --outfile ./dist/publish-reader/reader.js --target browser --format esm && bun build ./src/publish-reader/theme.ts --outfile ./dist/publish-reader/theme.js --target browser --format iife && cp ./src/publish-reader/reader.css ./dist/publish-reader/reader.css",
|
|
478
481
|
"check:workflows": "bun ./scripts/check-workflow-yaml.ts",
|
|
479
482
|
"check:installed-command-docs": "bun ./scripts/check-installed-command-docs.ts",
|
|
@@ -484,11 +487,12 @@
|
|
|
484
487
|
"url-metadata:tool:build": "bun ./dist/cli.js url-metadata tool build",
|
|
485
488
|
"url-metadata:tool:check": "bun ./dist/cli.js url-metadata tool check",
|
|
486
489
|
"test:package": "bun run ./scripts/package-smoke.ts",
|
|
490
|
+
"check:fast": "bun run check:worker && bun run check:effect && bun run check:workflows && bun run check:portfolio-inventory && bun run check:installed-command-docs && bun run typecheck && bun run build && bun run test",
|
|
487
491
|
"check": "bun run check:worker && bun run check:effect && bun run check:workflows && bun run check:portfolio-inventory && bun run check:installed-command-docs && bun run typecheck && bun run build && bun run test:package && bun run test && bun run url-metadata:tool:check",
|
|
488
492
|
"prepack": "bun run check",
|
|
489
493
|
"check:effect": "bun run scripts/check-effect-policy.ts",
|
|
490
|
-
"kb:search": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.
|
|
491
|
-
"kb:search:local": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.
|
|
494
|
+
"kb:search": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell search --root kb --mode exact --selected-passage --rerank typesafe --rerank-limit 25",
|
|
495
|
+
"kb:search:local": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.0/hraness-wordcell-0.24.0.tgz wordcell search --root kb --mode exact --selected-passage",
|
|
492
496
|
"check:worker": "tsc -p worker/tsconfig.json --noEmit"
|
|
493
497
|
},
|
|
494
498
|
"dependencies": {
|
package/skills/wordcell/SKILL.md
CHANGED
|
@@ -58,7 +58,7 @@ missing:
|
|
|
58
58
|
```sh
|
|
59
59
|
command -v wordcell >/dev/null 2>&1 || {
|
|
60
60
|
command -v bun >/dev/null 2>&1 || exit 1
|
|
61
|
-
bun add --global --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.
|
|
61
|
+
bun add --global --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz
|
|
62
62
|
}
|
|
63
63
|
wordcell --help
|
|
64
64
|
```
|
|
@@ -96,7 +96,8 @@ The full artifact contract and hosting options are in
|
|
|
96
96
|
|
|
97
97
|
Agents on platforms without a filesystem or Bun runtime can publish the same
|
|
98
98
|
`hraness.wordcell.site.v1` artifact through the hosted surface. It runs the
|
|
99
|
-
identical projection server-side; published sites are public
|
|
99
|
+
identical projection server-side; published sites are public, and search
|
|
100
|
+
engines may index them unless the publish request sets `"noindex": true`.
|
|
100
101
|
|
|
101
102
|
```sh
|
|
102
103
|
# Self-serve capability token (IP-limited; shown once — store it).
|
|
@@ -54,7 +54,7 @@ returned:
|
|
|
54
54
|
```sh
|
|
55
55
|
wordcell context packages/parser/src/index.ts --root "$KB_ROOT" --repo "$KB_REPO"
|
|
56
56
|
wordcell search "why parser retries stop" --root "$KB_ROOT" --mode exact \
|
|
57
|
-
--history --repo "$KB_REPO" --json
|
|
57
|
+
--selected-passage --history --repo "$KB_REPO" --json
|
|
58
58
|
wordcell backlinks notes/parser-contract --root "$KB_ROOT" --json
|
|
59
59
|
wordcell history notes/parser-contract --root "$KB_ROOT" \
|
|
60
60
|
--repo "$KB_REPO" --json
|
|
@@ -80,7 +80,7 @@ read them with the commands under
|
|
|
80
80
|
resolve note identities before returning authored relationships.
|
|
81
81
|
- A whole-vault structural question or relationship audit: use `wordcell graph --json`,
|
|
82
82
|
then inspect the smallest relevant portion of its canonical output.
|
|
83
|
-
- A phrase, identity, or concept expressed with different vocabulary: use `wordcell search`, whose default hybrid result preserves exact and QMD evidence separately.
|
|
83
|
+
- A phrase, identity, or concept expressed with different vocabulary: use `wordcell search`, whose default hybrid result preserves exact and QMD evidence separately. Add `--selected-passage` when you will read, quote, or act on results: each hit then carries the note's best-matching excerpt with its line range and section headings.
|
|
84
84
|
- Direct provenance for one note or repository path: use `wordcell history` or
|
|
85
85
|
`wordcell history search` without changing authored metadata or links.
|
|
86
86
|
- Recent captures awaiting maintained disposition: use the advisory `wordcell inbox` view.
|
|
@@ -96,7 +96,7 @@ wordcell backlinks "Plan title or path" --root "$KB_ROOT" --json
|
|
|
96
96
|
wordcell links "Plan title or path" --root "$KB_ROOT" --direction both --depth 1 --limit 25 --json
|
|
97
97
|
wordcell relation list "Plan title or path" --root "$KB_ROOT" --json
|
|
98
98
|
wordcell graph --root "$KB_ROOT" --json
|
|
99
|
-
wordcell search "why browser capture uses the current tab" --root "$KB_ROOT" --json
|
|
99
|
+
wordcell search "why browser capture uses the current tab" --root "$KB_ROOT" --selected-passage --json
|
|
100
100
|
wordcell search "accepted ingestion plans" --root "$KB_ROOT" --where type=plan --where status=accepted --tag ingestion --json
|
|
101
101
|
wordcell search "notes/write-path" --root "$KB_ROOT" --mode exact --no-history --json
|
|
102
102
|
wordcell history "notes/write-path" --root "$KB_ROOT" --repo "$KB_REPO" --json
|
|
@@ -211,6 +211,20 @@ For a repository's ordinary KB searches, prefer its approved, pinned
|
|
|
211
211
|
choice. Read returned notes before acting; model probabilities are ranking
|
|
212
212
|
signals, not proof of truth. Explicit priority rules still run last.
|
|
213
213
|
|
|
214
|
+
Add `--selected-passage` to attach one source excerpt to each returned note.
|
|
215
|
+
Wordcell chooses it locally, without model calls: the paragraph, or window of
|
|
216
|
+
at most 512 UTF-8 bytes, that contains the most distinct query words, outside
|
|
217
|
+
frontmatter. The excerpt is unedited note text with its byte offsets, line
|
|
218
|
+
range, the SHA-256 of the note text, and the enclosing Markdown headings as
|
|
219
|
+
separate spans. Offsets count from the start of the note text, after any
|
|
220
|
+
byte-order mark. Ranking, scores, the `snippet` field, and reranker input do not
|
|
221
|
+
change. A note without matching body text reports `status: "none"`; a note
|
|
222
|
+
past a size limit reports `status: "unavailable"` with a reason. Both keep
|
|
223
|
+
their snippet. Terminal output shows CRLF as LF and tabs as four spaces, and
|
|
224
|
+
reports `display-sanitized` instead of an excerpt that credential redaction
|
|
225
|
+
would alter. An excerpt shows where query words appear; it is not a verified
|
|
226
|
+
answer. SDK and MCP `search` callers pass `selectedPassage: true`.
|
|
227
|
+
|
|
214
228
|
`wordcell history <note>` returns the bounded commit history already associated with
|
|
215
229
|
one resolved note. `wordcell history search <query-or-path>` searches the bounded Git
|
|
216
230
|
projection directly and retains hashes, subjects, matched paths, co-change
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { acquireNoteLock } from "./note-lock.js";
|
|
2
|
+
import { syncsDirectories } from "./directory-sync.js";
|
|
2
3
|
import { rename } from "node:fs/promises";
|
|
3
4
|
import { randomUUID } from "node:crypto";
|
|
4
5
|
import { constants } from "node:fs";
|
|
@@ -202,7 +203,9 @@ export async function cleanupTemporary(
|
|
|
202
203
|
export async function fsyncDirectory(
|
|
203
204
|
path: string,
|
|
204
205
|
openDirectory: typeof open = open,
|
|
206
|
+
platform: NodeJS.Platform = process.platform,
|
|
205
207
|
): Promise<void> {
|
|
208
|
+
if (!syncsDirectories(platform)) return;
|
|
206
209
|
const handle = await openDirectory(path, constants.O_RDONLY);
|
|
207
210
|
try {
|
|
208
211
|
await handle.sync();
|
package/src/cli-help.ts
CHANGED
|
@@ -114,6 +114,7 @@ export const commandHelp: readonly CommandHelp[] = [
|
|
|
114
114
|
["--min-score <score>", "Drop results scoring below this (0 to 1)"],
|
|
115
115
|
["--rerank <typesafe>", "Rerank results with the hosted TypeSafe service"],
|
|
116
116
|
["--rerank-limit <2..25>", "How many results the reranker sees"],
|
|
117
|
+
["--selected-passage", "Add a local source excerpt to each result"],
|
|
117
118
|
JSON_OPTION,
|
|
118
119
|
],
|
|
119
120
|
examples: ['wordcell search "retries" --root kb --mode exact', 'wordcell search "retry policy" --root kb --limit 5'],
|
package/src/cli-program.ts
CHANGED
|
@@ -385,6 +385,7 @@ type ParsedCommand =
|
|
|
385
385
|
readonly minScore?: number;
|
|
386
386
|
readonly rerank?: "typesafe";
|
|
387
387
|
readonly rerankLimit?: number;
|
|
388
|
+
readonly selectedPassage?: boolean;
|
|
388
389
|
readonly query: string;
|
|
389
390
|
readonly json: boolean;
|
|
390
391
|
}
|
|
@@ -1274,6 +1275,7 @@ function parseSemanticCommand(command: "index" | "search", arguments_: readonly
|
|
|
1274
1275
|
let minScore: number | undefined;
|
|
1275
1276
|
let rerank: "typesafe" | undefined;
|
|
1276
1277
|
let rerankLimit: number | undefined;
|
|
1278
|
+
let selectedPassage = false;
|
|
1277
1279
|
let graphDepth: number | undefined;
|
|
1278
1280
|
let noGraph = false;
|
|
1279
1281
|
let history = false;
|
|
@@ -1300,6 +1302,10 @@ function parseSemanticCommand(command: "index" | "search", arguments_: readonly
|
|
|
1300
1302
|
noGraph = true;
|
|
1301
1303
|
continue;
|
|
1302
1304
|
}
|
|
1305
|
+
if (argument === "--selected-passage" && command === "search") {
|
|
1306
|
+
selectedPassage = true;
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1303
1309
|
if (argument === "--no-history" && command === "search") {
|
|
1304
1310
|
noHistory = true;
|
|
1305
1311
|
continue;
|
|
@@ -1535,6 +1541,7 @@ function parseSemanticCommand(command: "index" | "search", arguments_: readonly
|
|
|
1535
1541
|
...(minScore === undefined ? {} : { minScore }),
|
|
1536
1542
|
...(rerank === undefined ? {} : { rerank }),
|
|
1537
1543
|
...(rerankLimit === undefined ? {} : { rerankLimit }),
|
|
1544
|
+
...(selectedPassage ? { selectedPassage: true } : {}),
|
|
1538
1545
|
query,
|
|
1539
1546
|
json,
|
|
1540
1547
|
},
|
|
@@ -2418,6 +2425,22 @@ function renderSemanticIndex(result: SemanticIndexResult): string {
|
|
|
2418
2425
|
].join("\n");
|
|
2419
2426
|
}
|
|
2420
2427
|
|
|
2428
|
+
function searchForDisplay(result: KnowledgeBaseSearchResult): KnowledgeBaseSearchResult {
|
|
2429
|
+
return {
|
|
2430
|
+
...result,
|
|
2431
|
+
results: result.results.map((hit) => {
|
|
2432
|
+
const passage = hit.selectedPassage;
|
|
2433
|
+
if (passage?.status !== "selected") return hit;
|
|
2434
|
+
const texts = [passage.text, ...passage.headings.map(({ text }) => text)];
|
|
2435
|
+
// Terminal output always renders CRLF as LF and tabs as four spaces; only other changes lose content.
|
|
2436
|
+
if (texts.every((text) => sanitizeTerminalText(redactSensitiveText(text))
|
|
2437
|
+
=== text.replaceAll("\r\n", "\n").replaceAll("\t", " "))) return hit;
|
|
2438
|
+
// Redacted display text cannot retain a claim of exact source bytes.
|
|
2439
|
+
return { ...hit, selectedPassage: { status: "unavailable", reason: "display-sanitized" } as const };
|
|
2440
|
+
}),
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2421
2444
|
function renderKnowledgeBaseSearch(result: KnowledgeBaseSearchResult): string {
|
|
2422
2445
|
const lines = [
|
|
2423
2446
|
`${result.mode[0]?.toLocaleUpperCase("en-US") ?? ""}${result.mode.slice(1)} results for “${safe(result.query)}” (${result.results.length})${result.partial ? " [partial]" : ""}`,
|
|
@@ -2445,7 +2468,20 @@ function renderKnowledgeBaseSearch(result: KnowledgeBaseSearchResult): string {
|
|
|
2445
2468
|
.map((item) => `${item.kind}#${searchEvidenceRank(item)}`)
|
|
2446
2469
|
.join(", ");
|
|
2447
2470
|
lines.push(` ${hit.rank}. ${hit.score.toFixed(3)} ${location} — ${safe(hit.title)} [${safe(evidence)}]`);
|
|
2448
|
-
|
|
2471
|
+
const passage = hit.selectedPassage;
|
|
2472
|
+
if (passage?.status === "selected") {
|
|
2473
|
+
lines.push(` Selected passage: ${safe(hit.path)}:${passage.startLine}-${passage.endLine}`
|
|
2474
|
+
+ (passage.clippedStart || passage.clippedEnd ? " (clipped excerpt)" : ""));
|
|
2475
|
+
for (const heading of passage.headings) {
|
|
2476
|
+
lines.push(` Section: ${safe(heading.text)}${heading.truncated ? " (clipped)" : ""}`);
|
|
2477
|
+
}
|
|
2478
|
+
for (const line of passage.text.split(/\r?\n/u)) lines.push(` ${safe(line)}`);
|
|
2479
|
+
} else {
|
|
2480
|
+
if (hit.snippet !== "") lines.push(` ${safe(hit.snippet)}`);
|
|
2481
|
+
if (passage !== undefined) {
|
|
2482
|
+
lines.push(` Selected passage: ${passage.status} (${safe(passage.reason)}); showing the search snippet.`);
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2449
2485
|
}
|
|
2450
2486
|
if ((result.graph?.related.length ?? 0) > 0) {
|
|
2451
2487
|
lines.push(` Related graph context: ${result.graph?.related.length ?? 0}`);
|
|
@@ -2523,6 +2559,7 @@ async function runSemantic(
|
|
|
2523
2559
|
? {}
|
|
2524
2560
|
: { candidateLimit: command.candidateLimit }),
|
|
2525
2561
|
...(command.minScore === undefined ? {} : { minScore: command.minScore }),
|
|
2562
|
+
...(command.selectedPassage === undefined ? {} : { selectedPassage: command.selectedPassage }),
|
|
2526
2563
|
...(command.rerank === undefined ? {} : {
|
|
2527
2564
|
rerank: {
|
|
2528
2565
|
engine: command.rerank,
|
|
@@ -2530,9 +2567,10 @@ async function runSemantic(
|
|
|
2530
2567
|
},
|
|
2531
2568
|
}),
|
|
2532
2569
|
});
|
|
2570
|
+
const display = searchForDisplay(result);
|
|
2533
2571
|
output.stdout(command.json
|
|
2534
|
-
? terminalSafeJson(
|
|
2535
|
-
: sanitizeTerminalText(renderKnowledgeBaseSearch(
|
|
2572
|
+
? terminalSafeJson(display)
|
|
2573
|
+
: sanitizeTerminalText(renderKnowledgeBaseSearch(display)));
|
|
2536
2574
|
if (withoutIndex && person) {
|
|
2537
2575
|
output.stderr("Searched without an index, so only exact words matched. "
|
|
2538
2576
|
+ `For meaning-based search, run wordcell index --root ${safe(shellWord(command.root))} `
|
package/src/clip/jobs.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Buffer } from "node:buffer";
|
|
2
|
+
import { syncsDirectories } from "../directory-sync.js";
|
|
2
3
|
import { randomUUID } from "node:crypto";
|
|
3
4
|
import { constants } from "node:fs";
|
|
4
5
|
import {
|
|
@@ -500,7 +501,7 @@ async function fsyncStore(store: CaptureJobStore): Promise<void> {
|
|
|
500
501
|
if (!stat.isDirectory() || !sameIdentity(stat, expected)) {
|
|
501
502
|
throw new CaptureJobSafetyError("Capture job store changed before synchronization.");
|
|
502
503
|
}
|
|
503
|
-
await handle.sync();
|
|
504
|
+
if (syncsDirectories()) await handle.sync();
|
|
504
505
|
} finally {
|
|
505
506
|
await handle.close();
|
|
506
507
|
}
|
|
@@ -8,6 +8,8 @@ publish = false
|
|
|
8
8
|
metadata-search-engine-rs = { git = "https://github.com/MikeLuu99/searxng-rust", rev = "f40a00ea67a857ee996e1caba1ebab3ee7a14a47" }
|
|
9
9
|
libc = "=0.2.189"
|
|
10
10
|
reqwest = { version = "=0.12.28", features = ["brotli", "cookies", "gzip"] }
|
|
11
|
+
scraper = "=0.20.0"
|
|
12
|
+
url = "=2.5.8"
|
|
11
13
|
serde = { version = "1", features = ["derive"] }
|
|
12
14
|
serde_json = "1"
|
|
13
15
|
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { syncsDirectories } from "../../directory-sync.js";
|
|
2
3
|
import {
|
|
3
4
|
closeSync,
|
|
4
5
|
constants,
|
|
@@ -387,7 +388,9 @@ export function installMetadataSearchExecutable(input: {
|
|
|
387
388
|
const stagingPath = join(toolDirectory, stagingName);
|
|
388
389
|
const backupPath = join(toolDirectory, backupName);
|
|
389
390
|
const syncDirectory = input.syncDirectory
|
|
390
|
-
?? ((descriptor: number) =>
|
|
391
|
+
?? ((descriptor: number) => {
|
|
392
|
+
if (syncsDirectories()) fsyncSync(descriptor);
|
|
393
|
+
});
|
|
391
394
|
|
|
392
395
|
const toolBinding = openBoundDirectory(toolDirectory, "metadata-search tool directory");
|
|
393
396
|
let targetBinding: DirectoryBinding | null = null;
|