@hraness/wordcell 0.24.1 → 0.25.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 CHANGED
@@ -54,14 +54,14 @@ Wordcell keeps the record in Markdown files you own, rebuilds every index from t
54
54
  The CLI and TypeScript SDK run with Bun. Install the versioned GitHub archive:
55
55
 
56
56
  ```sh
57
- bun add --global --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz
57
+ bun add --global --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.25.1/hraness-wordcell-0.25.1.tgz
58
58
  wordcell --help
59
59
  ```
60
60
 
61
61
  Prefer npm? The same release is [mirrored there](https://www.npmjs.com/package/@hraness/wordcell):
62
62
 
63
63
  ```sh
64
- npm install --global --ignore-scripts @hraness/wordcell@0.24.1
64
+ npm install --global --ignore-scripts @hraness/wordcell@0.25.1
65
65
  wordcell --help
66
66
  ```
67
67
 
@@ -103,7 +103,7 @@ After trying the CLI, install the public Agent Skill into a compatible agent,
103
103
  such as Claude Code, Codex, Cursor, or GitHub Copilot:
104
104
 
105
105
  ```sh
106
- bunx skills add hraness/wordcell#v0.24.1 --skill wordcell
106
+ bunx skills add hraness/wordcell#v0.25.1 --skill wordcell
107
107
  ```
108
108
 
109
109
  Then ask:
@@ -334,7 +334,7 @@ exist. [Graph queries and proof limits](https://github.com/hraness/wordcell/blob
334
334
  Add the same immutable release to a Bun project:
335
335
 
336
336
  ```sh
337
- bun add --exact --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz
337
+ bun add --exact --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.25.1/hraness-wordcell-0.25.1.tgz
338
338
  ```
339
339
 
340
340
  The SDK provides read-only vault sessions, metadata queries, search, graph
package/dist/capture.js CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  captureSummary,
6
6
  main,
7
7
  runCapture
8
- } from "./index-2fmnttca.js";
9
- import"./index-6jcz0m1c.js";
8
+ } from "./index-t3abkwk4.js";
9
+ import"./index-hxyjer3x.js";
10
10
  import"./index-k86wepd8.js";
11
11
  import {
12
12
  adapterCapabilities,
package/dist/cli.js CHANGED
@@ -6,13 +6,13 @@ import {
6
6
  parseArguments,
7
7
  runExecutable,
8
8
  usage
9
- } from "./index-jqkkb4fr.js";
10
- import"./index-t0fh8a1q.js";
9
+ } from "./index-1wccy765.js";
10
+ import"./index-47893rgw.js";
11
11
  import"./index-qfqjfxaa.js";
12
12
  import"./index-hz2wyggk.js";
13
13
  import"./index-j4zgmzjr.js";
14
- import"./index-2fmnttca.js";
15
- import"./index-6jcz0m1c.js";
14
+ import"./index-t3abkwk4.js";
15
+ import"./index-hxyjer3x.js";
16
16
  import"./index-k86wepd8.js";
17
17
  import"./index-nwrehke7.js";
18
18
  import"./index-5n05se68.js";
