@bedolla/enriweb 0.1.5 → 0.1.7
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/README.md +48 -20
- package/dist/client/EnriProxyClient.d.ts +176 -5
- package/dist/client/EnriProxyClient.d.ts.map +1 -1
- package/dist/client/EnriProxyClient.js +255 -31
- package/dist/client/EnriProxyClient.js.map +1 -1
- package/dist/index.js +65 -25
- package/dist/index.js.map +1 -1
- package/dist/package-info.d.ts +26 -0
- package/dist/package-info.d.ts.map +1 -1
- package/dist/package-info.js +29 -2
- package/dist/package-info.js.map +1 -1
- package/dist/server/EnriWebServer.d.ts +33 -0
- package/dist/server/EnriWebServer.d.ts.map +1 -1
- package/dist/server/EnriWebServer.js +338 -28
- package/dist/server/EnriWebServer.js.map +1 -1
- package/dist/shared/Utf8SafeTextSlicer.d.ts +47 -0
- package/dist/shared/Utf8SafeTextSlicer.d.ts.map +1 -0
- package/dist/shared/Utf8SafeTextSlicer.js +97 -0
- package/dist/shared/Utf8SafeTextSlicer.js.map +1 -0
- package/dist/shared/validation.d.ts +13 -1
- package/dist/shared/validation.d.ts.map +1 -1
- package/dist/shared/validation.js +41 -17
- package/dist/shared/validation.js.map +1 -1
- package/dist/tools/WebFetchNpmProjection.d.ts +143 -0
- package/dist/tools/WebFetchNpmProjection.d.ts.map +1 -0
- package/dist/tools/WebFetchNpmProjection.js +480 -0
- package/dist/tools/WebFetchNpmProjection.js.map +1 -0
- package/dist/tools/WebFetchParamsParser.d.ts +26 -0
- package/dist/tools/WebFetchParamsParser.d.ts.map +1 -0
- package/dist/tools/WebFetchParamsParser.js +157 -0
- package/dist/tools/WebFetchParamsParser.js.map +1 -0
- package/dist/tools/WebFetchRangesExecutor.d.ts +86 -0
- package/dist/tools/WebFetchRangesExecutor.d.ts.map +1 -0
- package/dist/tools/WebFetchRangesExecutor.js +277 -0
- package/dist/tools/WebFetchRangesExecutor.js.map +1 -0
- package/dist/tools/WebFetchTool.d.ts +187 -71
- package/dist/tools/WebFetchTool.d.ts.map +1 -1
- package/dist/tools/WebFetchTool.js +145 -367
- package/dist/tools/WebFetchTool.js.map +1 -1
- package/dist/tools/WebFetchToolTextFormatter.d.ts +57 -0
- package/dist/tools/WebFetchToolTextFormatter.d.ts.map +1 -0
- package/dist/tools/WebFetchToolTextFormatter.js +135 -0
- package/dist/tools/WebFetchToolTextFormatter.js.map +1 -0
- package/dist/tools/WebSearchRegistryHttpReader.d.ts +116 -0
- package/dist/tools/WebSearchRegistryHttpReader.d.ts.map +1 -0
- package/dist/tools/WebSearchRegistryHttpReader.js +157 -0
- package/dist/tools/WebSearchRegistryHttpReader.js.map +1 -0
- package/dist/tools/WebSearchRegistryVerifier.d.ts +111 -6
- package/dist/tools/WebSearchRegistryVerifier.d.ts.map +1 -1
- package/dist/tools/WebSearchRegistryVerifier.js +406 -125
- package/dist/tools/WebSearchRegistryVerifier.js.map +1 -1
- package/dist/tools/WebSearchTool.d.ts +85 -2
- package/dist/tools/WebSearchTool.d.ts.map +1 -1
- package/dist/tools/WebSearchTool.js +197 -19
- package/dist/tools/WebSearchTool.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Argument parsing for the web_fetch MCP tool.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Lenient for malformed optional values (they degrade to documented
|
|
6
|
+
* defaults, matching the EnriCode client parser: unusable or out-of-domain
|
|
7
|
+
* budgets fall back to the documented default instead of failing the call,
|
|
8
|
+
* per the shared AR-4 client policy) but strict for structural mistakes
|
|
9
|
+
* (broken ranges, unknown action without cursor), which fail fast in
|
|
10
|
+
* Spanish. Snake_case field names
|
|
11
|
+
* are canonical; camelCase aliases (maxChars, offsetChars, limitChars,
|
|
12
|
+
* includeLinks, includeMetadata) are accepted as fallbacks for parity with
|
|
13
|
+
* the EnriCode tool surface. Extracted from {@link WebFetchTool} as a pure
|
|
14
|
+
* function module.
|
|
15
|
+
*
|
|
16
|
+
* @module tools/WebFetchParamsParser
|
|
17
|
+
*/
|
|
18
|
+
import { assertHttpUrl, assertObject, optionalInt, optionalString } from "../shared/validation.js";
|
|
19
|
+
import { sliceUtf8Safe } from "../shared/Utf8SafeTextSlicer.js";
|
|
20
|
+
import { MAX_ANCHOR_CHARS, MAX_TOOL_RANGES } from "./WebFetchTool.js";
|
|
21
|
+
/**
|
|
22
|
+
* Validates raw MCP tool arguments.
|
|
23
|
+
*
|
|
24
|
+
* @param raw - Raw tool arguments
|
|
25
|
+
* @returns Validated parameters
|
|
26
|
+
*/
|
|
27
|
+
export function parseWebFetchParams(raw) {
|
|
28
|
+
const obj = assertObject(raw, "arguments");
|
|
29
|
+
const cursorRaw = optionalString(obj["cursor"]);
|
|
30
|
+
const cursor = cursorRaw?.trim() ? cursorRaw.trim() : undefined;
|
|
31
|
+
const urlRaw = optionalString(obj["url"]);
|
|
32
|
+
const urlTrimmed = urlRaw?.trim() ? urlRaw.trim() : undefined;
|
|
33
|
+
// A valid cursor always wins over a coexisting `url`: on cursor calls the
|
|
34
|
+
// url degrades to an optional display label (invalid shapes are dropped
|
|
35
|
+
// instead of hard-failing the whole call), while cursor-less calls keep
|
|
36
|
+
// the strict http(s) validation.
|
|
37
|
+
let url;
|
|
38
|
+
if (cursor !== undefined) {
|
|
39
|
+
url = urlTrimmed !== undefined && /^https?:\/\//iu.test(urlTrimmed) ? urlTrimmed : undefined;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
url = urlTrimmed !== undefined ? assertHttpUrl(urlTrimmed, "url") : undefined;
|
|
43
|
+
}
|
|
44
|
+
if (!cursor && !url) {
|
|
45
|
+
throw new Error("web_fetch requiere 'url' o 'cursor'.");
|
|
46
|
+
}
|
|
47
|
+
if (cursor && !/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/u.test(cursor)) {
|
|
48
|
+
throw new Error("Cursor inválido. Se esperaba un cursor devuelto por una llamada previa a web_fetch.");
|
|
49
|
+
}
|
|
50
|
+
const prompt = optionalString(obj["prompt"]);
|
|
51
|
+
// max_chars is canonical; maxChars is the camelCase alias accepted for
|
|
52
|
+
// parity with the EnriCode tool surface.
|
|
53
|
+
let maxChars = optionalInt(obj["max_chars"]) ?? optionalInt(obj["maxChars"]);
|
|
54
|
+
// Invalid format/content values degrade to the documented defaults
|
|
55
|
+
// ("text"/"main") instead of failing the call, matching EnriCode and
|
|
56
|
+
// EnriProxy projection fallbacks.
|
|
57
|
+
const format = obj["format"] === "markdown"
|
|
58
|
+
? "markdown"
|
|
59
|
+
: obj["format"] === "text"
|
|
60
|
+
? "text"
|
|
61
|
+
: obj["format"] === "html"
|
|
62
|
+
? "html"
|
|
63
|
+
: undefined;
|
|
64
|
+
const content = obj["content"] === "main" ? "main" : obj["content"] === "full" ? "full" : undefined;
|
|
65
|
+
const includeLinks = obj["include_links"] === true || obj["includeLinks"] === true
|
|
66
|
+
? true
|
|
67
|
+
: obj["include_links"] === false || obj["includeLinks"] === false
|
|
68
|
+
? false
|
|
69
|
+
: undefined;
|
|
70
|
+
const includeMetadata = obj["include_metadata"] === true || obj["includeMetadata"] === true
|
|
71
|
+
? true
|
|
72
|
+
: obj["include_metadata"] === false || obj["includeMetadata"] === false
|
|
73
|
+
? false
|
|
74
|
+
: undefined;
|
|
75
|
+
const anchorRaw = optionalString(obj["anchor"]);
|
|
76
|
+
const anchorClean = anchorRaw ? sliceUtf8Safe(anchorRaw.trim().replace(/^#+/, "").trim(), 0, MAX_ANCHOR_CHARS) : "";
|
|
77
|
+
const anchor = anchorClean ? anchorClean : undefined;
|
|
78
|
+
const offsetCharsRaw = optionalInt(obj["offset_chars"]) ?? optionalInt(obj["offsetChars"]) ?? optionalInt(obj["offset"]);
|
|
79
|
+
const limitCharsRaw = optionalInt(obj["limit_chars"]) ?? optionalInt(obj["limitChars"]) ?? optionalInt(obj["limit"]);
|
|
80
|
+
const action = obj["action"] === "delete" ? "delete" : undefined;
|
|
81
|
+
const ranges = parseRanges(obj["ranges"]);
|
|
82
|
+
if (action === "delete" && !cursor) {
|
|
83
|
+
throw new Error("action 'delete' requiere 'cursor'.");
|
|
84
|
+
}
|
|
85
|
+
// AR-4 client parity (EnriCode readOptionalPositiveInteger): a
|
|
86
|
+
// non-positive or otherwise unusable budget degrades to the server
|
|
87
|
+
// default instead of failing the call mid-task.
|
|
88
|
+
if (maxChars !== undefined && maxChars < 1) {
|
|
89
|
+
maxChars = undefined;
|
|
90
|
+
}
|
|
91
|
+
// offset/limit travel with cursor reads (server-side window over the
|
|
92
|
+
// capture) and with url reads (local slice over the returned content,
|
|
93
|
+
// matching EnriCode's first-read range semantics).
|
|
94
|
+
// AR-4 client parity: negative offsets/limits degrade to the
|
|
95
|
+
// documented defaults (no offset / no explicit limit).
|
|
96
|
+
const offsetChars = offsetCharsRaw !== undefined && offsetCharsRaw >= 0 ? offsetCharsRaw : undefined;
|
|
97
|
+
let limitChars = limitCharsRaw;
|
|
98
|
+
if (limitChars !== undefined && limitChars <= 0) {
|
|
99
|
+
limitChars = undefined;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
url,
|
|
103
|
+
cursor,
|
|
104
|
+
prompt,
|
|
105
|
+
maxChars,
|
|
106
|
+
format,
|
|
107
|
+
content,
|
|
108
|
+
includeLinks,
|
|
109
|
+
includeMetadata,
|
|
110
|
+
anchor,
|
|
111
|
+
offsetChars,
|
|
112
|
+
limitChars,
|
|
113
|
+
action,
|
|
114
|
+
ranges
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Parses an optional `ranges` array of character windows.
|
|
119
|
+
*
|
|
120
|
+
* @param raw - Raw input
|
|
121
|
+
* @returns Range specs, or undefined when absent/empty
|
|
122
|
+
*/
|
|
123
|
+
function parseRanges(raw) {
|
|
124
|
+
if (raw === undefined || raw === null) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
if (!Array.isArray(raw)) {
|
|
128
|
+
throw new Error("ranges debe ser un arreglo de objetos {offset_chars, limit_chars}.");
|
|
129
|
+
}
|
|
130
|
+
if (raw.length === 0) {
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
if (raw.length > MAX_TOOL_RANGES) {
|
|
134
|
+
throw new Error(`ranges admite un máximo de ${MAX_TOOL_RANGES} rangos por llamada.`);
|
|
135
|
+
}
|
|
136
|
+
const collected = [];
|
|
137
|
+
for (const entry of raw) {
|
|
138
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
139
|
+
throw new Error("cada rango en ranges debe ser un objeto {offset_chars, limit_chars}.");
|
|
140
|
+
}
|
|
141
|
+
const record = entry;
|
|
142
|
+
const offsetChars = optionalInt(record["offset_chars"]) ?? optionalInt(record["offsetChars"]) ?? optionalInt(record["offset"]) ?? 0;
|
|
143
|
+
const limitRaw = optionalInt(record["limit_chars"]) ?? optionalInt(record["limitChars"]) ?? optionalInt(record["limit"]);
|
|
144
|
+
if (offsetChars < 0) {
|
|
145
|
+
throw new Error("offset_chars de cada rango debe ser no negativo.");
|
|
146
|
+
}
|
|
147
|
+
if (limitRaw !== undefined && limitRaw < 0) {
|
|
148
|
+
throw new Error("limit_chars de cada rango debe ser positivo.");
|
|
149
|
+
}
|
|
150
|
+
collected.push({
|
|
151
|
+
offsetChars,
|
|
152
|
+
limitChars: limitRaw === undefined || limitRaw === 0 ? undefined : Math.max(1, limitRaw)
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return collected;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=WebFetchParamsParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetchParamsParser.js","sourceRoot":"","sources":["../../src/tools/WebFetchParamsParser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grouped-ranges execution for the web_fetch MCP tool.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Cursor slices are independent reads of one immutable capture: the batch
|
|
6
|
+
* runs concurrently (bounded by MAX_TOOL_RANGES) with order following the
|
|
7
|
+
* requested ranges — same semantics as EnriCode's grouped cursor ranges,
|
|
8
|
+
* including the Spanish continuation hints and the early cursor release
|
|
9
|
+
* when every window is exhausted. Extracted from {@link WebFetchTool}.
|
|
10
|
+
*
|
|
11
|
+
* @module tools/WebFetchRangesExecutor
|
|
12
|
+
*/
|
|
13
|
+
import { type EnriProxyClient } from "../client/EnriProxyClient.js";
|
|
14
|
+
import { type WebFetchRangeSpec, type WebFetchToolResult, type WebFetchToolRangesResult } from "./WebFetchTool.js";
|
|
15
|
+
/**
|
|
16
|
+
* Executes grouped ranges for the web_fetch tool.
|
|
17
|
+
*/
|
|
18
|
+
export declare class WebFetchRangesExecutor {
|
|
19
|
+
/**
|
|
20
|
+
* Reads the undecorated page one local range batch addresses.
|
|
21
|
+
*
|
|
22
|
+
* @param result - Single-read result holding the captured content.
|
|
23
|
+
* @returns Raw page text (bounds-resolved when the proxy reported
|
|
24
|
+
* them, verbatim `content` otherwise).
|
|
25
|
+
*/
|
|
26
|
+
static readUndecoratedPage(result: WebFetchToolResult): string;
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the first-read capture budget for grouped ranges.
|
|
29
|
+
*
|
|
30
|
+
* @param ranges - Requested ranges
|
|
31
|
+
* @param maxChars - Call budget
|
|
32
|
+
* @returns Capture budget reaching the furthest requested range end
|
|
33
|
+
*/
|
|
34
|
+
resolveRangesCaptureMaxChars(ranges: readonly WebFetchRangeSpec[], maxChars: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* Executes grouped ranges as concurrent cursor reads of one capture.
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* Cursor slices are independent reads of one immutable capture, so the
|
|
40
|
+
* batch runs concurrently (bounded by {@link MAX_TOOL_RANGES}) with order
|
|
41
|
+
* following the requested ranges — same semantics as EnriCode's grouped
|
|
42
|
+
* cursor ranges. One failed slice does not kill the batch: every range
|
|
43
|
+
* yields a result row and failures surface as Spanish `error` rows while
|
|
44
|
+
* the surviving slices return normally. A definitive proxy rejection on
|
|
45
|
+
* one slice (for example an expired cursor) cancels the sibling reads
|
|
46
|
+
* through a shared signal, since every slice reads the same cursor.
|
|
47
|
+
*
|
|
48
|
+
* @param client - EnriProxy client
|
|
49
|
+
* @param cursor - Cursor addressing the capture
|
|
50
|
+
* @param ranges - Requested ranges
|
|
51
|
+
* @param maxChars - Call budget used as default slice length
|
|
52
|
+
* @param resolvedUrl - URL reported for the grouped result
|
|
53
|
+
* @param signal - Optional caller abort signal
|
|
54
|
+
* @returns Grouped ranges result
|
|
55
|
+
* @throws Error when the caller cancelled the request mid-flight
|
|
56
|
+
*/
|
|
57
|
+
executeGroupedCursorRanges(client: EnriProxyClient, cursor: string, ranges: readonly WebFetchRangeSpec[], maxChars: number, resolvedUrl: string, signal?: AbortSignal): Promise<WebFetchToolRangesResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Describes one failed range read with an honest Spanish diagnostic.
|
|
60
|
+
*
|
|
61
|
+
* @param reason - Raw rejection reason of the failed slice.
|
|
62
|
+
* @param abortedBySiblingFailure - Whether the shared batch abort fired.
|
|
63
|
+
* @returns Spanish failure description for the model-facing error row.
|
|
64
|
+
*/
|
|
65
|
+
private static describeRangeFailure;
|
|
66
|
+
/**
|
|
67
|
+
* Applies grouped ranges locally over already-fetched content.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* A range whose offset lies beyond the UNDECORATED page is out of range,
|
|
71
|
+
* not truncated: the slice comes back empty with an honest Spanish note
|
|
72
|
+
* and `truncated: false`, so the model does not infer more pages behind
|
|
73
|
+
* an empty window. A range that starts inside the page but hits its end
|
|
74
|
+
* is the real truncation case. Windows address the raw page (via the
|
|
75
|
+
* `page_offset_chars`/`page_chars` bounds the proxy reports), so the
|
|
76
|
+
* status header and truncation footer never land inside a requested
|
|
77
|
+
* window; responses without bounds slice `content` verbatim.
|
|
78
|
+
*
|
|
79
|
+
* @param result - Single-read result holding the captured content
|
|
80
|
+
* @param ranges - Requested ranges
|
|
81
|
+
* @param maxChars - Call budget used as default slice length
|
|
82
|
+
* @returns Grouped ranges result
|
|
83
|
+
*/
|
|
84
|
+
applyLocalRangesToResult(result: WebFetchToolResult, ranges: readonly WebFetchRangeSpec[], maxChars: number): WebFetchToolRangesResult;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=WebFetchRangesExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetchRangesExecutor.d.ts","sourceRoot":"","sources":["../../src/tools/WebFetchRangesExecutor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,eAAe,EAA0C,MAAM,8BAA8B,CAAC;AAE5G,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC9B,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,qBAAa,sBAAsB;IACjC;;;;;;OAMG;WACW,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM;IAiBrE;;;;;;OAMG;IACI,4BAA4B,CACjC,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,QAAQ,EAAE,MAAM,GACf,MAAM;IAOT;;;;;;;;;;;;;;;;;;;;;OAqBG;IACU,0BAA0B,CACrC,MAAM,EAAE,eAAe,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC;IAyIpC;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAcnC;;;;;;;;;;;;;;;;;OAiBG;IACI,wBAAwB,CAC7B,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,QAAQ,EAAE,MAAM,GACf,wBAAwB;CAwD5B"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grouped-ranges execution for the web_fetch MCP tool.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Cursor slices are independent reads of one immutable capture: the batch
|
|
6
|
+
* runs concurrently (bounded by MAX_TOOL_RANGES) with order following the
|
|
7
|
+
* requested ranges — same semantics as EnriCode's grouped cursor ranges,
|
|
8
|
+
* including the Spanish continuation hints and the early cursor release
|
|
9
|
+
* when every window is exhausted. Extracted from {@link WebFetchTool}.
|
|
10
|
+
*
|
|
11
|
+
* @module tools/WebFetchRangesExecutor
|
|
12
|
+
*/
|
|
13
|
+
import { EnriProxyHttpError, MAX_WIRE_MAX_CHARS } from "../client/EnriProxyClient.js";
|
|
14
|
+
import { sliceUtf8Safe } from "../shared/Utf8SafeTextSlicer.js";
|
|
15
|
+
/**
|
|
16
|
+
* Executes grouped ranges for the web_fetch tool.
|
|
17
|
+
*/
|
|
18
|
+
export class WebFetchRangesExecutor {
|
|
19
|
+
/**
|
|
20
|
+
* Reads the undecorated page one local range batch addresses.
|
|
21
|
+
*
|
|
22
|
+
* @param result - Single-read result holding the captured content.
|
|
23
|
+
* @returns Raw page text (bounds-resolved when the proxy reported
|
|
24
|
+
* them, verbatim `content` otherwise).
|
|
25
|
+
*/
|
|
26
|
+
static readUndecoratedPage(result) {
|
|
27
|
+
const content = result.content;
|
|
28
|
+
const pageOffset = result.page_offset_chars;
|
|
29
|
+
const pageChars = result.page_chars;
|
|
30
|
+
if (typeof pageOffset === "number" &&
|
|
31
|
+
Number.isFinite(pageOffset) &&
|
|
32
|
+
pageOffset >= 0 &&
|
|
33
|
+
typeof pageChars === "number" &&
|
|
34
|
+
Number.isFinite(pageChars) &&
|
|
35
|
+
pageChars >= 0 &&
|
|
36
|
+
pageOffset <= content.length) {
|
|
37
|
+
return sliceUtf8Safe(content, pageOffset, pageOffset + pageChars);
|
|
38
|
+
}
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolves the first-read capture budget for grouped ranges.
|
|
43
|
+
*
|
|
44
|
+
* @param ranges - Requested ranges
|
|
45
|
+
* @param maxChars - Call budget
|
|
46
|
+
* @returns Capture budget reaching the furthest requested range end
|
|
47
|
+
*/
|
|
48
|
+
resolveRangesCaptureMaxChars(ranges, maxChars) {
|
|
49
|
+
const furthestEnd = Math.max(...ranges.map((range) => range.offsetChars + (range.limitChars ?? 0)));
|
|
50
|
+
return Math.min(MAX_WIRE_MAX_CHARS, Math.max(maxChars, furthestEnd));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Executes grouped ranges as concurrent cursor reads of one capture.
|
|
54
|
+
*
|
|
55
|
+
* @remarks
|
|
56
|
+
* Cursor slices are independent reads of one immutable capture, so the
|
|
57
|
+
* batch runs concurrently (bounded by {@link MAX_TOOL_RANGES}) with order
|
|
58
|
+
* following the requested ranges — same semantics as EnriCode's grouped
|
|
59
|
+
* cursor ranges. One failed slice does not kill the batch: every range
|
|
60
|
+
* yields a result row and failures surface as Spanish `error` rows while
|
|
61
|
+
* the surviving slices return normally. A definitive proxy rejection on
|
|
62
|
+
* one slice (for example an expired cursor) cancels the sibling reads
|
|
63
|
+
* through a shared signal, since every slice reads the same cursor.
|
|
64
|
+
*
|
|
65
|
+
* @param client - EnriProxy client
|
|
66
|
+
* @param cursor - Cursor addressing the capture
|
|
67
|
+
* @param ranges - Requested ranges
|
|
68
|
+
* @param maxChars - Call budget used as default slice length
|
|
69
|
+
* @param resolvedUrl - URL reported for the grouped result
|
|
70
|
+
* @param signal - Optional caller abort signal
|
|
71
|
+
* @returns Grouped ranges result
|
|
72
|
+
* @throws Error when the caller cancelled the request mid-flight
|
|
73
|
+
*/
|
|
74
|
+
async executeGroupedCursorRanges(client, cursor, ranges, maxChars, resolvedUrl, signal) {
|
|
75
|
+
// Shared signal: caller aborts propagate to every slice, and a proxy
|
|
76
|
+
// rejection on one slice cancels the siblings still in flight.
|
|
77
|
+
const sharedController = new AbortController();
|
|
78
|
+
const forwardCallerAbort = () => {
|
|
79
|
+
sharedController.abort();
|
|
80
|
+
};
|
|
81
|
+
if (signal !== undefined) {
|
|
82
|
+
if (signal.aborted) {
|
|
83
|
+
sharedController.abort();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
signal.addEventListener("abort", forwardCallerAbort, { once: true });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const settled = await Promise.allSettled(ranges.map(async (range, index) => {
|
|
90
|
+
const limitChars = range.limitChars ?? maxChars;
|
|
91
|
+
try {
|
|
92
|
+
const response = await client.webFetch({ cursor, offsetChars: range.offsetChars, limitChars, maxChars }, sharedController.signal, {
|
|
93
|
+
// Per-slice byte ceiling: ten concurrent windows must not
|
|
94
|
+
// each reserve the full max_chars-derived cap (up to ~25MB);
|
|
95
|
+
// the expected slice payload bounds the buffer instead, so
|
|
96
|
+
// the grouped fan-out stays within a bounded transient
|
|
97
|
+
// memory budget instead of ~10x the call budget.
|
|
98
|
+
maxResponseBytes: 6 * Math.min(limitChars, MAX_WIRE_MAX_CHARS) + 1024 * 1024
|
|
99
|
+
});
|
|
100
|
+
return {
|
|
101
|
+
index: index + 1,
|
|
102
|
+
offset_chars: range.offsetChars,
|
|
103
|
+
limit_chars: limitChars,
|
|
104
|
+
content: response.content,
|
|
105
|
+
status: response.status,
|
|
106
|
+
content_type: response.content_type,
|
|
107
|
+
truncated: response.truncated,
|
|
108
|
+
has_more: response.has_more,
|
|
109
|
+
total_chars: response.total_chars,
|
|
110
|
+
cursor: response.cursor
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
// A definitive proxy answer (HTTP error) rejects the cursor
|
|
115
|
+
// itself: every sibling slice would fail identically, so the
|
|
116
|
+
// shared signal cancels them instead of burning the budget.
|
|
117
|
+
if (error instanceof EnriProxyHttpError && !sharedController.signal.aborted) {
|
|
118
|
+
sharedController.abort();
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}));
|
|
123
|
+
if (signal !== undefined) {
|
|
124
|
+
signal.removeEventListener("abort", forwardCallerAbort);
|
|
125
|
+
}
|
|
126
|
+
// Caller cancellation keeps traveling as a thrown abort (SDK
|
|
127
|
+
// cancellation semantics) instead of a grouped result of error rows.
|
|
128
|
+
if (signal?.aborted) {
|
|
129
|
+
throw new Error("La petición fue cancelada por el cliente.");
|
|
130
|
+
}
|
|
131
|
+
const abortedBySiblingFailure = sharedController.signal.aborted && signal?.aborted !== true;
|
|
132
|
+
const slices = settled.map((outcome, index) => {
|
|
133
|
+
if (outcome.status === "fulfilled") {
|
|
134
|
+
return outcome.value;
|
|
135
|
+
}
|
|
136
|
+
const range = ranges[index];
|
|
137
|
+
const limitChars = range.limitChars ?? maxChars;
|
|
138
|
+
// A definitive proxy answer keeps its own message (plus the Spanish
|
|
139
|
+
// body diagnostic it carries) even when it triggered the shared
|
|
140
|
+
// abort; sibling reads cancelled by that rejection get the
|
|
141
|
+
// cancellation wording, and raw transport failures are wrapped in
|
|
142
|
+
// Spanish so no English stack jargon reaches the model.
|
|
143
|
+
const reason = WebFetchRangesExecutor.describeRangeFailure(outcome.reason, abortedBySiblingFailure);
|
|
144
|
+
return {
|
|
145
|
+
index: index + 1,
|
|
146
|
+
offset_chars: range.offsetChars,
|
|
147
|
+
limit_chars: limitChars,
|
|
148
|
+
content: "",
|
|
149
|
+
status: 0,
|
|
150
|
+
content_type: "",
|
|
151
|
+
truncated: false,
|
|
152
|
+
error: `Rango ${String(index + 1)} falló: ${reason}`
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
// Early reclamation parity with EnriCode: only windows that actually
|
|
156
|
+
// read content through the capture end count as exhaustion. Out-of-range
|
|
157
|
+
// empty windows (has_more: false with no content) never release, so a
|
|
158
|
+
// typo'd offset cannot destroy a capture whose bulk was never read.
|
|
159
|
+
let captureReleased = false;
|
|
160
|
+
const everyWindowReadThroughEnd = slices.length > 0 &&
|
|
161
|
+
slices.every((slice) => slice.error === undefined &&
|
|
162
|
+
slice.has_more === false &&
|
|
163
|
+
slice.content.length > 0 &&
|
|
164
|
+
(slice.total_chars === undefined || slice.offset_chars + slice.content.length >= slice.total_chars));
|
|
165
|
+
if (everyWindowReadThroughEnd) {
|
|
166
|
+
if (signal?.aborted !== true) {
|
|
167
|
+
captureReleased = true;
|
|
168
|
+
void client
|
|
169
|
+
.webFetch({ cursor, action: "delete" }, signal)
|
|
170
|
+
.then(() => undefined)
|
|
171
|
+
.catch(() => undefined);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
range_applied: true,
|
|
176
|
+
range_count: slices.length,
|
|
177
|
+
ranges: slices,
|
|
178
|
+
truncated: slices.some((slice) => slice.truncated),
|
|
179
|
+
range_hint: captureReleased
|
|
180
|
+
? "Todas las ventanas agotaron la captura y el cursor quedó liberado del servidor; para releer el documento use la url original."
|
|
181
|
+
: `Vuelva a llamar web_fetch con el mismo cursor (cursor="${cursor}") y ranges para pedir otros tramos no contiguos del documento sin volver a descargarlo.`,
|
|
182
|
+
url: resolvedUrl,
|
|
183
|
+
cursor
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Describes one failed range read with an honest Spanish diagnostic.
|
|
188
|
+
*
|
|
189
|
+
* @param reason - Raw rejection reason of the failed slice.
|
|
190
|
+
* @param abortedBySiblingFailure - Whether the shared batch abort fired.
|
|
191
|
+
* @returns Spanish failure description for the model-facing error row.
|
|
192
|
+
*/
|
|
193
|
+
static describeRangeFailure(reason, abortedBySiblingFailure) {
|
|
194
|
+
if (reason instanceof EnriProxyHttpError) {
|
|
195
|
+
const bodyDetail = sliceUtf8Safe(reason.body.trim(), 0, 300);
|
|
196
|
+
return bodyDetail.length > 0 ? `${reason.message} ${bodyDetail}` : reason.message;
|
|
197
|
+
}
|
|
198
|
+
if (abortedBySiblingFailure) {
|
|
199
|
+
return "lectura cancelada porque el servidor rechazó el cursor en otro rango del mismo lote";
|
|
200
|
+
}
|
|
201
|
+
if (reason instanceof Error) {
|
|
202
|
+
return `fallo de red leyendo el rango (${sliceUtf8Safe(reason.message, 0, 120)})`;
|
|
203
|
+
}
|
|
204
|
+
return String(reason);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Applies grouped ranges locally over already-fetched content.
|
|
208
|
+
*
|
|
209
|
+
* @remarks
|
|
210
|
+
* A range whose offset lies beyond the UNDECORATED page is out of range,
|
|
211
|
+
* not truncated: the slice comes back empty with an honest Spanish note
|
|
212
|
+
* and `truncated: false`, so the model does not infer more pages behind
|
|
213
|
+
* an empty window. A range that starts inside the page but hits its end
|
|
214
|
+
* is the real truncation case. Windows address the raw page (via the
|
|
215
|
+
* `page_offset_chars`/`page_chars` bounds the proxy reports), so the
|
|
216
|
+
* status header and truncation footer never land inside a requested
|
|
217
|
+
* window; responses without bounds slice `content` verbatim.
|
|
218
|
+
*
|
|
219
|
+
* @param result - Single-read result holding the captured content
|
|
220
|
+
* @param ranges - Requested ranges
|
|
221
|
+
* @param maxChars - Call budget used as default slice length
|
|
222
|
+
* @returns Grouped ranges result
|
|
223
|
+
*/
|
|
224
|
+
applyLocalRangesToResult(result, ranges, maxChars) {
|
|
225
|
+
const page = WebFetchRangesExecutor.readUndecoratedPage(result);
|
|
226
|
+
const slices = ranges.map((range, index) => {
|
|
227
|
+
const limitChars = range.limitChars ?? maxChars;
|
|
228
|
+
if (range.offsetChars >= page.length) {
|
|
229
|
+
return {
|
|
230
|
+
index: index + 1,
|
|
231
|
+
offset_chars: range.offsetChars,
|
|
232
|
+
limit_chars: limitChars,
|
|
233
|
+
content: "",
|
|
234
|
+
status: result.status,
|
|
235
|
+
content_type: result.content_type,
|
|
236
|
+
truncated: false,
|
|
237
|
+
note: `El offset queda fuera de la página devuelta (${String(page.length)} caracteres sin decoraciones); este rango está vacío.`
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const slice = sliceUtf8Safe(page, range.offsetChars, range.offsetChars + limitChars);
|
|
241
|
+
return {
|
|
242
|
+
index: index + 1,
|
|
243
|
+
offset_chars: range.offsetChars,
|
|
244
|
+
limit_chars: limitChars,
|
|
245
|
+
content: slice,
|
|
246
|
+
status: result.status,
|
|
247
|
+
content_type: result.content_type,
|
|
248
|
+
truncated: range.offsetChars + limitChars > page.length
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
return {
|
|
252
|
+
range_applied: true,
|
|
253
|
+
range_count: slices.length,
|
|
254
|
+
ranges: slices,
|
|
255
|
+
truncated: result.truncated,
|
|
256
|
+
range_hint: "Los rangos se aplicaron localmente sobre la captura devuelta; para leer más allá de la captura vuelva a llamar web_fetch con un max_chars mayor.",
|
|
257
|
+
url: result.url,
|
|
258
|
+
// Raw-capture continuation fields only travel when the delivered
|
|
259
|
+
// content shares the raw base: a reduced excerpt pack reorders the
|
|
260
|
+
// text, and an npm projection stitches a metadata header in front of
|
|
261
|
+
// the README (its cursor addresses the README alone), so local offsets
|
|
262
|
+
// would mispage the raw capture in both cases (EnriCode excludes the
|
|
263
|
+
// same fields in its URL projections).
|
|
264
|
+
...(result.reduced === true || result.applied_max_chars !== undefined
|
|
265
|
+
? {}
|
|
266
|
+
: result.cursor !== undefined
|
|
267
|
+
? { cursor: result.cursor }
|
|
268
|
+
: {}),
|
|
269
|
+
...(result.reduced === true || result.applied_max_chars !== undefined
|
|
270
|
+
? {}
|
|
271
|
+
: result.total_chars !== undefined
|
|
272
|
+
? { total_chars: result.total_chars }
|
|
273
|
+
: {})
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=WebFetchRangesExecutor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetchRangesExecutor.js","sourceRoot":"","sources":["../../src/tools/WebFetchRangesExecutor.ts"],"names":[],"mappings":"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"}
|