@jini-ai/platform 0.5.7 → 0.5.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 +5 -0
- package/dist/http/guarded/client.js +5 -4
- package/dist/web/web-page.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# @jini-ai/platform
|
|
2
2
|
|
|
3
|
+
## 0.5.8 — 2026-10-15
|
|
4
|
+
|
|
5
|
+
- SECURITY: the guarded HTTP client forwards only `accept`, `accept-language` and `user-agent` on a cross-origin redirect (4de69b67). It used to strip only Authorization/Cookie, so custom credential headers (`x-api-key`, `X-Shopify-Access-Token`, …) followed a redirect to another origin. Same-origin hops keep all headers.
|
|
6
|
+
- `./web` page fetch applies `maxChars` to the readable text, not the raw HTML (0625844e): raw HTML uses the fixed 1,000,000-char parser ceiling, and the result says `truncated: true` when cut. A page with a large script/style head no longer returns almost no text.
|
|
7
|
+
|
|
3
8
|
## 0.5.7 — 2026-10-14
|
|
4
9
|
|
|
5
10
|
- The asset cache's optional `undici` load moves behind `asset-cache.adapter.ts` (64eafe35); injected dispatchers, DNS validation and the MODULE_NOT_FOUND message are unchanged. No API change.
|
|
@@ -38,7 +38,7 @@ export function classifyAddress({ ip }) {
|
|
|
38
38
|
// it is not globally routable and belongs with RFC 1918 private ranges for egress decisions.
|
|
39
39
|
return "private";
|
|
40
40
|
}
|
|
41
|
-
const
|
|
41
|
+
const CROSS_ORIGIN_HEADERS = new Set(["accept", "accept-language", "user-agent"]);
|
|
42
42
|
// HTTP header names are case-insensitive; preserve the caller's explicit User-Agent in any casing.
|
|
43
43
|
function hasUserAgentHeader(headers) {
|
|
44
44
|
return Object.keys(headers).some((key) => key.toLowerCase() === "user-agent");
|
|
@@ -105,10 +105,10 @@ async function resolvePinnedPeer(url, policy, dns) {
|
|
|
105
105
|
tlsServerName: isIP(hostname) === 0 ? url.hostname : undefined,
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
-
function
|
|
108
|
+
function withCrossOriginHeaders(headers) {
|
|
109
109
|
const next = {};
|
|
110
110
|
for (const [key, value] of Object.entries(headers)) {
|
|
111
|
-
if (
|
|
111
|
+
if (!CROSS_ORIGIN_HEADERS.has(key.toLowerCase()))
|
|
112
112
|
continue;
|
|
113
113
|
next[key] = value;
|
|
114
114
|
}
|
|
@@ -179,8 +179,9 @@ async function sendWithPolicy(transport, policy, request, redirectsFollowed, dns
|
|
|
179
179
|
return cappedResponse;
|
|
180
180
|
const nextUrl = new URL(location, url);
|
|
181
181
|
// Cross-origin hops must not inherit authorization or cookies entrusted to the original origin.
|
|
182
|
+
// Custom headers can carry credentials too; forward only the explicit noncredential allowlist.
|
|
182
183
|
const nextHeaders = isCrossOrigin(url, nextUrl)
|
|
183
|
-
?
|
|
184
|
+
? withCrossOriginHeaders(request.headers)
|
|
184
185
|
: request.headers;
|
|
185
186
|
return sendWithPolicy(transport, policy, { ...request, url: nextUrl.toString(), headers: nextHeaders }, redirectsFollowed + 1, dns, redirect);
|
|
186
187
|
}
|
package/dist/web/web-page.js
CHANGED
|
@@ -245,8 +245,8 @@ function project({ input, ports, url, response }) {
|
|
|
245
245
|
const body = decodeBody(response, contentType, isHtml);
|
|
246
246
|
if (body.includes("\u0000"))
|
|
247
247
|
throw new ToolInputError({ message: "web_fetch_page: the response is binary, not a text page." });
|
|
248
|
-
//
|
|
249
|
-
const bounded = isHtml ? boundHtml({ html: body }
|
|
248
|
+
// A fixed ceiling limits synchronous parsing without letting a large head consume the output budget.
|
|
249
|
+
const bounded = isHtml ? boundHtml({ html: body }) : { html: body, truncated: false };
|
|
250
250
|
const facts = isHtml ? readHtmlDocument({ html: bounded.html, pageUrl: finalUrl }) : /xml/.test(mediaType) ? sitemapFacts(body, finalUrl) : EMPTY_FACTS;
|
|
251
251
|
const rendered = render(input.format, input.format === "raw" ? body : bounded.html, isHtml, finalUrl, ports);
|
|
252
252
|
const content = clip(rendered, input.maxChars);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/platform",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "Generic OS/platform primitives: process exec and lifecycle, filesystem containment, HTTP readiness polling, toolchain discovery, blob storage, AWS signing, and an SSRF-safe asset cache.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|