@absolutejs/rag 0.22.8 → 0.22.9

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/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.22.9 — 2026-10-28
10
+
11
+ ### Fixed
12
+
13
+ - **Retain complete extracted source text separately from bounded previews; select exact model passages across full documents and preserve originals for continued research.** (`WebReadResult`, `ResearchResult`, `readRAGWebpage`, `readRAGWebsite`, `createWebpageReaderClient`, `createResearch`)
14
+
9
15
  ## 0.22.8 — 2026-10-28
10
16
 
11
17
  ### Fixed
package/changelog.json CHANGED
@@ -2,6 +2,24 @@
2
2
  "contract": 1,
3
3
  "name": "@absolutejs/rag",
4
4
  "releases": [
5
+ {
6
+ "version": "0.22.9",
7
+ "date": "2026-10-28",
8
+ "changes": [
9
+ {
10
+ "kind": "fixed",
11
+ "summary": "Retain complete extracted source text separately from bounded previews; select exact model passages across full documents and preserve originals for continued research.",
12
+ "symbols": [
13
+ "WebReadResult",
14
+ "ResearchResult",
15
+ "readRAGWebpage",
16
+ "readRAGWebsite",
17
+ "createWebpageReaderClient",
18
+ "createResearch"
19
+ ]
20
+ }
21
+ ]
22
+ },
5
23
  {
6
24
  "changes": [
7
25
  {
@@ -101400,6 +101400,28 @@ var init_pdf = __esm(() => {
101400
101400
  };
101401
101401
  });
101402
101402
 
101403
+ // src/research/sourceExcerpts.ts
101404
+ import { createAITextSource } from "@absolutejs/ai";
101405
+ var selectResearchExcerpts = (text, budget, query) => {
101406
+ if (budget <= 0)
101407
+ return [];
101408
+ if (text.length <= budget)
101409
+ return [text];
101410
+ const source = createAITextSource([{ role: "user", content: text }]);
101411
+ const hits = source.search(query);
101412
+ const passages = hits.length ? hits : source.search("");
101413
+ let remaining = budget;
101414
+ const selected = [];
101415
+ for (const passage of passages) {
101416
+ if (!remaining)
101417
+ break;
101418
+ const excerpt = passage.text.slice(0, remaining);
101419
+ selected.push({ start: passage.start, text: excerpt });
101420
+ remaining -= excerpt.length;
101421
+ }
101422
+ return selected.sort((a, b) => a.start - b.start).map((passage) => passage.text);
101423
+ };
101424
+
101403
101425
  // src/research/budget.ts
101404
101426
  var createResearchBudgetAdmission = (config) => {
101405
101427
  if (!config.scope.trim())
@@ -120842,7 +120864,7 @@ var readRAGWebsite = async (options) => {
120842
120864
  const page = await readRAGWebpage({
120843
120865
  ...options,
120844
120866
  url: next.url,
120845
- maxChars: Math.min(maxChars, 12000),
120867
+ maxChars,
120846
120868
  signal: AbortSignal.any([signal, AbortSignal.timeout(30000)])
120847
120869
  });
120848
120870
  pages.push(page);
@@ -120898,24 +120920,27 @@ var readRAGWebsite = async (options) => {
120898
120920
  let remainingDocumentChars = maxChars;
120899
120921
  const documents = sources.flatMap((source) => {
120900
120922
  const page = pages.find((item) => item.finalUrl === source.url && item.text);
120901
- if (!page || remainingDocumentChars <= 0)
120923
+ if (!page)
120902
120924
  return [];
120903
120925
  const imageLabels = page.evidence.images.filter((image) => image.label).map((image) => `${image.context ? `${image.context}: ` : ""}${image.label}`);
120904
120926
  const fullText = [
120905
- page.text,
120927
+ page.fullText ?? page.text,
120906
120928
  ...imageLabels.length ? [
120907
120929
  "Image labels supplied by the website (not independently verified customer relationships):",
120908
120930
  ...imageLabels
120909
120931
  ] : []
120910
120932
  ].join(`
120911
120933
  `);
120912
- const text = fullText.slice(0, remainingDocumentChars);
120934
+ const text = fullText.slice(0, Math.max(0, remainingDocumentChars));
120913
120935
  remainingDocumentChars -= text.length;
120914
120936
  return [
120915
120937
  {
120916
120938
  sourceId: source.id,
120917
120939
  text,
120918
- truncated: page.truncated || text.length < fullText.length
120940
+ fullText,
120941
+ originalChars: fullText.length,
120942
+ sourceTruncated: page.status !== "ok" || page.fullText === undefined && page.truncated,
120943
+ truncated: page.fullText === undefined && page.truncated || text.length < fullText.length
120919
120944
  }
120920
120945
  ];
120921
120946
  });
@@ -120934,10 +120959,11 @@ ${page.text}`).join(`
120934
120959
  sources,
120935
120960
  citationRequirements: "The final answer must contain clickable Markdown source links, not just source names or bare domain mentions. Reuse sources[].citation beside the factual paragraph, list or table row it supports. Cite the actual supporting page, not the homepage for everything. Every factual section needs its supporting links. Do not invent sources or use unread links as evidence. Before responding, check that company facts, service descriptions, customer examples and numerical claims have supporting links; retrieve or omit unsupported claims. A list of large customers does not prove smaller customers are excluded. Preserve the brands actually named in the evidence; do not append parent companies, ownership relationships, current-account status, market rankings or rebrand history from memory. Label reasoned inferences as such. A verified brand change needs at most one short, cited sentence unless the user asks for its history.",
120936
120961
  ...first,
120962
+ fullText: undefined,
120937
120963
  status: readable.length ? incomplete ? "partial" : "ok" : "error",
120938
120964
  text: evidenceText.slice(0, maxChars),
120939
120965
  truncated: evidenceText.length > maxChars || pages.some((page) => page.truncated),
120940
- pages: pages.map(({ text: _text, ...page }) => page),
120966
+ pages: pages.map(({ text: _text, fullText: _fullText, ...page }) => page),
120941
120967
  captionEvidence,
120942
120968
  coverage: {
120943
120969
  pagesRead: pages.length,
@@ -120948,10 +120974,10 @@ ${page.text}`).join(`
120948
120974
  deadlineReached: signal.aborted,
120949
120975
  exhaustive: false,
120950
120976
  stopReason: signal.aborted ? "deadline" : unvisited.length ? "page_limit" : "links_exhausted",
120951
- incompleteReads: pages.filter((page) => page.status !== "ok" || page.truncated).map((page) => ({
120977
+ incompleteReads: pages.filter((page) => page.status !== "ok" || page.fullText === undefined && page.truncated).map((page) => ({
120952
120978
  url: page.finalUrl,
120953
120979
  status: page.status,
120954
- truncated: page.truncated,
120980
+ truncated: page.fullText === undefined && page.truncated,
120955
120981
  error: page.error
120956
120982
  }))
120957
120983
  },
@@ -121066,12 +121092,15 @@ var createWebpageReaderClient = (options) => {
121066
121092
  if (![evidence.links, evidence.images, evidence.media].every(Array.isArray))
121067
121093
  throw new Error("Invalid page evidence");
121068
121094
  const limit = Math.max(1000, Math.min(input.maxChars ?? 24000, 1e5));
121095
+ const fullText = typeof document2.fullText === "string" ? document2.fullText : document2.text;
121069
121096
  return {
121070
121097
  status: result.status,
121071
121098
  url: input.url,
121072
121099
  finalUrl: result.finalUrl,
121073
121100
  title: typeof result.title === "string" ? result.title : null,
121074
- text: document2.text.slice(0, limit),
121101
+ text: fullText.slice(0, limit),
121102
+ fullText,
121103
+ originalChars: fullText.length,
121075
121104
  method: result.method,
121076
121105
  truncated: result.truncated === true || document2.truncated === true || document2.text.length > limit,
121077
121106
  fetchedAt: result.fetchedAt,
@@ -121114,6 +121143,8 @@ var readRAGWebpage = async (options) => {
121114
121143
  finalUrl,
121115
121144
  title,
121116
121145
  text: text.slice(0, maxChars),
121146
+ fullText: text,
121147
+ originalChars: text.length,
121117
121148
  method,
121118
121149
  truncated: text.length > maxChars,
121119
121150
  attempts,
@@ -121465,8 +121496,8 @@ ${prompt}`,
121465
121496
  const text = sourceText.get(source.url);
121466
121497
  const allowance = Math.floor(remaining * weight(source) / remainingWeight);
121467
121498
  remainingWeight -= weight(source);
121468
- source.excerpts = [text.slice(0, allowance)];
121469
- remaining -= source.excerpts[0].length;
121499
+ source.excerpts = selectResearchExcerpts(text, allowance, [input.query, ...input.queries ?? []].join(" "));
121500
+ remaining -= source.excerpts.reduce((sum, excerpt) => sum + excerpt.length, 0);
121470
121501
  }
121471
121502
  evidenceChars = limits.evidenceChars - remaining;
121472
121503
  };
@@ -121550,7 +121581,7 @@ ${prompt}`,
121550
121581
  }
121551
121582
  const prior = result.sources.find((source) => source.url === url);
121552
121583
  if (prior) {
121553
- sourceText.set(prior.url, page.text.slice(0, limits.evidenceChars));
121584
+ sourceText.set(prior.url, page.fullText ?? page.text);
121554
121585
  prior.contentFetchedAt = page.fetchedAt;
121555
121586
  prior.metadata = { ...prior.metadata, readFinalUrl: page.finalUrl };
121556
121587
  if (page.finalUrl !== prior.url)
@@ -121663,6 +121694,7 @@ ${prompt}`,
121663
121694
  result.status = result.sources.length ? "partial" : "unavailable";
121664
121695
  return result;
121665
121696
  } finally {
121697
+ result.documents = result.sources.filter((source) => source.contentFetchedAt).map((source) => ({ sourceId: source.id, url: source.url, text: sourceText.get(source.url) ?? "", originalChars: (sourceText.get(source.url) ?? "").length }));
121666
121698
  result.limitations = [...new Set(result.limitations)];
121667
121699
  input.onProgress?.({
121668
121700
  phase: "complete",
@@ -122511,5 +122543,5 @@ export {
122511
122543
  selectResearchMonitorEvents
122512
122544
  };
122513
122545
 
122514
- //# debugId=98A81F60666A9C0F64756E2164756E21
122546
+ //# debugId=B2B2CCEDC66F56B564756E2164756E21
122515
122547
  //# sourceMappingURL=index.js.map