openclaw-abacusai-auth 1.2.5 → 1.2.6
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/index.ts +78 -0
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -270,6 +270,8 @@ async function validateApiKey(
|
|
|
270
270
|
|
|
271
271
|
let proxyServer: ReturnType<typeof createServer> | null = null;
|
|
272
272
|
let proxyApiKey = "";
|
|
273
|
+
let activeProxyRequests = 0;
|
|
274
|
+
let proxyShuttingDown = false;
|
|
273
275
|
|
|
274
276
|
function readBody(req: IncomingMessage): Promise<Buffer> {
|
|
275
277
|
return new Promise((resolve, reject) => {
|
|
@@ -554,6 +556,19 @@ function normalizeResponseToolCalls(json: Record<string, unknown>): Record<strin
|
|
|
554
556
|
}
|
|
555
557
|
|
|
556
558
|
async function handleProxyRequest(req: IncomingMessage, res: ServerResponse) {
|
|
559
|
+
if (proxyShuttingDown) {
|
|
560
|
+
sendJsonResponse(res, 503, { error: { message: "Proxy is shutting down", type: "service_unavailable" } });
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
activeProxyRequests++;
|
|
564
|
+
try {
|
|
565
|
+
await handleProxyRequestInner(req, res);
|
|
566
|
+
} finally {
|
|
567
|
+
activeProxyRequests--;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
async function handleProxyRequestInner(req: IncomingMessage, res: ServerResponse) {
|
|
557
572
|
const path = req.url ?? "/";
|
|
558
573
|
const target = `${ROUTELLM_BASE}${path}`;
|
|
559
574
|
const headers: Record<string, string> = {
|
|
@@ -718,6 +733,48 @@ function startProxy(apiKey: string): Promise<void> {
|
|
|
718
733
|
});
|
|
719
734
|
}
|
|
720
735
|
|
|
736
|
+
/**
|
|
737
|
+
* Gracefully stop the RouteLLM proxy server.
|
|
738
|
+
* 1. Stop accepting new connections
|
|
739
|
+
* 2. Wait for all in-flight requests to complete (up to 10s timeout)
|
|
740
|
+
* 3. Close the server and release the port
|
|
741
|
+
*/
|
|
742
|
+
function stopProxy(): Promise<void> {
|
|
743
|
+
return new Promise((resolve) => {
|
|
744
|
+
if (!proxyServer) {
|
|
745
|
+
resolve();
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
proxyShuttingDown = true;
|
|
750
|
+
console.log(`[abacusai] Proxy shutting down (${activeProxyRequests} active requests)...`);
|
|
751
|
+
|
|
752
|
+
// Stop accepting new connections immediately
|
|
753
|
+
proxyServer.close(() => {
|
|
754
|
+
console.log("[abacusai] Proxy server closed, port released.");
|
|
755
|
+
proxyServer = null;
|
|
756
|
+
proxyShuttingDown = false;
|
|
757
|
+
activeProxyRequests = 0;
|
|
758
|
+
resolve();
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
// Force-close after 10s if requests don't drain
|
|
762
|
+
const forceTimeout = setTimeout(() => {
|
|
763
|
+
console.warn(`[abacusai] Force-closing proxy (${activeProxyRequests} requests still active after 10s).`);
|
|
764
|
+
proxyServer?.closeAllConnections?.();
|
|
765
|
+
}, 10_000);
|
|
766
|
+
|
|
767
|
+
// Poll for active requests to finish, resolve early if all done
|
|
768
|
+
const drainInterval = setInterval(() => {
|
|
769
|
+
if (activeProxyRequests <= 0) {
|
|
770
|
+
clearInterval(drainInterval);
|
|
771
|
+
clearTimeout(forceTimeout);
|
|
772
|
+
// server.close callback will resolve
|
|
773
|
+
}
|
|
774
|
+
}, 200);
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
|
|
721
778
|
// ---------------------------------------------------------------------------
|
|
722
779
|
// Helpers
|
|
723
780
|
// ---------------------------------------------------------------------------
|
|
@@ -818,11 +875,32 @@ const abacusaiPlugin = {
|
|
|
818
875
|
register(api: unknown) {
|
|
819
876
|
const pluginApi = api as {
|
|
820
877
|
registerProvider: (config: unknown) => void;
|
|
878
|
+
registerHook?: (events: string | string[], handler: Function, opts?: { name?: string }) => void;
|
|
821
879
|
config?: {
|
|
822
880
|
models?: { providers?: { abacusai?: { compat?: { supportsStrictMode?: boolean } } } };
|
|
823
881
|
};
|
|
824
882
|
};
|
|
825
883
|
|
|
884
|
+
// ================================================================
|
|
885
|
+
// Register gateway_stop hook for graceful proxy shutdown
|
|
886
|
+
// ================================================================
|
|
887
|
+
if (typeof pluginApi.registerHook === "function") {
|
|
888
|
+
pluginApi.registerHook(
|
|
889
|
+
"gateway_stop",
|
|
890
|
+
async () => {
|
|
891
|
+
await stopProxy();
|
|
892
|
+
},
|
|
893
|
+
{ name: "openclaw-abacusai-auth:gateway-stop" },
|
|
894
|
+
);
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// Fallback: handle process signals if gateway_stop hook is unavailable
|
|
898
|
+
const shutdownHandler = () => {
|
|
899
|
+
stopProxy().then(() => process.exit(0));
|
|
900
|
+
};
|
|
901
|
+
process.once("SIGTERM", shutdownHandler);
|
|
902
|
+
process.once("SIGINT", shutdownHandler);
|
|
903
|
+
|
|
826
904
|
// Use local proxy mode to handle schema cleaning internally
|
|
827
905
|
// This is required because OpenClaw core may not support requiresCleanSchema yet
|
|
828
906
|
// The proxy normalizes tool schemas before forwarding to RouteLLM
|