backpack-ontology 0.2.25 → 0.3.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/README.md +153 -3
- package/dist/bin/backpack-benchmark.d.ts +3 -0
- package/dist/bin/backpack-benchmark.d.ts.map +1 -0
- package/dist/bin/backpack-benchmark.js +213 -0
- package/dist/bin/backpack-benchmark.js.map +1 -0
- package/dist/bin/backpack.js +3 -3
- package/dist/bin/backpack.js.map +1 -1
- package/dist/bin/init.js +8 -11
- package/dist/bin/init.js.map +1 -1
- package/dist/core/backpack.d.ts +69 -2
- package/dist/core/backpack.d.ts.map +1 -1
- package/dist/core/backpack.js +205 -3
- package/dist/core/backpack.js.map +1 -1
- package/dist/core/draft.d.ts +42 -0
- package/dist/core/draft.d.ts.map +1 -0
- package/dist/core/draft.js +232 -0
- package/dist/core/draft.js.map +1 -0
- package/dist/core/events.d.ts +114 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +375 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/graph.d.ts +3 -1
- package/dist/core/graph.d.ts.map +1 -1
- package/dist/core/graph.js +50 -0
- package/dist/core/graph.js.map +1 -1
- package/dist/core/hooks.d.ts +11 -3
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/hooks.js +53 -47
- package/dist/core/hooks.js.map +1 -1
- package/dist/core/normalize.d.ts +28 -0
- package/dist/core/normalize.d.ts.map +1 -0
- package/dist/core/normalize.js +133 -0
- package/dist/core/normalize.js.map +1 -0
- package/dist/core/remote-fetch.d.ts +50 -0
- package/dist/core/remote-fetch.d.ts.map +1 -0
- package/dist/core/remote-fetch.js +338 -0
- package/dist/core/remote-fetch.js.map +1 -0
- package/dist/core/remote-registry.d.ts +95 -0
- package/dist/core/remote-registry.d.ts.map +1 -0
- package/dist/core/remote-registry.js +296 -0
- package/dist/core/remote-registry.js.map +1 -0
- package/dist/core/remote-schema.d.ts +31 -0
- package/dist/core/remote-schema.d.ts.map +1 -0
- package/dist/core/remote-schema.js +252 -0
- package/dist/core/remote-schema.js.map +1 -0
- package/dist/core/role-audit.d.ts +20 -0
- package/dist/core/role-audit.d.ts.map +1 -0
- package/dist/core/role-audit.js +197 -0
- package/dist/core/role-audit.js.map +1 -0
- package/dist/core/telemetry.d.ts +2 -0
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js +16 -0
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/token-estimate.d.ts +16 -0
- package/dist/core/token-estimate.d.ts.map +1 -0
- package/dist/core/token-estimate.js +29 -0
- package/dist/core/token-estimate.js.map +1 -0
- package/dist/core/types.d.ts +30 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +9 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/bulk-tools.d.ts.map +1 -1
- package/dist/mcp/tools/bulk-tools.js +80 -12
- package/dist/mcp/tools/bulk-tools.js.map +1 -1
- package/dist/mcp/tools/edge-tools.d.ts.map +1 -1
- package/dist/mcp/tools/edge-tools.js +14 -18
- package/dist/mcp/tools/edge-tools.js.map +1 -1
- package/dist/mcp/tools/error-helpers.d.ts +16 -0
- package/dist/mcp/tools/error-helpers.d.ts.map +1 -0
- package/dist/mcp/tools/error-helpers.js +34 -0
- package/dist/mcp/tools/error-helpers.js.map +1 -0
- package/dist/mcp/tools/intelligence-tools.d.ts.map +1 -1
- package/dist/mcp/tools/intelligence-tools.js +28 -18
- package/dist/mcp/tools/intelligence-tools.js.map +1 -1
- package/dist/mcp/tools/node-tools.d.ts.map +1 -1
- package/dist/mcp/tools/node-tools.js +43 -40
- package/dist/mcp/tools/node-tools.js.map +1 -1
- package/dist/mcp/tools/ontology-tools.d.ts.map +1 -1
- package/dist/mcp/tools/ontology-tools.js +237 -12
- package/dist/mcp/tools/ontology-tools.js.map +1 -1
- package/dist/mcp/tools/remote-tools.d.ts +5 -0
- package/dist/mcp/tools/remote-tools.d.ts.map +1 -0
- package/dist/mcp/tools/remote-tools.js +295 -0
- package/dist/mcp/tools/remote-tools.js.map +1 -0
- package/dist/storage/backpack-app-backend.d.ts +1 -1
- package/dist/storage/backpack-app-backend.d.ts.map +1 -1
- package/dist/storage/backpack-app-backend.js +3 -1
- package/dist/storage/backpack-app-backend.js.map +1 -1
- package/dist/storage/event-sourced-backend.d.ts +174 -0
- package/dist/storage/event-sourced-backend.d.ts.map +1 -0
- package/dist/storage/event-sourced-backend.js +840 -0
- package/dist/storage/event-sourced-backend.js.map +1 -0
- package/dist/storage/json-file-backend.d.ts +1 -72
- package/dist/storage/json-file-backend.d.ts.map +1 -1
- package/dist/storage/json-file-backend.js +11 -549
- package/dist/storage/json-file-backend.js.map +1 -1
- package/package.json +3 -3
- package/hooks/auto-capture-prompt.md +0 -40
- package/hooks/hooks.json +0 -16
- package/hooks/suggest-viewer.sh +0 -4
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Hardened HTTPS fetch for remote learning graphs.
|
|
3
|
+
//
|
|
4
|
+
// Threats this module defends against:
|
|
5
|
+
// 1. SSRF — a malicious URL points at the user's private network
|
|
6
|
+
// (router admin, cloud metadata, internal services)
|
|
7
|
+
// 2. DNS rebinding — a hostname resolves once for validation,
|
|
8
|
+
// then to a different IP for the actual request
|
|
9
|
+
// 3. Resource exhaustion — slow loris, infinite stream, oversized body
|
|
10
|
+
// 4. Redirect loops to private addresses
|
|
11
|
+
//
|
|
12
|
+
// The contract:
|
|
13
|
+
// - HTTPS only
|
|
14
|
+
// - DNS resolved once; the IP is checked against a private-range
|
|
15
|
+
// blocklist; the request is dispatched against the IP directly
|
|
16
|
+
// so DNS rebinding cannot redirect to a different host
|
|
17
|
+
// - Hard size cap (default 10 MB)
|
|
18
|
+
// - Hard total timeout (15s) and connect timeout (5s)
|
|
19
|
+
// - Max 3 redirects, each re-validated
|
|
20
|
+
// - Returns the body bytes plus an ETag if present
|
|
21
|
+
// ============================================================
|
|
22
|
+
import * as https from "node:https";
|
|
23
|
+
import * as dns from "node:dns/promises";
|
|
24
|
+
import * as net from "node:net";
|
|
25
|
+
import { URL } from "node:url";
|
|
26
|
+
// --- Defaults ---
|
|
27
|
+
export const REMOTE_FETCH_DEFAULTS = {
|
|
28
|
+
maxBytes: 10 * 1024 * 1024, // 10 MB
|
|
29
|
+
totalTimeoutMs: 15_000,
|
|
30
|
+
connectTimeoutMs: 5_000,
|
|
31
|
+
maxRedirects: 3,
|
|
32
|
+
};
|
|
33
|
+
// --- Errors ---
|
|
34
|
+
export class RemoteFetchError extends Error {
|
|
35
|
+
code;
|
|
36
|
+
url;
|
|
37
|
+
constructor(message, code, url) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.code = code;
|
|
40
|
+
this.url = url;
|
|
41
|
+
this.name = "RemoteFetchError";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Fetch a remote URL with full SSRF / size / timeout protections.
|
|
46
|
+
*
|
|
47
|
+
* Throws RemoteFetchError on any policy violation, network error,
|
|
48
|
+
* or oversized response.
|
|
49
|
+
*/
|
|
50
|
+
export async function remoteFetch(rawUrl, options = {}) {
|
|
51
|
+
const opts = {
|
|
52
|
+
maxBytes: options.maxBytes ?? REMOTE_FETCH_DEFAULTS.maxBytes,
|
|
53
|
+
totalTimeoutMs: options.totalTimeoutMs ?? REMOTE_FETCH_DEFAULTS.totalTimeoutMs,
|
|
54
|
+
connectTimeoutMs: options.connectTimeoutMs ?? REMOTE_FETCH_DEFAULTS.connectTimeoutMs,
|
|
55
|
+
maxRedirects: options.maxRedirects ?? REMOTE_FETCH_DEFAULTS.maxRedirects,
|
|
56
|
+
ifNoneMatch: options.ifNoneMatch,
|
|
57
|
+
};
|
|
58
|
+
let currentUrl = rawUrl;
|
|
59
|
+
let redirectCount = 0;
|
|
60
|
+
const startedAt = Date.now();
|
|
61
|
+
while (true) {
|
|
62
|
+
if (Date.now() - startedAt > opts.totalTimeoutMs) {
|
|
63
|
+
throw new RemoteFetchError("total fetch timeout exceeded", "TIMEOUT", currentUrl);
|
|
64
|
+
}
|
|
65
|
+
const parsed = parseAndValidateUrl(currentUrl);
|
|
66
|
+
const resolvedIp = await resolveAndCheckHost(parsed.hostname);
|
|
67
|
+
const remaining = opts.totalTimeoutMs - (Date.now() - startedAt);
|
|
68
|
+
const response = await singleRequest(parsed, resolvedIp, {
|
|
69
|
+
maxBytes: opts.maxBytes,
|
|
70
|
+
totalTimeoutMs: remaining,
|
|
71
|
+
connectTimeoutMs: opts.connectTimeoutMs,
|
|
72
|
+
ifNoneMatch: opts.ifNoneMatch,
|
|
73
|
+
});
|
|
74
|
+
// 304 Not Modified — no body, return immediately
|
|
75
|
+
if (response.status === 304) {
|
|
76
|
+
return {
|
|
77
|
+
body: "",
|
|
78
|
+
bytes: 0,
|
|
79
|
+
etag: response.etag,
|
|
80
|
+
finalUrl: currentUrl,
|
|
81
|
+
status: 304,
|
|
82
|
+
notModified: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Redirect handling
|
|
86
|
+
if (response.status >= 300 && response.status < 400 && response.location) {
|
|
87
|
+
if (redirectCount >= opts.maxRedirects) {
|
|
88
|
+
throw new RemoteFetchError(`too many redirects (max ${opts.maxRedirects})`, "TOO_MANY_REDIRECTS", currentUrl);
|
|
89
|
+
}
|
|
90
|
+
// Resolve relative redirects against the current URL
|
|
91
|
+
const nextUrl = new URL(response.location, currentUrl).toString();
|
|
92
|
+
redirectCount++;
|
|
93
|
+
currentUrl = nextUrl;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (response.status < 200 || response.status >= 300) {
|
|
97
|
+
throw new RemoteFetchError(`HTTP ${response.status}`, "HTTP_ERROR", currentUrl);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
body: response.body,
|
|
101
|
+
bytes: response.bytes,
|
|
102
|
+
etag: response.etag,
|
|
103
|
+
finalUrl: currentUrl,
|
|
104
|
+
status: response.status,
|
|
105
|
+
notModified: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function parseAndValidateUrl(rawUrl) {
|
|
110
|
+
let url;
|
|
111
|
+
try {
|
|
112
|
+
url = new URL(rawUrl);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new RemoteFetchError(`invalid URL: ${rawUrl}`, "INVALID_URL", rawUrl);
|
|
116
|
+
}
|
|
117
|
+
if (url.protocol !== "https:") {
|
|
118
|
+
throw new RemoteFetchError(`only https:// URLs are allowed (got ${url.protocol})`, "INVALID_SCHEME", rawUrl);
|
|
119
|
+
}
|
|
120
|
+
if (!url.hostname) {
|
|
121
|
+
throw new RemoteFetchError("URL has no hostname", "INVALID_URL", rawUrl);
|
|
122
|
+
}
|
|
123
|
+
// Reject userinfo (https://user:pass@host) which can confuse parsers
|
|
124
|
+
if (url.username || url.password) {
|
|
125
|
+
throw new RemoteFetchError("URLs with userinfo are not allowed", "INVALID_URL", rawUrl);
|
|
126
|
+
}
|
|
127
|
+
// Node's URL parser keeps IPv6 brackets in `hostname` (e.g. "[::1]").
|
|
128
|
+
// Strip them so net.isIP() and DNS resolution work correctly.
|
|
129
|
+
let hostname = url.hostname;
|
|
130
|
+
if (hostname.startsWith("[") && hostname.endsWith("]")) {
|
|
131
|
+
hostname = hostname.slice(1, -1);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
href: url.href,
|
|
135
|
+
hostname,
|
|
136
|
+
port: url.port ? parseInt(url.port, 10) : 443,
|
|
137
|
+
pathname: url.pathname || "/",
|
|
138
|
+
search: url.search || "",
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Resolves a hostname to an IP and rejects if the IP is in a private,
|
|
143
|
+
* loopback, link-local, multicast, or otherwise reserved range.
|
|
144
|
+
*
|
|
145
|
+
* Returns the resolved IP. Callers should dispatch the request against
|
|
146
|
+
* the IP directly to prevent DNS rebinding.
|
|
147
|
+
*/
|
|
148
|
+
async function resolveAndCheckHost(hostname) {
|
|
149
|
+
// If the hostname is already a literal IP, check it directly
|
|
150
|
+
if (net.isIP(hostname)) {
|
|
151
|
+
if (isBlockedIp(hostname)) {
|
|
152
|
+
throw new RemoteFetchError(`IP address ${hostname} is in a blocked range`, "BLOCKED_IP");
|
|
153
|
+
}
|
|
154
|
+
return hostname;
|
|
155
|
+
}
|
|
156
|
+
let addrs;
|
|
157
|
+
try {
|
|
158
|
+
addrs = await dns.lookup(hostname, { all: true, verbatim: true });
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
throw new RemoteFetchError(`DNS lookup failed: ${err.message}`, "DNS_ERROR");
|
|
162
|
+
}
|
|
163
|
+
if (addrs.length === 0) {
|
|
164
|
+
throw new RemoteFetchError("DNS lookup returned no addresses", "DNS_ERROR");
|
|
165
|
+
}
|
|
166
|
+
// Check ALL returned addresses — if any is private, refuse the whole hostname
|
|
167
|
+
for (const a of addrs) {
|
|
168
|
+
if (isBlockedIp(a.address)) {
|
|
169
|
+
throw new RemoteFetchError(`hostname ${hostname} resolves to blocked IP ${a.address}`, "BLOCKED_IP");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return addrs[0].address;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Returns true if the IP is in a private, loopback, link-local,
|
|
176
|
+
* multicast, broadcast, or reserved range. Both IPv4 and IPv6.
|
|
177
|
+
*/
|
|
178
|
+
export function isBlockedIp(ip) {
|
|
179
|
+
if (net.isIPv4(ip)) {
|
|
180
|
+
return isBlockedIpv4(ip);
|
|
181
|
+
}
|
|
182
|
+
if (net.isIPv6(ip)) {
|
|
183
|
+
return isBlockedIpv6(ip);
|
|
184
|
+
}
|
|
185
|
+
return true; // unknown family — block by default
|
|
186
|
+
}
|
|
187
|
+
function isBlockedIpv4(ip) {
|
|
188
|
+
const parts = ip.split(".").map((p) => parseInt(p, 10));
|
|
189
|
+
if (parts.length !== 4 || parts.some((p) => isNaN(p) || p < 0 || p > 255)) {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
const [a, b] = parts;
|
|
193
|
+
// 0.0.0.0/8 — "this network"
|
|
194
|
+
if (a === 0)
|
|
195
|
+
return true;
|
|
196
|
+
// 10.0.0.0/8 — private
|
|
197
|
+
if (a === 10)
|
|
198
|
+
return true;
|
|
199
|
+
// 100.64.0.0/10 — CGNAT shared address space
|
|
200
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
201
|
+
return true;
|
|
202
|
+
// 127.0.0.0/8 — loopback
|
|
203
|
+
if (a === 127)
|
|
204
|
+
return true;
|
|
205
|
+
// 169.254.0.0/16 — link-local (includes AWS/GCP metadata 169.254.169.254)
|
|
206
|
+
if (a === 169 && b === 254)
|
|
207
|
+
return true;
|
|
208
|
+
// 172.16.0.0/12 — private
|
|
209
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
210
|
+
return true;
|
|
211
|
+
// 192.0.0.0/24, 192.0.2.0/24 — IETF protocol assignments / TEST-NET-1
|
|
212
|
+
if (a === 192 && b === 0)
|
|
213
|
+
return true;
|
|
214
|
+
// 192.168.0.0/16 — private
|
|
215
|
+
if (a === 192 && b === 168)
|
|
216
|
+
return true;
|
|
217
|
+
// 198.18.0.0/15 — benchmarking
|
|
218
|
+
if (a === 198 && (b === 18 || b === 19))
|
|
219
|
+
return true;
|
|
220
|
+
// 198.51.100.0/24 — TEST-NET-2
|
|
221
|
+
if (a === 198 && b === 51)
|
|
222
|
+
return true;
|
|
223
|
+
// 203.0.113.0/24 — TEST-NET-3
|
|
224
|
+
if (a === 203 && b === 0)
|
|
225
|
+
return true;
|
|
226
|
+
// 224.0.0.0/4 — multicast
|
|
227
|
+
if (a >= 224 && a <= 239)
|
|
228
|
+
return true;
|
|
229
|
+
// 240.0.0.0/4 — reserved + 255.255.255.255 broadcast
|
|
230
|
+
if (a >= 240)
|
|
231
|
+
return true;
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
function isBlockedIpv6(ip) {
|
|
235
|
+
const lower = ip.toLowerCase();
|
|
236
|
+
// ::1 — loopback
|
|
237
|
+
if (lower === "::1")
|
|
238
|
+
return true;
|
|
239
|
+
// :: — unspecified
|
|
240
|
+
if (lower === "::")
|
|
241
|
+
return true;
|
|
242
|
+
// ::ffff:x.x.x.x — IPv4-mapped, recheck the IPv4
|
|
243
|
+
const v4MappedMatch = lower.match(/^::ffff:([\d.]+)$/);
|
|
244
|
+
if (v4MappedMatch) {
|
|
245
|
+
return isBlockedIpv4(v4MappedMatch[1]);
|
|
246
|
+
}
|
|
247
|
+
// fc00::/7 — unique local
|
|
248
|
+
if (lower.startsWith("fc") || lower.startsWith("fd"))
|
|
249
|
+
return true;
|
|
250
|
+
// fe80::/10 — link-local
|
|
251
|
+
if (lower.startsWith("fe8") || lower.startsWith("fe9") ||
|
|
252
|
+
lower.startsWith("fea") || lower.startsWith("feb"))
|
|
253
|
+
return true;
|
|
254
|
+
// ff00::/8 — multicast
|
|
255
|
+
if (lower.startsWith("ff"))
|
|
256
|
+
return true;
|
|
257
|
+
// 2001:db8::/32 — documentation
|
|
258
|
+
if (lower.startsWith("2001:db8:"))
|
|
259
|
+
return true;
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
function singleRequest(parsed, resolvedIp, opts) {
|
|
263
|
+
return new Promise((resolve, reject) => {
|
|
264
|
+
const headers = {
|
|
265
|
+
Host: parsed.hostname, // SNI / virtual host header still uses the name
|
|
266
|
+
"User-Agent": "backpack-remote-fetch/1.0",
|
|
267
|
+
Accept: "application/json",
|
|
268
|
+
};
|
|
269
|
+
if (opts.ifNoneMatch) {
|
|
270
|
+
headers["If-None-Match"] = opts.ifNoneMatch;
|
|
271
|
+
}
|
|
272
|
+
const req = https.request({
|
|
273
|
+
host: resolvedIp,
|
|
274
|
+
port: parsed.port,
|
|
275
|
+
path: parsed.pathname + parsed.search,
|
|
276
|
+
method: "GET",
|
|
277
|
+
headers,
|
|
278
|
+
servername: parsed.hostname, // SNI
|
|
279
|
+
// Strict TLS — no insecure fallback
|
|
280
|
+
rejectUnauthorized: true,
|
|
281
|
+
timeout: opts.connectTimeoutMs,
|
|
282
|
+
}, (res) => {
|
|
283
|
+
const status = res.statusCode || 0;
|
|
284
|
+
const etag = res.headers.etag || null;
|
|
285
|
+
const location = res.headers.location || null;
|
|
286
|
+
// 304 / 3xx — no body needed (or shouldn't read it)
|
|
287
|
+
if (status === 304 || (status >= 300 && status < 400)) {
|
|
288
|
+
res.resume(); // drain
|
|
289
|
+
resolve({ status, body: "", bytes: 0, etag, location });
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
// Check declared content-length up front
|
|
293
|
+
const declared = parseInt(res.headers["content-length"] || "0", 10);
|
|
294
|
+
if (declared > opts.maxBytes) {
|
|
295
|
+
req.destroy();
|
|
296
|
+
reject(new RemoteFetchError(`Content-Length ${declared} exceeds max ${opts.maxBytes}`, "TOO_LARGE", parsed.href));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const chunks = [];
|
|
300
|
+
let totalBytes = 0;
|
|
301
|
+
res.on("data", (chunk) => {
|
|
302
|
+
totalBytes += chunk.length;
|
|
303
|
+
if (totalBytes > opts.maxBytes) {
|
|
304
|
+
req.destroy();
|
|
305
|
+
reject(new RemoteFetchError(`response exceeds max ${opts.maxBytes} bytes`, "TOO_LARGE", parsed.href));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
chunks.push(chunk);
|
|
309
|
+
});
|
|
310
|
+
res.on("end", () => {
|
|
311
|
+
const body = Buffer.concat(chunks).toString("utf8");
|
|
312
|
+
resolve({ status, body, bytes: totalBytes, etag, location });
|
|
313
|
+
});
|
|
314
|
+
res.on("error", (err) => {
|
|
315
|
+
reject(new RemoteFetchError(`response error: ${err.message}`, "NETWORK_ERROR", parsed.href));
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
// Total timeout (separate from connect timeout)
|
|
319
|
+
const totalTimer = setTimeout(() => {
|
|
320
|
+
req.destroy();
|
|
321
|
+
reject(new RemoteFetchError("request timeout exceeded", "TIMEOUT", parsed.href));
|
|
322
|
+
}, opts.totalTimeoutMs);
|
|
323
|
+
req.on("timeout", () => {
|
|
324
|
+
req.destroy();
|
|
325
|
+
reject(new RemoteFetchError("connect timeout exceeded", "CONNECT_TIMEOUT", parsed.href));
|
|
326
|
+
});
|
|
327
|
+
req.on("error", (err) => {
|
|
328
|
+
clearTimeout(totalTimer);
|
|
329
|
+
// Already rejected above? Promise is idempotent, second reject is no-op
|
|
330
|
+
reject(new RemoteFetchError(`network error: ${err.message}`, "NETWORK_ERROR", parsed.href));
|
|
331
|
+
});
|
|
332
|
+
req.on("close", () => {
|
|
333
|
+
clearTimeout(totalTimer);
|
|
334
|
+
});
|
|
335
|
+
req.end();
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=remote-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-fetch.js","sourceRoot":"","sources":["../../src/core/remote-fetch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { LearningGraphData } from "./types.js";
|
|
2
|
+
export interface RemoteEntry {
|
|
3
|
+
/** Local alias used in the viewer / MCP. Unique within the registry. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** Source URL (must be https://). */
|
|
6
|
+
url: string;
|
|
7
|
+
/** Optional human-readable source label (e.g. "github:user/repo"). */
|
|
8
|
+
source?: string;
|
|
9
|
+
/** ISO timestamp when first registered. */
|
|
10
|
+
addedAt: string;
|
|
11
|
+
/** ISO timestamp of the last successful fetch. */
|
|
12
|
+
lastFetched: string;
|
|
13
|
+
/** Last seen ETag, for conditional GETs. */
|
|
14
|
+
etag: string | null;
|
|
15
|
+
/** SHA256 of the last fetched body. */
|
|
16
|
+
sha256: string;
|
|
17
|
+
/** If true, refetch refuses to overwrite when sha256 changes. */
|
|
18
|
+
pinned: boolean;
|
|
19
|
+
/** Size in bytes of the cached body. */
|
|
20
|
+
sizeBytes: number;
|
|
21
|
+
}
|
|
22
|
+
export interface RegistryFile {
|
|
23
|
+
version: number;
|
|
24
|
+
remotes: RemoteEntry[];
|
|
25
|
+
}
|
|
26
|
+
export declare class RemoteRegistryError extends Error {
|
|
27
|
+
readonly code: string;
|
|
28
|
+
constructor(message: string, code: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class RemoteRegistry {
|
|
31
|
+
private baseDir;
|
|
32
|
+
constructor(baseDir?: string);
|
|
33
|
+
private registryFile;
|
|
34
|
+
private cacheDir;
|
|
35
|
+
private cacheFile;
|
|
36
|
+
/**
|
|
37
|
+
* Ensures the base directory and cache directory exist.
|
|
38
|
+
* Safe to call multiple times.
|
|
39
|
+
*/
|
|
40
|
+
initialize(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Reads the registry file. Returns an empty registry if the file
|
|
43
|
+
* doesn't exist yet.
|
|
44
|
+
*/
|
|
45
|
+
load(): Promise<RegistryFile>;
|
|
46
|
+
/**
|
|
47
|
+
* Atomically writes the registry file.
|
|
48
|
+
*/
|
|
49
|
+
private save;
|
|
50
|
+
/**
|
|
51
|
+
* List all registered remotes.
|
|
52
|
+
*/
|
|
53
|
+
list(): Promise<RemoteEntry[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Look up a single remote by name.
|
|
56
|
+
*/
|
|
57
|
+
get(name: string): Promise<RemoteEntry | null>;
|
|
58
|
+
/**
|
|
59
|
+
* Register a new remote: validate the name, fetch the URL, validate
|
|
60
|
+
* the graph schema, write to cache, and append to the registry.
|
|
61
|
+
*
|
|
62
|
+
* Throws if the name already exists, if the URL fails to fetch, or
|
|
63
|
+
* if the schema validation fails.
|
|
64
|
+
*
|
|
65
|
+
* The caller is responsible for ensuring the name does not collide
|
|
66
|
+
* with a local graph (this module doesn't know about local graphs).
|
|
67
|
+
*/
|
|
68
|
+
register(opts: {
|
|
69
|
+
name: string;
|
|
70
|
+
url: string;
|
|
71
|
+
source?: string;
|
|
72
|
+
pin?: boolean;
|
|
73
|
+
}): Promise<RemoteEntry>;
|
|
74
|
+
/**
|
|
75
|
+
* Refetch a registered remote. Uses ETag for conditional GET.
|
|
76
|
+
*
|
|
77
|
+
* If pinned and the SHA256 changes, throws RemoteRegistryError with
|
|
78
|
+
* code "PIN_VIOLATION" without overwriting the cache.
|
|
79
|
+
*/
|
|
80
|
+
refresh(name: string): Promise<{
|
|
81
|
+
entry: RemoteEntry;
|
|
82
|
+
changed: boolean;
|
|
83
|
+
notModified: boolean;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Remove a remote from the registry and delete its cache file.
|
|
87
|
+
*/
|
|
88
|
+
unregister(name: string): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Load the cached graph contents for a registered remote.
|
|
91
|
+
* Throws if the remote is not registered or the cache file is missing.
|
|
92
|
+
*/
|
|
93
|
+
loadCached(name: string): Promise<LearningGraphData>;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=remote-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-registry.d.ts","sourceRoot":"","sources":["../../src/core/remote-registry.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAIpD,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,wCAAwC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAOD,qBAAa,mBAAoB,SAAQ,KAAK;aAG1B,IAAI,EAAE,MAAM;gBAD5B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM;CAK/B;AAuBD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,CAAC,EAAE,MAAM;IAI5B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAcjB;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC;IAwBnC;;OAEG;YACW,IAAI;IAMlB;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAKpC;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAMpD;;;;;;;;;OASG;IACG,QAAQ,CAAC,IAAI,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,GAAG,CAAC,EAAE,OAAO,CAAC;KACf,GAAG,OAAO,CAAC,WAAW,CAAC;IA0ExB;;;;;OAKG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QACnC,KAAK,EAAE,WAAW,CAAC;QACnB,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,OAAO,CAAC;KACtB,CAAC;IAgFF;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB7C;;;OAGG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAwB3D"}
|