@absolutejs/rag 0.22.6 → 0.22.8
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 +13 -0
- package/changelog.json +29 -0
- package/dist/research/index.js +32 -7
- package/dist/research/index.js.map +5 -5
- package/dist/src/research/plugin.d.ts +5 -0
- package/dist/src/research/types.d.ts +2 -0
- package/dist/web-index/index.js +30 -7
- package/dist/web-index/index.js.map +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@ 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.8 — 2026-10-28
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Allow bounded research to follow validated links discovered in fetched pages, without treating unread links as evidence or admitting invented URLs.** (`createResearch`)
|
|
14
|
+
|
|
15
|
+
## 0.22.7 — 2026-10-28
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Separate structured research tasks from literal search queries** (`createResearch`, `researchPlugin`, `ResearchInput`)
|
|
20
|
+
Task mode plans concise initial searches within the existing round budget and does not treat quoted JSON fields as required source phrases. Exact-phrase search mode retains identity filtering.
|
|
21
|
+
|
|
9
22
|
## 0.22.6 — 2026-10-22
|
|
10
23
|
|
|
11
24
|
### Changed
|
package/changelog.json
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
"contract": 1,
|
|
3
3
|
"name": "@absolutejs/rag",
|
|
4
4
|
"releases": [
|
|
5
|
+
{
|
|
6
|
+
"changes": [
|
|
7
|
+
{
|
|
8
|
+
"kind": "fixed",
|
|
9
|
+
"summary": "Allow bounded research to follow validated links discovered in fetched pages, without treating unread links as evidence or admitting invented URLs.",
|
|
10
|
+
"symbols": [
|
|
11
|
+
"createResearch"
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"date": "2026-10-28",
|
|
16
|
+
"version": "0.22.8"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"changes": [
|
|
20
|
+
{
|
|
21
|
+
"detail": "Task mode plans concise initial searches within the existing round budget and does not treat quoted JSON fields as required source phrases. Exact-phrase search mode retains identity filtering.",
|
|
22
|
+
"kind": "fixed",
|
|
23
|
+
"summary": "Separate structured research tasks from literal search queries",
|
|
24
|
+
"symbols": [
|
|
25
|
+
"createResearch",
|
|
26
|
+
"researchPlugin",
|
|
27
|
+
"ResearchInput"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"date": "2026-10-28",
|
|
32
|
+
"version": "0.22.7"
|
|
33
|
+
},
|
|
5
34
|
{
|
|
6
35
|
"changes": [
|
|
7
36
|
{
|
package/dist/research/index.js
CHANGED
|
@@ -121450,9 +121450,10 @@ ${prompt}`,
|
|
|
121450
121450
|
return generated.object;
|
|
121451
121451
|
};
|
|
121452
121452
|
const normalize = (text) => text.normalize("NFKC").toLowerCase().replace(/\s+/gu, " ").trim();
|
|
121453
|
-
const requiredPhrases = input.requiredPhrases ?? [...input.query.matchAll(/"([^"\n]+)"/gu)].map((match) => match[1]);
|
|
121453
|
+
const requiredPhrases = input.requiredPhrases ?? (input.queryMode === "task" ? [] : [...input.query.matchAll(/"([^"\n]+)"/gu)].map((match) => match[1]));
|
|
121454
121454
|
const urls = new Set;
|
|
121455
121455
|
const queries = new Set;
|
|
121456
|
+
const discoveredLinks = new Map;
|
|
121456
121457
|
let evidenceChars = 0;
|
|
121457
121458
|
const sourceText = new Map;
|
|
121458
121459
|
const rebalanceEvidence = () => {
|
|
@@ -121524,7 +121525,7 @@ ${prompt}`,
|
|
|
121524
121525
|
const doRead = async (url) => {
|
|
121525
121526
|
if (urls.has(url) || urls.size >= limits.reads)
|
|
121526
121527
|
return;
|
|
121527
|
-
if (!result.searches.some((search) => search.sources.some((source) => source.url === url)))
|
|
121528
|
+
if (!discoveredLinks.has(url) && !result.searches.some((search) => search.sources.some((source) => source.url === url)))
|
|
121528
121529
|
return;
|
|
121529
121530
|
urls.add(url);
|
|
121530
121531
|
const page = await operate("read", () => (config.reader ?? readRAGWebpage)({
|
|
@@ -121537,6 +121538,16 @@ ${prompt}`,
|
|
|
121537
121538
|
if (page.status !== "ok")
|
|
121538
121539
|
result.limitations.push(`Page read ${page.status}: ${url}`);
|
|
121539
121540
|
if (page.text && page.status !== "error") {
|
|
121541
|
+
for (const link of page.evidence.links) {
|
|
121542
|
+
if (discoveredLinks.size >= 64)
|
|
121543
|
+
break;
|
|
121544
|
+
try {
|
|
121545
|
+
const target = validatePublicWebUrl(new URL(link.url, page.finalUrl).href);
|
|
121546
|
+
target.hash = "";
|
|
121547
|
+
if (!discoveredLinks.has(target.href))
|
|
121548
|
+
discoveredLinks.set(target.href, { url: target.href, label: link.label.slice(0, 200), discoveredOn: page.finalUrl });
|
|
121549
|
+
} catch {}
|
|
121550
|
+
}
|
|
121540
121551
|
const prior = result.sources.find((source) => source.url === url);
|
|
121541
121552
|
if (prior) {
|
|
121542
121553
|
sourceText.set(prior.url, page.text.slice(0, limits.evidenceChars));
|
|
@@ -121557,18 +121568,30 @@ ${prompt}`,
|
|
|
121557
121568
|
}
|
|
121558
121569
|
};
|
|
121559
121570
|
try {
|
|
121560
|
-
|
|
121561
|
-
|
|
121562
|
-
|
|
121571
|
+
const needsInitialPlan = !input.queries && (input.queryMode === "task" || boundedQueries(input.query).length > 1) && limits.rounds > 0;
|
|
121572
|
+
if (needsInitialPlan) {
|
|
121573
|
+
const initial = await generate("plan", PlanSchema, "Turn the research task into concise search-engine queries. Preserve the requested company identity and target criteria, but never copy instructions, JSON, internal markers, or the whole brief into a query. Prioritize the most useful query first. Return at most remainingSearches queries. Return no URLs: source URLs must be discovered rather than invented.", {
|
|
121574
|
+
query: input.query,
|
|
121575
|
+
instructions: task.instructions,
|
|
121576
|
+
remainingSearches: limits.searches
|
|
121577
|
+
});
|
|
121578
|
+
for (const query of initial.queries)
|
|
121579
|
+
await doSearch(query);
|
|
121580
|
+
} else {
|
|
121581
|
+
for (const query of input.queries ?? [input.query])
|
|
121582
|
+
await doSearch(query);
|
|
121583
|
+
}
|
|
121584
|
+
for (let round = needsInitialPlan ? 1 : 0;round < limits.rounds; round++) {
|
|
121563
121585
|
if (!result.sources.length && queries.size >= limits.searches)
|
|
121564
121586
|
break;
|
|
121565
121587
|
let plan;
|
|
121566
121588
|
try {
|
|
121567
|
-
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.", {
|
|
121589
|
+
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.", {
|
|
121568
121590
|
query: input.query,
|
|
121569
121591
|
schema: task.schema,
|
|
121570
121592
|
instructions: task.instructions,
|
|
121571
121593
|
sources: result.sources,
|
|
121594
|
+
discoveredLinks: [...discoveredLinks.values()].filter((link) => !urls.has(link.url)),
|
|
121572
121595
|
searched: [...queries],
|
|
121573
121596
|
read: [...urls],
|
|
121574
121597
|
remainingSearches: limits.searches - queries.size,
|
|
@@ -121669,6 +121692,7 @@ var renderResearchResult = (result) => `<section aria-label="Research result"><p
|
|
|
121669
121692
|
}).join("")}</li>`).join("")}</ul>${result.limitations.map((message) => `<p>${escape5(message)}</p>`).join("")}</section>`;
|
|
121670
121693
|
var bodySchema = t.Object({
|
|
121671
121694
|
query: t.String({ minLength: 1, maxLength: 8000 }),
|
|
121695
|
+
queryMode: t.Optional(t.Union([t.Literal("search"), t.Literal("task")])),
|
|
121672
121696
|
task: t.Optional(t.String({ maxLength: 128 })),
|
|
121673
121697
|
freshness: t.Optional(t.String({ maxLength: 64 }))
|
|
121674
121698
|
}, { additionalProperties: false });
|
|
@@ -122388,6 +122412,7 @@ var researchManifest = defineManifest()({
|
|
|
122388
122412
|
},
|
|
122389
122413
|
input: Type.Object({
|
|
122390
122414
|
query: Type.String({ minLength: 1, maxLength: 8000 }),
|
|
122415
|
+
queryMode: Type.Optional(Type.Union([Type.Literal("search"), Type.Literal("task")])),
|
|
122391
122416
|
task: Type.Optional(Type.String({ maxLength: 128 }))
|
|
122392
122417
|
}),
|
|
122393
122418
|
handler: async (input, runtime) => JSON.stringify(await runtime.run(input))
|
|
@@ -122486,5 +122511,5 @@ export {
|
|
|
122486
122511
|
selectResearchMonitorEvents
|
|
122487
122512
|
};
|
|
122488
122513
|
|
|
122489
|
-
//# debugId=
|
|
122514
|
+
//# debugId=98A81F60666A9C0F64756E2164756E21
|
|
122490
122515
|
//# sourceMappingURL=index.js.map
|