openclaw-abacusai-auth 1.2.5 → 1.2.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/index.ts +101 -17
- 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
|
// ---------------------------------------------------------------------------
|
|
@@ -757,7 +814,7 @@ function buildModelDefinition(modelId: string) {
|
|
|
757
814
|
* but the config still stores the port from when `openclaw models auth login`
|
|
758
815
|
* was first run.
|
|
759
816
|
*/
|
|
760
|
-
function updateBaseUrlInConfig(): void {
|
|
817
|
+
function updateBaseUrlInConfig(pluginApi: any): void {
|
|
761
818
|
if (!proxyPort) return;
|
|
762
819
|
const newBaseUrl = `http://${PROXY_HOST}:${proxyPort}`;
|
|
763
820
|
try {
|
|
@@ -766,24 +823,30 @@ function updateBaseUrlInConfig(): void {
|
|
|
766
823
|
process.env.CLAWDBOT_STATE_DIR ||
|
|
767
824
|
join(homedir(), ".openclaw");
|
|
768
825
|
const configPath = join(stateDir, "openclaw.json");
|
|
769
|
-
if (!existsSync(configPath)) return;
|
|
770
|
-
|
|
771
|
-
let raw = readFileSync(configPath, "utf-8");
|
|
772
|
-
// Strip UTF-8 BOM if present
|
|
773
|
-
if (raw.charCodeAt(0) === 0xFEFF) raw = raw.slice(1);
|
|
774
|
-
const config = JSON.parse(raw);
|
|
775
|
-
const currentUrl = config?.models?.providers?.abacusai?.baseUrl;
|
|
776
826
|
|
|
777
|
-
if (
|
|
778
|
-
|
|
779
|
-
|
|
827
|
+
// 1. Update in-memory OpenClaw config if available (so it works immediately and saves correctly)
|
|
828
|
+
let inMemoryUpdated = false;
|
|
829
|
+
if (pluginApi?.config?.models?.providers?.abacusai) {
|
|
830
|
+
if (pluginApi.config.models.providers.abacusai.baseUrl !== newBaseUrl) {
|
|
831
|
+
pluginApi.config.models.providers.abacusai.baseUrl = newBaseUrl;
|
|
832
|
+
inMemoryUpdated = true;
|
|
833
|
+
}
|
|
780
834
|
}
|
|
781
835
|
|
|
782
|
-
//
|
|
783
|
-
if (
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
836
|
+
// 2. Fallback to writing the disk file directly if needed
|
|
837
|
+
if (existsSync(configPath)) {
|
|
838
|
+
let raw = readFileSync(configPath, "utf-8");
|
|
839
|
+
if (raw.charCodeAt(0) === 0xFEFF) raw = raw.slice(1);
|
|
840
|
+
const config = JSON.parse(raw);
|
|
841
|
+
const currentUrl = config?.models?.providers?.abacusai?.baseUrl;
|
|
842
|
+
|
|
843
|
+
if (currentUrl !== newBaseUrl && config.models?.providers?.abacusai) {
|
|
844
|
+
config.models.providers.abacusai.baseUrl = newBaseUrl;
|
|
845
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
846
|
+
console.log(`[abacusai] Updated config baseUrl on disk: ${currentUrl} → ${newBaseUrl}`);
|
|
847
|
+
} else if (inMemoryUpdated) {
|
|
848
|
+
console.log(`[abacusai] Updated in-memory baseUrl to ${newBaseUrl}`);
|
|
849
|
+
}
|
|
787
850
|
}
|
|
788
851
|
} catch (err) {
|
|
789
852
|
console.error("[abacusai] Failed to update baseUrl in config:", err);
|
|
@@ -818,11 +881,32 @@ const abacusaiPlugin = {
|
|
|
818
881
|
register(api: unknown) {
|
|
819
882
|
const pluginApi = api as {
|
|
820
883
|
registerProvider: (config: unknown) => void;
|
|
884
|
+
registerHook?: (events: string | string[], handler: Function, opts?: { name?: string }) => void;
|
|
821
885
|
config?: {
|
|
822
886
|
models?: { providers?: { abacusai?: { compat?: { supportsStrictMode?: boolean } } } };
|
|
823
887
|
};
|
|
824
888
|
};
|
|
825
889
|
|
|
890
|
+
// ================================================================
|
|
891
|
+
// Register gateway_stop hook for graceful proxy shutdown
|
|
892
|
+
// ================================================================
|
|
893
|
+
if (typeof pluginApi.registerHook === "function") {
|
|
894
|
+
pluginApi.registerHook(
|
|
895
|
+
"gateway_stop",
|
|
896
|
+
async () => {
|
|
897
|
+
await stopProxy();
|
|
898
|
+
},
|
|
899
|
+
{ name: "openclaw-abacusai-auth:gateway-stop" },
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// Fallback: handle process signals if gateway_stop hook is unavailable
|
|
904
|
+
const shutdownHandler = () => {
|
|
905
|
+
stopProxy().then(() => process.exit(0));
|
|
906
|
+
};
|
|
907
|
+
process.once("SIGTERM", shutdownHandler);
|
|
908
|
+
process.once("SIGINT", shutdownHandler);
|
|
909
|
+
|
|
826
910
|
// Use local proxy mode to handle schema cleaning internally
|
|
827
911
|
// This is required because OpenClaw core may not support requiresCleanSchema yet
|
|
828
912
|
// The proxy normalizes tool schemas before forwarding to RouteLLM
|
|
@@ -835,7 +919,7 @@ const abacusaiPlugin = {
|
|
|
835
919
|
// Update baseUrl in config to match the new proxy port
|
|
836
920
|
// (The proxy gets a new random port each time the gateway starts,
|
|
837
921
|
// but the config still has the port from when auth was first run)
|
|
838
|
-
updateBaseUrlInConfig();
|
|
922
|
+
updateBaseUrlInConfig(pluginApi);
|
|
839
923
|
})
|
|
840
924
|
.catch((err) => {
|
|
841
925
|
console.error("[abacusai] Failed to auto-start proxy:", err);
|