@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,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npm package-page projection for the web_fetch tool.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* npm package pages answer with a marketing shell; this projection queries
|
|
6
|
+
* the official registry metadata and fetches the README from the resolved
|
|
7
|
+
* repository (GitHub raw with branch preference and a bounded worker pool),
|
|
8
|
+
* stitching a structured Spanish result with early-exit on the first hit.
|
|
9
|
+
* Extracted from {@link WebFetchTool} as a pure collaborator.
|
|
10
|
+
*
|
|
11
|
+
* Size note (~590 lines, alert zone by design): the npm path owns metadata
|
|
12
|
+
* fetch, version pinning, the README pool and the stitched composition as
|
|
13
|
+
* one cohesive pipeline; the shared registry transport already lives in
|
|
14
|
+
* WebSearchRegistryHttpReader. Splitting is tracked debt; any future edit
|
|
15
|
+
* must extract the touched unit instead of growing this file.
|
|
16
|
+
*
|
|
17
|
+
* @module tools/WebFetchNpmProjection
|
|
18
|
+
*/
|
|
19
|
+
import { sliceUtf8Safe } from "../shared/Utf8SafeTextSlicer.js";
|
|
20
|
+
/**
|
|
21
|
+
* Maximum concurrent README sub-fetches.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* Bounds the npm fan-out while keeping the worst case near one timeout for
|
|
25
|
+
* fast 404s; candidates dispatch in preference order.
|
|
26
|
+
*/
|
|
27
|
+
const README_FETCH_CONCURRENCY = 3;
|
|
28
|
+
/**
|
|
29
|
+
* Bounds one npm sub-fetch to the short subfetch timeout.
|
|
30
|
+
*
|
|
31
|
+
* @param signal - Optional caller abort signal.
|
|
32
|
+
* @returns Combined signal, or undefined when the caller passed none.
|
|
33
|
+
*/
|
|
34
|
+
function subfetchSignal(signal) {
|
|
35
|
+
if (signal === undefined) {
|
|
36
|
+
return AbortSignal.timeout(README_SUBFETCH_TIMEOUT_MS);
|
|
37
|
+
}
|
|
38
|
+
if (signal.aborted) {
|
|
39
|
+
return signal;
|
|
40
|
+
}
|
|
41
|
+
return AbortSignal.any([signal, AbortSignal.timeout(README_SUBFETCH_TIMEOUT_MS)]);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Per-subfetch timeout (ms) for npm registry/metadata/README reads.
|
|
45
|
+
*
|
|
46
|
+
* @remarks
|
|
47
|
+
* Raw files answer in milliseconds; a hung candidate must not consume the
|
|
48
|
+
* whole tool budget. Combined with the pool, the npm path stays near one
|
|
49
|
+
* tool timeout even when every candidate hangs.
|
|
50
|
+
*/
|
|
51
|
+
const README_SUBFETCH_TIMEOUT_MS = 20_000;
|
|
52
|
+
/**
|
|
53
|
+
* npm package-page projection collaborator.
|
|
54
|
+
*/
|
|
55
|
+
export class WebFetchNpmProjection {
|
|
56
|
+
/**
|
|
57
|
+
* Readme file candidates commonly used in GitHub repositories.
|
|
58
|
+
*/
|
|
59
|
+
static README_FILENAMES = [
|
|
60
|
+
"README.md",
|
|
61
|
+
"readme.md",
|
|
62
|
+
"README.MD",
|
|
63
|
+
"README.rst",
|
|
64
|
+
"README.txt"
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* Default branches to try when resolving GitHub raw README URLs.
|
|
68
|
+
*/
|
|
69
|
+
static README_BRANCHES = ["main", "master"];
|
|
70
|
+
/**
|
|
71
|
+
* Attempts to provide a higher-quality fetch for npm package pages.
|
|
72
|
+
*
|
|
73
|
+
* @param params - Tool parameters
|
|
74
|
+
* @param client - EnriProxy client
|
|
75
|
+
* @param maxChars - Maximum content length to return
|
|
76
|
+
* @param projection - Effective projection traveling to README sub-fetches
|
|
77
|
+
* @param signal - Optional caller abort signal
|
|
78
|
+
* @returns Tool result if the URL is an npm package page, otherwise null
|
|
79
|
+
*/
|
|
80
|
+
async tryExecuteNpmPackageFetch(params, client, maxChars, projection, signal) {
|
|
81
|
+
const requestedUrl = new URL(params.url);
|
|
82
|
+
const packageRef = this.tryParseNpmPackagePageRef(requestedUrl);
|
|
83
|
+
if (!packageRef) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
// A pinned `/v/<version>` page resolves its own registry manifest; only
|
|
87
|
+
// the unversioned page asks for `/latest` (small payload, parity with
|
|
88
|
+
// EnriProxy's registry tier).
|
|
89
|
+
const metadataUrl = packageRef.version !== undefined
|
|
90
|
+
? `https://registry.npmjs.org/${encodeURIComponent(packageRef.name)}/${encodeURIComponent(packageRef.version)}`
|
|
91
|
+
: `https://registry.npmjs.org/${encodeURIComponent(packageRef.name)}/latest`;
|
|
92
|
+
// A signal that never fires stands in for the caller when it passed
|
|
93
|
+
// none, so subfetch timeouts are labeled as timeouts (not cancellations).
|
|
94
|
+
const callerSignal = signal ?? new AbortController().signal;
|
|
95
|
+
let metadataResponse;
|
|
96
|
+
try {
|
|
97
|
+
metadataResponse = await client.webFetch({
|
|
98
|
+
url: metadataUrl,
|
|
99
|
+
maxChars: Math.min(maxChars, 20000)
|
|
100
|
+
}, subfetchSignal(signal), { callerSignal, subfetchTimeoutMs: README_SUBFETCH_TIMEOUT_MS });
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
// Transport failures on the metadata leg (proxy 5xx, subfetch timeout)
|
|
104
|
+
// degrade to the generic fetch path instead of failing the whole call;
|
|
105
|
+
// only a genuine caller abort propagates.
|
|
106
|
+
if (signal?.aborted) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
if (metadataResponse.status < 200 || metadataResponse.status >= 300) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const metadata = this.tryParseJsonObject(metadataResponse.content);
|
|
115
|
+
if (!metadata) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
const name = this.tryGetString(metadata["name"]) ?? packageRef.name;
|
|
119
|
+
const version = this.tryGetString(metadata["version"]);
|
|
120
|
+
const description = this.tryGetString(metadata["description"]);
|
|
121
|
+
const license = this.tryGetString(metadata["license"]);
|
|
122
|
+
const repositoryUrl = this.tryGetRepositoryUrl(metadata["repository"]);
|
|
123
|
+
const homepageUrl = this.tryGetString(metadata["homepage"]);
|
|
124
|
+
let gitHubRepoUrl = null;
|
|
125
|
+
if (repositoryUrl) {
|
|
126
|
+
gitHubRepoUrl = this.tryNormalizeGitHubRepoUrl(repositoryUrl);
|
|
127
|
+
}
|
|
128
|
+
let readmeText = null;
|
|
129
|
+
let readmeTruncated = false;
|
|
130
|
+
let readmeCursor;
|
|
131
|
+
let readmeTotalChars;
|
|
132
|
+
if (gitHubRepoUrl) {
|
|
133
|
+
const readmeResult = await this.tryFetchGitHubReadme(client, gitHubRepoUrl, maxChars, projection, signal);
|
|
134
|
+
if (readmeResult) {
|
|
135
|
+
readmeText = readmeResult.content;
|
|
136
|
+
readmeTruncated = readmeResult.truncated;
|
|
137
|
+
readmeCursor = readmeResult.cursor;
|
|
138
|
+
readmeTotalChars = readmeResult.totalChars;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const lines = [];
|
|
142
|
+
lines.push(`# ${name}`);
|
|
143
|
+
lines.push("");
|
|
144
|
+
lines.push(`URL solicitada: ${params.url}`);
|
|
145
|
+
lines.push("");
|
|
146
|
+
if (description) {
|
|
147
|
+
lines.push(`Descripción: ${description}`);
|
|
148
|
+
}
|
|
149
|
+
const versionLabel = version ?? packageRef.version ?? null;
|
|
150
|
+
if (versionLabel) {
|
|
151
|
+
// A pinned `/v/<version>` page labels the requested version; only the
|
|
152
|
+
// unversioned page reports the rolling "latest".
|
|
153
|
+
lines.push(packageRef.version !== undefined
|
|
154
|
+
? `Versión solicitada: ${versionLabel}`
|
|
155
|
+
: `Última versión: ${versionLabel}`);
|
|
156
|
+
}
|
|
157
|
+
if (license) {
|
|
158
|
+
lines.push(`Licencia: ${license}`);
|
|
159
|
+
}
|
|
160
|
+
if (homepageUrl) {
|
|
161
|
+
lines.push(`Página principal: ${homepageUrl}`);
|
|
162
|
+
}
|
|
163
|
+
if (gitHubRepoUrl) {
|
|
164
|
+
lines.push(`Repositorio: ${gitHubRepoUrl}`);
|
|
165
|
+
}
|
|
166
|
+
else if (repositoryUrl) {
|
|
167
|
+
lines.push(`Repositorio: ${repositoryUrl}`);
|
|
168
|
+
}
|
|
169
|
+
if (readmeText) {
|
|
170
|
+
lines.push("");
|
|
171
|
+
lines.push("## README");
|
|
172
|
+
lines.push("");
|
|
173
|
+
lines.push(readmeText);
|
|
174
|
+
}
|
|
175
|
+
const combined = lines.join("\n").trim() + "\n";
|
|
176
|
+
const shouldTrim = combined.length > maxChars;
|
|
177
|
+
const content = shouldTrim ? sliceUtf8Safe(combined, 0, maxChars) : combined;
|
|
178
|
+
return {
|
|
179
|
+
content,
|
|
180
|
+
status: 200,
|
|
181
|
+
content_type: "text/markdown",
|
|
182
|
+
truncated: shouldTrim || readmeTruncated || metadataResponse.truncated,
|
|
183
|
+
url: params.url,
|
|
184
|
+
// The winning README sub-fetch may have emitted a continuation cursor
|
|
185
|
+
// for its raw capture: propagate it (plus the capture total) so the
|
|
186
|
+
// model can paginate without re-downloading.
|
|
187
|
+
...(readmeCursor
|
|
188
|
+
? { cursor: readmeCursor, total_chars: readmeTotalChars, has_more: true }
|
|
189
|
+
: { total_chars: combined.length, has_more: shouldTrim }),
|
|
190
|
+
applied_max_chars: maxChars
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Attempts to parse package coordinates from an npmjs.com package page URL.
|
|
195
|
+
*
|
|
196
|
+
* @remarks
|
|
197
|
+
* Versioned pages (`/package/<name>/v/<version>`, including scoped
|
|
198
|
+
* packages) pin the registry manifest to the requested version; every
|
|
199
|
+
* other form resolves through `/latest`.
|
|
200
|
+
*
|
|
201
|
+
* @param url - Parsed URL
|
|
202
|
+
* @returns Package name plus optional pinned version, or null when the URL
|
|
203
|
+
* is not an npm package page
|
|
204
|
+
*/
|
|
205
|
+
tryParseNpmPackagePageRef(url) {
|
|
206
|
+
const hostname = url.hostname.toLowerCase();
|
|
207
|
+
if (hostname !== "www.npmjs.com" && hostname !== "npmjs.com") {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
// Path segments may arrive percent-encoded (e.g. `%40scope%2Fname` when
|
|
211
|
+
// copied from the registry); decode before parsing so scoped packages
|
|
212
|
+
// resolve to `@scope/name` like their canonical page form.
|
|
213
|
+
const segments = url.pathname
|
|
214
|
+
.split("/")
|
|
215
|
+
.filter(Boolean)
|
|
216
|
+
.map((segment) => {
|
|
217
|
+
try {
|
|
218
|
+
return decodeURIComponent(segment);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return segment;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
if (segments.length < 2) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
if (segments[0] !== "package") {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
// Reads the pinned version from the segments starting at `from`.
|
|
231
|
+
const readPinnedVersion = (from) => {
|
|
232
|
+
const marker = segments[from];
|
|
233
|
+
const value = segments[from + 1];
|
|
234
|
+
return marker === "v" && value !== undefined && value.length > 0 ? value : undefined;
|
|
235
|
+
};
|
|
236
|
+
const first = segments[1];
|
|
237
|
+
if (!first) {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
// A single percent-encoded segment (`%40scope%2Fname`) decodes to a name
|
|
241
|
+
// that already contains the slash; split it back into scope + name.
|
|
242
|
+
if (first.startsWith("@") && first.includes("/")) {
|
|
243
|
+
const [scope, name] = first.split("/");
|
|
244
|
+
if (!scope || !name) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
return { name: `${scope}/${name}`, version: readPinnedVersion(2) };
|
|
248
|
+
}
|
|
249
|
+
if (first.startsWith("@")) {
|
|
250
|
+
const second = segments[2];
|
|
251
|
+
if (!second) {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
return { name: `${first}/${second}`, version: readPinnedVersion(3) };
|
|
255
|
+
}
|
|
256
|
+
return { name: first, version: readPinnedVersion(2) };
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Tries to parse a JSON object from a string.
|
|
260
|
+
*
|
|
261
|
+
* @param input - JSON string
|
|
262
|
+
* @returns Parsed object or null
|
|
263
|
+
*/
|
|
264
|
+
tryParseJsonObject(input) {
|
|
265
|
+
try {
|
|
266
|
+
const parsed = JSON.parse(input);
|
|
267
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
return parsed;
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Extracts a string from an unknown value if possible.
|
|
278
|
+
*
|
|
279
|
+
* @param value - Unknown input
|
|
280
|
+
* @returns Trimmed string or null
|
|
281
|
+
*/
|
|
282
|
+
tryGetString(value) {
|
|
283
|
+
if (typeof value !== "string") {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const trimmed = value.trim();
|
|
287
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Extracts a repository URL from npm metadata.
|
|
291
|
+
*
|
|
292
|
+
* @param repository - Repository field value
|
|
293
|
+
* @returns Normalized URL string or null
|
|
294
|
+
*/
|
|
295
|
+
tryGetRepositoryUrl(repository) {
|
|
296
|
+
if (typeof repository === "string") {
|
|
297
|
+
return this.normalizeRepositoryUrl(repository);
|
|
298
|
+
}
|
|
299
|
+
if (typeof repository === "object" && repository !== null && !Array.isArray(repository)) {
|
|
300
|
+
const record = repository;
|
|
301
|
+
const rawUrl = this.tryGetString(record["url"]);
|
|
302
|
+
if (!rawUrl) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
return this.normalizeRepositoryUrl(rawUrl);
|
|
306
|
+
}
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Normalizes common git repository URL schemes into an https URL.
|
|
311
|
+
*
|
|
312
|
+
* @param rawUrl - Raw repository URL from metadata
|
|
313
|
+
* @returns Normalized URL string or null
|
|
314
|
+
*/
|
|
315
|
+
normalizeRepositoryUrl(rawUrl) {
|
|
316
|
+
let urlText = rawUrl.trim();
|
|
317
|
+
if (urlText.startsWith("github:")) {
|
|
318
|
+
urlText = `https://github.com/${urlText.slice("github:".length)}`;
|
|
319
|
+
}
|
|
320
|
+
const scpMatch = urlText.match(/^git@([^:]+):(.+)$/u);
|
|
321
|
+
if (scpMatch) {
|
|
322
|
+
urlText = `https://${scpMatch[1]}/${scpMatch[2]}`;
|
|
323
|
+
}
|
|
324
|
+
if (urlText.startsWith("git+")) {
|
|
325
|
+
urlText = urlText.slice("git+".length);
|
|
326
|
+
}
|
|
327
|
+
if (urlText.startsWith("git://")) {
|
|
328
|
+
urlText = `https://${urlText.slice("git://".length)}`;
|
|
329
|
+
}
|
|
330
|
+
if (urlText.endsWith(".git")) {
|
|
331
|
+
urlText = urlText.slice(0, -".git".length);
|
|
332
|
+
}
|
|
333
|
+
try {
|
|
334
|
+
const parsed = new URL(urlText);
|
|
335
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
return parsed.toString();
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Normalizes a GitHub repository URL to the canonical https form.
|
|
346
|
+
*
|
|
347
|
+
* @param repositoryUrl - Repository URL
|
|
348
|
+
* @returns Canonical GitHub repo URL (https://github.com/{owner}/{repo}) or null
|
|
349
|
+
*/
|
|
350
|
+
tryNormalizeGitHubRepoUrl(repositoryUrl) {
|
|
351
|
+
try {
|
|
352
|
+
const parsed = new URL(repositoryUrl);
|
|
353
|
+
if (parsed.hostname.toLowerCase() !== "github.com") {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
357
|
+
if (segments.length < 2) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
const owner = segments[0];
|
|
361
|
+
const repoRaw = segments[1];
|
|
362
|
+
if (!owner || !repoRaw) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
const repo = repoRaw.replace(/\.git$/iu, "");
|
|
366
|
+
return `https://github.com/${owner}/${repo}`;
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return null;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Attempts to fetch a GitHub repository README via raw.githubusercontent.com.
|
|
374
|
+
*
|
|
375
|
+
* @remarks
|
|
376
|
+
* Candidates dispatch in preference order through a bounded worker pool;
|
|
377
|
+
* the first completed hit wins and aborts the stragglers, so the common
|
|
378
|
+
* case costs one fast fetch instead of the slowest of ten. Projection
|
|
379
|
+
* fields travel to the README sub-fetches; the registry metadata fetch
|
|
380
|
+
* stays raw because its JSON is parsed.
|
|
381
|
+
*
|
|
382
|
+
* @param client - EnriProxy client
|
|
383
|
+
* @param githubRepoUrl - Canonical GitHub repo URL
|
|
384
|
+
* @param maxChars - Maximum content length
|
|
385
|
+
* @param projection - Effective projection for the README page
|
|
386
|
+
* @param signal - Optional caller abort signal
|
|
387
|
+
* @returns README content with pagination fields, or null
|
|
388
|
+
*/
|
|
389
|
+
async tryFetchGitHubReadme(client, githubRepoUrl, maxChars, projection, signal) {
|
|
390
|
+
const parsed = new URL(githubRepoUrl);
|
|
391
|
+
const segments = parsed.pathname.split("/").filter(Boolean);
|
|
392
|
+
if (segments.length < 2) {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
const owner = segments[0];
|
|
396
|
+
const repo = segments[1];
|
|
397
|
+
if (!owner || !repo) {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
const candidates = [];
|
|
401
|
+
for (const branch of WebFetchNpmProjection.README_BRANCHES) {
|
|
402
|
+
for (const filename of WebFetchNpmProjection.README_FILENAMES) {
|
|
403
|
+
candidates.push(`https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${filename}`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const controller = new AbortController();
|
|
407
|
+
const onCallerAbort = () => controller.abort();
|
|
408
|
+
if (signal !== undefined) {
|
|
409
|
+
if (signal.aborted) {
|
|
410
|
+
controller.abort();
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
signal.addEventListener("abort", onCallerAbort, { once: true });
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
let nextIndex = 0;
|
|
418
|
+
let hit = null;
|
|
419
|
+
const worker = async () => {
|
|
420
|
+
while (hit === null) {
|
|
421
|
+
const candidateIndex = nextIndex;
|
|
422
|
+
nextIndex += 1;
|
|
423
|
+
if (candidateIndex >= candidates.length) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (controller.signal.aborted) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
const candidateUrl = candidates[candidateIndex] ?? "";
|
|
430
|
+
let response;
|
|
431
|
+
try {
|
|
432
|
+
response = await client.webFetch({
|
|
433
|
+
url: candidateUrl,
|
|
434
|
+
maxChars,
|
|
435
|
+
format: projection.format,
|
|
436
|
+
content: projection.content,
|
|
437
|
+
includeLinks: projection.includeLinks,
|
|
438
|
+
includeMetadata: projection.includeMetadata,
|
|
439
|
+
...(projection.anchor !== undefined ? { anchor: projection.anchor } : {}),
|
|
440
|
+
...(projection.prompt !== undefined ? { prompt: projection.prompt } : {})
|
|
441
|
+
}, subfetchSignal(controller.signal), { callerSignal: controller.signal, subfetchTimeoutMs: README_SUBFETCH_TIMEOUT_MS });
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
// One candidate failing (404/timeout) must not orphan the rest,
|
|
445
|
+
// but a CALLER cancellation is not a candidate failure: it
|
|
446
|
+
// propagates so the npm projection surfaces an aborted call
|
|
447
|
+
// instead of composing a normal result for a cancelled request
|
|
448
|
+
// (same contract as the metadata leg above).
|
|
449
|
+
if (signal?.aborted === true) {
|
|
450
|
+
throw error;
|
|
451
|
+
}
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
if (hit !== null) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
if (response.status >= 200 && response.status < 300 && response.content.trim().length > 0) {
|
|
458
|
+
hit = {
|
|
459
|
+
content: response.content,
|
|
460
|
+
truncated: response.truncated,
|
|
461
|
+
cursor: response.cursor,
|
|
462
|
+
totalChars: response.total_chars
|
|
463
|
+
};
|
|
464
|
+
controller.abort();
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
const workers = [];
|
|
469
|
+
for (let i = 0; i < Math.min(README_FETCH_CONCURRENCY, candidates.length); i += 1) {
|
|
470
|
+
workers.push(worker());
|
|
471
|
+
}
|
|
472
|
+
await Promise.all(workers);
|
|
473
|
+
return hit;
|
|
474
|
+
}
|
|
475
|
+
finally {
|
|
476
|
+
signal?.removeEventListener("abort", onCallerAbort);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
//# sourceMappingURL=WebFetchNpmProjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetchNpmProjection.js","sourceRoot":"","sources":["../../src/tools/WebFetchNpmProjection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
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 { type WebFetchToolParams } from "./WebFetchTool.js";
|
|
19
|
+
/**
|
|
20
|
+
* Validates raw MCP tool arguments.
|
|
21
|
+
*
|
|
22
|
+
* @param raw - Raw tool arguments
|
|
23
|
+
* @returns Validated parameters
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseWebFetchParams(raw: unknown): WebFetchToolParams;
|
|
26
|
+
//# sourceMappingURL=WebFetchParamsParser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebFetchParamsParser.d.ts","sourceRoot":"","sources":["../../src/tools/WebFetchParamsParser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAqC,KAAK,kBAAkB,EAA0B,MAAM,mBAAmB,CAAC;AAEvH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAsGpE"}
|