diff --git a/docs/plugins/architecture.md b/docs/plugins/architecture.md index 5e771b0b796..9fba7fe34d9 100644 --- a/docs/plugins/architecture.md +++ b/docs/plugins/architecture.md @@ -473,7 +473,7 @@ Keep capability registration public. Trim non-contract helper exports: - vendor-specific convenience helpers - setup/onboarding helpers that are implementation details -Some bundled-plugin helper subpaths still remain in the generated SDK export map for bundled-plugin maintenance when they have tracked owner usage. Current examples include `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/github-copilot-token`, `plugin-sdk/memory-core`, `plugin-sdk/bundled-channel-config-schema`, and `plugin-sdk/channel-config-schema-legacy`. Treat those as reserved exports, not as the recommended SDK pattern for new third-party plugins. +Reserved bundled-plugin helper subpaths have been retired from the generated SDK export map. Keep owner-specific helpers inside the owning plugin package; promote only reusable host behavior to generic SDK contracts such as `plugin-sdk/gateway-runtime`, `plugin-sdk/security-runtime`, and `plugin-sdk/plugin-config-runtime`. ## Internals and reference diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md index 91551a1a7af..6c0d18933b3 100644 --- a/docs/plugins/sdk-migration.md +++ b/docs/plugins/sdk-migration.md @@ -544,23 +544,15 @@ This table is intentionally the common migration subset, not the full SDK surface. The full list of 200+ entrypoints lives in `scripts/lib/plugin-sdk-entrypoints.json`. -That list still includes a few bundled-plugin helper seams that have tracked -owner usage. They remain exported for bundled-plugin maintenance, but they are -intentionally omitted from the common migration table and are not the -recommended target for new plugin code. - -The same rule applies to other bundled-helper families such as: - -- browser support helpers: `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools` -- Matrix: `plugin-sdk/matrix-runtime-shared` -- bundled helper/plugin surfaces like `plugin-sdk/github-copilot-token` and `plugin-sdk/memory-core` - -`plugin-sdk/github-copilot-token` currently exposes the narrow token-helper -surface `DEFAULT_COPILOT_API_BASE_URL`, -`deriveCopilotApiBaseUrlFromToken`, and `resolveCopilotApiToken`. +Reserved bundled-plugin helper seams have been retired from the public SDK +export map. Owner-specific helpers live inside the owning plugin package; shared +host behavior should move through generic SDK contracts such as +`plugin-sdk/gateway-runtime`, `plugin-sdk/security-runtime`, and +`plugin-sdk/plugin-config-runtime`. Use the narrowest import that matches the job. If you cannot find an export, -check the source at `src/plugin-sdk/` or ask in Discord. +check the source at `src/plugin-sdk/` or ask maintainers which generic contract +should own it. ## Active deprecations diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md index 3bcf51c28d7..73710a12964 100644 --- a/docs/plugins/sdk-subpaths.md +++ b/docs/plugins/sdk-subpaths.md @@ -313,11 +313,10 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview) - | Family | Current subpaths | Intended use | - | --- | --- | --- | - | Browser | `plugin-sdk/browser-config-runtime`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-node-runtime`, `plugin-sdk/browser-security-runtime`, `plugin-sdk/browser-setup-tools` | Bundled browser plugin support helpers still consumed by the owner package. | - | Matrix | `plugin-sdk/matrix-runtime-shared` | Bundled Matrix runtime surface still consumed by the owner package. | - | Auth/plugin-specific helpers | `plugin-sdk/github-copilot-token`, `plugin-sdk/memory-core` | Bundled feature/plugin helper seams still consumed by their owners; `plugin-sdk/github-copilot-token` currently exports `DEFAULT_COPILOT_API_BASE_URL`, `deriveCopilotApiBaseUrlFromToken`, and `resolveCopilotApiToken`. | + There are currently no reserved bundled-helper SDK subpaths. Owner-specific + helpers live inside the owning plugin package, while reusable host contracts + use generic SDK subpaths such as `plugin-sdk/gateway-runtime`, + `plugin-sdk/security-runtime`, and `plugin-sdk/plugin-config-runtime`. diff --git a/extensions/browser/src/browser-tool.runtime.ts b/extensions/browser/src/browser-tool.runtime.ts index 4d39ab21d7a..3896c876d39 100644 --- a/extensions/browser/src/browser-tool.runtime.ts +++ b/extensions/browser/src/browser-tool.runtime.ts @@ -1,4 +1,4 @@ -export { getRuntimeConfig } from "openclaw/plugin-sdk/browser-config-runtime"; +export { getRuntimeConfig } from "./sdk-config.js"; export { callGatewayTool, imageResultFromFile, @@ -7,9 +7,9 @@ export { readStringParam, resolveNodeIdFromList, selectDefaultNodeFromList, -} from "openclaw/plugin-sdk/browser-setup-tools"; -export type { AnyAgentTool, NodeListNode } from "openclaw/plugin-sdk/browser-setup-tools"; -export { wrapExternalContent } from "openclaw/plugin-sdk/browser-security-runtime"; +} from "./sdk-setup-tools.js"; +export type { AnyAgentTool, NodeListNode } from "./sdk-setup-tools.js"; +export { wrapExternalContent } from "./sdk-security-runtime.js"; export { normalizeOptionalString, readStringValue } from "openclaw/plugin-sdk/text-runtime"; export { BrowserToolSchema } from "./browser-tool.schema.js"; export { diff --git a/extensions/browser/src/browser-tool.test.ts b/extensions/browser/src/browser-tool.test.ts index be941686fc1..5223fe78201 100644 --- a/extensions/browser/src/browser-tool.test.ts +++ b/extensions/browser/src/browser-tool.test.ts @@ -146,10 +146,9 @@ vi.mock("./browser/session-tab-registry.js", () => sessionTabRegistryMocks); const toolCommonMocks = vi.hoisted(() => ({ imageResultFromFile: vi.fn(), })); -vi.mock("openclaw/plugin-sdk/browser-setup-tools", async () => { - const actual = await vi.importActual( - "openclaw/plugin-sdk/browser-setup-tools", - ); +vi.mock("./sdk-setup-tools.js", async () => { + const actual = + await vi.importActual("./sdk-setup-tools.js"); return { ...actual, callGatewayTool: gatewayMocks.callGatewayTool, diff --git a/extensions/browser/src/browser/cdp.test.ts b/extensions/browser/src/browser/cdp.test.ts index a68efdc27a6..dc3972d9138 100644 --- a/extensions/browser/src/browser/cdp.test.ts +++ b/extensions/browser/src/browser/cdp.test.ts @@ -5,7 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type WebSocket, WebSocketServer } from "ws"; import { SsrFBlockedError } from "../infra/net/ssrf.js"; import { rawDataToString } from "../infra/ws.js"; -import "../../test-support/browser-security-runtime.mock.js"; +import "../../test-support/browser-security.mock.js"; import { isDirectCdpWebSocketEndpoint, isWebSocketUrl, diff --git a/extensions/browser/src/browser/client-fetch.loopback-auth.test.ts b/extensions/browser/src/browser/client-fetch.loopback-auth.test.ts index da32f857657..3289601078e 100644 --- a/extensions/browser/src/browser/client-fetch.loopback-auth.test.ts +++ b/extensions/browser/src/browser/client-fetch.loopback-auth.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import "../../test-support/browser-security-runtime.mock.js"; +import "../../test-support/browser-security.mock.js"; import type { OpenClawConfig } from "../config/config.js"; import type { BrowserDispatchResponse } from "./routes/dispatcher.js"; diff --git a/extensions/browser/src/browser/navigation-guard.ts b/extensions/browser/src/browser/navigation-guard.ts index b9337ab6448..6d5749f89b5 100644 --- a/extensions/browser/src/browser/navigation-guard.ts +++ b/extensions/browser/src/browser/navigation-guard.ts @@ -1,14 +1,11 @@ import { isIP } from "node:net"; -import { - matchesHostnameAllowlist, - normalizeHostname, -} from "openclaw/plugin-sdk/browser-security-runtime"; import { isPrivateNetworkAllowedByPolicy, resolvePinnedHostnameWithPolicy, type LookupFn, type SsrFPolicy, } from "../infra/net/ssrf.js"; +import { matchesHostnameAllowlist, normalizeHostname } from "../sdk-security-runtime.js"; const NETWORK_NAVIGATION_PROTOCOLS = new Set(["http:", "https:"]); const SAFE_NON_NETWORK_URLS = new Set(["about:blank"]); diff --git a/extensions/browser/src/browser/pw-session.create-page.navigation-guard.test.ts b/extensions/browser/src/browser/pw-session.create-page.navigation-guard.test.ts index adaffb6efd1..e52d4bf3b37 100644 --- a/extensions/browser/src/browser/pw-session.create-page.navigation-guard.test.ts +++ b/extensions/browser/src/browser/pw-session.create-page.navigation-guard.test.ts @@ -1,7 +1,7 @@ import { chromium } from "playwright-core"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { SsrFBlockedError } from "../infra/net/ssrf.js"; -import "../../test-support/browser-security-runtime.mock.js"; +import "../../test-support/browser-security.mock.js"; import * as chromeModule from "./chrome.js"; import { BrowserTabNotFoundError } from "./errors.js"; import { InvalidBrowserNavigationUrlError } from "./navigation-guard.js"; diff --git a/extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts b/extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts index 3569bae847f..8076c2d52bd 100644 --- a/extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts +++ b/extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { SsrFBlockedError } from "../infra/net/ssrf.js"; -import "../../test-support/browser-security-runtime.mock.js"; +import "../../test-support/browser-security.mock.js"; import { InvalidBrowserNavigationUrlError } from "./navigation-guard.js"; import { getPwToolsCoreSessionMocks, diff --git a/extensions/browser/src/browser/server-context.existing-session.test.ts b/extensions/browser/src/browser/server-context.existing-session.test.ts index b6fb1f20283..007821d0c85 100644 --- a/extensions/browser/src/browser/server-context.existing-session.test.ts +++ b/extensions/browser/src/browser/server-context.existing-session.test.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import "../../test-support/browser-security-runtime.mock.js"; +import "../../test-support/browser-security.mock.js"; import type { BrowserServerState } from "./server-context.js"; const chromeMcpMock = vi.hoisted(() => ({ diff --git a/extensions/browser/src/cli/browser-cli-inspect.test.ts b/extensions/browser/src/cli/browser-cli-inspect.test.ts index e428c60eab4..03944621020 100644 --- a/extensions/browser/src/cli/browser-cli-inspect.test.ts +++ b/extensions/browser/src/cli/browser-cli-inspect.test.ts @@ -16,10 +16,9 @@ const gatewayMocks = vi.hoisted(() => ({ })), })); -vi.mock("openclaw/plugin-sdk/browser-node-runtime", async () => { - const actual = await vi.importActual( - "openclaw/plugin-sdk/browser-node-runtime", - ); +vi.mock("../sdk-node-runtime.js", async () => { + const actual = + await vi.importActual("../sdk-node-runtime.js"); return { ...actual, callGatewayFromCli: gatewayMocks.callGatewayFromCli, diff --git a/extensions/browser/src/cli/command-format.ts b/extensions/browser/src/cli/command-format.ts index 4cc355beddb..7cac2ed2f9a 100644 --- a/extensions/browser/src/cli/command-format.ts +++ b/extensions/browser/src/cli/command-format.ts @@ -1 +1 @@ -export { formatCliCommand } from "openclaw/plugin-sdk/browser-setup-tools"; +export { formatCliCommand } from "../sdk-setup-tools.js"; diff --git a/extensions/browser/src/config/config.ts b/extensions/browser/src/config/config.ts index 0e1a4df0102..30f8194af71 100644 --- a/extensions/browser/src/config/config.ts +++ b/extensions/browser/src/config/config.ts @@ -5,4 +5,4 @@ export { type BrowserConfig, type BrowserProfileConfig, type OpenClawConfig, -} from "openclaw/plugin-sdk/browser-config-runtime"; +} from "../sdk-config.js"; diff --git a/extensions/browser/src/config/paths.ts b/extensions/browser/src/config/paths.ts index 085adb06654..e3c16efcc0e 100644 --- a/extensions/browser/src/config/paths.ts +++ b/extensions/browser/src/config/paths.ts @@ -1 +1 @@ -export { resolveGatewayPort } from "openclaw/plugin-sdk/browser-config-support"; +export { resolveGatewayPort } from "../sdk-config.js"; diff --git a/extensions/browser/src/config/port-defaults.ts b/extensions/browser/src/config/port-defaults.ts index f37e01f58bc..eb3d5f3e248 100644 --- a/extensions/browser/src/config/port-defaults.ts +++ b/extensions/browser/src/config/port-defaults.ts @@ -2,4 +2,4 @@ export { DEFAULT_BROWSER_CONTROL_PORT, deriveDefaultBrowserCdpPortRange, deriveDefaultBrowserControlPort, -} from "openclaw/plugin-sdk/browser-config-support"; +} from "../sdk-config.js"; diff --git a/extensions/browser/src/core-api.ts b/extensions/browser/src/core-api.ts index bda9d6a6d1f..c11c6e6c6c3 100644 --- a/extensions/browser/src/core-api.ts +++ b/extensions/browser/src/core-api.ts @@ -83,14 +83,14 @@ export { selectDefaultNodeFromList, stringEnum, theme, -} from "openclaw/plugin-sdk/browser-setup-tools"; +} from "./sdk-setup-tools.js"; export { getRuntimeConfig, normalizePluginsConfig, parseBooleanValue, resolveEffectiveEnableState, shortenHomePath, -} from "openclaw/plugin-sdk/browser-config-runtime"; +} from "./sdk-config.js"; export { addGatewayClientOptions, callGatewayFromCli, @@ -103,16 +103,13 @@ export { runCommandWithRuntime, safeParseJson, withTimeout, -} from "openclaw/plugin-sdk/browser-node-runtime"; -export { - createSubsystemLogger, - wrapExternalContent, -} from "openclaw/plugin-sdk/browser-security-runtime"; -export type { AnyAgentTool, NodeListNode } from "openclaw/plugin-sdk/browser-setup-tools"; -export type { OpenClawConfig } from "openclaw/plugin-sdk/browser-config-runtime"; +} from "./sdk-node-runtime.js"; +export { createSubsystemLogger, wrapExternalContent } from "./sdk-security-runtime.js"; +export type { AnyAgentTool, NodeListNode } from "./sdk-setup-tools.js"; +export type { OpenClawConfig } from "./sdk-config.js"; export type { GatewayRequestHandlers, GatewayRpcOpts, NodeSession, OpenClawPluginService, -} from "openclaw/plugin-sdk/browser-node-runtime"; +} from "./sdk-node-runtime.js"; diff --git a/extensions/browser/src/doctor-browser.ts b/extensions/browser/src/doctor-browser.ts index 681ab773560..53f9fbec731 100644 --- a/extensions/browser/src/doctor-browser.ts +++ b/extensions/browser/src/doctor-browser.ts @@ -1,4 +1,3 @@ -import { note } from "openclaw/plugin-sdk/browser-setup-tools"; import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; import { parseBrowserMajorVersion, @@ -9,6 +8,7 @@ import { import { resolveBrowserConfig } from "./browser/config.js"; import type { OpenClawConfig } from "./config/config.js"; import { asRecord } from "./record-shared.js"; +import { note } from "./sdk-setup-tools.js"; const CHROME_MCP_MIN_MAJOR = 144; const REMOTE_DEBUGGING_PAGES = [ diff --git a/extensions/browser/src/gateway/auth.ts b/extensions/browser/src/gateway/auth.ts index ecef85414ae..d87bc43638c 100644 --- a/extensions/browser/src/gateway/auth.ts +++ b/extensions/browser/src/gateway/auth.ts @@ -1 +1 @@ -export { resolveGatewayAuth } from "openclaw/plugin-sdk/browser-node-runtime"; +export { resolveGatewayAuth } from "../sdk-node-runtime.js"; diff --git a/extensions/browser/src/gateway/browser-request.profile-from-body.test.ts b/extensions/browser/src/gateway/browser-request.profile-from-body.test.ts index 4a2baa4205f..756b214edad 100644 --- a/extensions/browser/src/gateway/browser-request.profile-from-body.test.ts +++ b/extensions/browser/src/gateway/browser-request.profile-from-body.test.ts @@ -18,10 +18,9 @@ vi.mock("openclaw/plugin-sdk/runtime-config-snapshot", async () => { }; }); -vi.mock("openclaw/plugin-sdk/browser-node-runtime", async () => { - const actual = await vi.importActual( - "openclaw/plugin-sdk/browser-node-runtime", - ); +vi.mock("../sdk-node-runtime.js", async () => { + const actual = + await vi.importActual("../sdk-node-runtime.js"); return { ...actual, isNodeCommandAllowed: isNodeCommandAllowedMock, diff --git a/extensions/browser/src/gateway/net.ts b/extensions/browser/src/gateway/net.ts index f00fe85275d..0d0b55a016a 100644 --- a/extensions/browser/src/gateway/net.ts +++ b/extensions/browser/src/gateway/net.ts @@ -1 +1 @@ -export { isLoopbackHost } from "openclaw/plugin-sdk/browser-config-support"; +export { isLoopbackHost } from "../sdk-node-runtime.js"; diff --git a/extensions/browser/src/gateway/startup-auth.ts b/extensions/browser/src/gateway/startup-auth.ts index 36989e82dcc..3d6e7f14402 100644 --- a/extensions/browser/src/gateway/startup-auth.ts +++ b/extensions/browser/src/gateway/startup-auth.ts @@ -1 +1 @@ -export { ensureGatewayStartupAuth } from "openclaw/plugin-sdk/browser-node-runtime"; +export { ensureGatewayStartupAuth } from "../sdk-node-runtime.js"; diff --git a/extensions/browser/src/infra/errors.ts b/extensions/browser/src/infra/errors.ts index 0fe8d180abe..49963db651b 100644 --- a/extensions/browser/src/infra/errors.ts +++ b/extensions/browser/src/infra/errors.ts @@ -1 +1 @@ -export { extractErrorCode, formatErrorMessage } from "openclaw/plugin-sdk/browser-security-runtime"; +export { extractErrorCode, formatErrorMessage } from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/infra/fs-safe.ts b/extensions/browser/src/infra/fs-safe.ts index aec2988474c..3e9b84b51f1 100644 --- a/extensions/browser/src/infra/fs-safe.ts +++ b/extensions/browser/src/infra/fs-safe.ts @@ -2,4 +2,4 @@ export { SafeOpenError, openFileWithinRoot, writeFileFromPathWithinRoot, -} from "openclaw/plugin-sdk/browser-security-runtime"; +} from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/infra/net/proxy-env.ts b/extensions/browser/src/infra/net/proxy-env.ts index e9770a3e2ad..665a73568c9 100644 --- a/extensions/browser/src/infra/net/proxy-env.ts +++ b/extensions/browser/src/infra/net/proxy-env.ts @@ -1 +1 @@ -export { hasProxyEnvConfigured } from "openclaw/plugin-sdk/browser-security-runtime"; +export { hasProxyEnvConfigured } from "../../sdk-security-runtime.js"; diff --git a/extensions/browser/src/infra/net/ssrf.ts b/extensions/browser/src/infra/net/ssrf.ts index a25e674a866..052b16c189a 100644 --- a/extensions/browser/src/infra/net/ssrf.ts +++ b/extensions/browser/src/infra/net/ssrf.ts @@ -4,4 +4,4 @@ export { resolvePinnedHostnameWithPolicy, type LookupFn, type SsrFPolicy, -} from "openclaw/plugin-sdk/browser-security-runtime"; +} from "../../sdk-security-runtime.js"; diff --git a/extensions/browser/src/infra/path-guards.ts b/extensions/browser/src/infra/path-guards.ts index 834b0992190..1d790b633f8 100644 --- a/extensions/browser/src/infra/path-guards.ts +++ b/extensions/browser/src/infra/path-guards.ts @@ -1 +1 @@ -export { isNotFoundPathError, isPathInside } from "openclaw/plugin-sdk/browser-security-runtime"; +export { isNotFoundPathError, isPathInside } from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/infra/ports.ts b/extensions/browser/src/infra/ports.ts index 3e81fec2a7a..d9d1f156b09 100644 --- a/extensions/browser/src/infra/ports.ts +++ b/extensions/browser/src/infra/ports.ts @@ -1 +1 @@ -export { ensurePortAvailable } from "openclaw/plugin-sdk/browser-security-runtime"; +export { ensurePortAvailable } from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/infra/secure-random.ts b/extensions/browser/src/infra/secure-random.ts index dbe57bc7a3c..e80e94444c7 100644 --- a/extensions/browser/src/infra/secure-random.ts +++ b/extensions/browser/src/infra/secure-random.ts @@ -1 +1 @@ -export { generateSecureToken } from "openclaw/plugin-sdk/browser-security-runtime"; +export { generateSecureToken } from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/logging/redact.ts b/extensions/browser/src/logging/redact.ts index 5cfb75aa946..1bcc89bf3ac 100644 --- a/extensions/browser/src/logging/redact.ts +++ b/extensions/browser/src/logging/redact.ts @@ -1 +1 @@ -export { redactSensitiveText } from "openclaw/plugin-sdk/browser-security-runtime"; +export { redactSensitiveText } from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/media/image-ops.ts b/extensions/browser/src/media/image-ops.ts index 28a63b80842..b8024a6757c 100644 --- a/extensions/browser/src/media/image-ops.ts +++ b/extensions/browser/src/media/image-ops.ts @@ -3,4 +3,4 @@ export { buildImageResizeSideGrid, getImageMetadata, resizeToJpeg, -} from "openclaw/plugin-sdk/browser-setup-tools"; +} from "../sdk-setup-tools.js"; diff --git a/extensions/browser/src/media/store.ts b/extensions/browser/src/media/store.ts index 2a5ba93d507..405a824a205 100644 --- a/extensions/browser/src/media/store.ts +++ b/extensions/browser/src/media/store.ts @@ -1 +1 @@ -export { ensureMediaDir, saveMediaBuffer } from "openclaw/plugin-sdk/browser-setup-tools"; +export { ensureMediaDir, saveMediaBuffer } from "../sdk-setup-tools.js"; diff --git a/extensions/browser/src/node-host/invoke-browser.test.ts b/extensions/browser/src/node-host/invoke-browser.test.ts index 193f5cf28d9..620e3f389f4 100644 --- a/extensions/browser/src/node-host/invoke-browser.test.ts +++ b/extensions/browser/src/node-host/invoke-browser.test.ts @@ -26,12 +26,12 @@ const browserConfigMocks = vi.hoisted(() => ({ })), })); -vi.mock("openclaw/plugin-sdk/browser-config-runtime", () => ({ +vi.mock("../sdk-config.js", () => ({ getRuntimeConfig: configMocks.loadConfig, loadConfig: configMocks.loadConfig, })); -vi.mock("openclaw/plugin-sdk/browser-node-runtime", () => ({ +vi.mock("../sdk-node-runtime.js", () => ({ withTimeout: vi.fn( async ( run: (signal: AbortSignal | undefined) => Promise, @@ -66,7 +66,7 @@ vi.mock("openclaw/plugin-sdk/browser-node-runtime", () => ({ ), })); -vi.mock("openclaw/plugin-sdk/browser-setup-tools", () => ({ +vi.mock("../sdk-setup-tools.js", () => ({ detectMime: vi.fn(async () => "image/png"), })); diff --git a/extensions/browser/src/node-host/invoke-browser.ts b/extensions/browser/src/node-host/invoke-browser.ts index 4c7edafe9a5..5b655bf958c 100644 --- a/extensions/browser/src/node-host/invoke-browser.ts +++ b/extensions/browser/src/node-host/invoke-browser.ts @@ -1,7 +1,4 @@ import fsPromises from "node:fs/promises"; -import { getRuntimeConfig } from "openclaw/plugin-sdk/browser-config-runtime"; -import { withTimeout } from "openclaw/plugin-sdk/browser-node-runtime"; -import { detectMime } from "openclaw/plugin-sdk/browser-setup-tools"; import { redactCdpUrl } from "../browser/cdp.helpers.js"; import { resolveBrowserConfig } from "../browser/config.js"; import { @@ -14,6 +11,9 @@ import { createBrowserControlContext, startBrowserControlServiceFromConfig, } from "../control-service.js"; +import { getRuntimeConfig } from "../sdk-config.js"; +import { withTimeout } from "../sdk-node-runtime.js"; +import { detectMime } from "../sdk-setup-tools.js"; type BrowserProxyParams = { method?: string; diff --git a/extensions/browser/src/plugin-enabled.ts b/extensions/browser/src/plugin-enabled.ts index 2ab2d09c9e2..8d26e873139 100644 --- a/extensions/browser/src/plugin-enabled.ts +++ b/extensions/browser/src/plugin-enabled.ts @@ -1,8 +1,5 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk/browser-config-runtime"; -import { - normalizePluginsConfig, - resolveEffectiveEnableState, -} from "openclaw/plugin-sdk/browser-config-runtime"; +import type { OpenClawConfig } from "./sdk-config.js"; +import { normalizePluginsConfig, resolveEffectiveEnableState } from "./sdk-config.js"; export function isDefaultBrowserPluginEnabled(cfg: OpenClawConfig): boolean { return resolveEffectiveEnableState({ diff --git a/extensions/browser/src/plugin-service.test.ts b/extensions/browser/src/plugin-service.test.ts index b6d150a0af3..e8e4c7aec5b 100644 --- a/extensions/browser/src/plugin-service.test.ts +++ b/extensions/browser/src/plugin-service.test.ts @@ -20,7 +20,7 @@ const runtimeMocks = vi.hoisted(() => ({ startLazyPluginServiceModule: vi.fn(async (_params: StartLazyPluginServiceModuleParams) => null), })); -vi.mock("openclaw/plugin-sdk/browser-node-runtime", () => ({ +vi.mock("./sdk-node-runtime.js", () => ({ startLazyPluginServiceModule: runtimeMocks.startLazyPluginServiceModule, })); diff --git a/extensions/browser/src/plugin-service.ts b/extensions/browser/src/plugin-service.ts index b68cc3334f5..47a361d858c 100644 --- a/extensions/browser/src/plugin-service.ts +++ b/extensions/browser/src/plugin-service.ts @@ -2,7 +2,7 @@ import { startLazyPluginServiceModule, type LazyPluginServiceHandle, type OpenClawPluginService, -} from "openclaw/plugin-sdk/browser-node-runtime"; +} from "./sdk-node-runtime.js"; type BrowserControlHandle = LazyPluginServiceHandle | null; const UNSAFE_BROWSER_CONTROL_OVERRIDE_SPECIFIER = /^(?:data|http|https|node):/i; diff --git a/extensions/browser/src/process/exec.ts b/extensions/browser/src/process/exec.ts index 8cef8f8fc7c..e0f23baa49f 100644 --- a/extensions/browser/src/process/exec.ts +++ b/extensions/browser/src/process/exec.ts @@ -1 +1 @@ -export { runExec } from "openclaw/plugin-sdk/browser-node-runtime"; +export { runExec } from "../sdk-node-runtime.js"; diff --git a/extensions/browser/src/sdk-config.ts b/extensions/browser/src/sdk-config.ts new file mode 100644 index 00000000000..0123fb597d2 --- /dev/null +++ b/extensions/browser/src/sdk-config.ts @@ -0,0 +1,98 @@ +import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime"; + +export { + getRuntimeConfig, + getRuntimeConfigSnapshot, + replaceConfigFile, +} from "openclaw/plugin-sdk/config-runtime"; +export type { + BrowserConfig, + BrowserProfileConfig, + OpenClawConfig, +} from "openclaw/plugin-sdk/config-types"; +export { + normalizePluginsConfig, + resolveEffectiveEnableState, +} from "openclaw/plugin-sdk/plugin-config-runtime"; +export { resolveGatewayPort } from "openclaw/plugin-sdk/core"; +export { + CONFIG_DIR, + escapeRegExp, + resolveUserPath, + shortenHomePath, +} from "openclaw/plugin-sdk/text-runtime"; +export { normalizeOptionalLowercaseString }; + +export type PortRange = { start: number; end: number }; + +const DEFAULT_BROWSER_CDP_PORT_RANGE_START = 18800; +const DEFAULT_BROWSER_CDP_PORT_RANGE_END = 18899; +const DEFAULT_BROWSER_CDP_PORT_RANGE_SPAN = + DEFAULT_BROWSER_CDP_PORT_RANGE_END - DEFAULT_BROWSER_CDP_PORT_RANGE_START; + +export const DEFAULT_BROWSER_CONTROL_PORT = 18791; + +function isValidPort(port: number): boolean { + return Number.isFinite(port) && port > 0 && port <= 65535; +} + +function clampPort(port: number, fallback: number): number { + return isValidPort(port) ? port : fallback; +} + +function derivePort(base: number, offset: number, fallback: number): number { + return clampPort(base + offset, fallback); +} + +export function deriveDefaultBrowserControlPort(gatewayPort: number): number { + return derivePort(gatewayPort, 2, DEFAULT_BROWSER_CONTROL_PORT); +} + +export function deriveDefaultBrowserCdpPortRange(browserControlPort: number): PortRange { + const start = derivePort(browserControlPort, 9, DEFAULT_BROWSER_CDP_PORT_RANGE_START); + const end = start + DEFAULT_BROWSER_CDP_PORT_RANGE_SPAN; + if (end <= 65535) { + return { start, end }; + } + return { + start: DEFAULT_BROWSER_CDP_PORT_RANGE_START, + end: DEFAULT_BROWSER_CDP_PORT_RANGE_END, + }; +} + +export type BooleanParseOptions = { + truthy?: string[]; + falsy?: string[]; +}; + +const DEFAULT_TRUTHY = ["true", "1", "yes", "on"] as const; +const DEFAULT_FALSY = ["false", "0", "no", "off"] as const; +const DEFAULT_TRUTHY_SET = new Set(DEFAULT_TRUTHY); +const DEFAULT_FALSY_SET = new Set(DEFAULT_FALSY); + +export function parseBooleanValue( + value: unknown, + options: BooleanParseOptions = {}, +): boolean | undefined { + if (typeof value === "boolean") { + return value; + } + if (typeof value !== "string") { + return undefined; + } + const normalized = normalizeOptionalLowercaseString(value); + if (!normalized) { + return undefined; + } + const truthy = options.truthy ?? DEFAULT_TRUTHY; + const falsy = options.falsy ?? DEFAULT_FALSY; + const truthySet = truthy === DEFAULT_TRUTHY ? DEFAULT_TRUTHY_SET : new Set(truthy); + const falsySet = falsy === DEFAULT_FALSY ? DEFAULT_FALSY_SET : new Set(falsy); + if (truthySet.has(normalized)) { + return true; + } + if (falsySet.has(normalized)) { + return false; + } + return undefined; +} diff --git a/extensions/browser/src/sdk-node-runtime.ts b/extensions/browser/src/sdk-node-runtime.ts new file mode 100644 index 00000000000..34e20591896 --- /dev/null +++ b/extensions/browser/src/sdk-node-runtime.ts @@ -0,0 +1,63 @@ +export { + addGatewayClientOptions, + callGatewayFromCli, + ensureGatewayStartupAuth, + ErrorCodes, + errorShape, + isLoopbackHost, + isNodeCommandAllowed, + rawDataToString, + respondUnavailableOnNodeInvokeError, + resolveGatewayAuth, + resolveNodeCommandAllowlist, + safeParseJson, +} from "openclaw/plugin-sdk/gateway-runtime"; +export type { + GatewayRequestHandlers, + GatewayRpcOpts, + NodeSession, +} from "openclaw/plugin-sdk/gateway-runtime"; +export { runExec } from "openclaw/plugin-sdk/process-runtime"; +export { runCommandWithRuntime } from "openclaw/plugin-sdk/cli-runtime"; +export type { OpenClawPluginService } from "openclaw/plugin-sdk/plugin-entry"; +export { + startLazyPluginServiceModule, + type LazyPluginServiceHandle, +} from "openclaw/plugin-sdk/plugin-runtime"; +export { defaultRuntime } from "openclaw/plugin-sdk/runtime-env"; + +export async function withTimeout( + work: (signal: AbortSignal | undefined) => Promise, + timeoutMs?: number, + label?: string, +): Promise { + const resolved = + typeof timeoutMs === "number" && Number.isFinite(timeoutMs) + ? Math.max(1, Math.floor(timeoutMs)) + : undefined; + if (!resolved) { + return await work(undefined); + } + + const abortCtrl = new AbortController(); + const timeoutError = new Error(`${label ?? "request"} timed out`); + const timer = setTimeout(() => abortCtrl.abort(timeoutError), resolved); + timer.unref?.(); + + let abortListener: (() => void) | undefined; + const abortPromise: Promise = abortCtrl.signal.aborted + ? Promise.reject(abortCtrl.signal.reason ?? timeoutError) + : new Promise((_, reject) => { + abortListener = () => reject(abortCtrl.signal.reason ?? timeoutError); + abortCtrl.signal.addEventListener("abort", abortListener, { once: true }); + }); + + try { + return await Promise.race([work(abortCtrl.signal), abortPromise]); + } finally { + clearTimeout(timer); + if (abortListener) { + abortCtrl.signal.removeEventListener("abort", abortListener); + } + } +} diff --git a/extensions/browser/src/sdk-security-runtime.ts b/extensions/browser/src/sdk-security-runtime.ts new file mode 100644 index 00000000000..56de1ea7b51 --- /dev/null +++ b/extensions/browser/src/sdk-security-runtime.ts @@ -0,0 +1,24 @@ +export { createSubsystemLogger } from "openclaw/plugin-sdk/logging-core"; +export { + ensurePortAvailable, + extractErrorCode, + formatErrorMessage, + generateSecureToken, + hasProxyEnvConfigured, + isBlockedHostnameOrIp, + isNotFoundPathError, + isPathInside, + isPrivateNetworkAllowedByPolicy, + matchesHostnameAllowlist, + normalizeHostname, + openFileWithinRoot, + redactSensitiveText, + resolvePinnedHostnameWithPolicy, + resolvePreferredOpenClawTmpDir, + safeEqualSecret, + SafeOpenError, + SsrFBlockedError, + wrapExternalContent, + writeFileFromPathWithinRoot, +} from "openclaw/plugin-sdk/security-runtime"; +export type { LookupFn, SsrFPolicy } from "openclaw/plugin-sdk/security-runtime"; diff --git a/extensions/browser/src/sdk-setup-tools.ts b/extensions/browser/src/sdk-setup-tools.ts new file mode 100644 index 00000000000..03fc423c38b --- /dev/null +++ b/extensions/browser/src/sdk-setup-tools.ts @@ -0,0 +1,30 @@ +export { + callGatewayTool, + listNodes, + resolveNodeIdFromList, + selectDefaultNodeFromList, +} from "openclaw/plugin-sdk/agent-harness-runtime"; +export type { AnyAgentTool, NodeListNode } from "openclaw/plugin-sdk/agent-harness-runtime"; +export { + imageResultFromFile, + jsonResult, + readStringParam, +} from "openclaw/plugin-sdk/channel-actions"; +export { optionalStringEnum, stringEnum } from "openclaw/plugin-sdk/channel-actions"; +export { + formatCliCommand, + formatHelpExamples, + inheritOptionFromParent, + note, + theme, +} from "openclaw/plugin-sdk/cli-runtime"; +export { danger, info } from "openclaw/plugin-sdk/runtime-env"; +export { + IMAGE_REDUCE_QUALITY_STEPS, + buildImageResizeSideGrid, + getImageMetadata, + resizeToJpeg, +} from "openclaw/plugin-sdk/media-runtime"; +export { detectMime } from "openclaw/plugin-sdk/media-mime"; +export { ensureMediaDir, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime"; +export { formatDocsLink } from "openclaw/plugin-sdk/setup-tools"; diff --git a/extensions/browser/src/security/secret-equal.ts b/extensions/browser/src/security/secret-equal.ts index b885781aa02..61cd4da2ea8 100644 --- a/extensions/browser/src/security/secret-equal.ts +++ b/extensions/browser/src/security/secret-equal.ts @@ -1 +1 @@ -export { safeEqualSecret } from "openclaw/plugin-sdk/browser-security-runtime"; +export { safeEqualSecret } from "../sdk-security-runtime.js"; diff --git a/extensions/browser/src/test-utils/vitest-mock-fn.ts b/extensions/browser/src/test-utils/vitest-mock-fn.ts index 36d5e481eb5..eab9c6ec04d 100644 --- a/extensions/browser/src/test-utils/vitest-mock-fn.ts +++ b/extensions/browser/src/test-utils/vitest-mock-fn.ts @@ -1 +1,3 @@ -export type { MockFn } from "openclaw/plugin-sdk/browser-setup-tools"; +// oxlint-disable-next-line typescript/no-explicit-any +export type MockFn any = (...args: any[]) => any> = + import("vitest").Mock; diff --git a/extensions/browser/src/utils.ts b/extensions/browser/src/utils.ts index ef7f7958d72..10786b9270c 100644 --- a/extensions/browser/src/utils.ts +++ b/extensions/browser/src/utils.ts @@ -1,6 +1 @@ -export { - CONFIG_DIR, - escapeRegExp, - resolveUserPath, - shortenHomePath, -} from "openclaw/plugin-sdk/browser-config-support"; +export { CONFIG_DIR, escapeRegExp, resolveUserPath, shortenHomePath } from "./sdk-config.js"; diff --git a/extensions/browser/src/utils/boolean.ts b/extensions/browser/src/utils/boolean.ts index bef72de2b4d..6ae213c2a67 100644 --- a/extensions/browser/src/utils/boolean.ts +++ b/extensions/browser/src/utils/boolean.ts @@ -1 +1 @@ -export { parseBooleanValue } from "openclaw/plugin-sdk/browser-config-runtime"; +export { parseBooleanValue } from "../sdk-config.js"; diff --git a/extensions/browser/test-support/browser-security.mock.ts b/extensions/browser/test-support/browser-security.mock.ts new file mode 100644 index 00000000000..7f0bd6e20d1 --- /dev/null +++ b/extensions/browser/test-support/browser-security.mock.ts @@ -0,0 +1,16 @@ +import { vi } from "vitest"; + +vi.mock("../src/sdk-security-runtime.js", async () => { + const actual = await vi.importActual( + "../src/sdk-security-runtime.js", + ); + const lookupFn = async (_hostname: string, options?: { all?: boolean }) => { + const result = { address: "93.184.216.34", family: 4 }; + return options?.all === true ? [result] : result; + }; + return { + ...actual, + resolvePinnedHostnameWithPolicy: (hostname: string, params: object = {}) => + actual.resolvePinnedHostnameWithPolicy(hostname, { ...params, lookupFn: lookupFn as never }), + }; +}); diff --git a/extensions/github-copilot/embeddings.test.ts b/extensions/github-copilot/embeddings.test.ts index df6564574a5..dfe104fa5dc 100644 --- a/extensions/github-copilot/embeddings.test.ts +++ b/extensions/github-copilot/embeddings.test.ts @@ -13,7 +13,7 @@ vi.mock("openclaw/plugin-sdk/secret-input-runtime", () => ({ resolveConfiguredSecretInputString: resolveConfiguredSecretInputStringMock, })); -vi.mock("openclaw/plugin-sdk/github-copilot-token", () => ({ +vi.mock("./token.js", () => ({ DEFAULT_COPILOT_API_BASE_URL: "https://api.githubcopilot.test", resolveCopilotApiToken: resolveCopilotApiTokenMock, })); diff --git a/extensions/github-copilot/embeddings.ts b/extensions/github-copilot/embeddings.ts index 6283764233c..0bd1401c4b1 100644 --- a/extensions/github-copilot/embeddings.ts +++ b/extensions/github-copilot/embeddings.ts @@ -1,7 +1,3 @@ -import { - DEFAULT_COPILOT_API_BASE_URL, - resolveCopilotApiToken, -} from "openclaw/plugin-sdk/github-copilot-token"; import { buildRemoteBaseUrlPolicy, sanitizeAndNormalizeEmbedding, @@ -12,6 +8,7 @@ import { import { resolveConfiguredSecretInputString } from "openclaw/plugin-sdk/secret-input-runtime"; import { fetchWithSsrFGuard, type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime"; import { resolveFirstGithubToken } from "./auth.js"; +import { DEFAULT_COPILOT_API_BASE_URL, resolveCopilotApiToken } from "./token.js"; const COPILOT_EMBEDDING_PROVIDER_ID = "github-copilot"; diff --git a/extensions/github-copilot/token.ts b/extensions/github-copilot/token.ts index b2d8625f184..16715538a1c 100644 --- a/extensions/github-copilot/token.ts +++ b/extensions/github-copilot/token.ts @@ -1,7 +1,169 @@ -import { - DEFAULT_COPILOT_API_BASE_URL, - deriveCopilotApiBaseUrlFromToken, - resolveCopilotApiToken, -} from "openclaw/plugin-sdk/github-copilot-token"; +import path from "node:path"; +import { loadJsonFile, saveJsonFile } from "openclaw/plugin-sdk/json-store"; +import { resolveProviderEndpoint } from "openclaw/plugin-sdk/provider-model-shared"; +import { resolveStateDir } from "openclaw/plugin-sdk/state-paths"; +import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime"; -export { DEFAULT_COPILOT_API_BASE_URL, deriveCopilotApiBaseUrlFromToken, resolveCopilotApiToken }; +const COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token"; +const COPILOT_EDITOR_VERSION = "vscode/1.96.2"; +const COPILOT_USER_AGENT = "GitHubCopilotChat/0.26.7"; +const COPILOT_EDITOR_PLUGIN_VERSION = "copilot-chat/0.35.0"; +const COPILOT_GITHUB_API_VERSION = "2025-04-01"; + +export const DEFAULT_COPILOT_API_BASE_URL = "https://api.individual.githubcopilot.com"; + +export type CachedCopilotToken = { + token: string; + expiresAt: number; + updatedAt: number; +}; + +function buildCopilotIdeHeaders( + params: { + includeApiVersion?: boolean; + } = {}, +): Record { + return { + "Editor-Version": COPILOT_EDITOR_VERSION, + "Editor-Plugin-Version": COPILOT_EDITOR_PLUGIN_VERSION, + "User-Agent": COPILOT_USER_AGENT, + ...(params.includeApiVersion ? { "X-Github-Api-Version": COPILOT_GITHUB_API_VERSION } : {}), + }; +} + +function resolveCopilotTokenCachePath(env: NodeJS.ProcessEnv = process.env) { + return path.join(resolveStateDir(env), "credentials", "github-copilot.token.json"); +} + +function isTokenUsable(cache: CachedCopilotToken, now = Date.now()): boolean { + return cache.expiresAt - now > 5 * 60 * 1000; +} + +function parseCopilotTokenResponse(value: unknown): { + token: string; + expiresAt: number; +} { + if (!value || typeof value !== "object") { + throw new Error("Unexpected response from GitHub Copilot token endpoint"); + } + const asRecord = value as Record; + const token = asRecord.token; + const expiresAt = asRecord.expires_at; + if (typeof token !== "string" || token.trim().length === 0) { + throw new Error("Copilot token response missing token"); + } + + let expiresAtMs: number; + if (typeof expiresAt === "number" && Number.isFinite(expiresAt)) { + expiresAtMs = expiresAt < 100_000_000_000 ? expiresAt * 1000 : expiresAt; + } else if (typeof expiresAt === "string" && expiresAt.trim().length > 0) { + const parsed = Number.parseInt(expiresAt, 10); + if (!Number.isFinite(parsed)) { + throw new Error("Copilot token response has invalid expires_at"); + } + expiresAtMs = parsed < 100_000_000_000 ? parsed * 1000 : parsed; + } else { + throw new Error("Copilot token response missing expires_at"); + } + + return { token, expiresAt: expiresAtMs }; +} + +function resolveCopilotProxyHost(proxyEp: string): string | null { + const trimmed = proxyEp.trim(); + if (!trimmed) { + return null; + } + + const urlText = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`; + try { + const url = new URL(urlText); + if (url.protocol !== "http:" && url.protocol !== "https:") { + return null; + } + return normalizeLowercaseStringOrEmpty(url.hostname); + } catch { + return null; + } +} + +export function deriveCopilotApiBaseUrlFromToken(token: string): string | null { + const trimmed = token.trim(); + if (!trimmed) { + return null; + } + + const match = trimmed.match(/(?:^|;)\s*proxy-ep=([^;\s]+)/i); + const proxyEp = match?.[1]?.trim(); + if (!proxyEp) { + return null; + } + + const proxyHost = resolveCopilotProxyHost(proxyEp); + if (!proxyHost) { + return null; + } + const host = proxyHost.replace(/^proxy\./i, "api."); + + const baseUrl = `https://${host}`; + return resolveProviderEndpoint(baseUrl).endpointClass === "invalid" ? null : baseUrl; +} + +export async function resolveCopilotApiToken(params: { + githubToken: string; + env?: NodeJS.ProcessEnv; + fetchImpl?: typeof fetch; + cachePath?: string; + loadJsonFileImpl?: (path: string) => unknown; + saveJsonFileImpl?: (path: string, value: CachedCopilotToken) => void; +}): Promise<{ + token: string; + expiresAt: number; + source: string; + baseUrl: string; +}> { + const env = params.env ?? process.env; + const cachePath = params.cachePath?.trim() || resolveCopilotTokenCachePath(env); + const loadJsonFileFn = params.loadJsonFileImpl ?? loadJsonFile; + const saveJsonFileFn = params.saveJsonFileImpl ?? saveJsonFile; + const cached = loadJsonFileFn(cachePath) as CachedCopilotToken | undefined; + if (cached && typeof cached.token === "string" && typeof cached.expiresAt === "number") { + if (isTokenUsable(cached)) { + return { + token: cached.token, + expiresAt: cached.expiresAt, + source: `cache:${cachePath}`, + baseUrl: deriveCopilotApiBaseUrlFromToken(cached.token) ?? DEFAULT_COPILOT_API_BASE_URL, + }; + } + } + + const fetchImpl = params.fetchImpl ?? fetch; + const res = await fetchImpl(COPILOT_TOKEN_URL, { + method: "GET", + headers: { + Accept: "application/json", + Authorization: `Bearer ${params.githubToken}`, + ...buildCopilotIdeHeaders({ includeApiVersion: true }), + }, + }); + + if (!res.ok) { + throw new Error(`Copilot token exchange failed: HTTP ${res.status}`); + } + + const json = parseCopilotTokenResponse(await res.json()); + const payload: CachedCopilotToken = { + token: json.token, + expiresAt: json.expiresAt, + updatedAt: Date.now(), + }; + saveJsonFileFn(cachePath, payload); + + return { + token: payload.token, + expiresAt: payload.expiresAt, + source: `fetched:${COPILOT_TOKEN_URL}`, + baseUrl: deriveCopilotApiBaseUrlFromToken(payload.token) ?? DEFAULT_COPILOT_API_BASE_URL, + }; +} diff --git a/extensions/matrix/src/runtime-api.ts b/extensions/matrix/src/runtime-api.ts index 7b534880674..eeabd6fab76 100644 --- a/extensions/matrix/src/runtime-api.ts +++ b/extensions/matrix/src/runtime-api.ts @@ -107,7 +107,7 @@ export { formatZonedTimestamp, type PluginRuntime, type RuntimeLogger, -} from "openclaw/plugin-sdk/matrix-runtime-shared"; +} from "openclaw/plugin-sdk/core"; export type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime"; // resolveMatrixAccountStringValues already comes from the Matrix API barrel. // Re-exporting auth-precedence here makes Jiti try to define the same export twice. diff --git a/extensions/memory-core/index.test.ts b/extensions/memory-core/index.test.ts index b12877352b8..867481d24c0 100644 --- a/extensions/memory-core/index.test.ts +++ b/extensions/memory-core/index.test.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core"; +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { describe, expect, it } from "vitest"; import { buildMemoryFlushPlan, diff --git a/extensions/memory-core/src/dreaming-command.test.ts b/extensions/memory-core/src/dreaming-command.test.ts index 872fd312788..4ad14cb9742 100644 --- a/extensions/memory-core/src/dreaming-command.test.ts +++ b/extensions/memory-core/src/dreaming-command.test.ts @@ -1,8 +1,9 @@ +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import type { OpenClawPluginCommandDefinition, PluginCommandContext, } from "openclaw/plugin-sdk/core"; -import type { OpenClawConfig, OpenClawPluginApi } from "openclaw/plugin-sdk/memory-core"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"; import { describe, expect, it, vi } from "vitest"; import { registerDreamingCommand } from "./dreaming-command.js"; diff --git a/extensions/memory-core/src/dreaming-phases.test.ts b/extensions/memory-core/src/dreaming-phases.test.ts index 72c79b382a2..c7d9d382d24 100644 --- a/extensions/memory-core/src/dreaming-phases.test.ts +++ b/extensions/memory-core/src/dreaming-phases.test.ts @@ -1,9 +1,9 @@ import { createHash } from "node:crypto"; import fs from "node:fs/promises"; import path from "node:path"; +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { RequestScopedSubagentRuntimeError } from "openclaw/plugin-sdk/error-runtime"; -import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core"; -import { resolveSessionTranscriptsDirForAgent } from "openclaw/plugin-sdk/memory-core"; +import { resolveSessionTranscriptsDirForAgent } from "openclaw/plugin-sdk/memory-core-host-runtime-core"; import { resolveMemoryCorePluginConfig, resolveMemoryLightDreamingConfig, diff --git a/extensions/memory-core/src/dreaming.test.ts b/extensions/memory-core/src/dreaming.test.ts index 6a05ea77c3f..d381e8722ef 100644 --- a/extensions/memory-core/src/dreaming.test.ts +++ b/extensions/memory-core/src/dreaming.test.ts @@ -1,6 +1,6 @@ import fs from "node:fs/promises"; import path from "node:path"; -import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core"; +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types"; import { enqueueSystemEvent, resetSystemEventsForTest, diff --git a/extensions/memory-core/src/memory/index.test.ts b/extensions/memory-core/src/memory/index.test.ts index 3db96d20d93..9f280c92c9a 100644 --- a/extensions/memory-core/src/memory/index.test.ts +++ b/extensions/memory-core/src/memory/index.test.ts @@ -2,12 +2,12 @@ import { mkdirSync, rmSync } from "node:fs"; import fs from "node:fs/promises"; import os from "node:os"; import path from "node:path"; -import { resolveSessionTranscriptsDirForAgent } from "openclaw/plugin-sdk/memory-core"; import { clearMemoryEmbeddingProviders as clearRegistry, listRegisteredMemoryEmbeddingProviderAdapters as listRegisteredAdapters, registerMemoryEmbeddingProvider as registerAdapter, } from "openclaw/plugin-sdk/memory-core-host-engine-embeddings"; +import { resolveSessionTranscriptsDirForAgent } from "openclaw/plugin-sdk/memory-core-host-runtime-core"; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import "./test-runtime-mocks.js"; import type { MemoryIndexManager } from "./index.js"; diff --git a/extensions/tsconfig.package-boundary.paths.json b/extensions/tsconfig.package-boundary.paths.json index c439cb65c5d..c0448ba22ef 100644 --- a/extensions/tsconfig.package-boundary.paths.json +++ b/extensions/tsconfig.package-boundary.paths.json @@ -12,18 +12,6 @@ "openclaw/plugin-sdk/browser-maintenance": [ "../packages/plugin-sdk/dist/extensions/browser/browser-maintenance.d.ts" ], - "openclaw/plugin-sdk/browser-config-runtime": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-config-runtime.d.ts" - ], - "openclaw/plugin-sdk/browser-node-runtime": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-node-runtime.d.ts" - ], - "openclaw/plugin-sdk/browser-setup-tools": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-setup-tools.d.ts" - ], - "openclaw/plugin-sdk/browser-security-runtime": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-security-runtime.d.ts" - ], "openclaw/plugin-sdk/channel-secret-basic-runtime": [ "../packages/plugin-sdk/dist/src/plugin-sdk/channel-secret-basic-runtime.d.ts" ], diff --git a/extensions/xai/tsconfig.json b/extensions/xai/tsconfig.json index 319004f3bc9..dd1837a92d4 100644 --- a/extensions/xai/tsconfig.json +++ b/extensions/xai/tsconfig.json @@ -13,18 +13,6 @@ "openclaw/plugin-sdk/browser-maintenance": [ "../../dist/plugin-sdk/src/plugin-sdk/browser-maintenance.d.ts" ], - "openclaw/plugin-sdk/browser-config-runtime": [ - "../../dist/plugin-sdk/src/plugin-sdk/browser-config-runtime.d.ts" - ], - "openclaw/plugin-sdk/browser-node-runtime": [ - "../../dist/plugin-sdk/src/plugin-sdk/browser-node-runtime.d.ts" - ], - "openclaw/plugin-sdk/browser-setup-tools": [ - "../../dist/plugin-sdk/src/plugin-sdk/browser-setup-tools.d.ts" - ], - "openclaw/plugin-sdk/browser-security-runtime": [ - "../../dist/plugin-sdk/src/plugin-sdk/browser-security-runtime.d.ts" - ], "openclaw/plugin-sdk/channel-secret-runtime": [ "../../dist/plugin-sdk/src/plugin-sdk/channel-secret-runtime.d.ts" ], diff --git a/package.json b/package.json index 01e25a5e0e4..9fea64b7924 100644 --- a/package.json +++ b/package.json @@ -370,10 +370,6 @@ "types": "./dist/plugin-sdk/conversation-runtime.d.ts", "default": "./dist/plugin-sdk/conversation-runtime.js" }, - "./plugin-sdk/matrix-runtime-shared": { - "types": "./dist/plugin-sdk/matrix-runtime-shared.d.ts", - "default": "./dist/plugin-sdk/matrix-runtime-shared.js" - }, "./plugin-sdk/thread-bindings-runtime": { "types": "./dist/plugin-sdk/thread-bindings-runtime.d.ts", "default": "./dist/plugin-sdk/thread-bindings-runtime.js" @@ -442,10 +438,6 @@ "types": "./dist/plugin-sdk/gateway-runtime.d.ts", "default": "./dist/plugin-sdk/gateway-runtime.js" }, - "./plugin-sdk/github-copilot-token": { - "types": "./dist/plugin-sdk/github-copilot-token.d.ts", - "default": "./dist/plugin-sdk/github-copilot-token.js" - }, "./plugin-sdk/cli-runtime": { "types": "./dist/plugin-sdk/cli-runtime.d.ts", "default": "./dist/plugin-sdk/cli-runtime.js" @@ -598,26 +590,6 @@ "types": "./dist/plugin-sdk/browser-config.d.ts", "default": "./dist/plugin-sdk/browser-config.js" }, - "./plugin-sdk/browser-config-runtime": { - "types": "./dist/plugin-sdk/browser-config-runtime.d.ts", - "default": "./dist/plugin-sdk/browser-config-runtime.js" - }, - "./plugin-sdk/browser-config-support": { - "types": "./dist/plugin-sdk/browser-config-support.d.ts", - "default": "./dist/plugin-sdk/browser-config-support.js" - }, - "./plugin-sdk/browser-node-runtime": { - "types": "./dist/plugin-sdk/browser-node-runtime.d.ts", - "default": "./dist/plugin-sdk/browser-node-runtime.js" - }, - "./plugin-sdk/browser-security-runtime": { - "types": "./dist/plugin-sdk/browser-security-runtime.d.ts", - "default": "./dist/plugin-sdk/browser-security-runtime.js" - }, - "./plugin-sdk/browser-setup-tools": { - "types": "./dist/plugin-sdk/browser-setup-tools.d.ts", - "default": "./dist/plugin-sdk/browser-setup-tools.js" - }, "./plugin-sdk/boolean-param": { "types": "./dist/plugin-sdk/boolean-param.d.ts", "default": "./dist/plugin-sdk/boolean-param.js" @@ -954,10 +926,6 @@ "types": "./dist/plugin-sdk/qa-runner-runtime.d.ts", "default": "./dist/plugin-sdk/qa-runner-runtime.js" }, - "./plugin-sdk/memory-core": { - "types": "./dist/plugin-sdk/memory-core.d.ts", - "default": "./dist/plugin-sdk/memory-core.js" - }, "./plugin-sdk/memory-core-engine-runtime": { "types": "./dist/plugin-sdk/memory-core-engine-runtime.d.ts", "default": "./dist/plugin-sdk/memory-core-engine-runtime.js" diff --git a/packages/plugin-sdk/package.json b/packages/plugin-sdk/package.json index 2c82f027859..1fe473bf70a 100644 --- a/packages/plugin-sdk/package.json +++ b/packages/plugin-sdk/package.json @@ -56,18 +56,10 @@ "types": "./dist/src/plugin-sdk/transport-ready-runtime.d.ts", "default": "./src/transport-ready-runtime.ts" }, - "./browser-config-runtime": { - "types": "./dist/src/plugin-sdk/browser-config-runtime.d.ts", - "default": "./src/browser-config-runtime.ts" - }, "./core": { "types": "./dist/src/plugin-sdk/core.d.ts", "default": "./src/core.ts" }, - "./browser-node-runtime": { - "types": "./dist/src/plugin-sdk/browser-node-runtime.d.ts", - "default": "./src/browser-node-runtime.ts" - }, "./config-runtime": { "types": "./dist/src/plugin-sdk/config-runtime.d.ts", "default": "./src/config-runtime.ts" @@ -88,14 +80,6 @@ "types": "./dist/src/plugin-sdk/cron-store-runtime.d.ts", "default": "./src/cron-store-runtime.ts" }, - "./browser-setup-tools": { - "types": "./dist/src/plugin-sdk/browser-setup-tools.d.ts", - "default": "./src/browser-setup-tools.ts" - }, - "./browser-security-runtime": { - "types": "./dist/src/plugin-sdk/browser-security-runtime.d.ts", - "default": "./src/browser-security-runtime.ts" - }, "./channel-secret-runtime": { "types": "./dist/src/plugin-sdk/channel-secret-runtime.d.ts", "default": "./src/channel-secret-runtime.ts" diff --git a/scripts/e2e/npm-telegram-live-docker.sh b/scripts/e2e/npm-telegram-live-docker.sh index aadc454d06f..1fa6946da86 100755 --- a/scripts/e2e/npm-telegram-live-docker.sh +++ b/scripts/e2e/npm-telegram-live-docker.sh @@ -251,8 +251,8 @@ for (const packageJsonPath of [ }; if (!pkg.exports["./plugin-sdk/gateway-runtime"]) { pkg.exports["./plugin-sdk/gateway-runtime"] = { - types: "./dist/plugin-sdk/browser-node-runtime.d.ts", - default: "./dist/plugin-sdk/browser-node-runtime.js", + types: "./dist/plugin-sdk/gateway-runtime.d.ts", + default: "./dist/plugin-sdk/gateway-runtime.js", }; } fs.writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`); diff --git a/scripts/lib/config-boundary-guard.mjs b/scripts/lib/config-boundary-guard.mjs index 7348b1c03e4..d4e4988e5ec 100644 --- a/scripts/lib/config-boundary-guard.mjs +++ b/scripts/lib/config-boundary-guard.mjs @@ -9,9 +9,7 @@ const COMPAT_CONFIG_API_FILES = new Set([ "src/config/io.ts", "src/config/mutate.ts", "src/memory-host-sdk/runtime-core.ts", - "src/plugin-sdk/browser-config-runtime.ts", "src/plugin-sdk/config-runtime.ts", - "src/plugin-sdk/memory-core.ts", "src/plugin-sdk/memory-core-host-runtime-core.ts", "src/plugins/compat/registry.ts", "src/plugins/contracts/config-boundary-guard.test.ts", @@ -224,7 +222,7 @@ export function collectDeprecatedInternalConfigApiViolations({ const guards = [ { pattern: - /\b(?:import|export)\s+(?:type\s+)?\{[^}]*\bloadConfig\b[^}]*\}\s+from\s+["']openclaw\/plugin-sdk\/(?:browser-config-runtime|config-runtime|memory-core-host-runtime-core)["']/, + /\b(?:import|export)\s+(?:type\s+)?\{[^}]*\bloadConfig\b[^}]*\}\s+from\s+["']openclaw\/plugin-sdk\/(?:config-runtime|memory-core-host-runtime-core)["']/, replacement: "use getRuntimeConfig(), runtime.config.current(), or pass the already loaded config", }, @@ -280,13 +278,13 @@ export function collectDeprecatedInternalConfigApiViolations({ const guards = [ { pattern: - /\b(?:import|export)\s+(?:type\s+)?\{[\s\S]*?\b(?:loadConfig|writeConfigFile)\b[\s\S]*?\}\s+from\s+["']openclaw\/plugin-sdk\/(?:browser-config-runtime|config-runtime|memory-core-host-runtime-core|memory-core)["']/, + /\b(?:import|export)\s+(?:type\s+)?\{[\s\S]*?\b(?:loadConfig|writeConfigFile)\b[\s\S]*?\}\s+from\s+["']openclaw\/plugin-sdk\/(?:config-runtime|memory-core-host-runtime-core)["']/, replacement: "use getRuntimeConfig(), runtime.config.current(), or mutation helpers with afterWrite", }, { pattern: - /ReturnType/, + /ReturnType/, replacement: "use OpenClawConfig or the explicit mutation helper type", }, ]; diff --git a/scripts/lib/extension-package-boundary.ts b/scripts/lib/extension-package-boundary.ts index 8cadd0df2ce..50bf76764c4 100644 --- a/scripts/lib/extension-package-boundary.ts +++ b/scripts/lib/extension-package-boundary.ts @@ -25,18 +25,6 @@ export const EXTENSION_PACKAGE_BOUNDARY_BASE_PATHS = { "openclaw/plugin-sdk/browser-maintenance": [ "../packages/plugin-sdk/dist/extensions/browser/browser-maintenance.d.ts", ], - "openclaw/plugin-sdk/browser-config-runtime": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-config-runtime.d.ts", - ], - "openclaw/plugin-sdk/browser-node-runtime": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-node-runtime.d.ts", - ], - "openclaw/plugin-sdk/browser-setup-tools": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-setup-tools.d.ts", - ], - "openclaw/plugin-sdk/browser-security-runtime": [ - "../dist/plugin-sdk/src/plugin-sdk/browser-security-runtime.d.ts", - ], "openclaw/plugin-sdk/channel-secret-basic-runtime": [ "../packages/plugin-sdk/dist/src/plugin-sdk/channel-secret-basic-runtime.d.ts", ], diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index a0b66c8ed30..196eacfe897 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -76,7 +76,6 @@ "media-generation-runtime", "conversation-binding-runtime", "conversation-runtime", - "matrix-runtime-shared", "thread-bindings-runtime", "thread-bindings-session-runtime", "text-runtime", @@ -94,7 +93,6 @@ "secret-file-runtime", "security-runtime", "gateway-runtime", - "github-copilot-token", "cli-runtime", "cli-backend", "agent-harness", @@ -133,11 +131,6 @@ "allow-from", "allowlist-config-edit", "browser-config", - "browser-config-runtime", - "browser-config-support", - "browser-node-runtime", - "browser-security-runtime", - "browser-setup-tools", "boolean-param", "channel-contract-testing", "dangerous-name-runtime", @@ -222,7 +215,6 @@ "persistent-dedupe", "keyed-async-queue", "qa-runner-runtime", - "memory-core", "memory-core-engine-runtime", "memory-core-host-engine-embeddings", "memory-core-host-engine-foundation", diff --git a/scripts/openclaw-cross-os-release-checks.ts b/scripts/openclaw-cross-os-release-checks.ts index 09de747daf8..948ce5ddd96 100644 --- a/scripts/openclaw-cross-os-release-checks.ts +++ b/scripts/openclaw-cross-os-release-checks.ts @@ -2240,7 +2240,7 @@ export function shouldRunWindowsInstalledBrowserOverrideImportSmoke(platform = p } export function buildInstalledBrowserOverrideImportProbeScript( - runtimeModuleSpecifier = "openclaw/plugin-sdk/browser-node-runtime", + runtimeModuleSpecifier = "openclaw/plugin-sdk/plugin-runtime", ) { return ` import { existsSync } from "node:fs"; @@ -2309,7 +2309,7 @@ async function runInstalledBrowserOverrideImportSmoke(params) { const startedPath = join(probeDir, "started.txt"); const stoppedPath = join(probeDir, "stopped.txt"); const packageRoot = installedPackageRoot(params.prefixDir); - const runtimeModulePath = join(packageRoot, "dist", "plugin-sdk", "browser-node-runtime.js"); + const runtimeModulePath = join(packageRoot, "dist", "plugin-sdk", "plugin-runtime.js"); if (!existsSync(runtimeModulePath)) { throw new Error(`Installed browser runtime module not found: ${runtimeModulePath}`); } diff --git a/scripts/plugin-boundary-report.ts b/scripts/plugin-boundary-report.ts index f7c421aa754..9bd7cd54bda 100644 --- a/scripts/plugin-boundary-report.ts +++ b/scripts/plugin-boundary-report.ts @@ -429,7 +429,7 @@ function buildReport(options: Pick = {}): BoundaryReport { !usedReserved.has(subpath) && matchesOwner(options.owner, resolvePluginOwner(subpath, pluginIds)), ) - .toSorted(); + .toSorted((a, b) => a.localeCompare(b)); return { generatedAt: new Date().toISOString(), compat: { diff --git a/src/plugin-sdk/agent-harness-runtime.ts b/src/plugin-sdk/agent-harness-runtime.ts index 1616f5acc3f..9c01c1c251f 100644 --- a/src/plugin-sdk/agent-harness-runtime.ts +++ b/src/plugin-sdk/agent-harness-runtime.ts @@ -66,6 +66,12 @@ export { classifyEmbeddedPiRunResultForModelFallback } from "../agents/pi-embedd export { resolveEmbeddedAgentRuntime } from "../agents/pi-embedded-runner/runtime.js"; export { resolveUserPath } from "../utils.js"; export { callGatewayTool } from "../agents/tools/gateway.js"; +export type { NodeListNode } from "../agents/tools/nodes-utils.js"; +export { + listNodes, + resolveNodeIdFromList, + selectDefaultNodeFromList, +} from "../agents/tools/nodes-utils.js"; export { formatToolAggregate } from "../auto-reply/tool-meta.js"; export { isMessagingTool, isMessagingToolSendAction } from "../agents/pi-embedded-messaging.js"; export { diff --git a/src/plugin-sdk/browser-config-runtime.ts b/src/plugin-sdk/browser-config-runtime.ts deleted file mode 100644 index 87cd6414d85..00000000000 --- a/src/plugin-sdk/browser-config-runtime.ts +++ /dev/null @@ -1,38 +0,0 @@ -export { - /** - * @deprecated Use getRuntimeConfig(), runtime.config.current(), or pass the - * already loaded config through the call path. Runtime code must not reload - * config on demand. Bundled plugins and repo code are blocked from using - * this by the deprecated-internal-config-api architecture guard. - */ - createConfigIO, - getRuntimeConfig, - getRuntimeConfigSnapshot, - /** - * @deprecated Use getRuntimeConfig(), runtime.config.current(), or pass the - * already loaded config through the call path. Runtime code must not reload - * config on demand. Bundled plugins and repo code are blocked from using - * this by the deprecated-internal-config-api architecture guard. - */ - loadConfig, - /** - * @deprecated Use mutateConfigFile() or replaceConfigFile() with an explicit - * afterWrite intent so restart behavior stays under host control. Bundled - * plugins and repo code are blocked from using this by the - * deprecated-internal-config-api architecture guard. - */ - writeConfigFile, - type BrowserConfig, - type BrowserProfileConfig, - type OpenClawConfig, -} from "../config/config.js"; -export { mutateConfigFile, replaceConfigFile } from "../config/mutate.js"; -export { resolveConfigPath, resolveGatewayPort } from "../config/paths.js"; -export { - DEFAULT_BROWSER_CONTROL_PORT, - deriveDefaultBrowserCdpPortRange, - deriveDefaultBrowserControlPort, -} from "../config/port-defaults.js"; -export { normalizePluginsConfig, resolveEffectiveEnableState } from "../plugins/config-state.js"; -export { parseBooleanValue } from "../utils/boolean.js"; -export { CONFIG_DIR, escapeRegExp, resolveUserPath, shortenHomePath } from "../utils.js"; diff --git a/src/plugin-sdk/browser-config-support.ts b/src/plugin-sdk/browser-config-support.ts deleted file mode 100644 index 5406d274092..00000000000 --- a/src/plugin-sdk/browser-config-support.ts +++ /dev/null @@ -1,8 +0,0 @@ -export { resolveGatewayPort } from "../config/paths.js"; -export { - DEFAULT_BROWSER_CONTROL_PORT, - deriveDefaultBrowserCdpPortRange, - deriveDefaultBrowserControlPort, -} from "../config/port-defaults.js"; -export { isLoopbackHost } from "../gateway/net.js"; -export { CONFIG_DIR, escapeRegExp, resolveUserPath, shortenHomePath } from "../utils.js"; diff --git a/src/plugin-sdk/browser-node-runtime.ts b/src/plugin-sdk/browser-node-runtime.ts deleted file mode 100644 index 02294b07809..00000000000 --- a/src/plugin-sdk/browser-node-runtime.ts +++ /dev/null @@ -1,26 +0,0 @@ -export { addGatewayClientOptions, callGatewayFromCli } from "../cli/gateway-rpc.js"; -export type { GatewayRpcOpts } from "../cli/gateway-rpc.js"; -export { runCommandWithRuntime } from "../cli/cli-utils.js"; -export { resolveGatewayAuth } from "../gateway/auth.js"; -export { isLoopbackHost } from "../gateway/net.js"; -export { - isNodeCommandAllowed, - resolveNodeCommandAllowlist, -} from "../gateway/node-command-policy.js"; -export type { NodeSession } from "../gateway/node-registry.js"; -export { ErrorCodes, errorShape } from "../gateway/protocol/index.js"; -export { - respondUnavailableOnNodeInvokeError, - safeParseJson, -} from "../gateway/server-methods/nodes.helpers.js"; -export type { GatewayRequestHandlers } from "../gateway/server-methods/types.js"; -export { ensureGatewayStartupAuth } from "../gateway/startup-auth.js"; -export { rawDataToString } from "../infra/ws.js"; -export { - startLazyPluginServiceModule, - type LazyPluginServiceHandle, -} from "../plugins/lazy-service-module.js"; -export type { OpenClawPluginService } from "../plugins/types.js"; -export { runExec } from "../process/exec.js"; -export { defaultRuntime } from "./runtime.js"; -export { withTimeout } from "../node-host/with-timeout.js"; diff --git a/src/plugin-sdk/browser-security-runtime.ts b/src/plugin-sdk/browser-security-runtime.ts deleted file mode 100644 index 690e8069660..00000000000 --- a/src/plugin-sdk/browser-security-runtime.ts +++ /dev/null @@ -1,26 +0,0 @@ -export { hasConfiguredSecretInput } from "../config/types.secrets.js"; -export { extractErrorCode, formatErrorMessage } from "../infra/errors.js"; -export { - SafeOpenError, - openFileWithinRoot, - writeFileFromPathWithinRoot, -} from "../infra/fs-safe.js"; -export { hasProxyEnvConfigured } from "../infra/net/proxy-env.js"; -export { - SsrFBlockedError, - isBlockedHostnameOrIp, - matchesHostnameAllowlist, - isPrivateNetworkAllowedByPolicy, - resolvePinnedHostnameWithPolicy, - type LookupFn, - type SsrFPolicy, -} from "../infra/net/ssrf.js"; -export { normalizeHostname } from "../infra/net/hostname.js"; -export { isNotFoundPathError, isPathInside } from "../infra/path-guards.js"; -export { ensurePortAvailable } from "../infra/ports.js"; -export { generateSecureToken } from "../infra/secure-random.js"; -export { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js"; -export { createSubsystemLogger } from "../logging/subsystem.js"; -export { redactSensitiveText } from "../logging/redact.js"; -export { wrapExternalContent } from "../security/external-content.js"; -export { safeEqualSecret } from "../security/secret-equal.js"; diff --git a/src/plugin-sdk/browser-setup-tools.ts b/src/plugin-sdk/browser-setup-tools.ts deleted file mode 100644 index 576a812c49a..00000000000 --- a/src/plugin-sdk/browser-setup-tools.ts +++ /dev/null @@ -1,31 +0,0 @@ -export type { AnyAgentTool } from "../agents/tools/common.js"; -export { imageResultFromFile, jsonResult, readStringParam } from "../agents/tools/common.js"; -export type { NodeListNode } from "../agents/tools/nodes-utils.js"; -export { - listNodes, - resolveNodeIdFromList, - selectDefaultNodeFromList, -} from "../agents/tools/nodes-utils.js"; -export { callGatewayTool } from "../agents/tools/gateway.js"; -export { optionalStringEnum, stringEnum } from "../agents/schema/typebox.js"; -export { formatCliCommand } from "../cli/command-format.js"; -export { inheritOptionFromParent } from "../cli/command-options.js"; -export { formatHelpExamples } from "../cli/help-format.js"; -export { danger, info } from "../globals.js"; -export { - IMAGE_REDUCE_QUALITY_STEPS, - buildImageResizeSideGrid, - getImageMetadata, - resizeToJpeg, -} from "../media/image-ops.js"; -export { detectMime } from "../media/mime.js"; -export { ensureMediaDir, saveMediaBuffer } from "../media/store.js"; -export { formatDocsLink } from "../terminal/links.js"; -export { note } from "../terminal/note.js"; -export { theme } from "../terminal/theme.js"; -export { captureEnv, withEnv, withEnvAsync } from "../test-utils/env.js"; -export { withFetchPreconnect } from "../test-utils/fetch-mock.js"; -export type { FetchMock } from "../test-utils/fetch-mock.js"; -export { createTempHomeEnv } from "../test-utils/temp-home.js"; -export type { TempHomeEnv } from "../test-utils/temp-home.js"; -export type { MockFn } from "../test-utils/vitest-mock-fn.js"; diff --git a/src/plugin-sdk/cli-runtime.ts b/src/plugin-sdk/cli-runtime.ts index fb1dcb0dce0..640b105a49a 100644 --- a/src/plugin-sdk/cli-runtime.ts +++ b/src/plugin-sdk/cli-runtime.ts @@ -1,6 +1,9 @@ // Public CLI/output helpers for plugins that share terminal-facing command behavior. export * from "../cli/command-format.js"; +export { inheritOptionFromParent } from "../cli/command-options.js"; +export { runCommandWithRuntime } from "../cli/cli-utils.js"; +export { formatHelpExamples } from "../cli/help-format.js"; export { registerCommandGroups, type CommandGroupEntry, @@ -10,5 +13,7 @@ export * from "../cli/parse-duration.js"; export { resolveCliArgvInvocation, type CliArgvInvocation } from "../cli/argv-invocation.js"; export { shouldEagerRegisterSubcommands } from "../cli/command-registration-policy.js"; export * from "../cli/wait.js"; +export { note } from "../terminal/note.js"; export { stylePromptTitle } from "../terminal/prompt-style.js"; +export { theme } from "../terminal/theme.js"; export * from "../version.js"; diff --git a/src/plugin-sdk/entrypoints.ts b/src/plugin-sdk/entrypoints.ts index 37be5a34446..af53ffdc691 100644 --- a/src/plugin-sdk/entrypoints.ts +++ b/src/plugin-sdk/entrypoints.ts @@ -6,16 +6,7 @@ export const pluginSdkSubpaths = pluginSdkEntrypoints.filter((entry) => entry != // Transitional compatibility/helper surfaces owned by their matching bundled plugin. // Cross-owner extension imports are blocked by the package contract guardrails. -export const reservedBundledPluginSdkEntrypoints = [ - "browser-config-runtime", - "browser-config-support", - "browser-node-runtime", - "browser-security-runtime", - "browser-setup-tools", - "github-copilot-token", - "matrix-runtime-shared", - "memory-core", -] as const; +export const reservedBundledPluginSdkEntrypoints = [] as const; // Supported SDK facades backed by bundled plugins. These are intentionally public // until they move to generic, plugin-neutral contracts. diff --git a/src/plugin-sdk/gateway-runtime.ts b/src/plugin-sdk/gateway-runtime.ts index d7cff644fb7..119efc343d5 100644 --- a/src/plugin-sdk/gateway-runtime.ts +++ b/src/plugin-sdk/gateway-runtime.ts @@ -3,6 +3,20 @@ export * from "../gateway/channel-status-patches.js"; export { addGatewayClientOptions, callGatewayFromCli } from "../cli/gateway-rpc.js"; export type { GatewayRpcOpts } from "../cli/gateway-rpc.js"; +export { isLoopbackHost } from "../gateway/net.js"; +export { + isNodeCommandAllowed, + resolveNodeCommandAllowlist, +} from "../gateway/node-command-policy.js"; +export type { NodeSession } from "../gateway/node-registry.js"; +export { + respondUnavailableOnNodeInvokeError, + safeParseJson, +} from "../gateway/server-methods/nodes.helpers.js"; +export type { GatewayRequestHandlers } from "../gateway/server-methods/types.js"; +export { ensureGatewayStartupAuth } from "../gateway/startup-auth.js"; +export { resolveGatewayAuth } from "../gateway/auth.js"; +export { rawDataToString } from "../infra/ws.js"; export { GatewayClient } from "../gateway/client.js"; export { createOperatorApprovalsGatewayClient, diff --git a/src/plugin-sdk/github-copilot-token.ts b/src/plugin-sdk/github-copilot-token.ts deleted file mode 100644 index 743daf1842e..00000000000 --- a/src/plugin-sdk/github-copilot-token.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "../agents/github-copilot-token.js"; diff --git a/src/plugin-sdk/matrix-runtime-shared.ts b/src/plugin-sdk/matrix-runtime-shared.ts deleted file mode 100644 index 2fa24c5ec5d..00000000000 --- a/src/plugin-sdk/matrix-runtime-shared.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Narrow shared Matrix runtime exports for light runtime-api consumers. - -export type { - ChannelDirectoryEntry, - ChannelMessageActionContext, -} from "../channels/plugins/types.public.js"; -export type { OpenClawConfig } from "../config/config.js"; -export { formatZonedTimestamp } from "../infra/format-time/format-datetime.js"; -export type { PluginRuntime, RuntimeLogger } from "../plugins/runtime/types.js"; -export type { RuntimeEnv } from "../runtime.js"; -export type { WizardPrompter } from "../wizard/prompts.js"; diff --git a/src/plugin-sdk/memory-core.ts b/src/plugin-sdk/memory-core.ts deleted file mode 100644 index 728a8d66449..00000000000 --- a/src/plugin-sdk/memory-core.ts +++ /dev/null @@ -1,78 +0,0 @@ -// Narrow plugin-sdk surface for the bundled memory-core plugin. -// Keep this list additive and scoped to the bundled memory-core surface. - -export { getMemorySearchManager, MemoryIndexManager } from "./memory-core-engine-runtime.js"; -export { - DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR, - emptyPluginConfigSchema, - jsonResult, - /** - * @deprecated Use getRuntimeConfig(), runtime.config.current(), or pass the - * already loaded config through the call path. Runtime code must not reload - * config on demand. Bundled plugins and repo code are blocked from using - * this by the deprecated-internal-config-api architecture guard. - */ - loadConfig, - parseAgentSessionKey, - parseNonNegativeByteSize, - readNumberParam, - readStringParam, - resolveCronStyleNow, - resolveDefaultAgentId, - resolveMemorySearchConfig, - resolveSessionAgentId, - resolveSessionTranscriptsDirForAgent, - resolveStateDir, - SILENT_REPLY_TOKEN, -} from "./memory-core-host-runtime-core.js"; -export type { - AnyAgentTool, - MemoryCitationsMode, - MemoryFlushPlan, - MemoryFlushPlanResolver, - MemoryPluginCapability, - MemoryPluginPublicArtifact, - MemoryPluginPublicArtifactsProvider, - MemoryPluginRuntime, - MemoryPromptSectionBuilder, - OpenClawConfig, - OpenClawPluginApi, -} from "./memory-core-host-runtime-core.js"; -export { - colorize, - defaultRuntime, - formatDocsLink, - formatErrorMessage, - formatHelpExamples, - isRich, - isVerbose, - resolveCommandSecretRefsViaGateway, - setVerbose, - shortenHomeInString, - shortenHomePath, - theme, - withManager, - withProgress, - withProgressTotals, -} from "./memory-core-host-runtime-cli.js"; -export { - appendMemoryHostEvent, - readMemoryHostEvents, - resolveMemoryHostEventLogPath, -} from "./memory-core-host-events.js"; -export type { MemoryHostEvent } from "./memory-core-host-events.js"; -export { - resolveMemoryCorePluginConfig, - formatMemoryDreamingDay, - isSameMemoryDreamingDay, - resolveMemoryDeepDreamingConfig, - resolveMemoryDreamingConfig, - resolveMemoryDreamingWorkspaces, -} from "./memory-core-host-status.js"; -export { - listMemoryFiles, - normalizeExtraMemoryPaths, - readAgentMemoryFile, - resolveMemoryBackendConfig, -} from "./memory-core-host-runtime-files.js"; -export type { MemorySearchResult } from "./memory-core-host-runtime-files.js"; diff --git a/src/plugin-sdk/plugin-config-runtime.ts b/src/plugin-sdk/plugin-config-runtime.ts index c9ec85ce4ed..c6d898ff648 100644 --- a/src/plugin-sdk/plugin-config-runtime.ts +++ b/src/plugin-sdk/plugin-config-runtime.ts @@ -1,5 +1,7 @@ import type { OpenClawConfig } from "../config/types.js"; +export { normalizePluginsConfig, resolveEffectiveEnableState } from "../plugins/config-state.js"; + export function requireRuntimeConfig(config: OpenClawConfig, context: string): OpenClawConfig { if (config) { return config; diff --git a/src/plugin-sdk/security-runtime.ts b/src/plugin-sdk/security-runtime.ts index 7d847e5f401..60ed1a9e432 100644 --- a/src/plugin-sdk/security-runtime.ts +++ b/src/plugin-sdk/security-runtime.ts @@ -9,5 +9,26 @@ export * from "../security/context-visibility.js"; export * from "../security/dm-policy-shared.js"; export * from "../security/external-content.js"; export * from "../security/safe-regex.js"; +export { + SafeOpenError, + openFileWithinRoot, + writeFileFromPathWithinRoot, +} from "../infra/fs-safe.js"; +export { extractErrorCode, formatErrorMessage } from "../infra/errors.js"; +export { hasProxyEnvConfigured } from "../infra/net/proxy-env.js"; +export { normalizeHostname } from "../infra/net/hostname.js"; +export { + SsrFBlockedError, + isBlockedHostnameOrIp, + isPrivateNetworkAllowedByPolicy, + matchesHostnameAllowlist, + resolvePinnedHostnameWithPolicy, + type LookupFn, + type SsrFPolicy, +} from "../infra/net/ssrf.js"; +export { isNotFoundPathError, isPathInside } from "../infra/path-guards.js"; +export { ensurePortAvailable } from "../infra/ports.js"; +export { generateSecureToken } from "../infra/secure-random.js"; +export { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js"; export { redactSensitiveText } from "../logging/redact.js"; export { safeEqualSecret } from "../security/secret-equal.js"; diff --git a/src/plugins/contracts/extension-package-project-boundaries.test.ts b/src/plugins/contracts/extension-package-project-boundaries.test.ts index 13b4188f623..2a227271a5d 100644 --- a/src/plugins/contracts/extension-package-project-boundaries.test.ts +++ b/src/plugins/contracts/extension-package-project-boundaries.test.ts @@ -129,17 +129,8 @@ describe("opt-in extension package boundaries", () => { expect(packageJson.exports?.["./acp-runtime"]?.types).toBe( "./dist/src/plugin-sdk/acp-runtime.d.ts", ); - expect(packageJson.exports?.["./browser-config-runtime"]?.types).toBe( - "./dist/src/plugin-sdk/browser-config-runtime.d.ts", - ); - expect(packageJson.exports?.["./browser-node-runtime"]?.types).toBe( - "./dist/src/plugin-sdk/browser-node-runtime.d.ts", - ); - expect(packageJson.exports?.["./browser-setup-tools"]?.types).toBe( - "./dist/src/plugin-sdk/browser-setup-tools.d.ts", - ); - expect(packageJson.exports?.["./browser-security-runtime"]?.types).toBe( - "./dist/src/plugin-sdk/browser-security-runtime.d.ts", + expect(packageJson.exports?.["./browser-config"]?.types).toBe( + "./dist/src/plugin-sdk/browser-config.d.ts", ); expect(packageJson.exports?.["./channel-secret-runtime"]?.types).toBe( "./dist/src/plugin-sdk/channel-secret-runtime.d.ts", diff --git a/src/plugins/contracts/plugin-sdk-index.bundle.test.ts b/src/plugins/contracts/plugin-sdk-index.bundle.test.ts index 785cb185b5c..93301a0ccdc 100644 --- a/src/plugins/contracts/plugin-sdk-index.bundle.test.ts +++ b/src/plugins/contracts/plugin-sdk-index.bundle.test.ts @@ -9,7 +9,7 @@ import { resolveBundledPluginFile } from "./test-helpers/bundled-plugin-roots.js const require = createRequire(import.meta.url); const tsdownModuleUrl = pathToFileURL(require.resolve("tsdown")).href; -const bundledRepresentativeEntrypoints = ["matrix-runtime-shared"] as const; +const bundledRepresentativeEntrypoints = ["browser-config"] as const; const bundleTempRootTracker = createSuiteTempRootTracker( "openclaw-plugin-sdk-build", path.join(process.cwd(), "node_modules", ".cache"), diff --git a/src/plugins/contracts/plugin-sdk-subpaths.test.ts b/src/plugins/contracts/plugin-sdk-subpaths.test.ts index 4437a6f573b..160bf2cb578 100644 --- a/src/plugins/contracts/plugin-sdk-subpaths.test.ts +++ b/src/plugins/contracts/plugin-sdk-subpaths.test.ts @@ -1069,7 +1069,6 @@ describe("plugin-sdk subpath exports", () => { ]); expectSourceOmitsImportPattern("command-auth", "../auto-reply/status.js"); expectSourceOmitsSnippet("command-auth", "../../extensions/"); - expectSourceOmitsSnippet("matrix-runtime-shared", "../../extensions/"); expectSourceMentions("channel-send-result", [ "attachChannelToResult", "buildChannelSendResult", @@ -1108,7 +1107,6 @@ describe("plugin-sdk subpath exports", () => { "unregisterSessionBindingAdapter", "SessionBindingAdapter", ]); - expectSourceMentions("matrix-runtime-shared", ["formatZonedTimestamp"]); expectSourceMentions("ssrf-runtime", [ "closeDispatcher", "createPinnedDispatcher", diff --git a/test/scripts/npm-telegram-live.test.ts b/test/scripts/npm-telegram-live.test.ts index 493077eb333..070d02cbd21 100644 --- a/test/scripts/npm-telegram-live.test.ts +++ b/test/scripts/npm-telegram-live.test.ts @@ -75,10 +75,9 @@ describe("package Telegram live Docker E2E", () => { expect(script).toContain('pkg.exports["./plugin-sdk/qa-channel-protocol"]'); expect(script).toContain('"./extensions/qa-channel/src/protocol.ts"'); expect(script).toContain('pkg.exports["./plugin-sdk/gateway-runtime"]'); - expect(script).toContain('"./dist/plugin-sdk/browser-node-runtime.js"'); + expect(script).toContain('"./dist/plugin-sdk/gateway-runtime.js"'); expect(gatewayRpcClient).toContain('from "openclaw/plugin-sdk/gateway-runtime"'); expect(qaRuntimeApi).toContain('from "openclaw/plugin-sdk/gateway-runtime"'); - expect(gatewayRpcClient).not.toContain('from "openclaw/plugin-sdk/browser-node-runtime"'); }); it("exposes installed package dependencies to the mounted QA harness", () => { diff --git a/test/scripts/openclaw-cross-os-release-checks.test.ts b/test/scripts/openclaw-cross-os-release-checks.test.ts index ee77e1048ef..69d027c7ea4 100644 --- a/test/scripts/openclaw-cross-os-release-checks.test.ts +++ b/test/scripts/openclaw-cross-os-release-checks.test.ts @@ -326,17 +326,17 @@ describe("scripts/openclaw-cross-os-release-checks", () => { expect(shouldRunWindowsInstalledBrowserOverrideImportSmoke("linux")).toBe(false); const script = buildInstalledBrowserOverrideImportProbeScript(); - expect(script).toContain('from "openclaw/plugin-sdk/browser-node-runtime"'); + expect(script).toContain('from "openclaw/plugin-sdk/plugin-runtime"'); expect(script).toContain('overrideEnvVar: "OPENCLAW_BROWSER_CONTROL_MODULE"'); expect(script).toContain("startBrowserControlService"); expect(script).toContain("stopBrowserControlService"); expect(script).toContain("Browser control override start sentinel was not written."); const installedScript = buildInstalledBrowserOverrideImportProbeScript( - "file:///C:/Users/runner/AppData/Roaming/npm/node_modules/openclaw/dist/plugin-sdk/browser-node-runtime.js", + "file:///C:/Users/runner/AppData/Roaming/npm/node_modules/openclaw/dist/plugin-sdk/plugin-runtime.js", ); expect(installedScript).toContain( - 'from "file:///C:/Users/runner/AppData/Roaming/npm/node_modules/openclaw/dist/plugin-sdk/browser-node-runtime.js"', + 'from "file:///C:/Users/runner/AppData/Roaming/npm/node_modules/openclaw/dist/plugin-sdk/plugin-runtime.js"', ); expect(readFileSync("scripts/openclaw-cross-os-release-checks.ts", "utf8")).toContain( "OPENCLAW_BROWSER_CONTROL_MODULE: pathToFileURL(overridePath).href",