@gethelio/proxy 0.1.0 → 0.1.1
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 +13 -14
- package/dist/cli.js +44 -4
- package/dist/dashboard-assets/assets/{index-Yyo92yXC.js → index-CAgnN6wV.js} +28 -28
- package/dist/dashboard-assets/index.html +1 -1
- package/dist/index.js +44 -4
- package/package.json +16 -15
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<meta name="referrer" content="no-referrer" />
|
|
7
7
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
8
8
|
<title>Helio Dashboard</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-CAgnN6wV.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/index-DG3h7Cvn.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -1092,6 +1092,45 @@ async function parseUpstreamResponse(res) {
|
|
|
1092
1092
|
return { status: res.status, headers, body };
|
|
1093
1093
|
}
|
|
1094
1094
|
|
|
1095
|
+
// src/upstream/connection-error.ts
|
|
1096
|
+
var UPSTREAM_DOCS_URL = "https://github.com/gethelio/helio/blob/main/docs/getting-started.md";
|
|
1097
|
+
var UNREACHABLE_CODES = /* @__PURE__ */ new Set([
|
|
1098
|
+
"ECONNREFUSED",
|
|
1099
|
+
"ENOTFOUND",
|
|
1100
|
+
"EAI_AGAIN",
|
|
1101
|
+
"ECONNRESET",
|
|
1102
|
+
"EHOSTUNREACH",
|
|
1103
|
+
"ENETUNREACH",
|
|
1104
|
+
"ETIMEDOUT",
|
|
1105
|
+
"EPIPE",
|
|
1106
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
1107
|
+
"UND_ERR_SOCKET"
|
|
1108
|
+
]);
|
|
1109
|
+
function extractErrorCode(error) {
|
|
1110
|
+
let current = error;
|
|
1111
|
+
for (let depth = 0; depth < 5 && current != null; depth += 1) {
|
|
1112
|
+
if (typeof current === "object" && "code" in current) {
|
|
1113
|
+
const code = current.code;
|
|
1114
|
+
if (typeof code === "string") return code;
|
|
1115
|
+
}
|
|
1116
|
+
current = current.cause;
|
|
1117
|
+
}
|
|
1118
|
+
return void 0;
|
|
1119
|
+
}
|
|
1120
|
+
function describeUnreachableUpstream(error, url) {
|
|
1121
|
+
const code = extractErrorCode(error);
|
|
1122
|
+
const isGenericFetchFailure = error instanceof TypeError && error.message === "fetch failed";
|
|
1123
|
+
if (code !== void 0) {
|
|
1124
|
+
if (!UNREACHABLE_CODES.has(code)) return null;
|
|
1125
|
+
} else if (!isGenericFetchFailure) {
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
const codeSuffix = code ? ` (${code})` : "";
|
|
1129
|
+
return new Error(
|
|
1130
|
+
`Upstream MCP server at ${url} is unreachable${codeSuffix} \u2014 is it running? Helio proxies an existing MCP server: set upstream.url in helio.yaml to a reachable server, or start the server it points at. See ${UPSTREAM_DOCS_URL}`
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1095
1134
|
// src/upstream/forwarder.ts
|
|
1096
1135
|
var UpstreamForwarder = class {
|
|
1097
1136
|
url;
|
|
@@ -1139,7 +1178,7 @@ var UpstreamForwarder = class {
|
|
|
1139
1178
|
if (isTimeout) {
|
|
1140
1179
|
throw new Error(`upstream request timed out after ${String(this.requestTimeoutMs)}ms`);
|
|
1141
1180
|
}
|
|
1142
|
-
throw error;
|
|
1181
|
+
throw describeUnreachableUpstream(error, this.url) ?? error;
|
|
1143
1182
|
}
|
|
1144
1183
|
const durationMs = performance.now() - start;
|
|
1145
1184
|
const contentType = res.headers.get("content-type") ?? "";
|
|
@@ -1300,7 +1339,7 @@ var SseUpstreamForwarder = class {
|
|
|
1300
1339
|
);
|
|
1301
1340
|
return;
|
|
1302
1341
|
}
|
|
1303
|
-
reject(asError);
|
|
1342
|
+
reject(describeUnreachableUpstream(err, this.url) ?? asError);
|
|
1304
1343
|
}
|
|
1305
1344
|
});
|
|
1306
1345
|
});
|
|
@@ -1346,7 +1385,7 @@ var SseUpstreamForwarder = class {
|
|
|
1346
1385
|
`upstream notification POST timed out after ${String(this.requestTimeoutMs)}ms`
|
|
1347
1386
|
);
|
|
1348
1387
|
}
|
|
1349
|
-
throw asError;
|
|
1388
|
+
throw describeUnreachableUpstream(error, this.postUrl) ?? asError;
|
|
1350
1389
|
}
|
|
1351
1390
|
if (!res.ok) {
|
|
1352
1391
|
throw new Error(`upstream notification POST failed: HTTP ${String(res.status)}`);
|
|
@@ -1393,7 +1432,8 @@ var SseUpstreamForwarder = class {
|
|
|
1393
1432
|
const asError = error instanceof Error ? error : new Error(String(error));
|
|
1394
1433
|
const isTimeout = asError.name === "TimeoutError";
|
|
1395
1434
|
const isAborted = request.signal?.aborted === true;
|
|
1396
|
-
const
|
|
1435
|
+
const networkFailure = describeUnreachableUpstream(error, this.postUrl) ?? asError;
|
|
1436
|
+
const postFailure = isTimeout ? new Error(`upstream request POST timed out after ${String(this.requestTimeoutMs)}ms`) : networkFailure;
|
|
1397
1437
|
this.pending.reject(
|
|
1398
1438
|
requestId,
|
|
1399
1439
|
isAborted ? new Error("request aborted by downstream client") : postFailure
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gethelio/proxy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Open-source MCP governance proxy for AI agents",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -32,6 +32,19 @@
|
|
|
32
32
|
"types": "./dist/index.d.ts"
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"dev": "tsup --watch",
|
|
37
|
+
"build:dashboard": "pnpm --filter @gethelio/dashboard build",
|
|
38
|
+
"build:proxy": "tsup",
|
|
39
|
+
"bundle:dashboard-assets": "tsx scripts/bundle-dashboard-assets.ts",
|
|
40
|
+
"check:dashboard-assets": "tsx scripts/check-dashboard-assets.ts",
|
|
41
|
+
"build": "pnpm run build:dashboard && pnpm run build:proxy && pnpm run bundle:dashboard-assets && pnpm run check:dashboard-assets",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"benchmark": "tsx scripts/benchmark.ts",
|
|
46
|
+
"prepack": "pnpm run check:dashboard-assets"
|
|
47
|
+
},
|
|
35
48
|
"devDependencies": {
|
|
36
49
|
"@modelcontextprotocol/sdk": "1.28.0",
|
|
37
50
|
"@types/better-sqlite3": "7.6.13",
|
|
@@ -40,7 +53,7 @@
|
|
|
40
53
|
"@types/picomatch": "4.0.2",
|
|
41
54
|
"tsup": "8.5.1",
|
|
42
55
|
"tsx": "4.21.0",
|
|
43
|
-
"vitest": "
|
|
56
|
+
"vitest": "4.1.8"
|
|
44
57
|
},
|
|
45
58
|
"dependencies": {
|
|
46
59
|
"@hono/node-server": "1.19.13",
|
|
@@ -53,17 +66,5 @@
|
|
|
53
66
|
"picomatch": "4.0.4",
|
|
54
67
|
"safe-regex2": "5.0.0",
|
|
55
68
|
"zod": "4.3.6"
|
|
56
|
-
},
|
|
57
|
-
"scripts": {
|
|
58
|
-
"dev": "tsup --watch",
|
|
59
|
-
"build:dashboard": "pnpm --filter @gethelio/dashboard build",
|
|
60
|
-
"build:proxy": "tsup",
|
|
61
|
-
"bundle:dashboard-assets": "tsx scripts/bundle-dashboard-assets.ts",
|
|
62
|
-
"check:dashboard-assets": "tsx scripts/check-dashboard-assets.ts",
|
|
63
|
-
"build": "pnpm run build:dashboard && pnpm run build:proxy && pnpm run bundle:dashboard-assets && pnpm run check:dashboard-assets",
|
|
64
|
-
"test": "vitest run",
|
|
65
|
-
"test:watch": "vitest",
|
|
66
|
-
"typecheck": "tsc --noEmit",
|
|
67
|
-
"benchmark": "tsx scripts/benchmark.ts"
|
|
68
69
|
}
|
|
69
|
-
}
|
|
70
|
+
}
|