@absolutejs/rag 0.16.0 → 0.17.0
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 +10 -0
- package/README.md +2 -0
- package/changelog.json +235 -218
- package/dist/src/web/index.d.ts +1 -0
- package/dist/src/web/remote.d.ts +30 -0
- package/dist/web/index.js +116 -79
- package/dist/web/index.js.map +6 -5
- package/dist/web/playwright.js +38 -79
- package/dist/web/playwright.js.map +3 -3
- package/package.json +183 -182
package/dist/web/index.js
CHANGED
|
@@ -111057,10 +111057,12 @@ function Document4() {
|
|
|
111057
111057
|
setPrototypeOf(Document4, Document2).prototype = Document2.prototype;
|
|
111058
111058
|
|
|
111059
111059
|
// src/web/transport.ts
|
|
111060
|
+
import {
|
|
111061
|
+
isPublicNetworkAddress,
|
|
111062
|
+
pinnedPublicRequest
|
|
111063
|
+
} from "@absolutejs/egress/transport";
|
|
111060
111064
|
import { lookup } from "dns/promises";
|
|
111061
111065
|
import { isIP } from "net";
|
|
111062
|
-
import { request as httpRequest } from "http";
|
|
111063
|
-
import { request as httpsRequest } from "https";
|
|
111064
111066
|
import { brotliDecompressSync, gunzipSync, inflateSync } from "zlib";
|
|
111065
111067
|
|
|
111066
111068
|
class WebReadError extends Error {
|
|
@@ -111071,14 +111073,7 @@ class WebReadError extends Error {
|
|
|
111071
111073
|
this.name = "WebReadError";
|
|
111072
111074
|
}
|
|
111073
111075
|
}
|
|
111074
|
-
var isPublicWebAddress = (address) =>
|
|
111075
|
-
if (isIP(address) === 4) {
|
|
111076
|
-
const [a = 0, b = 0, c = 0] = address.split(".").map(Number);
|
|
111077
|
-
return !(a === 0 || a === 10 || a === 127 || a >= 224 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && (b === 168 || b === 0 || b === 88 && c === 99) || a === 198 && (b === 18 || b === 19 || b === 51 && c === 100) || a === 203 && b === 0 && c === 113);
|
|
111078
|
-
}
|
|
111079
|
-
const value = address.toLowerCase();
|
|
111080
|
-
return isIP(value) === 6 && /^[23]/u.test(value) && !/^2001:(?:db8|0):/u.test(value) && !value.startsWith("2002:");
|
|
111081
|
-
};
|
|
111076
|
+
var isPublicWebAddress = (address) => isPublicNetworkAddress(address);
|
|
111082
111077
|
var validatePublicWebUrl = (raw) => {
|
|
111083
111078
|
let url;
|
|
111084
111079
|
try {
|
|
@@ -111108,74 +111103,38 @@ var fetchPublicWebResource = async (raw, options = {}) => {
|
|
|
111108
111103
|
throw new WebReadError("blocked_url", "The destination resolved to a private or reserved network.");
|
|
111109
111104
|
signal.throwIfAborted();
|
|
111110
111105
|
const selected = addresses.find(({ family }) => family === 4) ?? addresses[0];
|
|
111111
|
-
const
|
|
111112
|
-
|
|
111113
|
-
|
|
111114
|
-
|
|
111115
|
-
|
|
111116
|
-
|
|
111117
|
-
|
|
111118
|
-
|
|
111119
|
-
|
|
111120
|
-
|
|
111121
|
-
|
|
111122
|
-
|
|
111123
|
-
|
|
111124
|
-
|
|
111125
|
-
|
|
111126
|
-
|
|
111127
|
-
|
|
111128
|
-
|
|
111129
|
-
|
|
111130
|
-
|
|
111131
|
-
|
|
111132
|
-
|
|
111133
|
-
|
|
111134
|
-
|
|
111135
|
-
|
|
111136
|
-
|
|
111137
|
-
|
|
111138
|
-
|
|
111139
|
-
|
|
111140
|
-
|
|
111141
|
-
|
|
111142
|
-
|
|
111143
|
-
res.on("end", () => {
|
|
111144
|
-
try {
|
|
111145
|
-
let data = Buffer.concat(chunks);
|
|
111146
|
-
const encoding = res.headers["content-encoding"];
|
|
111147
|
-
const limits = { maxOutputLength: maxBytes };
|
|
111148
|
-
if (encoding === "gzip")
|
|
111149
|
-
data = gunzipSync(data, limits);
|
|
111150
|
-
else if (encoding === "br")
|
|
111151
|
-
data = brotliDecompressSync(data, limits);
|
|
111152
|
-
else if (encoding === "deflate")
|
|
111153
|
-
data = inflateSync(data, limits);
|
|
111154
|
-
const headers = Object.fromEntries(Object.entries(res.headers).filter(([key2]) => ![
|
|
111155
|
-
"content-encoding",
|
|
111156
|
-
"content-length",
|
|
111157
|
-
"transfer-encoding",
|
|
111158
|
-
"set-cookie"
|
|
111159
|
-
].includes(key2)).map(([key2, value]) => [
|
|
111160
|
-
key2,
|
|
111161
|
-
Array.isArray(value) ? value.join(", ") : value ?? ""
|
|
111162
|
-
]));
|
|
111163
|
-
resolve({
|
|
111164
|
-
url: url.href,
|
|
111165
|
-
status: res.statusCode ?? 502,
|
|
111166
|
-
headers,
|
|
111167
|
-
body: data
|
|
111168
|
-
});
|
|
111169
|
-
} catch (error) {
|
|
111170
|
-
reject(error);
|
|
111171
|
-
}
|
|
111172
|
-
});
|
|
111173
|
-
});
|
|
111174
|
-
req.on("error", reject);
|
|
111175
|
-
if (body)
|
|
111176
|
-
req.write(body);
|
|
111177
|
-
req.end();
|
|
111178
|
-
});
|
|
111106
|
+
const incoming = await pinnedPublicRequest(new Request(url, {
|
|
111107
|
+
method,
|
|
111108
|
+
body,
|
|
111109
|
+
signal,
|
|
111110
|
+
headers: {
|
|
111111
|
+
"user-agent": "AbsoluteJSReader/1.0",
|
|
111112
|
+
accept: "*/*",
|
|
111113
|
+
"accept-encoding": "identity",
|
|
111114
|
+
...options.headers,
|
|
111115
|
+
host: url.host
|
|
111116
|
+
}
|
|
111117
|
+
}), { hostname: host, address: selected.address, maxResponseBytes: maxBytes });
|
|
111118
|
+
let data = new Uint8Array(await incoming.arrayBuffer());
|
|
111119
|
+
const encoding = incoming.headers.get("content-encoding");
|
|
111120
|
+
const limits = { maxOutputLength: maxBytes };
|
|
111121
|
+
if (encoding === "gzip")
|
|
111122
|
+
data = gunzipSync(data, limits);
|
|
111123
|
+
else if (encoding === "br")
|
|
111124
|
+
data = brotliDecompressSync(data, limits);
|
|
111125
|
+
else if (encoding === "deflate")
|
|
111126
|
+
data = inflateSync(data, limits);
|
|
111127
|
+
const response = {
|
|
111128
|
+
url: url.href,
|
|
111129
|
+
status: incoming.status,
|
|
111130
|
+
headers: Object.fromEntries([...incoming.headers].filter(([key2]) => ![
|
|
111131
|
+
"content-encoding",
|
|
111132
|
+
"content-length",
|
|
111133
|
+
"transfer-encoding",
|
|
111134
|
+
"set-cookie"
|
|
111135
|
+
].includes(key2))),
|
|
111136
|
+
body: data
|
|
111137
|
+
};
|
|
111179
111138
|
if (options.redirect === "manual")
|
|
111180
111139
|
return response;
|
|
111181
111140
|
if ([301, 302, 303, 307, 308].includes(response.status) && response.headers.location) {
|
|
@@ -117873,6 +117832,82 @@ ${page.text}`).join(`
|
|
|
117873
117832
|
citationGuidance: "Answer the user's question first, with exact source page URLs. Distinguish retrieved facts from inference. A page limit bounds this call, not the research task: if a material question remains unanswered, read the relevant remaining links in another call, using maxPages 1 for targeted detail pages. Do not stop with a list of next steps when those reads are needed to finish the request. Conversely, unvisited links do not by themselves mean the answer is incomplete. Report only gaps that materially limit the answer, unless a retrieval audit was explicitly requested. Successful browser fallback is a completed read, not an incomplete read. Normally summarize a redirected destination in one brief sentence; omit HTTP codes, hop chains, character counts and rendering mechanics unless explicitly requested for debugging. A redirect alone does not prove a rebrand; verify that claim from a source. Image labels do not establish customer relationships and media URLs are not watched video evidence."
|
|
117874
117833
|
};
|
|
117875
117834
|
};
|
|
117835
|
+
// src/web/remote.ts
|
|
117836
|
+
var parseWebsiteServiceResult = (value) => {
|
|
117837
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
117838
|
+
throw new Error("Website reader returned an invalid response");
|
|
117839
|
+
const row = value;
|
|
117840
|
+
if (typeof row.text !== "string" || !["ok", "partial", "error"].includes(String(row.status)))
|
|
117841
|
+
throw new Error("Website reader returned an invalid response");
|
|
117842
|
+
if (row.limitations !== undefined && (!Array.isArray(row.limitations) || !row.limitations.every((item) => typeof item === "string")))
|
|
117843
|
+
throw new Error("Invalid website limitations");
|
|
117844
|
+
if (row.sources !== undefined && (!Array.isArray(row.sources) || !row.sources.every((source) => {
|
|
117845
|
+
if (!source || typeof source !== "object" || typeof source.url !== "string")
|
|
117846
|
+
return false;
|
|
117847
|
+
try {
|
|
117848
|
+
const url = new URL(source.url);
|
|
117849
|
+
return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password;
|
|
117850
|
+
} catch {
|
|
117851
|
+
return false;
|
|
117852
|
+
}
|
|
117853
|
+
})))
|
|
117854
|
+
throw new Error("Invalid website sources");
|
|
117855
|
+
return row;
|
|
117856
|
+
};
|
|
117857
|
+
var createWebsiteReaderClient = (options) => async (input) => {
|
|
117858
|
+
const timeoutMs = options.timeoutMs ?? 85000, reserveMs = options.fallbackReserveMs ?? 15000;
|
|
117859
|
+
if (!(reserveMs > 0 && timeoutMs > reserveMs))
|
|
117860
|
+
throw new Error("Reader deadline must reserve fallback time");
|
|
117861
|
+
const signal = AbortSignal.any([
|
|
117862
|
+
...input.signal ? [input.signal] : [],
|
|
117863
|
+
AbortSignal.timeout(timeoutMs)
|
|
117864
|
+
]);
|
|
117865
|
+
signal.throwIfAborted();
|
|
117866
|
+
const request = {
|
|
117867
|
+
url: input.url,
|
|
117868
|
+
maxPages: input.maxPages ?? 8,
|
|
117869
|
+
mode: input.mode ?? "auto"
|
|
117870
|
+
};
|
|
117871
|
+
if (!Number.isInteger(request.maxPages) || request.maxPages < 1 || request.maxPages > 12)
|
|
117872
|
+
throw new Error("Reader page limit must be 1\u201312");
|
|
117873
|
+
try {
|
|
117874
|
+
const response = await (options.fetch ?? fetch)(options.endpoint, {
|
|
117875
|
+
method: "POST",
|
|
117876
|
+
headers: { "content-type": "application/json" },
|
|
117877
|
+
body: JSON.stringify(request),
|
|
117878
|
+
signal: AbortSignal.any([
|
|
117879
|
+
signal,
|
|
117880
|
+
AbortSignal.timeout(timeoutMs - reserveMs)
|
|
117881
|
+
])
|
|
117882
|
+
});
|
|
117883
|
+
if (response.status === 503)
|
|
117884
|
+
return {
|
|
117885
|
+
status: "error",
|
|
117886
|
+
text: "",
|
|
117887
|
+
error: {
|
|
117888
|
+
code: "reader_busy",
|
|
117889
|
+
message: "Website reader is busy. Retry shortly; this is not evidence of missing information.",
|
|
117890
|
+
retryAfterSeconds: 2
|
|
117891
|
+
}
|
|
117892
|
+
};
|
|
117893
|
+
if (!response.ok)
|
|
117894
|
+
throw new Error(`Website reader returned ${response.status}`);
|
|
117895
|
+
const result = parseWebsiteServiceResult(await response.json());
|
|
117896
|
+
signal.throwIfAborted();
|
|
117897
|
+
return result;
|
|
117898
|
+
} catch (error) {
|
|
117899
|
+
signal.throwIfAborted();
|
|
117900
|
+
const result = parseWebsiteServiceResult(await options.fallback({ ...request, signal }));
|
|
117901
|
+
signal.throwIfAborted();
|
|
117902
|
+
return {
|
|
117903
|
+
...result,
|
|
117904
|
+
limitations: [
|
|
117905
|
+
...result.limitations ?? [],
|
|
117906
|
+
"Browser service unavailable; static fallback may omit JavaScript-only evidence."
|
|
117907
|
+
]
|
|
117908
|
+
};
|
|
117909
|
+
}
|
|
117910
|
+
};
|
|
117876
117911
|
|
|
117877
117912
|
// src/web/index.ts
|
|
117878
117913
|
var messageFor = (error) => error instanceof Error ? error.message : "Website retrieval failed.";
|
|
@@ -118039,12 +118074,14 @@ var readRAGWebpage = async (options) => {
|
|
|
118039
118074
|
};
|
|
118040
118075
|
export {
|
|
118041
118076
|
WebReadError,
|
|
118077
|
+
createWebsiteReaderClient,
|
|
118042
118078
|
fetchPublicWebResource,
|
|
118043
118079
|
isPublicWebAddress,
|
|
118080
|
+
parseWebsiteServiceResult,
|
|
118044
118081
|
readRAGWebpage,
|
|
118045
118082
|
readRAGWebsite,
|
|
118046
118083
|
validatePublicWebUrl
|
|
118047
118084
|
};
|
|
118048
118085
|
|
|
118049
|
-
//# debugId=
|
|
118086
|
+
//# debugId=DCC029C3B5C261E064756E2164756E21
|
|
118050
118087
|
//# sourceMappingURL=index.js.map
|