@holin-work/holin-cli 1.3.8 → 1.4.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/bin/holin-cli.js +36 -13
- package/package.json +1 -1
package/bin/holin-cli.js
CHANGED
|
@@ -268,10 +268,30 @@ function createProxyServer() {
|
|
|
268
268
|
return;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
// Build upstream request
|
|
272
|
-
//
|
|
273
|
-
//
|
|
274
|
-
|
|
271
|
+
// Build upstream request based on path
|
|
272
|
+
// /mcp → https://api.holin.work/icbu/mcp (MCP protocol, holin-listing)
|
|
273
|
+
// /api/upload/* → https://api.holin.work/icbu/api/upload/* (file upload, holin-listing)
|
|
274
|
+
// /api/* → https://api.holin.work/api/* (platform API, holin-platform)
|
|
275
|
+
const upstreamBase = "https://api.holin.work";
|
|
276
|
+
let upstreamPath;
|
|
277
|
+
let isMcpRequest = false;
|
|
278
|
+
if (req.url.startsWith("/mcp")) {
|
|
279
|
+
upstreamPath = "/icbu/mcp";
|
|
280
|
+
isMcpRequest = true;
|
|
281
|
+
} else if (req.url.startsWith("/api/upload/")) {
|
|
282
|
+
// File upload APIs live in holin-listing (behind /icbu/ nginx prefix)
|
|
283
|
+
upstreamPath = "/icbu" + req.url;
|
|
284
|
+
} else if (req.url.startsWith("/api/")) {
|
|
285
|
+
upstreamPath = req.url;
|
|
286
|
+
} else {
|
|
287
|
+
// Unknown path
|
|
288
|
+
const body = JSON.stringify({ error: "not_found", message: `Unknown path: ${req.url}` });
|
|
289
|
+
res.writeHead(404, { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(body) });
|
|
290
|
+
res.end(body);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const upstreamUrl = new URL(upstreamBase);
|
|
275
295
|
const bodyBuffer = Buffer.concat(chunks);
|
|
276
296
|
const forwardHeaders = { ...req.headers };
|
|
277
297
|
delete forwardHeaders["transfer-encoding"];
|
|
@@ -282,25 +302,28 @@ function createProxyServer() {
|
|
|
282
302
|
const options = {
|
|
283
303
|
hostname: upstreamUrl.hostname,
|
|
284
304
|
port: upstreamUrl.port || 443,
|
|
285
|
-
path:
|
|
305
|
+
path: upstreamPath,
|
|
286
306
|
method: req.method,
|
|
287
307
|
headers: forwardHeaders,
|
|
288
308
|
};
|
|
289
309
|
|
|
290
|
-
// Parse request body to determine MCP method
|
|
310
|
+
// Parse request body to determine MCP method (only for MCP requests)
|
|
291
311
|
let mcpMethod = "";
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
312
|
+
if (isMcpRequest) {
|
|
313
|
+
try {
|
|
314
|
+
const parsed = JSON.parse(rawBody);
|
|
315
|
+
mcpMethod = parsed.method || "";
|
|
316
|
+
} catch { /* not JSON */ }
|
|
317
|
+
}
|
|
296
318
|
|
|
297
|
-
// Non-streaming methods should return JSON, not SSE
|
|
319
|
+
// Non-streaming methods should return JSON, not SSE (only for MCP requests)
|
|
298
320
|
// Accio expects JSON for initialize and tools/list
|
|
299
|
-
const shouldConvertToJson = mcpMethod === "initialize" || mcpMethod === "tools/list";
|
|
321
|
+
const shouldConvertToJson = isMcpRequest && (mcpMethod === "initialize" || mcpMethod === "tools/list");
|
|
300
322
|
|
|
301
323
|
const proxyReq = https.request(options, (proxyRes) => {
|
|
302
324
|
const elapsed = Date.now() - requestStart;
|
|
303
|
-
|
|
325
|
+
const routeLabel = isMcpRequest ? `mcp/${mcpMethod || "unknown"}` : req.url;
|
|
326
|
+
log(`[proxy] ← ${proxyRes.statusCode} ${elapsed}ms content-type=${proxyRes.headers["content-type"]} route=${routeLabel}`);
|
|
304
327
|
|
|
305
328
|
if (shouldConvertToJson && proxyRes.headers["content-type"]?.includes("text/event-stream")) {
|
|
306
329
|
// Collect SSE response and convert to JSON
|