@@ -63,7 +63,7 @@ import {
63
63
 
64
64
  // src/cli.ts
65
65
  if (import.meta.main) {
66
- const { standaloneSupportEnvironment, isUsefulSupportResult, runProductSupportCommand, showProductSupportInvitation } = await import("./support-07jpt1z4.js");
66
+ const { standaloneSupportEnvironment, isUsefulSupportResult, runProductSupportCommand, showProductSupportInvitation } = await import("./support-adj7bbge.js");
67
67
  const env = standaloneSupportEnvironment();
68
68
  const args = process.argv.slice(2);
69
69
  if (args[0] === "support") {
package/dist/clip/cli.js CHANGED
@@ -5,8 +5,8 @@ import {
5
5
  captureSucceeded,
6
6
  captureSummary,
7
7
  main
8
- } from "../index-2fmnttca.js";
9
- import"../index-6jcz0m1c.js";
8
+ } from "../index-t3abkwk4.js";
9
+ import"../index-hxyjer3x.js";
10
10
  import"../index-k86wepd8.js";
11
11
  import"../index-nwrehke7.js";
12
12
  import"../index-5n05se68.js";
@@ -1,6 +1,90 @@
1
1
  // @bun
2
+ import"../index-z1w83f81.js";
3
+
2
4
  // src/clip/defuddle-worker.ts
3
5
  import { Defuddle } from "defuddle/node";
6
+
7
+ // src/clip/embedded-article.ts
8
+ var EMBEDDED_ARTICLE_LIMITS = Object.freeze({ htmlBytes: 8 * 1024 * 1024, scripts: 64, jsonBytes: 256 * 1024, bodyBytes: 192 * 1024, depth: 8 });
9
+ function shallowJson(value) {
10
+ let depth = 0, quoted = false, escaped = false;
11
+ for (const char of value) {
12
+ if (quoted) {
13
+ if (escaped)
14
+ escaped = false;
15
+ else if (char === "\\")
16
+ escaped = true;
17
+ else if (char === '"')
18
+ quoted = false;
19
+ } else if (char === '"')
20
+ quoted = true;
21
+ else if (char === "{" || char === "[") {
22
+ if (++depth > EMBEDDED_ARTICLE_LIMITS.depth)
23
+ return false;
24
+ } else if (char === "}" || char === "]")
25
+ depth--;
26
+ }
27
+ return !quoted && depth === 0;
28
+ }
29
+ var escapeText = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
30
+ async function embeddedArticleHtml(html, sourceUrl) {
31
+ if (Buffer.byteLength(html) > EMBEDDED_ARTICLE_LIMITS.htmlBytes)
32
+ return null;
33
+ let source;
34
+ try {
35
+ source = new URL(sourceUrl);
36
+ } catch {
37
+ return null;
38
+ }
39
+ if (!/^https?:$/.test(source.protocol) || source.username || source.password)
40
+ return null;
41
+ source.hash = "";
42
+ let scripts = 0, candidates = 0, active = false, invalid = false, payload = "";
43
+ const rewriter = new HTMLRewriter().on("script", {
44
+ element(element) {
45
+ if (++scripts > EMBEDDED_ARTICLE_LIMITS.scripts)
46
+ invalid = true;
47
+ active = element.getAttribute("id") === "jsonArticle";
48
+ if (!active)
49
+ return;
50
+ candidates++;
51
+ if (element.getAttribute("type")?.toLowerCase() !== "application/json" || element.hasAttribute("src"))
52
+ invalid = true;
53
+ },
54
+ text(chunk) {
55
+ if (!active || invalid)
56
+ return;
57
+ payload += chunk.text;
58
+ if (Buffer.byteLength(payload) > EMBEDDED_ARTICLE_LIMITS.jsonBytes)
59
+ invalid = true;
60
+ }
61
+ });
62
+ await rewriter.transform(new Response(html)).text();
63
+ if (invalid || candidates !== 1 || !shallowJson(payload))
64
+ return null;
65
+ let value;
66
+ try {
67
+ value = JSON.parse(payload);
68
+ } catch {
69
+ return null;
70
+ }
71
+ if (typeof value !== "object" || value === null || Array.isArray(value))
72
+ return null;
73
+ const row = value;
74
+ if (Object.keys(row).length > 128 || row.dataType !== "Article" || !Number.isSafeInteger(row.dataId) || row.dataId <= 0 || typeof row.urlArticle !== "string" || row.urlArticle.length > 8192 || typeof row.title !== "string" || !row.title.trim() || Buffer.byteLength(row.title) > 4096 || typeof row.body !== "string" || !row.body.trim() || Buffer.byteLength(row.body) > EMBEDDED_ARTICLE_LIMITS.bodyBytes)
75
+ return null;
76
+ let article;
77
+ try {
78
+ article = new URL(row.urlArticle, source);
79
+ } catch {
80
+ return null;
81
+ }
82
+ if (article.username || article.password || article.hash || article.href !== source.href || article.pathname.split("/").filter(Boolean).at(-1) !== String(row.dataId))
83
+ return null;
84
+ return `<!doctype html><html><head><title>${escapeText(row.title)}</title></head><body><article><h1>${escapeText(row.title)}</h1>${row.body}</article></body></html>`;
85
+ }
86
+
87
+ // src/clip/defuddle-worker.ts
4
88
  var workerGlobal = globalThis;
5
89
  function asciiCaseEqualAt(value, offset, expected, end = value.length) {
6
90
  if (offset < 0 || offset + expected.length > end)
@@ -68,8 +152,9 @@ workerGlobal.onmessage = async (event) => {
68
152
  return;
69
153
  }
70
154
  try {
71
- const videoPosters = collectVideoPosters(request.html);
72
- const value = await Defuddle(request.html, request.url, {
155
+ const extractionHtml = request.includeReplies === false ? await embeddedArticleHtml(request.html, request.url) ?? request.html : request.html;
156
+ const videoPosters = collectVideoPosters(extractionHtml);
157
+ const value = await Defuddle(extractionHtml, request.url, {
73
158
  markdown: false,
74
159
  separateMarkdown: true,
75
160
  includeReplies: request.includeReplies,
@@ -3,7 +3,7 @@ import {
3
3
  backfillSavedUrlMetadata,
4
4
  createRustMetadataSearchProvider,
5
5
  savedSourceProblem
6
- } from "./index-t0fh8a1q.js";
6
+ } from "./index-47893rgw.js";
7
7
  import {
8
8
  main as main2
9
9
  } from "./index-qfqjfxaa.js";
@@ -19,7 +19,7 @@ import {
19
19
  } from "./index-j4zgmzjr.js";
20
20
  import {
21
21
  main
22
- } from "./index-2fmnttca.js";
22
+ } from "./index-t3abkwk4.js";
23
23
  import {
24
24
  detectAudience,
25
25
  renderFailure,
@@ -7879,7 +7879,7 @@ async function main4(rawArguments = process.argv.slice(2), output = defaultOutpu
7879
7879
  }
7880
7880
  try {
7881
7881
  if (command.kind === "clip") {
7882
- return await (dependencies.runClipCommand ?? main)(command.arguments, process.env, output);
7882
+ return await (dependencies.runClipCommand ?? main)(command.arguments, terminal.env, output);
7883
7883
  }
7884
7884
  if (command.kind === "capture-bundle")
7885
7885
  return await runCaptureBundle(command, output, dependencies);
@@ -7890,10 +7890,10 @@ async function main4(rawArguments = process.argv.slice(2), output = defaultOutpu
7890
7890
  if (command.kind === "portfolio-audit")
7891
7891
  return await runPortfolioAudit(command, output, dependencies);
7892
7892
  if (command.kind === "url-metadata") {
7893
- return await (dependencies.runUrlMetadataCommand ?? main3)(command.arguments, process.env, output);
7893
+ return await (dependencies.runUrlMetadataCommand ?? main3)(command.arguments, terminal.env, output);
7894
7894
  }
7895
7895
  if (command.kind === "pdf") {
7896
- return await (dependencies.runPdfCommand ?? main2)(command.arguments, process.env, output);
7896
+ return await (dependencies.runPdfCommand ?? main2)(command.arguments, terminal.env, output);
7897
7897
  }
7898
7898
  if (command.kind === "init") {
7899
7899
  return await runInit(command, output, dependencies.initVault ?? initVault, dependencies.terminal ?? processTerminal());
@@ -5,7 +5,7 @@ import {
5
5
  parseArchiveTodayMementoUrl,
6
6
  parseMetadataSearchResponse,
7
7
  rankMetadataSearchResults
8
- } from "./index-6jcz0m1c.js";
8
+ } from "./index-hxyjer3x.js";
9
9
  import {
10
10
  assertSafeNetworkUrl,
11
11
  isPrivateHostname,
@@ -314,11 +314,12 @@ function deterministicResponse(response, maximumResults) {
314
314
  results: Object.freeze(results),
315
315
  enginesQueried,
316
316
  enginesFailed: Object.freeze([...response.enginesFailed].sort()),
317
- engineStatus: response.engineStatus
317
+ engineStatus: response.engineStatus,
318
+ ...response.engineFailures === undefined ? {} : { engineFailures: Object.freeze([...response.engineFailures].sort((a, b) => compareText(a.engine, b.engine))) }
318
319
  });
319
320
  }
320
- async function resolveEngineHosts(resolver, timeoutMs) {
321
- const resolved = await Promise.all(METADATA_SEARCH_ENGINE_HOSTS.map(async (hostname) => {
321
+ async function resolveEngineHosts(resolver, timeoutMs, enableBingRss, enableOpenAlexDiscovery) {
322
+ const resolved = await Promise.all([...METADATA_SEARCH_ENGINE_HOSTS, ...enableBingRss ? ["www.bing.com"] : [], ...enableOpenAlexDiscovery ? ["api.openalex.org"] : []].map(async (hostname) => {
322
323
  const addresses = await resolver(new URL(`https://${hostname}/`), {
323
324
  allowPrivateNetwork: false,
324
325
  timeoutMs
@@ -364,6 +365,12 @@ function createExactUrlSearchQuery(value) {
364
365
  return `"${exactUrl}"`;
365
366
  }
366
367
  function createRustMetadataSearchProvider(options) {
368
+ if (options.enableBingRss !== undefined && typeof options.enableBingRss !== "boolean")
369
+ throw new TypeError("enableBingRss must be boolean.");
370
+ const enableBingRss = options.enableBingRss === true;
371
+ if (options.enableOpenAlexDiscovery !== undefined && typeof options.enableOpenAlexDiscovery !== "boolean")
372
+ throw new TypeError("enableOpenAlexDiscovery must be boolean.");
373
+ const enableOpenAlexDiscovery = options.enableOpenAlexDiscovery === true;
367
374
  if (!isAbsolute(options.binaryPath)) {
368
375
  throw new TypeError("The metadata search binary path must be absolute.");
369
376
  }
@@ -389,7 +396,7 @@ function createRustMetadataSearchProvider(options) {
389
396
  return failure("aborted", "Metadata search was aborted.");
390
397
  let engineHosts;
391
398
  try {
392
- engineHosts = await resolveEngineHosts(resolveNetworkTarget, validated.timeoutMs);
399
+ engineHosts = await resolveEngineHosts(resolveNetworkTarget, validated.timeoutMs, enableBingRss, enableOpenAlexDiscovery);
393
400
  } catch {
394
401
  return failure("unavailable", "Metadata search network targets are unavailable.");
395
402
  }
@@ -413,6 +420,9 @@ function createRustMetadataSearchProvider(options) {
413
420
  try {
414
421
  const input = JSON.stringify({
415
422
  schema_version: REQUEST_SCHEMA_VERSION,
423
+ diagnostics: true,
424
+ ...enableBingRss ? { bing_rss: true } : {},
425
+ ...enableOpenAlexDiscovery ? { openalex_discovery: true } : {},
416
426
  query: validated.query,
417
427
  max_results: validated.maxResults,
418
428
  timeout_ms: validated.timeoutMs,
@@ -30,6 +30,25 @@ var ARCHIVE_TODAY_HOSTS = Object.freeze([
30
30
  "archive.md",
31
31
  "archive.vn"
32
32
  ]);
33
+ var METADATA_SEARCH_FAILURE_CODES = [
34
+ "timeout",
35
+ "http",
36
+ "http-body",
37
+ "http-status",
38
+ "http-forbidden",
39
+ "http-rate-limited",
40
+ "http-redirect",
41
+ "parse",
42
+ "unverified-empty",
43
+ "challenge",
44
+ "content-type",
45
+ "content-encoding",
46
+ "body-limit",
47
+ "body-encoding",
48
+ "result-limit",
49
+ "unrecognized-html",
50
+ "query-mismatch"
51
+ ];
33
52
  var archiveTodayHosts = new Set(ARCHIVE_TODAY_HOSTS);
34
53
  var tokenCharacter = /^[!#$%&'*+.^_`|~0-9A-Za-z-]$/u;
35
54
  var engineName = /^[a-z0-9][a-z0-9._-]{0,127}$/u;
@@ -140,7 +159,7 @@ function parseMetadataResult(value, index, queried, failed, budget) {
140
159
  }
141
160
  function parseMetadataSearchResponse(value) {
142
161
  const input = record(value, "Metadata search response");
143
- strictKeys(input, ["query", "results", "engines_queried", "engines_failed"], "Metadata search response");
162
+ strictKeys(input, ["query", "results", "engines_queried", "engines_failed", "engine_failures", "engine_usage"], "Metadata search response");
144
163
  const budget = { bytes: 0 };
145
164
  const query = boundedString(input.query, "Metadata search response.query", MAX_METADATA_SEARCH_QUERY_UTF8_BYTES, budget);
146
165
  if (query === "" || query !== query.trim() || hasUnsafeControls(query)) {
@@ -157,12 +176,44 @@ function parseMetadataSearchResponse(value) {
157
176
  fail("Metadata search response.results", `must be an array with at most ${MAX_METADATA_SEARCH_RESULTS} entries.`);
158
177
  }
159
178
  const failed = new Set(enginesFailed);
179
+ let engineFailures;
180
+ if (Object.hasOwn(input, "engine_failures")) {
181
+ if (!Array.isArray(input.engine_failures) || input.engine_failures.length !== enginesFailed.length) {
182
+ fail("Metadata search response.engine_failures", "must cover every failed engine exactly once.");
183
+ }
184
+ const seen = new Set;
185
+ engineFailures = Object.freeze(input.engine_failures.map((value2, index) => {
186
+ const label = `Metadata search response.engine_failures[${index}]`;
187
+ const entry = record(value2, label);
188
+ strictKeys(entry, ["engine", "code"], label);
189
+ if (typeof entry.engine !== "string" || !failed.has(entry.engine) || seen.has(entry.engine)) {
190
+ fail(label, "must name a unique failed, queried engine.");
191
+ }
192
+ if (typeof entry.code !== "string" || !METADATA_SEARCH_FAILURE_CODES.some((code) => code === entry.code)) {
193
+ fail(label, "must contain a known categorical failure code.");
194
+ }
195
+ seen.add(entry.engine);
196
+ return Object.freeze({ engine: entry.engine, code: entry.code });
197
+ }));
198
+ }
160
199
  const results = Object.freeze(input.results.map((result, index) => parseMetadataResult(result, index, queried, failed, budget)));
200
+ let engineUsage;
201
+ if (Object.hasOwn(input, "engine_usage")) {
202
+ if (!Array.isArray(input.engine_usage) || input.engine_usage.length !== 1)
203
+ fail("Metadata search response.engine_usage", "must contain one bounded OpenAlex usage record.");
204
+ const entry = record(input.engine_usage[0], "engine usage");
205
+ strictKeys(entry, ["engine", "reported_cost_usd", "billing_status"], "engine usage");
206
+ if (entry.engine !== "openalex" || !enginesQueried.includes("openalex") || failed.has("openalex") || typeof entry.reported_cost_usd !== "number" || !Number.isFinite(entry.reported_cost_usd) || entry.reported_cost_usd < 0 || entry.reported_cost_usd > 1e6 || entry.billing_status !== "not-established")
207
+ fail("engine usage", "must preserve bounded provider-reported usage without asserting billing.");
208
+ engineUsage = Object.freeze([Object.freeze({ engine: "openalex", reportedCostUsd: entry.reported_cost_usd, billingStatus: "not-established" })]);
209
+ }
161
210
  return Object.freeze({
162
211
  query,
163
212
  results,
164
213
  enginesQueried,
165
214
  enginesFailed,
215
+ ...engineFailures === undefined ? {} : { engineFailures },
216
+ ...engineUsage === undefined ? {} : { engineUsage },
166
217
  engineStatus: enginesFailed.length === 0 ? "complete" : enginesFailed.length === enginesQueried.length ? "unavailable" : "partial"
167
218
  });
168
219
  }
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  acquireArchiveTodaySnapshot,
4
4
  discoverArchiveTodaySnapshot
5
- } from "./index-6jcz0m1c.js";
5
+ } from "./index-hxyjer3x.js";
6
6
  import {
7
7
  canonicalizeUrl,
8
8
  chooseBestExtraction,
@@ -2,15 +2,15 @@
2
2
  import {
3
3
  parseArguments as parseArguments2,
4
4
  parseUrlMetadataArguments
5
- } from "./index-jqkkb4fr.js";
6
- import"./index-t0fh8a1q.js";
5
+ } from "./index-1wccy765.js";
6
+ import"./index-47893rgw.js";
7
7
  import {
8
8
  parsePdfArguments
9
9
  } from "./index-qfqjfxaa.js";
10
10
  import"./index-hz2wyggk.js";
11
11
  import"./index-j4zgmzjr.js";
12
- import"./index-2fmnttca.js";
13
- import"./index-6jcz0m1c.js";
12
+ import"./index-t3abkwk4.js";
13
+ import"./index-hxyjer3x.js";
14
14
  import"./index-k86wepd8.js";
15
15
  import"./index-nwrehke7.js";
16
16
  import"./index-5n05se68.js";
@@ -10,7 +10,7 @@ import {
10
10
  readUrlMetadataDocument,
11
11
  renderUrlMetadataDocument,
12
12
  writeUrlMetadataDocument
13
- } from "./index-t0fh8a1q.js";
13
+ } from "./index-47893rgw.js";
14
14
  import {
15
15
  ARCHIVE_TODAY_HOSTS,
16
16
  ArchiveTodayFailure,
@@ -23,7 +23,7 @@ import {
23
23
  parseMetadataSearchResponse,
24
24
  rankMetadataSearchResults,
25
25
  selectNewestArchiveTodayMemento
26
- } from "./index-6jcz0m1c.js";
26
+ } from "./index-hxyjer3x.js";
27
27
  import"./index-e5fbsywq.js";
28
28
  import"./index-gh719d91.js";
29
29
  import"./index-mxxxytys.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hraness/wordcell",
3
- "version": "0.24.1",
3
+ "version": "0.25.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",
@@ -369,6 +369,8 @@
369
369
  "src/clip/metadata-search-tool/runner.ts",
370
370
  "src/clip/metadata-search-tool/src/main.rs",
371
371
  "src/clip/metadata-search-tool/src/duckduckgo.rs",
372
+ "src/clip/metadata-search-tool/src/bing.rs",
373
+ "src/clip/metadata-search-tool/src/openalex.rs",
372
374
  "src/git.ts",
373
375
  "src/evaluation-analysis-v2.ts",
374
376
  "src/evaluation-builder.ts",
@@ -473,10 +475,10 @@
473
475
  "src/directory-sync.ts"
474
476
  ],
475
477
  "scripts": {
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",
478
+ "kb:refresh": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell refresh --root kb",
479
+ "kb:check:lane": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell check --root kb --no-catalog",
480
+ "kb:check": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell check --root kb && bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell agents check --root kb --repo .",
481
+ "kb:catalog": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell catalog --root kb",
480
482
  "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",
481
483
  "check:workflows": "bun ./scripts/check-workflow-yaml.ts",
482
484
  "check:installed-command-docs": "bun ./scripts/check-installed-command-docs.ts",
@@ -491,8 +493,8 @@
491
493
  "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",
492
494
  "prepack": "bun run check",
493
495
  "check:effect": "bun run scripts/check-effect-policy.ts",
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",
496
+ "kb:search": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell search --root kb --mode exact --selected-passage --rerank typesafe --rerank-limit 25",
497
+ "kb:search:local": "bunx --bun --package https://github.com/hraness/wordcell/releases/download/v0.24.1/hraness-wordcell-0.24.1.tgz wordcell search --root kb --mode exact --selected-passage",
496
498
  "check:worker": "tsc -p worker/tsconfig.json --noEmit"
497
499
  },
498
500
  "dependencies": {
@@ -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.24.1/hraness-wordcell-0.24.1.tgz
61
+ bun add --global --ignore-scripts https://github.com/hraness/wordcell/releases/download/v0.25.1/hraness-wordcell-0.25.1.tgz
62
62
  }
63
63
  wordcell --help
64
64
  ```
@@ -4500,17 +4500,17 @@ export async function main(
4500
4500
  }
4501
4501
  try {
4502
4502
  if (command.kind === "clip") {
4503
- return await (dependencies.runClipCommand ?? runClipCommand)(command.arguments, process.env, output);
4503
+ return await (dependencies.runClipCommand ?? runClipCommand)(command.arguments, terminal.env, output);
4504
4504
  }
4505
4505
  if (command.kind === "capture-bundle") return await runCaptureBundle(command, output, dependencies);
4506
4506
  if (command.kind === "capture-diff") return await runCaptureDiff(command, output, dependencies);
4507
4507
  if (command.kind === "portfolio-search") return await runPortfolioSearch(command, output, dependencies);
4508
4508
  if (command.kind === "portfolio-audit") return await runPortfolioAudit(command, output, dependencies);
4509
4509
  if (command.kind === "url-metadata") {
4510
- return await (dependencies.runUrlMetadataCommand ?? runUrlMetadataCommand)(command.arguments, process.env, output);
4510
+ return await (dependencies.runUrlMetadataCommand ?? runUrlMetadataCommand)(command.arguments, terminal.env, output);
4511
4511
  }
4512
4512
  if (command.kind === "pdf") {
4513
- return await (dependencies.runPdfCommand ?? runPdfCommand)(command.arguments, process.env, output);
4513
+ return await (dependencies.runPdfCommand ?? runPdfCommand)(command.arguments, terminal.env, output);
4514
4514
  }
4515
4515
  if (command.kind === "init") {
4516
4516
  return await runInit(command, output, dependencies.initVault ?? initVault, dependencies.terminal ?? processTerminal());
@@ -896,6 +896,7 @@ version = "0.1.0"
896
896
  dependencies = [
897
897
  "libc",
898
898
  "metadata-search-engine-rs",
899
+ "quick-xml",
899
900
  "reqwest",
900
901
  "scraper",
901
902
  "serde",
@@ -1311,6 +1312,15 @@ dependencies = [
1311
1312
  "psl-types",
1312
1313
  ]
1313
1314
 
1315
+ [[package]]
1316
+ name = "quick-xml"
1317
+ version = "0.42.0"
1318
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1319
+ checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b"
1320
+ dependencies = [
1321
+ "memchr",
1322
+ ]
1323
+
1314
1324
  [[package]]
1315
1325
  name = "quote"
1316
1326
  version = "1.0.47"
@@ -9,6 +9,7 @@ metadata-search-engine-rs = { git = "https://github.com/MikeLuu99/searxng-rust",
9
9
  libc = "=0.2.189"
10
10
  reqwest = { version = "=0.12.28", features = ["brotli", "cookies", "gzip"] }
11
11
  scraper = "=0.20.0"
12
+ quick-xml = "=0.42.0"
12
13
  url = "=2.5.8"
13
14
  serde = { version = "1", features = ["derive"] }
14
15
  serde_json = "1"