diff --git a/extensions/feishu/src/app-registration.test.ts b/extensions/feishu/src/app-registration.test.ts index b46e6937a4ac..1c6b181b90b6 100644 --- a/extensions/feishu/src/app-registration.test.ts +++ b/extensions/feishu/src/app-registration.test.ts @@ -1,7 +1,6 @@ // Feishu tests cover app registration plugin behavior. import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; import { MAX_TIMER_TIMEOUT_MS } from "openclaw/plugin-sdk/number-runtime"; -import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http"; import type { LookupFn } from "openclaw/plugin-sdk/ssrf-runtime"; import { withFetchPreconnect } from "openclaw/plugin-sdk/test-env"; import { afterEach, describe, expect, it, vi } from "vitest"; @@ -410,57 +409,3 @@ describe("Feishu app registration", () => { ); }); }); - -describe("feishu bound reads — local HTTP server", () => { - it("rejects oversized response before fully buffering the response (OOM guard)", async () => { - const chunk = Buffer.alloc(1024 * 1024, 0x61); - const totalChunks = 64; - let chunksWritten = 0; - - const srv = await startLocalServer((_req, res) => { - res.writeHead(200, { "content-type": "application/json" }); - let sent = 0; - const sendChunk = () => { - if (sent >= totalChunks) { - res.end(); - return; - } - sent += 1; - chunksWritten += 1; - const ok = res.write(chunk); - if (ok) { - setImmediate(sendChunk); - return; - } - res.once("drain", sendChunk); - }; - sendChunk(); - }); - - try { - const response = await fetch(`http://127.0.0.1:${srv.port}/`); - // Mutation-control: bare `response.json()` would buffer all 20 MiB. - await expect(readProviderJsonResponse(response, "feishu.bound-proof")).rejects.toThrow( - /JSON response exceeds/, - ); - expect(chunksWritten).toBeLessThan(totalChunks); - console.log(`[bound-proof] canceled at ${chunksWritten}/${totalChunks} chunks`); - } finally { - await srv.stop(); - } - }); - - it("parses well-formed JSON response under the cap", async () => { - const payload = { code: 0, data: { app_id: "cli_test" } }; - const srv = await startLocalServer((_req, res) => { - writeJson(res, payload); - }); - try { - const response = await fetch(`http://127.0.0.1:${srv.port}/`); - const result = await readProviderJsonResponse(response, "feishu.bound-proof"); - expect(result).toEqual(payload); - } finally { - await srv.stop(); - } - }); -}); diff --git a/extensions/line/src/setup-surface.test.ts b/extensions/line/src/setup-surface.test.ts index 5915aec68423..d8c119693676 100644 --- a/extensions/line/src/setup-surface.test.ts +++ b/extensions/line/src/setup-surface.test.ts @@ -1,6 +1,4 @@ // Line tests cover setup surface plugin behavior. -import { readFileSync } from "node:fs"; -import path from "node:path"; import { createStartAccountContext, installChannelDmPolicyContractSuite, @@ -11,8 +9,6 @@ import { runSetupWizardConfigure, } from "openclaw/plugin-sdk/plugin-test-runtime"; import type { WizardPrompter } from "openclaw/plugin-sdk/plugin-test-runtime"; -import { bundledPluginRoot } from "openclaw/plugin-sdk/test-fixtures"; -import ts from "typescript"; import { afterAll, afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { OpenClawConfig, PluginRuntime, ResolvedLineAccount } from "../api.js"; import { linePlugin } from "./channel.js"; @@ -42,125 +38,6 @@ afterAll(() => { }); const lineConfigure = createPluginSetupWizardConfigure(linePlugin); -const LINE_SRC_PREFIX = `../../${bundledPluginRoot("line")}/src/`; - -function normalizeModuleSpecifier(specifier: string): string | null { - if (specifier.startsWith("./src/")) { - return specifier; - } - if (specifier.startsWith(LINE_SRC_PREFIX)) { - return `./src/${specifier.slice(LINE_SRC_PREFIX.length)}`; - } - return null; -} - -function collectModuleExportNames(filePath: string): string[] { - const sourcePath = filePath.replace(/\.js$/, ".ts"); - const sourceText = readFileSync(sourcePath, "utf8"); - const sourceFile = ts.createSourceFile(sourcePath, sourceText, ts.ScriptTarget.Latest, true); - const names = new Set(); - - for (const statement of sourceFile.statements) { - if ( - ts.isExportDeclaration(statement) && - statement.exportClause && - ts.isNamedExports(statement.exportClause) - ) { - for (const element of statement.exportClause.elements) { - if (!element.isTypeOnly) { - names.add(element.name.text); - } - } - continue; - } - - const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined; - const isExported = modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword); - if (!isExported) { - continue; - } - - if (ts.isVariableStatement(statement)) { - for (const declaration of statement.declarationList.declarations) { - if (ts.isIdentifier(declaration.name)) { - names.add(declaration.name.text); - } - } - continue; - } - - if ( - ts.isFunctionDeclaration(statement) || - ts.isClassDeclaration(statement) || - ts.isEnumDeclaration(statement) - ) { - if (statement.name) { - names.add(statement.name.text); - } - } - } - - return Array.from(names).toSorted(); -} - -function collectRuntimeApiPreExports(runtimeApiPath: string): string[] { - const runtimeApiSource = readFileSync(runtimeApiPath, "utf8"); - const runtimeApiFile = ts.createSourceFile( - runtimeApiPath, - runtimeApiSource, - ts.ScriptTarget.Latest, - true, - ); - const preExports = new Set(); - let pluginSdkLineRuntimeSeen = false; - const removedLineRuntimeSpecifier = ["openclaw", "plugin-sdk", "line-runtime"].join("/"); - - for (const statement of runtimeApiFile.statements) { - if (!ts.isExportDeclaration(statement)) { - continue; - } - const moduleSpecifier = - statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) - ? statement.moduleSpecifier.text - : undefined; - if (!moduleSpecifier) { - continue; - } - if (moduleSpecifier === removedLineRuntimeSpecifier) { - pluginSdkLineRuntimeSeen = true; - break; - } - const normalized = normalizeModuleSpecifier(moduleSpecifier); - if (!normalized) { - continue; - } - - if (!statement.exportClause) { - for (const name of collectModuleExportNames( - path.join(process.cwd(), "extensions", "line", normalized), - )) { - preExports.add(name); - } - continue; - } - - if (!ts.isNamedExports(statement.exportClause)) { - continue; - } - - for (const element of statement.exportClause.elements) { - if (!element.isTypeOnly) { - preExports.add(element.name.text); - } - } - } - - if (!pluginSdkLineRuntimeSeen) { - return []; - } - - return Array.from(preExports).toSorted(); -} describe("line setup wizard", () => { it("configures token and secret for the default account", async () => { @@ -306,14 +183,6 @@ describe("linePlugin status.probeAccount", () => { }); }); -describe("line runtime api", () => { - it("keeps the LINE runtime barrel self-contained", () => { - const runtimeApiPath = path.join(process.cwd(), "extensions", "line", "runtime-api.ts"); - expect(collectRuntimeApiPreExports(runtimeApiPath)).toStrictEqual([]); - expect(collectRuntimeApiPreExports(runtimeApiPath)).toStrictEqual([]); - }); -}); - function createRuntime() { const monitorLineProvider = vi.fn( async (_opts: { accountId?: string; channelAccessToken: string; channelSecret: string }) => ({ diff --git a/extensions/openai/openai-provider.test.ts b/extensions/openai/openai-provider.test.ts index 364b17429779..879237642590 100644 --- a/extensions/openai/openai-provider.test.ts +++ b/extensions/openai/openai-provider.test.ts @@ -2707,15 +2707,6 @@ describe("buildOpenAIProvider", () => { ).toBe(explicit); }); - it("shares OpenAI responses wrapper composition across provider variants", () => { - const provider = buildOpenAIProvider(); - const codexProvider = buildOpenAIProvider(); - - expect(provider.wrapStreamFn).toBe(codexProvider.wrapStreamFn); - expect(provider.buildReplayPolicy).toBe(codexProvider.buildReplayPolicy); - expect(provider.resolveTransportTurnState).toBe(codexProvider.resolveTransportTurnState); - }); - it("owns Azure OpenAI reasoning compatibility without forcing OpenAI transport defaults", () => { const provider = buildOpenAIProvider(); const wrap = provider.wrapStreamFn; diff --git a/extensions/vydra/shared.test.ts b/extensions/vydra/shared.test.ts index 1e395949c6bf..3990a870ae7e 100644 --- a/extensions/vydra/shared.test.ts +++ b/extensions/vydra/shared.test.ts @@ -1,7 +1,6 @@ // Vydra tests cover shared download timeout plugin behavior. import { once } from "node:events"; import http from "node:http"; -import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime"; import { installPinnedHostnameTestHooks } from "openclaw/plugin-sdk/test-media-understanding"; import { afterEach, describe, expect, it } from "vitest"; import { downloadVydraAsset } from "./shared.js"; @@ -205,31 +204,4 @@ describe("downloadVydraAsset", () => { expect(result).toBeInstanceOf(Error); expect(result).toMatchObject({ message: "broken success body" }); }); - - it("does not bound a dripping body when only chunk idle timeout is used", async () => { - // Negative control: chunkTimeoutMs resets on every drip, so idle alone never fires. - const port = await listenDripServer({ - statusCode: 200, - contentType: "image/png", - chunk: Buffer.from([0x00]), - }); - const response = await fetch(`http://127.0.0.1:${port}/`); - let settled = false; - void readResponseWithLimit(response, 1024 * 1024, { - chunkTimeoutMs: 100, - onIdleTimeout: ({ chunkTimeoutMs }) => new Error(`idle fired after ${chunkTimeoutMs}ms`), - }) - .then(() => { - settled = true; - }) - .catch(() => { - settled = true; - }); - - await new Promise((resolve) => { - setTimeout(resolve, 400); - }); - expect(settled).toBe(false); - // Body reader is locked by readResponseWithLimit; tear down via server close in afterEach. - }); }); diff --git a/extensions/zai/detect.test.ts b/extensions/zai/detect.test.ts index e0084ba6835a..8cc6ae8cbbae 100644 --- a/extensions/zai/detect.test.ts +++ b/extensions/zai/detect.test.ts @@ -1,6 +1,5 @@ // Zai tests cover detect plugin behavior. import { MAX_TIMER_TIMEOUT_MS } from "openclaw/plugin-sdk/number-runtime"; -import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime"; import { afterEach, describe, expect, it, vi } from "vitest"; import { detectZaiEndpoint } from "./detect.js"; @@ -321,21 +320,6 @@ describe("detectZaiEndpoint", () => { ); }); - it("rejects oversized bodies via the shared bounded reader the probe uses", async () => { - const { fetchFn } = makeOversizedStreamFetch({ - url: "https://api.z.ai/api/paas/v4/chat/completions", - status: 400, - }); - const res = await fetchFn("https://api.z.ai/api/paas/v4/chat/completions"); - - await expect( - readResponseWithLimit(res, ZAI_DETECT_ERROR_BODY_MAX_BYTES, { - onOverflow: ({ maxBytes }) => - new Error(`Z.AI probe error body exceeded size limit (${maxBytes} bytes)`), - }), - ).rejects.toThrow(/exceeded size limit/); - }); - it("fails closed when a probe error body stalls without chunks", async () => { // Headers return 400, but the error body never enqueues. Without // the whole-body deadline the probe would hang indefinitely.