mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:50:43 +00:00
fix(ci): clear extension lint regressions
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import http from "node:http";
|
||||
import https from "node:https";
|
||||
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import type {
|
||||
QaBusConversation,
|
||||
QaBusEvent,
|
||||
@@ -271,9 +272,17 @@ export async function injectQaBusInboundMessage(params: {
|
||||
}
|
||||
|
||||
export async function getQaBusState(baseUrl: string): Promise<QaBusStateSnapshot> {
|
||||
const response = await fetch(buildQaBusUrl(baseUrl, "/v1/state"));
|
||||
if (!response.ok) {
|
||||
throw new Error(`qa-bus request failed: ${response.status}`);
|
||||
const { response, release } = await fetchWithSsrFGuard({
|
||||
url: buildQaBusUrl(baseUrl, "/v1/state").toString(),
|
||||
policy: { allowPrivateNetwork: true },
|
||||
auditContext: "qa-channel.bus-state",
|
||||
});
|
||||
try {
|
||||
if (!response.ok) {
|
||||
throw new Error(`qa-bus request failed: ${response.status}`);
|
||||
}
|
||||
return (await response.json()) as QaBusStateSnapshot;
|
||||
} finally {
|
||||
await release();
|
||||
}
|
||||
return (await response.json()) as QaBusStateSnapshot;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/core";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { extractToolPayload } from "../../../src/infra/outbound/tool-payload.js";
|
||||
import {
|
||||
resetPluginRuntimeStateForTest,
|
||||
setActivePluginRegistry,
|
||||
} from "../../../src/plugins/runtime.js";
|
||||
import { createTestRegistry } from "../../../src/test-utils/channel-plugins.js";
|
||||
} from "openclaw/plugin-sdk/testing";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { extractToolPayload } from "../../../src/infra/outbound/tool-payload.js";
|
||||
import { createTestRegistry } from "../../../test/helpers/plugins/plugin-registry.js";
|
||||
import { createStartAccountContext } from "../../../test/helpers/plugins/start-account-context.js";
|
||||
import { createQaBusState, startQaBusServer } from "../../qa-lab/api.js";
|
||||
import { qaChannelPlugin, setQaChannelRuntime } from "../api.js";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createRequire } from "node:module";
|
||||
import os from "node:os";
|
||||
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
||||
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { debugLog, debugError } from "./utils/debug-log.js";
|
||||
import { sanitizeFileName } from "./utils/platform.js";
|
||||
@@ -112,12 +113,19 @@ async function doFetchToken(appId: string, clientSecret: string): Promise<string
|
||||
debugLog(`[qqbot-api:${appId}] >>> POST ${TOKEN_URL}`);
|
||||
|
||||
let response: Response;
|
||||
let release = async () => {};
|
||||
try {
|
||||
response = await fetch(TOKEN_URL, {
|
||||
method: "POST",
|
||||
headers: requestHeaders,
|
||||
body: JSON.stringify(requestBody),
|
||||
const guarded = await fetchWithSsrFGuard({
|
||||
url: TOKEN_URL,
|
||||
init: {
|
||||
method: "POST",
|
||||
headers: requestHeaders,
|
||||
body: JSON.stringify(requestBody),
|
||||
},
|
||||
auditContext: "qqbot.token",
|
||||
});
|
||||
response = guarded.response;
|
||||
release = guarded.release;
|
||||
} catch (err) {
|
||||
debugError(`[qqbot-api:${appId}] <<< Network error:`, err);
|
||||
throw new Error(`Network error getting access_token: ${formatErrorMessage(err)}`, {
|
||||
@@ -125,44 +133,48 @@ async function doFetchToken(appId: string, clientSecret: string): Promise<string
|
||||
});
|
||||
}
|
||||
|
||||
const responseHeaders: Record<string, string> = {};
|
||||
response.headers.forEach((value, key) => {
|
||||
responseHeaders[key] = value;
|
||||
});
|
||||
const tokenTraceId = response.headers.get("x-tps-trace-id") ?? "";
|
||||
debugLog(
|
||||
`[qqbot-api:${appId}] <<< Status: ${response.status} ${response.statusText}${tokenTraceId ? ` | TraceId: ${tokenTraceId}` : ""}`,
|
||||
);
|
||||
|
||||
let data: { access_token?: string; expires_in?: number };
|
||||
let rawBody: string;
|
||||
try {
|
||||
rawBody = await response.text();
|
||||
// Redact the token before logging the raw response body.
|
||||
const logBody = rawBody.replace(/"access_token"\s*:\s*"[^"]+"/g, '"access_token": "***"');
|
||||
debugLog(`[qqbot-api:${appId}] <<< Body:`, logBody);
|
||||
data = JSON.parse(rawBody) as { access_token?: string; expires_in?: number };
|
||||
} catch (err) {
|
||||
debugError(`[qqbot-api:${appId}] <<< Parse error:`, err);
|
||||
throw new Error(`Failed to parse access_token response: ${formatErrorMessage(err)}`, {
|
||||
cause: err,
|
||||
const responseHeaders: Record<string, string> = {};
|
||||
response.headers.forEach((value, key) => {
|
||||
responseHeaders[key] = value;
|
||||
});
|
||||
const tokenTraceId = response.headers.get("x-tps-trace-id") ?? "";
|
||||
debugLog(
|
||||
`[qqbot-api:${appId}] <<< Status: ${response.status} ${response.statusText}${tokenTraceId ? ` | TraceId: ${tokenTraceId}` : ""}`,
|
||||
);
|
||||
|
||||
let data: { access_token?: string; expires_in?: number };
|
||||
let rawBody: string;
|
||||
try {
|
||||
rawBody = await response.text();
|
||||
// Redact the token before logging the raw response body.
|
||||
const logBody = rawBody.replace(/"access_token"\s*:\s*"[^"]+"/g, '"access_token": "***"');
|
||||
debugLog(`[qqbot-api:${appId}] <<< Body:`, logBody);
|
||||
data = JSON.parse(rawBody) as { access_token?: string; expires_in?: number };
|
||||
} catch (err) {
|
||||
debugError(`[qqbot-api:${appId}] <<< Parse error:`, err);
|
||||
throw new Error(`Failed to parse access_token response: ${formatErrorMessage(err)}`, {
|
||||
cause: err,
|
||||
});
|
||||
}
|
||||
|
||||
if (!data.access_token) {
|
||||
throw new Error(`Failed to get access_token: ${JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
const expiresAt = Date.now() + (data.expires_in ?? 7200) * 1000;
|
||||
|
||||
tokenCacheMap.set(appId, {
|
||||
token: data.access_token,
|
||||
expiresAt,
|
||||
appId,
|
||||
});
|
||||
|
||||
debugLog(`[qqbot-api:${appId}] Token cached, expires at: ${new Date(expiresAt).toISOString()}`);
|
||||
return data.access_token;
|
||||
} finally {
|
||||
await release();
|
||||
}
|
||||
|
||||
if (!data.access_token) {
|
||||
throw new Error(`Failed to get access_token: ${JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
const expiresAt = Date.now() + (data.expires_in ?? 7200) * 1000;
|
||||
|
||||
tokenCacheMap.set(appId, {
|
||||
token: data.access_token,
|
||||
expiresAt,
|
||||
appId,
|
||||
});
|
||||
|
||||
debugLog(`[qqbot-api:${appId}] Token cached, expires at: ${new Date(expiresAt).toISOString()}`);
|
||||
return data.access_token;
|
||||
}
|
||||
|
||||
/** Clear one token cache or all token caches. */
|
||||
@@ -247,8 +259,15 @@ export async function apiRequest<T = unknown>(
|
||||
}
|
||||
|
||||
let res: Response;
|
||||
let release = async () => {};
|
||||
try {
|
||||
res = await fetch(url, options);
|
||||
const guarded = await fetchWithSsrFGuard({
|
||||
url,
|
||||
init: options,
|
||||
auditContext: `qqbot.api${path}`,
|
||||
});
|
||||
res = guarded.response;
|
||||
release = guarded.release;
|
||||
} catch (err) {
|
||||
clearTimeout(timeoutId);
|
||||
if (err instanceof Error && err.name === "AbortError") {
|
||||
@@ -270,24 +289,25 @@ export async function apiRequest<T = unknown>(
|
||||
`[qqbot-api] <<< Status: ${res.status} ${res.statusText}${traceId ? ` | TraceId: ${traceId}` : ""}`,
|
||||
);
|
||||
|
||||
let data: T;
|
||||
let rawBody: string;
|
||||
try {
|
||||
rawBody = await res.text();
|
||||
let data: T;
|
||||
const rawBody = await res.text();
|
||||
debugLog(`[qqbot-api] <<< Body:`, rawBody);
|
||||
data = JSON.parse(rawBody) as T;
|
||||
|
||||
if (!res.ok) {
|
||||
const error = data as { message?: string; code?: number };
|
||||
throw new Error(`API Error [${path}]: ${error.message ?? JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (err) {
|
||||
throw new Error(`Failed to parse response[${path}]: ${formatErrorMessage(err)}`, {
|
||||
cause: err,
|
||||
});
|
||||
} finally {
|
||||
await release();
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
const error = data as { message?: string; code?: number };
|
||||
throw new Error(`API Error [${path}]: ${error.message ?? JSON.stringify(data)}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Upload retry with exponential backoff.
|
||||
|
||||
Reference in New Issue
Block a user