@hraness/wordcell 0.21.3 → 0.22.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 +170 -64
- package/dist/authoring.js +5 -3
- package/dist/{authority-4sp9d552.js → authority-06eqhqam.js} +57 -12
- package/dist/benchmark.js +4 -4
- package/dist/capture.js +6 -5
- package/dist/cli.js +39 -33
- package/dist/clip/acquire.js +3 -2
- package/dist/clip/cli.js +6 -5
- package/dist/clip/doctor.js +4 -3
- package/dist/clip/jobs.js +3 -3
- package/dist/clip/refresh.js +1 -1
- package/dist/evaluation-builder.js +20 -19
- package/dist/evaluation-kb.js +16 -15
- package/dist/graph-authority.js +5 -5
- package/dist/graph-percolation.js +7 -7
- package/dist/graph.js +1 -1
- package/dist/{index-pbr6rv47.js → index-1k595z6v.js} +6 -6
- package/dist/{index-0k2x4nn9.js → index-233z9wmn.js} +17 -5
- package/dist/index-3agn8scn.js +306 -0
- package/dist/index-4knsp9qj.js +34 -0
- package/dist/index-66pshdtx.js +341 -0
- package/dist/{index-59ssmqqm.js → index-76dbn6pe.js} +1 -1
- package/dist/{index-0rfcqab6.js → index-810nfzdj.js} +617 -66
- package/dist/index-9rf81m0p.js +368 -0
- package/dist/{index-51bap0mq.js → index-bqtqeak3.js} +10 -10
- package/dist/{index-9zcpdbjg.js → index-de2w8crk.js} +13 -13
- package/dist/{index-bgfzwt4h.js → index-djrcc1yf.js} +6 -6
- package/dist/{index-6sw24nvv.js → index-ecqpgr5y.js} +53 -2
- package/dist/{index-van48n3g.js → index-fc4dr114.js} +4 -2
- package/dist/{index-jzcws0zn.js → index-g5vsqmdy.js} +27 -57
- package/dist/index-hmw17zaa.js +1985 -0
- package/dist/index-j70m75wd.js +217 -0
- package/dist/{index-nd6nynv2.js → index-jk1sgx36.js} +1 -1
- package/dist/{index-3ehtt59c.js → index-n386evxj.js} +1 -1
- package/dist/{index-vdw5yjfa.js → index-q7tbg07z.js} +110 -20
- package/dist/{index-ekpwvbra.js → index-qbssx940.js} +1 -2
- package/dist/{index-115b07ap.js → index-rr9kzq4n.js} +5 -5
- package/dist/{index-11621h23.js → index-tf4wzjew.js} +1 -1
- package/dist/{index-why54q5p.js → index-vnybgywh.js} +4 -4
- package/dist/{index-bcfn9xah.js → index-xv80vzfp.js} +7 -7
- package/dist/index.js +289 -95
- package/dist/percolate.js +2 -2
- package/dist/portfolio.js +16 -15
- package/dist/publish-model.js +36 -0
- package/dist/publish-reader/reader.css +1042 -0
- package/dist/publish-reader/reader.js +1534 -0
- package/dist/publish-reader/theme.js +92 -0
- package/dist/publish-search.js +52 -0
- package/dist/publish.js +36 -0
- package/dist/rerank-typesafe.js +13 -0
- package/dist/rerank.js +14 -0
- package/dist/sdk.js +16 -13
- package/dist/search.js +3 -3
- package/dist/semantic.js +5 -5
- package/dist/{support-vm4mkw0k.js → support-1rh2d7mt.js} +38 -32
- package/dist/workflows/decision-context.js +15 -14
- package/dist/workflows/index.js +15 -14
- package/package.json +65 -6
- package/skills/wordcell/AGENTS.md +1 -0
- package/skills/wordcell/SKILL.md +2 -1
- package/skills/wordcell/agents/openai.yaml +1 -1
- package/skills/wordcell/references/publish.md +127 -0
- package/skills/wordcell/references/query.md +22 -0
- package/skills/wordcell/references/refresh.md +14 -0
- package/src/authoring-model.ts +29 -0
- package/src/authoring-program.ts +38 -3
- package/src/authoring.ts +17 -3
- package/src/cli-program.ts +441 -12
- package/src/graph.ts +1 -1
- package/src/index.ts +4 -0
- package/src/oh/authority.ts +14 -5
- package/src/oh/canonical-rust.ts +127 -0
- package/src/oh/projection-rust.ts +63 -0
- package/src/oh-adoption.ts +7 -1
- package/src/publish-graph.ts +0 -0
- package/src/publish-index.ts +195 -0
- package/src/publish-markdown.ts +617 -0
- package/src/publish-model.ts +599 -0
- package/src/publish-nav.ts +204 -0
- package/src/publish-pages.ts +382 -0
- package/src/publish-reader/reader.css +1042 -0
- package/src/publish-reader/reader.ts +1017 -0
- package/src/publish-reader/theme.ts +97 -0
- package/src/publish-search.ts +418 -0
- package/src/publish-select.ts +419 -0
- package/src/publish-theme.ts +106 -0
- package/src/publish.ts +904 -0
- package/src/rerank-credentials.ts +56 -0
- package/src/rerank-typesafe.ts +472 -0
- package/src/rerank.ts +389 -0
- package/src/sdk.ts +157 -6
- package/src/serve.ts +180 -0
- package/src/vault.ts +23 -9
|
@@ -3,22 +3,28 @@ import {
|
|
|
3
3
|
backfillSavedUrlMetadata,
|
|
4
4
|
createRustMetadataSearchProvider
|
|
5
5
|
} from "./index-bcknqxrq.js";
|
|
6
|
+
import {
|
|
7
|
+
main as main2
|
|
8
|
+
} from "./index-054mb7d3.js";
|
|
6
9
|
import {
|
|
7
10
|
MAX_AUTHORIZED_VAULTS,
|
|
8
11
|
auditKnowledgePortfolio,
|
|
9
12
|
loadPortfolioRegistry,
|
|
10
13
|
openKnowledgePortfolio,
|
|
11
14
|
snapshotPortfolioRegistry
|
|
12
|
-
} from "./index-
|
|
13
|
-
import {
|
|
14
|
-
main as main2
|
|
15
|
-
} from "./index-054mb7d3.js";
|
|
15
|
+
} from "./index-bqtqeak3.js";
|
|
16
16
|
import {
|
|
17
17
|
diffCaptureBundle
|
|
18
18
|
} from "./index-j4zgmzjr.js";
|
|
19
|
+
import {
|
|
20
|
+
main
|
|
21
|
+
} from "./index-de2w8crk.js";
|
|
19
22
|
import {
|
|
20
23
|
verifyCaptureBundle
|
|
21
24
|
} from "./index-npg9z1a4.js";
|
|
25
|
+
import {
|
|
26
|
+
redactSensitiveText
|
|
27
|
+
} from "./index-mxxxytys.js";
|
|
22
28
|
import {
|
|
23
29
|
initVault
|
|
24
30
|
} from "./index-23z4zxgg.js";
|
|
@@ -27,18 +33,22 @@ import {
|
|
|
27
33
|
MAX_SOURCE_INBOX_RESULTS,
|
|
28
34
|
sourceInbox
|
|
29
35
|
} from "./index-pj501bh1.js";
|
|
36
|
+
import {
|
|
37
|
+
createTypeSafeReranker
|
|
38
|
+
} from "./index-9rf81m0p.js";
|
|
30
39
|
import {
|
|
31
40
|
knowledgeBaseEvaluationRetrieverIds,
|
|
32
41
|
openKnowledgeBaseEvaluation
|
|
33
|
-
} from "./index-
|
|
42
|
+
} from "./index-1k595z6v.js";
|
|
34
43
|
import {
|
|
35
44
|
DEFAULT_SEARCH_RESULTS,
|
|
36
45
|
MAX_SEARCH_CANDIDATES,
|
|
37
46
|
MAX_SEARCH_NOTE_REFERENCE_BYTES,
|
|
38
47
|
MAX_SEARCH_RELATED_SEEDS,
|
|
39
48
|
MAX_SEARCH_RESULTS,
|
|
40
|
-
openKnowledgeBase
|
|
41
|
-
|
|
49
|
+
openKnowledgeBase,
|
|
50
|
+
searchEvidenceRank
|
|
51
|
+
} from "./index-q7tbg07z.js";
|
|
42
52
|
import {
|
|
43
53
|
MAX_SEARCH_RULE_CONFIG_BYTES,
|
|
44
54
|
parseSearchRules
|
|
@@ -49,50 +59,55 @@ import {
|
|
|
49
59
|
recommendedEmbeddingModel,
|
|
50
60
|
recommendedEmbeddingModelSha256,
|
|
51
61
|
sha256EmbeddingModelFile
|
|
52
|
-
} from "./index-
|
|
62
|
+
} from "./index-rr9kzq4n.js";
|
|
53
63
|
import {
|
|
54
|
-
|
|
55
|
-
} from "./index-
|
|
64
|
+
MAX_RERANK_CANDIDATES
|
|
65
|
+
} from "./index-j70m75wd.js";
|
|
56
66
|
import {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
} from "./index-11621h23.js";
|
|
67
|
+
MAX_EVALUATION_RESULTS_PER_QUERY,
|
|
68
|
+
MAX_EVALUATION_TIMEOUT_MS,
|
|
69
|
+
buildRetrievalEvaluationReport,
|
|
70
|
+
parseRetrievalEvaluationCorpus,
|
|
71
|
+
runRetrievalEvaluation
|
|
72
|
+
} from "./index-b88v3vtm.js";
|
|
64
73
|
import {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} from "./index-0k2x4nn9.js";
|
|
74
|
+
percolateWithGraph
|
|
75
|
+
} from "./index-djrcc1yf.js";
|
|
68
76
|
import {
|
|
69
77
|
MAX_PERCOLATION_MENTIONS,
|
|
70
78
|
MAX_PERCOLATION_MENTION_PAIRS,
|
|
71
79
|
MAX_PERCOLATION_NOTES,
|
|
72
80
|
MAX_SCOPED_PERCOLATION_MENTION_PAIRS,
|
|
73
81
|
percolateVault
|
|
74
|
-
} from "./index-
|
|
82
|
+
} from "./index-jk1sgx36.js";
|
|
75
83
|
import {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
runRetrievalEvaluation
|
|
81
|
-
} from "./index-b88v3vtm.js";
|
|
84
|
+
queryGraph,
|
|
85
|
+
rebuildGraph,
|
|
86
|
+
verifyGraph
|
|
87
|
+
} from "./index-xv80vzfp.js";
|
|
82
88
|
import {
|
|
83
|
-
|
|
84
|
-
} from "./index-
|
|
89
|
+
validateGraphQueryRequest
|
|
90
|
+
} from "./index-tf4wzjew.js";
|
|
85
91
|
import {
|
|
86
|
-
|
|
87
|
-
} from "./index-
|
|
92
|
+
validateSearchQuery
|
|
93
|
+
} from "./index-vnybgywh.js";
|
|
88
94
|
import {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
} from "./index-6sw24nvv.js";
|
|
95
|
+
sanitizeTerminalLine,
|
|
96
|
+
sanitizeTerminalText
|
|
97
|
+
} from "./index-1xxnjn0d.js";
|
|
93
98
|
import {
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
DEFAULT_PUBLISH_LIST_LIMIT,
|
|
100
|
+
MAX_PUBLISH_LIST_LIMIT,
|
|
101
|
+
publishVault,
|
|
102
|
+
renderPublishReportText
|
|
103
|
+
} from "./index-hmw17zaa.js";
|
|
104
|
+
import {
|
|
105
|
+
refreshVault,
|
|
106
|
+
scanVault
|
|
107
|
+
} from "./index-233z9wmn.js";
|
|
108
|
+
import {
|
|
109
|
+
navigateLinks
|
|
110
|
+
} from "./index-d13v9ckt.js";
|
|
96
111
|
import {
|
|
97
112
|
MAX_QUERY_FILTERS,
|
|
98
113
|
MAX_QUERY_TAGS,
|
|
@@ -100,13 +115,18 @@ import {
|
|
|
100
115
|
validateQueryOptions
|
|
101
116
|
} from "./index-48pz4jpc.js";
|
|
102
117
|
import {
|
|
118
|
+
MAX_REPOSITORY_MEMORY_DETAIL_LIMIT,
|
|
103
119
|
MAX_REPOSITORY_SCOPES,
|
|
120
|
+
auditRepositoryMemoryScopes,
|
|
104
121
|
buildRepositoryMemoryContext,
|
|
105
122
|
repositoryMemoryGroupKeys
|
|
106
123
|
} from "./index-06c9ctr6.js";
|
|
107
124
|
import {
|
|
108
|
-
|
|
109
|
-
} from "./index-
|
|
125
|
+
findKbPackageRoot
|
|
126
|
+
} from "./index-4knsp9qj.js";
|
|
127
|
+
import {
|
|
128
|
+
auditAgentGuideRepository
|
|
129
|
+
} from "./index-hya40gb2.js";
|
|
110
130
|
import {
|
|
111
131
|
agentContextGuidePath,
|
|
112
132
|
agentContextMarkerForScope,
|
|
@@ -116,24 +136,19 @@ import {
|
|
|
116
136
|
inspectAgentContextRepository,
|
|
117
137
|
normalizeRepositoryScope
|
|
118
138
|
} from "./index-5vwpzb5a.js";
|
|
139
|
+
import {
|
|
140
|
+
validateMarkdownAttachments
|
|
141
|
+
} from "./index-x3fthpsc.js";
|
|
142
|
+
import {
|
|
143
|
+
addNoteRelation,
|
|
144
|
+
createNote,
|
|
145
|
+
removeNoteRelation
|
|
146
|
+
} from "./index-ecqpgr5y.js";
|
|
119
147
|
import {
|
|
120
148
|
lookupNote,
|
|
121
149
|
parseVaultKey,
|
|
122
150
|
renderCatalog
|
|
123
|
-
} from "./index-
|
|
124
|
-
import {
|
|
125
|
-
main
|
|
126
|
-
} from "./index-9zcpdbjg.js";
|
|
127
|
-
import {
|
|
128
|
-
findKbPackageRoot
|
|
129
|
-
} from "./index-jzcws0zn.js";
|
|
130
|
-
import {
|
|
131
|
-
redactSensitiveText
|
|
132
|
-
} from "./index-mxxxytys.js";
|
|
133
|
-
import {
|
|
134
|
-
sanitizeTerminalLine,
|
|
135
|
-
sanitizeTerminalText
|
|
136
|
-
} from "./index-1xxnjn0d.js";
|
|
151
|
+
} from "./index-qbssx940.js";
|
|
137
152
|
|
|
138
153
|
// src/clip/url-metadata-cli.ts
|
|
139
154
|
import { resolve as resolve2 } from "path";
|
|
@@ -800,7 +815,7 @@ function terminalIntro(terminal) {
|
|
|
800
815
|
}
|
|
801
816
|
|
|
802
817
|
// src/cli-program.ts
|
|
803
|
-
import { open } from "fs/promises";
|
|
818
|
+
import { open as open2 } from "fs/promises";
|
|
804
819
|
import { cpus, release, totalmem } from "os";
|
|
805
820
|
import { relative, resolve as resolve3 } from "path";
|
|
806
821
|
import { format } from "util";
|
|
@@ -905,13 +920,197 @@ Snapshot: ${value.revision}
|
|
|
905
920
|
};
|
|
906
921
|
}
|
|
907
922
|
|
|
923
|
+
// src/serve.ts
|
|
924
|
+
import { realpath, stat } from "fs/promises";
|
|
925
|
+
import { join as join2, sep } from "path";
|
|
926
|
+
var MAX_PATH_BYTES = 8 * 1024;
|
|
927
|
+
var CONTENT_TYPES = Object.freeze({
|
|
928
|
+
".avif": "image/avif",
|
|
929
|
+
".css": "text/css; charset=utf-8",
|
|
930
|
+
".gif": "image/gif",
|
|
931
|
+
".html": "text/html; charset=utf-8",
|
|
932
|
+
".ico": "image/x-icon",
|
|
933
|
+
".jpeg": "image/jpeg",
|
|
934
|
+
".jpg": "image/jpeg",
|
|
935
|
+
".js": "text/javascript; charset=utf-8",
|
|
936
|
+
".json": "application/json; charset=utf-8",
|
|
937
|
+
".map": "application/json; charset=utf-8",
|
|
938
|
+
".mp3": "audio/mpeg",
|
|
939
|
+
".mp4": "video/mp4",
|
|
940
|
+
".pdf": "application/pdf",
|
|
941
|
+
".png": "image/png",
|
|
942
|
+
".svg": "image/svg+xml",
|
|
943
|
+
".txt": "text/plain; charset=utf-8",
|
|
944
|
+
".wasm": "application/wasm",
|
|
945
|
+
".wav": "audio/wav",
|
|
946
|
+
".webm": "video/webm",
|
|
947
|
+
".webp": "image/webp",
|
|
948
|
+
".woff": "font/woff",
|
|
949
|
+
".woff2": "font/woff2",
|
|
950
|
+
".xml": "application/xml; charset=utf-8"
|
|
951
|
+
});
|
|
952
|
+
function contentType(path) {
|
|
953
|
+
const extension = path.slice(path.lastIndexOf("."));
|
|
954
|
+
return CONTENT_TYPES[extension] ?? "application/octet-stream";
|
|
955
|
+
}
|
|
956
|
+
async function regularFileUnder(rootReal, candidate) {
|
|
957
|
+
let resolved;
|
|
958
|
+
try {
|
|
959
|
+
resolved = await realpath(candidate);
|
|
960
|
+
} catch {
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
if (resolved !== rootReal && !resolved.startsWith(`${rootReal}${sep}`))
|
|
964
|
+
return null;
|
|
965
|
+
try {
|
|
966
|
+
return (await stat(resolved)).isFile() ? resolved : null;
|
|
967
|
+
} catch {
|
|
968
|
+
return null;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
async function resolveRequest(rootReal, pathname) {
|
|
972
|
+
let decoded;
|
|
973
|
+
try {
|
|
974
|
+
decoded = decodeURIComponent(pathname);
|
|
975
|
+
} catch {
|
|
976
|
+
return null;
|
|
977
|
+
}
|
|
978
|
+
if (decoded.includes("\x00") || decoded.includes("\\"))
|
|
979
|
+
return null;
|
|
980
|
+
const segments = decoded.split("/").filter((segment) => segment !== "" && segment !== ".");
|
|
981
|
+
if (segments.some((segment) => segment === ".."))
|
|
982
|
+
return null;
|
|
983
|
+
const relative = segments.join("/");
|
|
984
|
+
const candidates = [
|
|
985
|
+
join2(rootReal, relative),
|
|
986
|
+
join2(rootReal, relative, "index.html")
|
|
987
|
+
];
|
|
988
|
+
for (const candidate of candidates) {
|
|
989
|
+
const file = await regularFileUnder(rootReal, candidate);
|
|
990
|
+
if (file !== null)
|
|
991
|
+
return file;
|
|
992
|
+
}
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
async function createServeHandler(root) {
|
|
996
|
+
const rootReal = await realpath(root);
|
|
997
|
+
return async (request) => {
|
|
998
|
+
const method = request.method.toUpperCase();
|
|
999
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
1000
|
+
return new Response("Method not allowed", { status: 405 });
|
|
1001
|
+
}
|
|
1002
|
+
let pathname;
|
|
1003
|
+
try {
|
|
1004
|
+
pathname = new URL(request.url).pathname;
|
|
1005
|
+
} catch {
|
|
1006
|
+
return new Response("Bad request", { status: 400 });
|
|
1007
|
+
}
|
|
1008
|
+
if (pathname.length > MAX_PATH_BYTES) {
|
|
1009
|
+
return new Response("URI too long", { status: 414 });
|
|
1010
|
+
}
|
|
1011
|
+
const head = method === "HEAD";
|
|
1012
|
+
const file = await resolveRequest(rootReal, pathname);
|
|
1013
|
+
if (file !== null) {
|
|
1014
|
+
const body = Bun.file(file);
|
|
1015
|
+
return new Response(head ? null : body, {
|
|
1016
|
+
headers: {
|
|
1017
|
+
"Cache-Control": "no-store",
|
|
1018
|
+
"Content-Length": String(body.size),
|
|
1019
|
+
"Content-Type": contentType(file)
|
|
1020
|
+
}
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
const notFound = await regularFileUnder(rootReal, join2(rootReal, "404.html"));
|
|
1024
|
+
if (notFound !== null) {
|
|
1025
|
+
const body = Bun.file(notFound);
|
|
1026
|
+
return new Response(head ? null : body, {
|
|
1027
|
+
status: 404,
|
|
1028
|
+
headers: {
|
|
1029
|
+
"Cache-Control": "no-store",
|
|
1030
|
+
"Content-Length": String(body.size),
|
|
1031
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
return new Response(head ? null : "Not found", {
|
|
1036
|
+
status: 404,
|
|
1037
|
+
headers: { "Cache-Control": "no-store" }
|
|
1038
|
+
});
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
async function serveSite(options, io = {}) {
|
|
1042
|
+
const host = options.host ?? "127.0.0.1";
|
|
1043
|
+
const port = options.port ?? 8080;
|
|
1044
|
+
if (!Number.isSafeInteger(port) || port < 0 || port > 65535) {
|
|
1045
|
+
throw new Error("Port must be an integer from 0 through 65535");
|
|
1046
|
+
}
|
|
1047
|
+
const rootReal = await realpath(options.root);
|
|
1048
|
+
if (!(await stat(rootReal)).isDirectory()) {
|
|
1049
|
+
throw new Error(`Site root is not a directory: ${options.root}`);
|
|
1050
|
+
}
|
|
1051
|
+
const listen = io.listen ?? ((init) => Bun.serve(init));
|
|
1052
|
+
const server = listen({
|
|
1053
|
+
hostname: host,
|
|
1054
|
+
port,
|
|
1055
|
+
fetch: await createServeHandler(rootReal)
|
|
1056
|
+
});
|
|
1057
|
+
const boundPort = server.port ?? port;
|
|
1058
|
+
return Object.freeze({
|
|
1059
|
+
root: rootReal,
|
|
1060
|
+
host,
|
|
1061
|
+
port: boundPort,
|
|
1062
|
+
url: `http://${host}:${String(boundPort)}/`,
|
|
1063
|
+
close: () => server.stop()
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// src/rerank-credentials.ts
|
|
1068
|
+
import { constants as constants2 } from "fs";
|
|
1069
|
+
import { open } from "fs/promises";
|
|
1070
|
+
import { homedir } from "os";
|
|
1071
|
+
import { isAbsolute as isAbsolute2, join as join3 } from "path";
|
|
1072
|
+
function unavailable(message) {
|
|
1073
|
+
return { id: "typesafe", rerank: async () => ({ status: "unavailable", message }) };
|
|
1074
|
+
}
|
|
1075
|
+
async function createCliTypeSafeReranker(environment = process.env, homeDirectory = homedir()) {
|
|
1076
|
+
if (Object.hasOwn(environment, "TYPESAFE_API_KEY")) {
|
|
1077
|
+
return createTypeSafeReranker({ environment: { TYPESAFE_API_KEY: environment["TYPESAFE_API_KEY"] } });
|
|
1078
|
+
}
|
|
1079
|
+
const explicitFile = environment["TYPESAFE_API_KEY_FILE"];
|
|
1080
|
+
const configDirectory = environment["XDG_CONFIG_HOME"];
|
|
1081
|
+
if (explicitFile !== undefined && !isAbsolute2(explicitFile) || configDirectory !== undefined && configDirectory !== "" && !isAbsolute2(configDirectory)) {
|
|
1082
|
+
return unavailable("TypeSafe credential file configuration requires absolute paths.");
|
|
1083
|
+
}
|
|
1084
|
+
const path = explicitFile ?? join3(configDirectory || join3(homeDirectory, ".config"), "wordcell", "typesafe-api-key");
|
|
1085
|
+
let handle;
|
|
1086
|
+
try {
|
|
1087
|
+
handle = await open(path, constants2.O_RDONLY | constants2.O_NOFOLLOW | constants2.O_NONBLOCK);
|
|
1088
|
+
const metadata = await handle.stat();
|
|
1089
|
+
const uid = process.getuid?.();
|
|
1090
|
+
if (!metadata.isFile() || metadata.nlink !== 1 || metadata.size < 1 || metadata.size > 514 || process.platform !== "win32" && ((metadata.mode & 63) !== 0 || metadata.uid !== uid)) {
|
|
1091
|
+
return unavailable("TypeSafe credential file must be an owner-only regular file containing one API key.");
|
|
1092
|
+
}
|
|
1093
|
+
const bytes = Buffer.alloc(515);
|
|
1094
|
+
const { bytesRead } = await handle.read(bytes, 0, bytes.length, 0);
|
|
1095
|
+
const key = bytes.subarray(0, bytesRead).toString("utf8").replace(/\r?\n$/u, "");
|
|
1096
|
+
if (!/^[\x21-\x7e]{1,512}$/u.test(key)) {
|
|
1097
|
+
return unavailable("TypeSafe credential file must contain one valid API key.");
|
|
1098
|
+
}
|
|
1099
|
+
return createTypeSafeReranker({ environment: { TYPESAFE_API_KEY: key } });
|
|
1100
|
+
} catch {
|
|
1101
|
+
return unavailable("TypeSafe credentials are unavailable; set TYPESAFE_API_KEY or an owner-only TYPESAFE_API_KEY_FILE.");
|
|
1102
|
+
} finally {
|
|
1103
|
+
await handle?.close();
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
|
|
908
1107
|
// src/cli-program.ts
|
|
909
1108
|
var defaultOutput2 = {
|
|
910
1109
|
stdout: (value) => process.stdout.write(value),
|
|
911
1110
|
stderr: (value) => process.stderr.write(value)
|
|
912
1111
|
};
|
|
913
1112
|
async function readBoundedUtf8(path, maximumBytes, label) {
|
|
914
|
-
const handle = await
|
|
1113
|
+
const handle = await open2(path, "r");
|
|
915
1114
|
try {
|
|
916
1115
|
const bytes = new Uint8Array(maximumBytes + 1);
|
|
917
1116
|
let offset = 0;
|
|
@@ -943,7 +1142,16 @@ async function loadSearchRulesFile(path) {
|
|
|
943
1142
|
}
|
|
944
1143
|
return parseSearchRules(input);
|
|
945
1144
|
}
|
|
946
|
-
var usage = `wordcell \u2014
|
|
1145
|
+
var usage = `wordcell \u2014 a local knowledge base for coding agents
|
|
1146
|
+
|
|
1147
|
+
Start here (no account or model needed):
|
|
1148
|
+
wordcell init kb
|
|
1149
|
+
wordcell note create notes/decision --title "A decision" --body "Keep retries bounded." --root kb
|
|
1150
|
+
wordcell search "retries" --root kb --mode exact
|
|
1151
|
+
|
|
1152
|
+
Already have Markdown? Search it with --root <your-notes-directory>.
|
|
1153
|
+
Use --mode exact for model-free search; optional hybrid search needs a local index.
|
|
1154
|
+
Quick start and examples: https://wordcell.io/docs
|
|
947
1155
|
|
|
948
1156
|
Usage:
|
|
949
1157
|
wordcell init [directory] [--json]
|
|
@@ -956,7 +1164,7 @@ Usage:
|
|
|
956
1164
|
wordcell inspect <url> [capture options]
|
|
957
1165
|
wordcell pdf <file-or-url> [PDF options]
|
|
958
1166
|
wordcell refresh [--root <directory>] [--index <path>] [--json]
|
|
959
|
-
wordcell check [--root <directory>] [--index <path>] [--no-catalog] [--json]
|
|
1167
|
+
wordcell check [--root <directory>] [--index <path>] [--no-catalog] [--repo <repository>] [--json]
|
|
960
1168
|
wordcell catalog [--root <directory>] [--index <path>] [--json]
|
|
961
1169
|
wordcell graph [--root <directory>] [--index <path>] [--json]
|
|
962
1170
|
wordcell graph rebuild [--fresh] [--root <directory>] [--index <path>] [--json]
|
|
@@ -971,12 +1179,14 @@ Usage:
|
|
|
971
1179
|
wordcell percolate [note] [--proofs] [--root <directory>] [--min-support <count>] [--limit <count>] [--json]
|
|
972
1180
|
wordcell list [--root <directory>] [--where <path=value>] [--has <path>] [--tag <tag>] [--scope <repository-path>] [--sort <field>] [--order <asc|desc>] [--limit <count>] [--json]
|
|
973
1181
|
wordcell index [--root <directory>] [--database <path>] [--force] [--json]
|
|
974
|
-
wordcell search <query> [--root <directory>] [--repo <repository>] [--database <path>] [--mode <hybrid|exact|keyword|semantic>] [--rules <file>] [--priority] [--where <path=value>] [--has <path>] [--tag <tag>] [--scope <repository-path>] [--related <note>] [--graph-depth <1|2>] [--no-graph] [--history | --no-history | --require-history] [--limit <count>] [--candidate-limit <count>] [--min-score <score>] [--json]
|
|
1182
|
+
wordcell search <query> [--root <directory>] [--repo <repository>] [--database <path>] [--mode <hybrid|exact|keyword|semantic>] [--rules <file>] [--priority] [--where <path=value>] [--has <path>] [--tag <tag>] [--scope <repository-path>] [--related <note>] [--graph-depth <1|2>] [--no-graph] [--history | --no-history | --require-history] [--limit <count>] [--candidate-limit <count>] [--min-score <score>] [--rerank <typesafe>] [--rerank-limit <2..25>] [--json]
|
|
975
1183
|
wordcell history <note> [--root <directory>] [--repo <repository>] [--limit <count>] [--cochanged-limit <count>] [--json]
|
|
976
1184
|
wordcell history search <query-or-path> [--root <directory>] [--repo <repository>] [--limit <count>] [--commit-limit <count>] [--cochanged-limit <count>] [--json]
|
|
977
1185
|
wordcell evaluate <manifest.json> [--root <directory>] [--repo <repository>] [--database <path>] [--retriever <id>] [--split <development|test|all>] [--limit <count>] [--cutoff <count>] [--timeout <milliseconds>] [--baseline <id>] [--model-file <path>] [--cache-state <cold|mixed|warm>] [--json]
|
|
978
1186
|
wordcell portfolio search <query> --registry <file> --workspace <directory> (--shared | --vault <owner/id>...) [--mode <hybrid|exact|keyword|semantic>] [--rules <file>] [--priority] [--limit <count>] [--require-all] [--json]
|
|
979
1187
|
wordcell portfolio audit --registry <file> --workspace <directory> (--all | --shared | --vault <owner/id>...) [--strict] [--json]
|
|
1188
|
+
wordcell publish --out <directory> [--root <directory>] [--index <path>] [--include <path>]... [--exclude <path>]... [--include-glob <pattern>]... [--exclude-glob <pattern>]... [--where <path=value>]... [--has <path>]... [--tag <tag>]... [--scope <repository-path>]... [--from <note> [--depth <count>] [--direction <in|out|both>]] [--title <title>] [--description <text>] [--base-path <path>] [--base-url <url>] [--noindex] [--no-index-content] [--deterministic] [--dry-run] [--list-limit <0-1000>] [--force] [--json]
|
|
1189
|
+
wordcell serve --root <directory> [--host <host>] [--port <port>] [--json]
|
|
980
1190
|
wordcell inbox [--root <directory>] [--source-prefix <directory>] [--limit <count>] [--json]
|
|
981
1191
|
wordcell context <repository-path> [--root <vault>] [--repo <repository>] [--kind <auto|file|directory>] [--json]
|
|
982
1192
|
wordcell agents identity <repository-scope> [--json]
|
|
@@ -1084,6 +1294,7 @@ function parseVaultCommand(command, arguments_) {
|
|
|
1084
1294
|
let depth = 1;
|
|
1085
1295
|
let limit;
|
|
1086
1296
|
let noCatalog = false;
|
|
1297
|
+
let repository;
|
|
1087
1298
|
const positional = [];
|
|
1088
1299
|
for (let cursor = 0;cursor < arguments_.length; cursor += 1) {
|
|
1089
1300
|
const argument = arguments_[cursor];
|
|
@@ -1097,6 +1308,14 @@ function parseVaultCommand(command, arguments_) {
|
|
|
1097
1308
|
noCatalog = true;
|
|
1098
1309
|
continue;
|
|
1099
1310
|
}
|
|
1311
|
+
if (argument === "--repo" && command === "check") {
|
|
1312
|
+
const value = readValue(arguments_, cursor);
|
|
1313
|
+
if (value === null)
|
|
1314
|
+
return { ok: false, message: "--repo requires a value" };
|
|
1315
|
+
repository = value;
|
|
1316
|
+
cursor += 1;
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1100
1319
|
if (argument === "--root" || argument === "--index") {
|
|
1101
1320
|
const value = readValue(arguments_, cursor);
|
|
1102
1321
|
if (value === null)
|
|
@@ -1163,7 +1382,8 @@ function parseVaultCommand(command, arguments_) {
|
|
|
1163
1382
|
root,
|
|
1164
1383
|
options: index === undefined ? {} : { index },
|
|
1165
1384
|
json,
|
|
1166
|
-
...command === "check" && noCatalog ? { noCatalog: true } : {}
|
|
1385
|
+
...command === "check" && noCatalog ? { noCatalog: true } : {},
|
|
1386
|
+
...command === "check" && repository !== undefined ? { repository } : {}
|
|
1167
1387
|
}
|
|
1168
1388
|
};
|
|
1169
1389
|
}
|
|
@@ -1367,6 +1587,220 @@ function parseListCommand(arguments_) {
|
|
|
1367
1587
|
}
|
|
1368
1588
|
};
|
|
1369
1589
|
}
|
|
1590
|
+
function parsePublishCommand(arguments_) {
|
|
1591
|
+
let root = ".";
|
|
1592
|
+
let out;
|
|
1593
|
+
let index;
|
|
1594
|
+
let title;
|
|
1595
|
+
let description;
|
|
1596
|
+
let basePath;
|
|
1597
|
+
let baseUrl;
|
|
1598
|
+
let noindex = false;
|
|
1599
|
+
let indexContent = true;
|
|
1600
|
+
let deterministic = false;
|
|
1601
|
+
let dryRun = false;
|
|
1602
|
+
let listLimit = DEFAULT_PUBLISH_LIST_LIMIT;
|
|
1603
|
+
let force = false;
|
|
1604
|
+
let json = false;
|
|
1605
|
+
let from;
|
|
1606
|
+
let depth = 1;
|
|
1607
|
+
let direction = "both";
|
|
1608
|
+
const includes = [];
|
|
1609
|
+
const excludes = [];
|
|
1610
|
+
const includeGlobs = [];
|
|
1611
|
+
const excludeGlobs = [];
|
|
1612
|
+
const filters = [];
|
|
1613
|
+
const tags = [];
|
|
1614
|
+
const repositoryScopes = [];
|
|
1615
|
+
for (let cursor = 0;cursor < arguments_.length; cursor += 1) {
|
|
1616
|
+
const argument = arguments_[cursor];
|
|
1617
|
+
if (argument === undefined)
|
|
1618
|
+
continue;
|
|
1619
|
+
if (argument === "--json") {
|
|
1620
|
+
json = true;
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1623
|
+
if (argument === "--noindex") {
|
|
1624
|
+
noindex = true;
|
|
1625
|
+
continue;
|
|
1626
|
+
}
|
|
1627
|
+
if (argument === "--no-index-content") {
|
|
1628
|
+
indexContent = false;
|
|
1629
|
+
continue;
|
|
1630
|
+
}
|
|
1631
|
+
if (argument === "--deterministic") {
|
|
1632
|
+
deterministic = true;
|
|
1633
|
+
continue;
|
|
1634
|
+
}
|
|
1635
|
+
if (argument === "--dry-run") {
|
|
1636
|
+
dryRun = true;
|
|
1637
|
+
continue;
|
|
1638
|
+
}
|
|
1639
|
+
if (argument === "--force") {
|
|
1640
|
+
force = true;
|
|
1641
|
+
continue;
|
|
1642
|
+
}
|
|
1643
|
+
if (argument === "--root" || argument === "--out" || argument === "--index" || argument === "--title" || argument === "--description" || argument === "--base-path" || argument === "--base-url" || argument === "--include" || argument === "--exclude" || argument === "--include-glob" || argument === "--exclude-glob" || argument === "--list-limit" || argument === "--where" || argument === "--has" || argument === "--tag" || argument === "--scope" || argument === "--repository-scope" || argument === "--from" || argument === "--depth" || argument === "--direction") {
|
|
1644
|
+
const value = readValue(arguments_, cursor);
|
|
1645
|
+
if (value === null)
|
|
1646
|
+
return { ok: false, message: `${argument} requires a value` };
|
|
1647
|
+
if (argument === "--root")
|
|
1648
|
+
root = value;
|
|
1649
|
+
else if (argument === "--out")
|
|
1650
|
+
out = value;
|
|
1651
|
+
else if (argument === "--index")
|
|
1652
|
+
index = value;
|
|
1653
|
+
else if (argument === "--title")
|
|
1654
|
+
title = value;
|
|
1655
|
+
else if (argument === "--description")
|
|
1656
|
+
description = value;
|
|
1657
|
+
else if (argument === "--base-path")
|
|
1658
|
+
basePath = value;
|
|
1659
|
+
else if (argument === "--base-url")
|
|
1660
|
+
baseUrl = value;
|
|
1661
|
+
else if (argument === "--include")
|
|
1662
|
+
includes.push(value);
|
|
1663
|
+
else if (argument === "--exclude")
|
|
1664
|
+
excludes.push(value);
|
|
1665
|
+
else if (argument === "--include-glob")
|
|
1666
|
+
includeGlobs.push(value);
|
|
1667
|
+
else if (argument === "--exclude-glob")
|
|
1668
|
+
excludeGlobs.push(value);
|
|
1669
|
+
else if (argument === "--list-limit") {
|
|
1670
|
+
if (!/^(0|[1-9][0-9]*)$/u.test(value) || Number(value) > MAX_PUBLISH_LIST_LIMIT) {
|
|
1671
|
+
return { ok: false, message: `--list-limit must be an integer from 0 through ${MAX_PUBLISH_LIST_LIMIT}` };
|
|
1672
|
+
}
|
|
1673
|
+
listLimit = Number(value);
|
|
1674
|
+
} else if (argument === "--from")
|
|
1675
|
+
from = value;
|
|
1676
|
+
else if (argument === "--depth") {
|
|
1677
|
+
const parsed = Number(value);
|
|
1678
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > 10) {
|
|
1679
|
+
return { ok: false, message: "--depth must be an integer from 1 through 10" };
|
|
1680
|
+
}
|
|
1681
|
+
depth = parsed;
|
|
1682
|
+
} else if (argument === "--direction") {
|
|
1683
|
+
if (value !== "in" && value !== "out" && value !== "both") {
|
|
1684
|
+
return { ok: false, message: "--direction must be in, out, or both" };
|
|
1685
|
+
}
|
|
1686
|
+
direction = value;
|
|
1687
|
+
} else if (argument === "--tag") {
|
|
1688
|
+
if (tags.length >= MAX_QUERY_TAGS) {
|
|
1689
|
+
return { ok: false, message: `Query tags may contain at most ${MAX_QUERY_TAGS} entries.` };
|
|
1690
|
+
}
|
|
1691
|
+
tags.push(value);
|
|
1692
|
+
} else if (argument === "--scope" || argument === "--repository-scope") {
|
|
1693
|
+
if (repositoryScopes.length >= MAX_REPOSITORY_SCOPES) {
|
|
1694
|
+
return { ok: false, message: `Repository scope filters may contain at most ${MAX_REPOSITORY_SCOPES} entries.` };
|
|
1695
|
+
}
|
|
1696
|
+
repositoryScopes.push(value);
|
|
1697
|
+
} else if (argument === "--has") {
|
|
1698
|
+
if (value.trim() === "")
|
|
1699
|
+
return { ok: false, message: "--has requires a metadata path" };
|
|
1700
|
+
if (filters.length >= MAX_QUERY_FILTERS) {
|
|
1701
|
+
return { ok: false, message: `Query filters may contain at most ${MAX_QUERY_FILTERS} entries.` };
|
|
1702
|
+
}
|
|
1703
|
+
filters.push({ kind: "exists", path: value });
|
|
1704
|
+
} else {
|
|
1705
|
+
const equals = value.indexOf("=");
|
|
1706
|
+
const path = equals === -1 ? "" : value.slice(0, equals).trim();
|
|
1707
|
+
if (path === "")
|
|
1708
|
+
return { ok: false, message: "--where requires path=value" };
|
|
1709
|
+
const scalar = metadataScalar(value.slice(equals + 1));
|
|
1710
|
+
if (!scalar.ok)
|
|
1711
|
+
return scalar;
|
|
1712
|
+
if (filters.length >= MAX_QUERY_FILTERS) {
|
|
1713
|
+
return { ok: false, message: `Query filters may contain at most ${MAX_QUERY_FILTERS} entries.` };
|
|
1714
|
+
}
|
|
1715
|
+
filters.push({ kind: "equals", path, value: scalar.value });
|
|
1716
|
+
}
|
|
1717
|
+
cursor += 1;
|
|
1718
|
+
continue;
|
|
1719
|
+
}
|
|
1720
|
+
return {
|
|
1721
|
+
ok: false,
|
|
1722
|
+
message: argument.startsWith("--") ? "unknown publish option" : "publish does not accept positional arguments"
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
if (out === undefined)
|
|
1726
|
+
return { ok: false, message: "publish requires --out <directory>" };
|
|
1727
|
+
try {
|
|
1728
|
+
validateQueryOptions({ filters, tags, repositoryScopes });
|
|
1729
|
+
} catch (error) {
|
|
1730
|
+
return { ok: false, message: error instanceof Error ? error.message : String(error) };
|
|
1731
|
+
}
|
|
1732
|
+
const selection = {
|
|
1733
|
+
includes,
|
|
1734
|
+
excludes,
|
|
1735
|
+
includeGlobs,
|
|
1736
|
+
excludeGlobs,
|
|
1737
|
+
filters,
|
|
1738
|
+
tags,
|
|
1739
|
+
repositoryScopes,
|
|
1740
|
+
...from === undefined ? {} : { from: { note: from, depth, direction } }
|
|
1741
|
+
};
|
|
1742
|
+
return {
|
|
1743
|
+
ok: true,
|
|
1744
|
+
value: {
|
|
1745
|
+
kind: "publish",
|
|
1746
|
+
root,
|
|
1747
|
+
out,
|
|
1748
|
+
noindex,
|
|
1749
|
+
indexContent,
|
|
1750
|
+
deterministic,
|
|
1751
|
+
dryRun,
|
|
1752
|
+
listLimit,
|
|
1753
|
+
force,
|
|
1754
|
+
selection,
|
|
1755
|
+
json,
|
|
1756
|
+
...index === undefined ? {} : { index },
|
|
1757
|
+
...title === undefined ? {} : { title },
|
|
1758
|
+
...description === undefined ? {} : { description },
|
|
1759
|
+
...basePath === undefined ? {} : { basePath },
|
|
1760
|
+
...baseUrl === undefined ? {} : { baseUrl }
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
function parseServeCommand(arguments_) {
|
|
1765
|
+
let root;
|
|
1766
|
+
let host = "127.0.0.1";
|
|
1767
|
+
let port = 8080;
|
|
1768
|
+
let json = false;
|
|
1769
|
+
for (let cursor = 0;cursor < arguments_.length; cursor += 1) {
|
|
1770
|
+
const argument = arguments_[cursor];
|
|
1771
|
+
if (argument === undefined)
|
|
1772
|
+
continue;
|
|
1773
|
+
if (argument === "--json") {
|
|
1774
|
+
json = true;
|
|
1775
|
+
continue;
|
|
1776
|
+
}
|
|
1777
|
+
if (argument === "--root" || argument === "--host" || argument === "--port") {
|
|
1778
|
+
const value = readValue(arguments_, cursor);
|
|
1779
|
+
if (value === null)
|
|
1780
|
+
return { ok: false, message: `${argument} requires a value` };
|
|
1781
|
+
if (argument === "--root")
|
|
1782
|
+
root = value;
|
|
1783
|
+
else if (argument === "--host")
|
|
1784
|
+
host = value;
|
|
1785
|
+
else {
|
|
1786
|
+
const parsed = Number(value);
|
|
1787
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > 65535) {
|
|
1788
|
+
return { ok: false, message: "--port must be an integer from 0 through 65535" };
|
|
1789
|
+
}
|
|
1790
|
+
port = parsed;
|
|
1791
|
+
}
|
|
1792
|
+
cursor += 1;
|
|
1793
|
+
continue;
|
|
1794
|
+
}
|
|
1795
|
+
return {
|
|
1796
|
+
ok: false,
|
|
1797
|
+
message: argument.startsWith("--") ? "unknown serve option" : "serve does not accept positional arguments"
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
if (root === undefined)
|
|
1801
|
+
return { ok: false, message: "serve requires --root <directory>" };
|
|
1802
|
+
return { ok: true, value: { kind: "serve", root, host, port, json } };
|
|
1803
|
+
}
|
|
1370
1804
|
function parseInboxCommand(arguments_) {
|
|
1371
1805
|
let root = ".";
|
|
1372
1806
|
let index;
|
|
@@ -1439,6 +1873,8 @@ function parseSemanticCommand(command, arguments_) {
|
|
|
1439
1873
|
let limit;
|
|
1440
1874
|
let candidateLimit;
|
|
1441
1875
|
let minScore;
|
|
1876
|
+
let rerank;
|
|
1877
|
+
let rerankLimit;
|
|
1442
1878
|
let graphDepth;
|
|
1443
1879
|
let noGraph = false;
|
|
1444
1880
|
let history = false;
|
|
@@ -1496,7 +1932,7 @@ function parseSemanticCommand(command, arguments_) {
|
|
|
1496
1932
|
cursor += 1;
|
|
1497
1933
|
continue;
|
|
1498
1934
|
}
|
|
1499
|
-
if (command === "search" && (argument === "--mode" || argument === "--limit" || argument === "--candidate-limit" || argument === "--min-score" || argument === "--where" || argument === "--has" || argument === "--tag" || argument === "--scope" || argument === "--repository-scope" || argument === "--related" || argument === "--graph-depth")) {
|
|
1935
|
+
if (command === "search" && (argument === "--mode" || argument === "--limit" || argument === "--candidate-limit" || argument === "--min-score" || argument === "--rerank" || argument === "--rerank-limit" || argument === "--where" || argument === "--has" || argument === "--tag" || argument === "--scope" || argument === "--repository-scope" || argument === "--related" || argument === "--graph-depth")) {
|
|
1500
1936
|
const value = readValue(arguments_, cursor);
|
|
1501
1937
|
if (value === null)
|
|
1502
1938
|
return { ok: false, message: `${argument} requires a value` };
|
|
@@ -1505,6 +1941,17 @@ function parseSemanticCommand(command, arguments_) {
|
|
|
1505
1941
|
return { ok: false, message: "--mode must be hybrid, exact, keyword, or semantic" };
|
|
1506
1942
|
}
|
|
1507
1943
|
mode = value;
|
|
1944
|
+
} else if (argument === "--rerank") {
|
|
1945
|
+
if (value !== "typesafe") {
|
|
1946
|
+
return { ok: false, message: "--rerank must be typesafe" };
|
|
1947
|
+
}
|
|
1948
|
+
rerank = value;
|
|
1949
|
+
} else if (argument === "--rerank-limit") {
|
|
1950
|
+
const parsed = Number(value);
|
|
1951
|
+
if (!Number.isSafeInteger(parsed) || parsed < 2 || parsed > MAX_RERANK_CANDIDATES) {
|
|
1952
|
+
return { ok: false, message: `--rerank-limit must be an integer from 2 through ${MAX_RERANK_CANDIDATES}` };
|
|
1953
|
+
}
|
|
1954
|
+
rerankLimit = parsed;
|
|
1508
1955
|
} else if (argument === "--where") {
|
|
1509
1956
|
const equals = value.indexOf("=");
|
|
1510
1957
|
const path = equals === -1 ? "" : value.slice(0, equals).trim();
|
|
@@ -1637,6 +2084,9 @@ function parseSemanticCommand(command, arguments_) {
|
|
|
1637
2084
|
message: "Search minimum score applies only to hybrid, keyword, or semantic mode."
|
|
1638
2085
|
};
|
|
1639
2086
|
}
|
|
2087
|
+
if (rerankLimit !== undefined && rerank === undefined) {
|
|
2088
|
+
return { ok: false, message: "--rerank-limit requires --rerank typesafe" };
|
|
2089
|
+
}
|
|
1640
2090
|
if (priority && rulesPath === undefined) {
|
|
1641
2091
|
return { ok: false, message: "--priority requires --rules" };
|
|
1642
2092
|
}
|
|
@@ -1674,6 +2124,8 @@ function parseSemanticCommand(command, arguments_) {
|
|
|
1674
2124
|
...limit === undefined ? {} : { limit },
|
|
1675
2125
|
...candidateLimit === undefined ? {} : { candidateLimit },
|
|
1676
2126
|
...minScore === undefined ? {} : { minScore },
|
|
2127
|
+
...rerank === undefined ? {} : { rerank },
|
|
2128
|
+
...rerankLimit === undefined ? {} : { rerankLimit },
|
|
1677
2129
|
query,
|
|
1678
2130
|
json
|
|
1679
2131
|
}
|
|
@@ -2420,6 +2872,10 @@ function parseArguments(arguments_) {
|
|
|
2420
2872
|
return parseRelationCommand(arguments_.slice(1));
|
|
2421
2873
|
if (command === "percolate")
|
|
2422
2874
|
return parsePercolateCommand(arguments_.slice(1));
|
|
2875
|
+
if (command === "publish")
|
|
2876
|
+
return parsePublishCommand(arguments_.slice(1));
|
|
2877
|
+
if (command === "serve")
|
|
2878
|
+
return parseServeCommand(arguments_.slice(1));
|
|
2423
2879
|
return { ok: false, message: "unknown command" };
|
|
2424
2880
|
}
|
|
2425
2881
|
function embeddingCount(result) {
|
|
@@ -2440,11 +2896,23 @@ function renderKnowledgeBaseSearch(result) {
|
|
|
2440
2896
|
const lines = [
|
|
2441
2897
|
`${result.mode[0]?.toLocaleUpperCase("en-US") ?? ""}${result.mode.slice(1)} results for \u201C${safe(result.query)}\u201D (${result.results.length})${result.partial ? " [partial]" : ""}`
|
|
2442
2898
|
];
|
|
2899
|
+
const rerankLane = result.diagnostics.lanes.find(({ lane }) => lane === "rerank");
|
|
2900
|
+
if (rerankLane !== undefined) {
|
|
2901
|
+
lines.push(` Rerank: typesafe over ${rerankLane.results} candidates (${rerankLane.status})` + (rerankLane.message === undefined ? "" : ` \u2014 ${safe(rerankLane.message)}`));
|
|
2902
|
+
const receipt = rerankLane.rerank;
|
|
2903
|
+
if (receipt?.accounting !== undefined) {
|
|
2904
|
+
const { attempted, candidates, completed, elapsedMs, usageComplete } = receipt.accounting;
|
|
2905
|
+
lines.push(` Rerank requests: ${attempted}/${candidates} attempted, ${completed} settled; ${elapsedMs.toFixed(0)} ms` + (usageComplete ? "; usage complete" : "; usage incomplete, additional charges may be unknown"));
|
|
2906
|
+
if (rerankLane.status !== "ready" && receipt.usage !== undefined) {
|
|
2907
|
+
lines.push(` Known rerank usage: ${receipt.usage.inputTokens ?? 0} input tokens, ${receipt.usage.outputTokens ?? 0} output tokens`);
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2443
2911
|
if (result.results.length === 0)
|
|
2444
2912
|
lines.push(" None.");
|
|
2445
2913
|
for (const hit of result.results) {
|
|
2446
2914
|
const location = `${safe(hit.path)}${hit.line === undefined ? "" : `:${hit.line}`}`;
|
|
2447
|
-
const evidence = hit.evidence.map((item) => `${item.kind}#${item
|
|
2915
|
+
const evidence = hit.evidence.map((item) => `${item.kind}#${searchEvidenceRank(item)}`).join(", ");
|
|
2448
2916
|
lines.push(` ${hit.rank}. ${hit.score.toFixed(3)} ${location} \u2014 ${safe(hit.title)} [${safe(evidence)}]`);
|
|
2449
2917
|
if (hit.snippet !== "")
|
|
2450
2918
|
lines.push(` ${safe(hit.snippet)}`);
|
|
@@ -2476,7 +2944,7 @@ async function runSemantic(command, output, dependencies) {
|
|
|
2476
2944
|
repository: command.repository,
|
|
2477
2945
|
...command.database === undefined ? {} : { database: command.database },
|
|
2478
2946
|
...searchRules === undefined ? {} : { searchRules }
|
|
2479
|
-
});
|
|
2947
|
+
}, ...command.rerank === undefined ? [] : [{ rerankers: dependencies.rerankers ?? [await createCliTypeSafeReranker()] }]);
|
|
2480
2948
|
try {
|
|
2481
2949
|
const result = await kb.search({
|
|
2482
2950
|
query: command.query,
|
|
@@ -2489,7 +2957,13 @@ async function runSemantic(command, output, dependencies) {
|
|
|
2489
2957
|
history: command.history,
|
|
2490
2958
|
...command.limit === undefined ? {} : { limit: command.limit },
|
|
2491
2959
|
...command.candidateLimit === undefined ? {} : { candidateLimit: command.candidateLimit },
|
|
2492
|
-
...command.minScore === undefined ? {} : { minScore: command.minScore }
|
|
2960
|
+
...command.minScore === undefined ? {} : { minScore: command.minScore },
|
|
2961
|
+
...command.rerank === undefined ? {} : {
|
|
2962
|
+
rerank: {
|
|
2963
|
+
engine: command.rerank,
|
|
2964
|
+
...command.rerankLimit === undefined ? {} : { limit: command.rerankLimit }
|
|
2965
|
+
}
|
|
2966
|
+
}
|
|
2493
2967
|
});
|
|
2494
2968
|
output.stdout(command.json ? terminalSafeJson(result) : sanitizeTerminalText(renderKnowledgeBaseSearch(result)));
|
|
2495
2969
|
return 0;
|
|
@@ -2744,7 +3218,8 @@ function summary(snapshot, options = {}) {
|
|
|
2744
3218
|
truncated: options.attachments.truncated,
|
|
2745
3219
|
issues: options.attachments.issues
|
|
2746
3220
|
}
|
|
2747
|
-
}
|
|
3221
|
+
},
|
|
3222
|
+
...options.repositoryScopes === undefined ? {} : { repositoryScopes: options.repositoryScopes }
|
|
2748
3223
|
};
|
|
2749
3224
|
}
|
|
2750
3225
|
function renderIssue(issue) {
|
|
@@ -2777,6 +3252,38 @@ function renderAdvisories(analysis) {
|
|
|
2777
3252
|
}
|
|
2778
3253
|
return lines;
|
|
2779
3254
|
}
|
|
3255
|
+
function renderRepositoryScopeAuditError(error) {
|
|
3256
|
+
if (error.kind === "invalid-record") {
|
|
3257
|
+
return `${safe(error.path)}: ${error.issues.map(safe).join(" ")}`;
|
|
3258
|
+
}
|
|
3259
|
+
const declared = error.recordPaths.map(safe).join(", ") + (error.recordPathsTruncated ? ", \u2026" : "");
|
|
3260
|
+
return `${safe(error.scope)}: ${safe(error.state.reason)} at ${safe(error.state.path)}` + ` (declared by ${declared})`;
|
|
3261
|
+
}
|
|
3262
|
+
function renderRepositoryScopeAudit(audit) {
|
|
3263
|
+
const { counts } = audit;
|
|
3264
|
+
const lines = [
|
|
3265
|
+
`Repository scopes: ${counts.authoredRecords} declaring note${counts.authoredRecords === 1 ? "" : "s"}; ` + `${counts.distinctScopes} distinct scope${counts.distinctScopes === 1 ? "" : "s"} ` + `(${counts.presentScopes} present, ${counts.absentScopes} absent, ${counts.invalidScopes} unusable).`
|
|
3266
|
+
];
|
|
3267
|
+
if (audit.advisories.total > 0) {
|
|
3268
|
+
lines.push(audit.advisories.total === 1 ? "Advisory: 1 current note declares a repository path that no longer exists." : `Advisory: ${audit.advisories.total} current notes declare repository paths that no longer exist.`);
|
|
3269
|
+
for (const advisory of audit.advisories.details) {
|
|
3270
|
+
lines.push(` ${safe(advisory.path)} declares absent scope ${safe(advisory.scope)}`);
|
|
3271
|
+
}
|
|
3272
|
+
if (audit.advisories.truncated) {
|
|
3273
|
+
lines.push(` \u2026 ${audit.advisories.total - audit.advisories.returned} more; rerun with --json for the complete audit.`);
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
if (audit.errors.total > 0) {
|
|
3277
|
+
lines.push(`Advisory: ${audit.errors.total} repository scope declaration problem${audit.errors.total === 1 ? "" : "s"}.`);
|
|
3278
|
+
for (const error of audit.errors.details) {
|
|
3279
|
+
lines.push(` ${renderRepositoryScopeAuditError(error)}`);
|
|
3280
|
+
}
|
|
3281
|
+
if (audit.errors.truncated) {
|
|
3282
|
+
lines.push(` \u2026 ${audit.errors.total - audit.errors.returned} more; rerun with --json for the complete audit.`);
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
return lines;
|
|
3286
|
+
}
|
|
2780
3287
|
function checkExitCode(snapshot, noCatalog = false, attachments) {
|
|
2781
3288
|
return !noCatalog && snapshot.index === "stale" || snapshot.analysis.issues.length > 0 || snapshot.analysis.relationIssues.length > 0 || (attachments?.issues.length ?? 0) > 0 || attachments?.truncated === true ? 3 : 0;
|
|
2782
3289
|
}
|
|
@@ -2784,7 +3291,7 @@ function renderAttachmentIssue(issue) {
|
|
|
2784
3291
|
const candidates = issue.candidates === undefined ? "" : ` (${issue.candidates.map(safe).join(", ")})`;
|
|
2785
3292
|
return `${safe(issue.source)}:${issue.line}: ${safe(issue.kind)} attachment ${safe(issue.target)}: ${safe(issue.message)}${candidates}`;
|
|
2786
3293
|
}
|
|
2787
|
-
function renderSnapshot(command, snapshot, noCatalog = false, attachments) {
|
|
3294
|
+
function renderSnapshot(command, snapshot, noCatalog = false, attachments, repositoryScopes) {
|
|
2788
3295
|
const lines = [
|
|
2789
3296
|
`${command === "refresh" ? "Refreshed" : "Checked"} ${safe(snapshot.root)}`,
|
|
2790
3297
|
`Index: ${noCatalog ? `not required (${snapshot.index})` : snapshot.index}; notes: ${snapshot.analysis.noteCount}; contextual links: ${snapshot.analysis.contextualLinks.length}; typed relationships: ${snapshot.analysis.authoredRelations.length}.`
|
|
@@ -2804,6 +3311,8 @@ function renderSnapshot(command, snapshot, noCatalog = false, attachments) {
|
|
|
2804
3311
|
lines.push("error: attachment validation was truncated by a resource limit");
|
|
2805
3312
|
}
|
|
2806
3313
|
lines.push(...renderAdvisories(snapshot.analysis));
|
|
3314
|
+
if (repositoryScopes !== undefined)
|
|
3315
|
+
lines.push(...renderRepositoryScopeAudit(repositoryScopes));
|
|
2807
3316
|
return `${lines.join(`
|
|
2808
3317
|
`)}
|
|
2809
3318
|
`;
|
|
@@ -3104,6 +3613,36 @@ async function runList(command, output, dependencies) {
|
|
|
3104
3613
|
output.stdout(command.json ? terminalSafeJson({ root: snapshot.root, count: rows.length, notes: rows }) : sanitizeTerminalText(renderList(rows)));
|
|
3105
3614
|
return 0;
|
|
3106
3615
|
}
|
|
3616
|
+
async function runPublish(command, output, dependencies) {
|
|
3617
|
+
const result = await (dependencies.publishVault ?? publishVault)({
|
|
3618
|
+
root: command.root,
|
|
3619
|
+
out: command.out,
|
|
3620
|
+
noindex: command.noindex,
|
|
3621
|
+
indexContent: command.indexContent,
|
|
3622
|
+
deterministic: command.deterministic,
|
|
3623
|
+
dryRun: command.dryRun,
|
|
3624
|
+
listLimit: command.listLimit,
|
|
3625
|
+
force: command.force,
|
|
3626
|
+
selection: command.selection,
|
|
3627
|
+
...command.index === undefined ? {} : { index: command.index },
|
|
3628
|
+
...command.title === undefined ? {} : { title: command.title },
|
|
3629
|
+
...command.description === undefined ? {} : { description: command.description },
|
|
3630
|
+
...command.basePath === undefined ? {} : { basePath: command.basePath },
|
|
3631
|
+
...command.baseUrl === undefined ? {} : { baseUrl: command.baseUrl }
|
|
3632
|
+
});
|
|
3633
|
+
output.stdout(command.json ? terminalSafeJson(result.report) : sanitizeTerminalText(renderPublishReportText(result.report, command.dryRun)));
|
|
3634
|
+
return 0;
|
|
3635
|
+
}
|
|
3636
|
+
async function runServe(command, output, dependencies) {
|
|
3637
|
+
const site = await (dependencies.serveSite ?? serveSite)({
|
|
3638
|
+
root: command.root,
|
|
3639
|
+
host: command.host,
|
|
3640
|
+
port: command.port
|
|
3641
|
+
});
|
|
3642
|
+
output.stdout(command.json ? terminalSafeJson({ root: site.root, host: site.host, port: site.port, url: site.url }) : `Serving ${safe(site.root)} at ${safe(site.url)}
|
|
3643
|
+
`);
|
|
3644
|
+
return 0;
|
|
3645
|
+
}
|
|
3107
3646
|
async function runCatalog(command, output, dependencies) {
|
|
3108
3647
|
const snapshot = await (dependencies.scanVault ?? scanVault)(command.root, command.options);
|
|
3109
3648
|
const relativeIndex = relative(snapshot.root, snapshot.indexPath).split("\\").join("/");
|
|
@@ -3558,7 +4097,15 @@ async function runVault(command, output, dependencies) {
|
|
|
3558
4097
|
root: snapshot.root,
|
|
3559
4098
|
documents: snapshot.notes.map(({ path, content }) => ({ path, content }))
|
|
3560
4099
|
}) : undefined;
|
|
3561
|
-
|
|
4100
|
+
const repositoryScopes = command.kind === "check" && command.repository !== undefined ? await (dependencies.auditRepositoryMemoryScopes ?? auditRepositoryMemoryScopes)(snapshot.notes, {
|
|
4101
|
+
repositoryRoot: command.repository,
|
|
4102
|
+
detailLimit: MAX_REPOSITORY_MEMORY_DETAIL_LIMIT
|
|
4103
|
+
}) : undefined;
|
|
4104
|
+
output.stdout(command.json ? terminalSafeJson(summary(snapshot, {
|
|
4105
|
+
noCatalog,
|
|
4106
|
+
...attachments === undefined ? {} : { attachments },
|
|
4107
|
+
...repositoryScopes === undefined ? {} : { repositoryScopes }
|
|
4108
|
+
})) : sanitizeTerminalText(renderSnapshot(command.kind, snapshot, noCatalog, attachments, repositoryScopes)));
|
|
3562
4109
|
return checkExitCode(snapshot, noCatalog, attachments);
|
|
3563
4110
|
}
|
|
3564
4111
|
if (command.kind === "graph") {
|
|
@@ -3673,6 +4220,10 @@ ${sanitizeTerminalText(usage)}`);
|
|
|
3673
4220
|
return await runPercolate(command, output, dependencies);
|
|
3674
4221
|
if (command.kind === "list")
|
|
3675
4222
|
return await runList(command, output, dependencies);
|
|
4223
|
+
if (command.kind === "publish")
|
|
4224
|
+
return await runPublish(command, output, dependencies);
|
|
4225
|
+
if (command.kind === "serve")
|
|
4226
|
+
return await runServe(command, output, dependencies);
|
|
3676
4227
|
if (command.kind === "inbox")
|
|
3677
4228
|
return await runInbox(command, output, dependencies);
|
|
3678
4229
|
if (command.kind === "catalog")
|