@absolutejs/rag 0.22.7 → 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.
@@ -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,
@@ -121453,6 +121484,7 @@ ${prompt}`,
121453
121484
  const requiredPhrases = input.requiredPhrases ?? (input.queryMode === "task" ? [] : [...input.query.matchAll(/"([^"\n]+)"/gu)].map((match) => match[1]));
121454
121485
  const urls = new Set;
121455
121486
  const queries = new Set;
121487
+ const discoveredLinks = new Map;
121456
121488
  let evidenceChars = 0;
121457
121489
  const sourceText = new Map;
121458
121490
  const rebalanceEvidence = () => {
@@ -121464,8 +121496,8 @@ ${prompt}`,
121464
121496
  const text = sourceText.get(source.url);
121465
121497
  const allowance = Math.floor(remaining * weight(source) / remainingWeight);
121466
121498
  remainingWeight -= weight(source);
121467
- source.excerpts = [text.slice(0, allowance)];
121468
- 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);
121469
121501
  }
121470
121502
  evidenceChars = limits.evidenceChars - remaining;
121471
121503
  };
@@ -121524,7 +121556,7 @@ ${prompt}`,
121524
121556
  const doRead = async (url) => {
121525
121557
  if (urls.has(url) || urls.size >= limits.reads)
121526
121558
  return;
121527
- if (!result.searches.some((search) => search.sources.some((source) => source.url === url)))
121559
+ if (!discoveredLinks.has(url) && !result.searches.some((search) => search.sources.some((source) => source.url === url)))
121528
121560
  return;
121529
121561
  urls.add(url);
121530
121562
  const page = await operate("read", () => (config.reader ?? readRAGWebpage)({
@@ -121537,9 +121569,19 @@ ${prompt}`,
121537
121569
  if (page.status !== "ok")
121538
121570
  result.limitations.push(`Page read ${page.status}: ${url}`);
121539
121571
  if (page.text && page.status !== "error") {
121572
+ for (const link of page.evidence.links) {
121573
+ if (discoveredLinks.size >= 64)
121574
+ break;
121575
+ try {
121576
+ const target = validatePublicWebUrl(new URL(link.url, page.finalUrl).href);
121577
+ target.hash = "";
121578
+ if (!discoveredLinks.has(target.href))
121579
+ discoveredLinks.set(target.href, { url: target.href, label: link.label.slice(0, 200), discoveredOn: page.finalUrl });
121580
+ } catch {}
121581
+ }
121540
121582
  const prior = result.sources.find((source) => source.url === url);
121541
121583
  if (prior) {
121542
- sourceText.set(prior.url, page.text.slice(0, limits.evidenceChars));
121584
+ sourceText.set(prior.url, page.fullText ?? page.text);
121543
121585
  prior.contentFetchedAt = page.fetchedAt;
121544
121586
  prior.metadata = { ...prior.metadata, readFinalUrl: page.finalUrl };
121545
121587
  if (page.finalUrl !== prior.url)
@@ -121575,11 +121617,12 @@ ${prompt}`,
121575
121617
  break;
121576
121618
  let plan;
121577
121619
  try {
121578
- plan = await generate("plan", PlanSchema, "Select follow-up searches for missing evidence and primary-source URLs to read. For current people or roles, seek the organization\u2019s own leadership/about/team pages; testimonials, package authors, and job listings are not staff identity evidence. For policies, read the full policy or agreement to preserve section scope and exceptions. URLs must come from the supplied search results. done means available evidence addresses the requested schema, not merely that some results exist. Return no actions if further work is not useful.", {
121620
+ plan = await generate("plan", PlanSchema, "Select follow-up searches for missing evidence and primary-source URLs to read. For current people or roles, seek the organization\u2019s own leadership/about/team pages; testimonials, package authors, and job listings are not staff identity evidence. For policies, read the full policy or agreement to preserve section scope and exceptions. URLs must come from the supplied search results or discoveredLinks. Discovered links are unread navigation hints, not evidence; read relevant product, pricing, checkout or policy details before concluding information is absent. done means available evidence addresses the requested schema, not merely that some results exist. Return no actions if further work is not useful.", {
121579
121621
  query: input.query,
121580
121622
  schema: task.schema,
121581
121623
  instructions: task.instructions,
121582
121624
  sources: result.sources,
121625
+ discoveredLinks: [...discoveredLinks.values()].filter((link) => !urls.has(link.url)),
121583
121626
  searched: [...queries],
121584
121627
  read: [...urls],
121585
121628
  remainingSearches: limits.searches - queries.size,
@@ -121651,6 +121694,7 @@ ${prompt}`,
121651
121694
  result.status = result.sources.length ? "partial" : "unavailable";
121652
121695
  return result;
121653
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 }));
121654
121698
  result.limitations = [...new Set(result.limitations)];
121655
121699
  input.onProgress?.({
121656
121700
  phase: "complete",
@@ -122499,5 +122543,5 @@ export {
122499
122543
  selectResearchMonitorEvents
122500
122544
  };
122501
122545
 
122502
- //# debugId=F48D3A6490A0A2CE64756E2164756E21
122546
+ //# debugId=B2B2CCEDC66F56B564756E2164756E21
122503
122547
  //# sourceMappingURL=index.js.map