diff --git a/docs/.generated/plugin-sdk-api-baseline.sha256 b/docs/.generated/plugin-sdk-api-baseline.sha256
index 6ba74fbbd9c..d4b0ceadd38 100644
--- a/docs/.generated/plugin-sdk-api-baseline.sha256
+++ b/docs/.generated/plugin-sdk-api-baseline.sha256
@@ -1,2 +1,2 @@
-9a9970607c4ee25d8b493ea1bb1ecef939dc11330c16188251bd69eee7ab6b2d plugin-sdk-api-baseline.json
-e37f1ec7f6a9b19466ab09935f713890f375cc6c8d67647dca701140a989f5f4 plugin-sdk-api-baseline.jsonl
+f826635804fdc28fb6e1725f1c9d7e6aa8486a9085262496445885ad246860f8 plugin-sdk-api-baseline.json
+0467fa5b0ce4060d7e45d5cb76c50136a0923ce19fda3550317d7734124f8af8 plugin-sdk-api-baseline.jsonl
diff --git a/docs/plugins/architecture-internals.md b/docs/plugins/architecture-internals.md
index df6a4977e97..a23aa8d631d 100644
--- a/docs/plugins/architecture-internals.md
+++ b/docs/plugins/architecture-internals.md
@@ -605,12 +605,16 @@ Channel plugins pick from a family of narrow seams — `channel-setup`,
on one `approvalCapability` contract rather than mixing across unrelated
plugin fields. See [Channel plugins](/plugins/sdk-channel-plugins).
-Runtime and config helpers live under matching `*-runtime` subpaths
-(`approval-runtime`, `config-runtime`, `infra-runtime`, `agent-runtime`,
-`lazy-runtime`, `directory-runtime`, `text-runtime`, `runtime-store`, etc.).
+Runtime and config helpers live under matching focused `*-runtime` subpaths
+(`approval-runtime`, `agent-runtime`, `lazy-runtime`, `directory-runtime`,
+`text-runtime`, `runtime-store`, `system-event-runtime`, `heartbeat-runtime`,
+`channel-activity-runtime`, etc.). Prefer `config-types`,
+`plugin-config-runtime`, `runtime-config-snapshot`, and `config-mutation`
+instead of the broad `config-runtime` compatibility barrel.
-`openclaw/plugin-sdk/channel-runtime` is deprecated — a compatibility shim for
+`openclaw/plugin-sdk/channel-runtime`, `openclaw/plugin-sdk/config-runtime`,
+and `openclaw/plugin-sdk/infra-runtime` are deprecated compatibility shims for
older plugins. New code should import narrower generic primitives instead.
diff --git a/docs/plugins/sdk-migration.md b/docs/plugins/sdk-migration.md
index 2fcc4e2a7e4..550829a5a5b 100644
--- a/docs/plugins/sdk-migration.md
+++ b/docs/plugins/sdk-migration.md
@@ -22,6 +22,12 @@ anything they needed from a single entry point:
- **`openclaw/plugin-sdk/compat`** — a single import that re-exported dozens of
helpers. It was introduced to keep older hook-based plugins working while the
new plugin architecture was being built.
+- **`openclaw/plugin-sdk/infra-runtime`** — a broad runtime helper barrel that
+ mixed system events, heartbeat state, delivery queues, fetch/proxy helpers,
+ file helpers, approval types, and unrelated utilities.
+- **`openclaw/plugin-sdk/config-runtime`** — a broad config compatibility barrel
+ that still carries deprecated direct load/write helpers during the migration
+ window.
- **`openclaw/extension-api`** — a bridge that gave plugins direct access to
host-side helpers like the embedded agent runner.
- **`api.registerEmbeddedExtensionFactory(...)`** — a removed Pi-only bundled
@@ -235,6 +241,7 @@ releases.
```bash
grep -r "plugin-sdk/compat" my-plugin/
+ grep -r "plugin-sdk/infra-runtime" my-plugin/
grep -r "plugin-sdk/config-runtime" my-plugin/
grep -r "openclaw/extension-api" my-plugin/
```
@@ -284,6 +291,37 @@ releases.
+
+ `openclaw/plugin-sdk/infra-runtime` still exists for external
+ compatibility, but new code should import the focused helper surface it
+ actually needs:
+
+ | Need | Import |
+ | --- | --- |
+ | System event queue helpers | `openclaw/plugin-sdk/system-event-runtime` |
+ | Heartbeat event and visibility helpers | `openclaw/plugin-sdk/heartbeat-runtime` |
+ | Pending delivery queue drain | `openclaw/plugin-sdk/delivery-queue-runtime` |
+ | Channel activity telemetry | `openclaw/plugin-sdk/channel-activity-runtime` |
+ | In-memory dedupe caches | `openclaw/plugin-sdk/dedupe-runtime` |
+ | Safe local-file/media path helpers | `openclaw/plugin-sdk/file-access-runtime` |
+ | Dispatcher-aware fetch | `openclaw/plugin-sdk/runtime-fetch` |
+ | Proxy and guarded fetch helpers | `openclaw/plugin-sdk/fetch-runtime` |
+ | SSRF dispatcher policy types | `openclaw/plugin-sdk/ssrf-dispatcher` |
+ | Approval request/resolution types | `openclaw/plugin-sdk/approval-runtime` |
+ | Approval reply payload and command helpers | `openclaw/plugin-sdk/approval-reply-runtime` |
+ | Error formatting helpers | `openclaw/plugin-sdk/error-runtime` |
+ | Transport readiness waits | `openclaw/plugin-sdk/transport-ready-runtime` |
+ | Secure token helpers | `openclaw/plugin-sdk/secure-random-runtime` |
+ | Bounded async task concurrency | `openclaw/plugin-sdk/concurrency-runtime` |
+ | Numeric coercion | `openclaw/plugin-sdk/number-runtime` |
+ | Process-local async lock | `openclaw/plugin-sdk/async-lock-runtime` |
+ | File locks | `openclaw/plugin-sdk/file-lock` |
+
+ Bundled plugins are scanner-guarded against `infra-runtime`, so repo code
+ cannot regress to the broad barrel.
+
+
+
```bash
pnpm build
@@ -338,7 +376,7 @@ releases.
| `plugin-sdk/process-runtime` | Process helpers | Shared exec helpers |
| `plugin-sdk/cli-runtime` | CLI runtime helpers | Command formatting, waits, version helpers |
| `plugin-sdk/gateway-runtime` | Gateway helpers | Gateway client and channel-status patch helpers |
- | `plugin-sdk/config-runtime` | Config helpers | Config load/write helpers |
+ | `plugin-sdk/config-runtime` | Deprecated config compatibility shim | Prefer `config-types`, `plugin-config-runtime`, `runtime-config-snapshot`, and `config-mutation` |
| `plugin-sdk/telegram-command-config` | Telegram command helpers | Fallback-stable Telegram command validation helpers when the bundled Telegram contract surface is unavailable |
| `plugin-sdk/approval-runtime` | Approval prompt helpers | Exec/plugin approval payload, approval capability/profile helpers, native approval routing/runtime helpers, and structured approval display path formatting |
| `plugin-sdk/approval-auth-runtime` | Approval auth helpers | Approver resolution, same-chat action auth |
@@ -353,6 +391,13 @@ releases.
| `plugin-sdk/security-runtime` | Security helpers | Shared trust, DM gating, external-content, and secret-collection helpers |
| `plugin-sdk/ssrf-policy` | SSRF policy helpers | Host allowlist and private-network policy helpers |
| `plugin-sdk/ssrf-runtime` | SSRF runtime helpers | Pinned-dispatcher, guarded fetch, SSRF policy helpers |
+ | `plugin-sdk/system-event-runtime` | System event helpers | `enqueueSystemEvent`, `peekSystemEventEntries` |
+ | `plugin-sdk/heartbeat-runtime` | Heartbeat helpers | Heartbeat event and visibility helpers |
+ | `plugin-sdk/delivery-queue-runtime` | Delivery queue helpers | `drainPendingDeliveries` |
+ | `plugin-sdk/channel-activity-runtime` | Channel activity helpers | `recordChannelActivity` |
+ | `plugin-sdk/dedupe-runtime` | Dedupe helpers | In-memory dedupe caches |
+ | `plugin-sdk/file-access-runtime` | File access helpers | Safe local-file/media path helpers |
+ | `plugin-sdk/transport-ready-runtime` | Transport readiness helpers | `waitForTransportReady` |
| `plugin-sdk/collection-runtime` | Bounded cache helpers | `pruneMapToMaxSize` |
| `plugin-sdk/diagnostic-runtime` | Diagnostic gating helpers | `isDiagnosticFlagEnabled`, `isDiagnosticsEnabled` |
| `plugin-sdk/error-runtime` | Error formatting helpers | `formatUncaughtError`, `isApprovalNotFoundError`, error graph helpers |
diff --git a/docs/plugins/sdk-subpaths.md b/docs/plugins/sdk-subpaths.md
index 9fc0f2da9ab..419a1803a51 100644
--- a/docs/plugins/sdk-subpaths.md
+++ b/docs/plugins/sdk-subpaths.md
@@ -205,7 +205,18 @@ For the plugin authoring guide, see [Plugin SDK overview](/plugins/sdk-overview)
| `plugin-sdk/native-command-registry` | Native command registry/build/serialize helpers |
| `plugin-sdk/agent-harness` | Experimental trusted-plugin surface for low-level agent harnesses: harness types, active-run steer/abort helpers, OpenClaw tool bridge helpers, runtime-plan tool policy helpers, terminal outcome classification, tool progress formatting/detail helpers, and attempt result utilities |
| `plugin-sdk/provider-zai-endpoint` | Z.AI endpoint detection helpers |
- | `plugin-sdk/infra-runtime` | System event/heartbeat helpers |
+ | `plugin-sdk/async-lock-runtime` | Process-local async lock helper for small runtime state files |
+ | `plugin-sdk/channel-activity-runtime` | Channel activity telemetry helper |
+ | `plugin-sdk/concurrency-runtime` | Bounded async task concurrency helper |
+ | `plugin-sdk/dedupe-runtime` | In-memory dedupe cache helpers |
+ | `plugin-sdk/delivery-queue-runtime` | Outbound pending-delivery drain helper |
+ | `plugin-sdk/file-access-runtime` | Safe local-file and media-source path helpers |
+ | `plugin-sdk/heartbeat-runtime` | Heartbeat event and visibility helpers |
+ | `plugin-sdk/number-runtime` | Numeric coercion helper |
+ | `plugin-sdk/secure-random-runtime` | Secure token/UUID helpers |
+ | `plugin-sdk/system-event-runtime` | System event queue helpers |
+ | `plugin-sdk/transport-ready-runtime` | Transport readiness wait helper |
+ | `plugin-sdk/infra-runtime` | Deprecated compatibility shim; use the focused runtime subpaths above |
| `plugin-sdk/collection-runtime` | Small bounded cache helpers |
| `plugin-sdk/diagnostic-runtime` | Diagnostic flag, event, and trace-context helpers |
| `plugin-sdk/error-runtime` | Error graph, formatting, shared error classification helpers, `isApprovalNotFoundError` |
diff --git a/extensions/bluebubbles/src/media-send.ts b/extensions/bluebubbles/src/media-send.ts
index 003e022d9d1..8b074a0059c 100644
--- a/extensions/bluebubbles/src/media-send.ts
+++ b/extensions/bluebubbles/src/media-send.ts
@@ -2,7 +2,10 @@ import { constants as fsConstants } from "node:fs";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
-import { basenameFromMediaSource, safeFileURLToPath } from "openclaw/plugin-sdk/infra-runtime";
+import {
+ basenameFromMediaSource,
+ safeFileURLToPath,
+} from "openclaw/plugin-sdk/file-access-runtime";
import { resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
import { lowercasePreservingWhitespace } from "openclaw/plugin-sdk/text-runtime";
import { resolveBlueBubblesAccount } from "./accounts.js";
diff --git a/extensions/bluebubbles/src/monitor-normalize.ts b/extensions/bluebubbles/src/monitor-normalize.ts
index 9ba319e0152..05dfb95a6e1 100644
--- a/extensions/bluebubbles/src/monitor-normalize.ts
+++ b/extensions/bluebubbles/src/monitor-normalize.ts
@@ -1,4 +1,4 @@
-import { parseFiniteNumber } from "openclaw/plugin-sdk/infra-runtime";
+import { parseFiniteNumber } from "openclaw/plugin-sdk/number-runtime";
import {
asNullableRecord,
normalizeLowercaseStringOrEmpty,
diff --git a/extensions/bluebubbles/src/runtime-api.ts b/extensions/bluebubbles/src/runtime-api.ts
index 71524ac363d..39d97eb8409 100644
--- a/extensions/bluebubbles/src/runtime-api.ts
+++ b/extensions/bluebubbles/src/runtime-api.ts
@@ -29,7 +29,7 @@ export type {
OpenClawConfig,
PluginRuntime,
} from "openclaw/plugin-sdk/channel-core";
-export { parseFiniteNumber } from "openclaw/plugin-sdk/infra-runtime";
+export { parseFiniteNumber } from "openclaw/plugin-sdk/number-runtime";
export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
export {
DM_GROUP_ACCESS_REASON,
diff --git a/extensions/discord/src/approval-handler.runtime.ts b/extensions/discord/src/approval-handler.runtime.ts
index e7cd416c85b..94e150af710 100644
--- a/extensions/discord/src/approval-handler.runtime.ts
+++ b/extensions/discord/src/approval-handler.runtime.ts
@@ -19,11 +19,9 @@ import type {
PluginApprovalResolvedView,
} from "openclaw/plugin-sdk/approval-handler-runtime";
import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
+import type { ExecApprovalActionDescriptor } from "openclaw/plugin-sdk/approval-reply-runtime";
+import type { ExecApprovalDecision } from "openclaw/plugin-sdk/approval-runtime";
import type { DiscordExecApprovalConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import type {
- ExecApprovalActionDescriptor,
- ExecApprovalDecision,
-} from "openclaw/plugin-sdk/infra-runtime";
import { logDebug, logError, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import { shouldHandleDiscordApprovalRequest } from "./approval-shared.js";
import { isDiscordExecApprovalClientEnabled } from "./exec-approvals.js";
diff --git a/extensions/discord/src/approval-shared.ts b/extensions/discord/src/approval-shared.ts
index cd7773fb11f..6255402b8d7 100644
--- a/extensions/discord/src/approval-shared.ts
+++ b/extensions/discord/src/approval-shared.ts
@@ -1,6 +1,9 @@
import { doesApprovalRequestMatchChannelAccount } from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { DiscordExecApprovalConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import { resolveDiscordAccount } from "./accounts.js";
import {
isChannelExecApprovalClientEnabledFromConfig,
diff --git a/extensions/discord/src/client.proxy.test.ts b/extensions/discord/src/client.proxy.test.ts
index 43012f35501..8559936cc7d 100644
--- a/extensions/discord/src/client.proxy.test.ts
+++ b/extensions/discord/src/client.proxy.test.ts
@@ -7,9 +7,9 @@ import { createDiscordRequestClient } from "./proxy-request-client.js";
const makeProxyFetchMock = vi.hoisted(() => vi.fn());
-vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
- const actual = await vi.importActual(
- "openclaw/plugin-sdk/infra-runtime",
+vi.mock("openclaw/plugin-sdk/fetch-runtime", async () => {
+ const actual = await vi.importActual(
+ "openclaw/plugin-sdk/fetch-runtime",
);
makeProxyFetchMock.mockImplementation((proxyUrl: string) => {
if (proxyUrl === "bad-proxy") {
diff --git a/extensions/discord/src/monitor.test.ts b/extensions/discord/src/monitor.test.ts
index cfd280c9872..e2004f9fa36 100644
--- a/extensions/discord/src/monitor.test.ts
+++ b/extensions/discord/src/monitor.test.ts
@@ -905,7 +905,7 @@ const { enqueueSystemEventSpy, resolveAgentRouteMock } = vi.hoisted(() => ({
})),
}));
-const channelRuntimeModule = await import("openclaw/plugin-sdk/infra-runtime");
+const channelRuntimeModule = await import("openclaw/plugin-sdk/system-event-runtime");
vi.spyOn(channelRuntimeModule, "enqueueSystemEvent").mockImplementation(enqueueSystemEventSpy);
const routingModule = await import("openclaw/plugin-sdk/routing");
diff --git a/extensions/discord/src/monitor/agent-components.deps.runtime.ts b/extensions/discord/src/monitor/agent-components.deps.runtime.ts
index 5b4bdefbe9a..afc2faac192 100644
--- a/extensions/discord/src/monitor/agent-components.deps.runtime.ts
+++ b/extensions/discord/src/monitor/agent-components.deps.runtime.ts
@@ -1,2 +1,2 @@
-export { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
+export { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
export { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
diff --git a/extensions/discord/src/monitor/exec-approvals.ts b/extensions/discord/src/monitor/exec-approvals.ts
index ee21e716f44..d42f95d7c07 100644
--- a/extensions/discord/src/monitor/exec-approvals.ts
+++ b/extensions/discord/src/monitor/exec-approvals.ts
@@ -1,14 +1,14 @@
import { Button, type ButtonInteraction, type ComponentData } from "@buape/carbon";
import { ButtonStyle } from "discord-api-types/v10";
import { resolveApprovalOverGateway } from "openclaw/plugin-sdk/approval-gateway-runtime";
-import type { DiscordExecApprovalConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import type {
ExecApprovalDecision,
ExecApprovalRequest,
ExecApprovalResolved,
PluginApprovalRequest,
PluginApprovalResolved,
-} from "openclaw/plugin-sdk/infra-runtime";
+} from "openclaw/plugin-sdk/approval-runtime";
+import type { DiscordExecApprovalConfig, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
export { buildExecApprovalCustomId } from "../approval-handler.runtime.js";
import { getDiscordExecApprovalApprovers } from "../exec-approvals.js";
@@ -18,7 +18,7 @@ export type {
ExecApprovalResolved,
PluginApprovalRequest,
PluginApprovalResolved,
-} from "openclaw/plugin-sdk/infra-runtime";
+} from "openclaw/plugin-sdk/approval-runtime";
function decodeCustomIdValue(value: string): string {
try {
diff --git a/extensions/discord/src/monitor/listeners.ts b/extensions/discord/src/monitor/listeners.ts
index 5f2c8aa9c44..e92fc9bb81b 100644
--- a/extensions/discord/src/monitor/listeners.ts
+++ b/extensions/discord/src/monitor/listeners.ts
@@ -9,7 +9,6 @@ import {
type User,
} from "@buape/carbon";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import {
createSubsystemLogger,
@@ -21,6 +20,7 @@ import {
readStoreAllowFromForDmPolicy,
resolveDmGroupAccessWithLists,
} from "openclaw/plugin-sdk/security-runtime";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import {
isDiscordGroupAllowedByPolicy,
normalizeDiscordAllowList,
diff --git a/extensions/discord/src/monitor/message-handler.preflight.ts b/extensions/discord/src/monitor/message-handler.preflight.ts
index 4a71a626c96..9eeba12b3fd 100644
--- a/extensions/discord/src/monitor/message-handler.preflight.ts
+++ b/extensions/discord/src/monitor/message-handler.preflight.ts
@@ -1,6 +1,7 @@
import { ChannelType, MessageType, type Message, type User } from "@buape/carbon";
import { Routes, type APIMessage } from "discord-api-types/v10";
import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/allow-from";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import {
buildMentionRegexes,
implicitMentionKindWhen,
@@ -13,12 +14,12 @@ import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
import type { SessionBindingRecord } from "openclaw/plugin-sdk/conversation-binding-runtime";
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
-import { enqueueSystemEvent, recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import {
recordPendingHistoryEntryIfEnabled,
type HistoryEntry,
} from "openclaw/plugin-sdk/reply-history";
import { getChildLogger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { logDebug, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import { resolveDefaultDiscordAccountId } from "../accounts.js";
import { resolveDiscordConversationIdentity } from "../conversation-identity.js";
diff --git a/extensions/discord/src/proxy-fetch.ts b/extensions/discord/src/proxy-fetch.ts
index 4ff393bf770..430878edb5e 100644
--- a/extensions/discord/src/proxy-fetch.ts
+++ b/extensions/discord/src/proxy-fetch.ts
@@ -1,6 +1,6 @@
import { isIP } from "node:net";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import { makeProxyFetch } from "openclaw/plugin-sdk/infra-runtime";
+import { makeProxyFetch } from "openclaw/plugin-sdk/fetch-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
diff --git a/extensions/discord/src/send.components.ts b/extensions/discord/src/send.components.ts
index 382df013738..f24ecefbbf7 100644
--- a/extensions/discord/src/send.components.ts
+++ b/extensions/discord/src/send.components.ts
@@ -5,8 +5,8 @@ import {
type RequestClient,
} from "@buape/carbon";
import { ChannelType, Routes } from "discord-api-types/v10";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import type { MarkdownTableMode, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
import type { ChunkMode } from "openclaw/plugin-sdk/reply-chunking";
import { resolveDiscordAccount } from "./accounts.js";
diff --git a/extensions/discord/src/send.outbound.ts b/extensions/discord/src/send.outbound.ts
index 727e4c9d9cb..81068f4c69a 100644
--- a/extensions/discord/src/send.outbound.ts
+++ b/extensions/discord/src/send.outbound.ts
@@ -3,8 +3,8 @@ import fs from "node:fs/promises";
import path from "node:path";
import { serializePayload, type MessagePayloadObject, type RequestClient } from "@buape/carbon";
import { ChannelType, Routes } from "discord-api-types/v10";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import type { MarkdownTableMode, OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
import { maxBytesForKind } from "openclaw/plugin-sdk/media-runtime";
import { extensionForMime } from "openclaw/plugin-sdk/media-runtime";
diff --git a/extensions/discord/src/send.webhook.proxy.test.ts b/extensions/discord/src/send.webhook.proxy.test.ts
index 325dabdc075..7add863fa4f 100644
--- a/extensions/discord/src/send.webhook.proxy.test.ts
+++ b/extensions/discord/src/send.webhook.proxy.test.ts
@@ -4,9 +4,9 @@ import { sendWebhookMessageDiscord } from "./send.outbound.js";
const makeProxyFetchMock = vi.hoisted(() => vi.fn());
-vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
- const actual = await vi.importActual(
- "openclaw/plugin-sdk/infra-runtime",
+vi.mock("openclaw/plugin-sdk/fetch-runtime", async () => {
+ const actual = await vi.importActual(
+ "openclaw/plugin-sdk/fetch-runtime",
);
return {
...actual,
diff --git a/extensions/discord/src/test-support/provider.test-support.ts b/extensions/discord/src/test-support/provider.test-support.ts
index d44162b3182..b23b3644f74 100644
--- a/extensions/discord/src/test-support/provider.test-support.ts
+++ b/extensions/discord/src/test-support/provider.test-support.ts
@@ -426,9 +426,9 @@ vi.mock("openclaw/plugin-sdk/runtime-env", async () => {
};
});
-vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
- const actual = await vi.importActual(
- "openclaw/plugin-sdk/infra-runtime",
+vi.mock("openclaw/plugin-sdk/error-runtime", async () => {
+ const actual = await vi.importActual(
+ "openclaw/plugin-sdk/error-runtime",
);
return {
...actual,
diff --git a/extensions/imessage/src/monitor.watch-subscribe-retry.test.ts b/extensions/imessage/src/monitor.watch-subscribe-retry.test.ts
index b57d21ed455..197819e19f5 100644
--- a/extensions/imessage/src/monitor.watch-subscribe-retry.test.ts
+++ b/extensions/imessage/src/monitor.watch-subscribe-retry.test.ts
@@ -1,4 +1,4 @@
-import type { waitForTransportReady } from "openclaw/plugin-sdk/infra-runtime";
+import type { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { createIMessageRpcClient, IMessageRpcClient } from "./client.js";
import { monitorIMessageProvider } from "./monitor.js";
@@ -12,7 +12,7 @@ const attachIMessageMonitorAbortHandlerMock = vi.hoisted(() =>
vi.fn(() => () => {}),
);
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/transport-ready-runtime", () => ({
waitForTransportReady: waitForTransportReadyMock,
}));
diff --git a/extensions/imessage/src/monitor/monitor-provider.ts b/extensions/imessage/src/monitor/monitor-provider.ts
index e82a030388a..8671e1e454a 100644
--- a/extensions/imessage/src/monitor/monitor-provider.ts
+++ b/extensions/imessage/src/monitor/monitor-provider.ts
@@ -12,7 +12,6 @@ import {
} from "openclaw/plugin-sdk/conversation-runtime";
import { recordInboundSession } from "openclaw/plugin-sdk/conversation-runtime";
import { normalizeScpRemoteHost } from "openclaw/plugin-sdk/host-runtime";
-import { waitForTransportReady } from "openclaw/plugin-sdk/infra-runtime";
import { isInboundPathAllowed, kindFromMime } from "openclaw/plugin-sdk/media-runtime";
import {
clearHistoryEntriesIfEnabled,
@@ -32,6 +31,7 @@ import {
import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
import { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-runtime";
+import { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
import { resolveIMessageAccount } from "../accounts.js";
import { createIMessageRpcClient, type IMessageRpcClient } from "../client.js";
import { DEFAULT_IMESSAGE_PROBE_TIMEOUT_MS } from "../constants.js";
diff --git a/extensions/line/src/bot-message-context.ts b/extensions/line/src/bot-message-context.ts
index c8b4dd5e7ed..e4bf514d541 100644
--- a/extensions/line/src/bot-message-context.ts
+++ b/extensions/line/src/bot-message-context.ts
@@ -1,4 +1,5 @@
import type { webhook } from "@line/bot-sdk";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import {
formatInboundEnvelope,
formatLocationText,
@@ -13,7 +14,6 @@ import {
resolveConfiguredBindingRoute,
resolveRuntimeConversationBindingRoute,
} from "openclaw/plugin-sdk/conversation-runtime";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime";
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
diff --git a/extensions/line/src/send.test.ts b/extensions/line/src/send.test.ts
index dda51189844..d0bdfabcfb5 100644
--- a/extensions/line/src/send.test.ts
+++ b/extensions/line/src/send.test.ts
@@ -62,7 +62,7 @@ vi.mock("./channel-access-token.js", () => ({
resolveLineChannelAccessToken: resolveLineChannelAccessTokenMock,
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/channel-activity-runtime", () => ({
recordChannelActivity: recordChannelActivityMock,
}));
diff --git a/extensions/line/src/send.ts b/extensions/line/src/send.ts
index 2f05cd65925..2bac388a97b 100644
--- a/extensions/line/src/send.ts
+++ b/extensions/line/src/send.ts
@@ -1,6 +1,6 @@
import { messagingApi } from "@line/bot-sdk";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { resolveLineAccount } from "./accounts.js";
diff --git a/extensions/matrix/src/approval-handler.runtime.ts b/extensions/matrix/src/approval-handler.runtime.ts
index 223d44d2a0a..8184f364017 100644
--- a/extensions/matrix/src/approval-handler.runtime.ts
+++ b/extensions/matrix/src/approval-handler.runtime.ts
@@ -11,7 +11,10 @@ import {
type ExecApprovalReplyDecision,
} from "openclaw/plugin-sdk/approval-reply-runtime";
import { buildPluginApprovalResolvedReplyPayload } from "openclaw/plugin-sdk/approval-runtime";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import {
buildMatrixApprovalReactionHint,
listMatrixApprovalReactionBindings,
diff --git a/extensions/matrix/src/approval-native.ts b/extensions/matrix/src/approval-native.ts
index 7baeee0009c..326559075cf 100644
--- a/extensions/matrix/src/approval-native.ts
+++ b/extensions/matrix/src/approval-native.ts
@@ -9,8 +9,11 @@ import {
createChannelNativeOriginTargetResolver,
resolveApprovalRequestSessionConversation,
} from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { ChannelApprovalCapability } from "openclaw/plugin-sdk/channel-contract";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalStringifiedId,
diff --git a/extensions/matrix/src/channel-account-paths.ts b/extensions/matrix/src/channel-account-paths.ts
index 18c53f57bbf..0d1cdc9bf9d 100644
--- a/extensions/matrix/src/channel-account-paths.ts
+++ b/extensions/matrix/src/channel-account-paths.ts
@@ -1,6 +1,6 @@
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
-import type { PinnedDispatcherPolicy, SsrFPolicy } from "openclaw/plugin-sdk/infra-runtime";
+import type { PinnedDispatcherPolicy, SsrFPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
import { formatMatrixErrorMessage } from "./matrix/errors.js";
import type { MatrixProbe } from "./matrix/probe.js";
import type { CoreConfig } from "./types.js";
diff --git a/extensions/matrix/src/exec-approvals.ts b/extensions/matrix/src/exec-approvals.ts
index edda9e0c1d7..ca553c1a320 100644
--- a/extensions/matrix/src/exec-approvals.ts
+++ b/extensions/matrix/src/exec-approvals.ts
@@ -7,8 +7,11 @@ import {
matchesApprovalRequestFilters,
} from "openclaw/plugin-sdk/approval-client-runtime";
import { resolveApprovalRequestChannelAccountId } from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
diff --git a/extensions/matrix/src/matrix/probe.ts b/extensions/matrix/src/matrix/probe.ts
index 9cde883a2e4..b8f2a064083 100644
--- a/extensions/matrix/src/matrix/probe.ts
+++ b/extensions/matrix/src/matrix/probe.ts
@@ -1,4 +1,5 @@
-import { formatErrorMessage, type PinnedDispatcherPolicy } from "openclaw/plugin-sdk/infra-runtime";
+import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
+import type { PinnedDispatcherPolicy } from "openclaw/plugin-sdk/ssrf-dispatcher";
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
import type { SsrFPolicy } from "../runtime-api.js";
import type { BaseProbeResult } from "../runtime-api.js";
diff --git a/extensions/matrix/src/matrix/sdk/idb-persistence.test.ts b/extensions/matrix/src/matrix/sdk/idb-persistence.test.ts
index 97e2f9c99f1..8a342c4a9a5 100644
--- a/extensions/matrix/src/matrix/sdk/idb-persistence.test.ts
+++ b/extensions/matrix/src/matrix/sdk/idb-persistence.test.ts
@@ -5,7 +5,7 @@ import path from "node:path";
import {
drainFileLockStateForTest,
resetFileLockStateForTest,
-} from "openclaw/plugin-sdk/infra-runtime";
+} from "openclaw/plugin-sdk/file-lock";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { persistIdbToDisk, restoreIdbFromDisk } from "./idb-persistence.js";
import {
diff --git a/extensions/memory-core/src/dreaming-narrative.ts b/extensions/memory-core/src/dreaming-narrative.ts
index 4e7fa5a06bc..347af57c2aa 100644
--- a/extensions/memory-core/src/dreaming-narrative.ts
+++ b/extensions/memory-core/src/dreaming-narrative.ts
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
import type { Dirent } from "node:fs";
import fs from "node:fs/promises";
import path from "node:path";
+import { createAsyncLock } from "openclaw/plugin-sdk/async-lock-runtime";
import {
extractErrorCode,
formatErrorMessage,
@@ -10,7 +11,6 @@ import {
SUBAGENT_RUNTIME_REQUEST_SCOPE_ERROR_CODE,
} from "openclaw/plugin-sdk/error-runtime";
import { resolveGlobalMap } from "openclaw/plugin-sdk/global-singleton";
-import { createAsyncLock } from "openclaw/plugin-sdk/infra-runtime";
import { resolveStateDir } from "openclaw/plugin-sdk/memory-core-host-runtime-core";
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
import {
diff --git a/extensions/memory-core/src/dreaming.test.ts b/extensions/memory-core/src/dreaming.test.ts
index 125e8a5fcf2..6a05ea77c3f 100644
--- a/extensions/memory-core/src/dreaming.test.ts
+++ b/extensions/memory-core/src/dreaming.test.ts
@@ -1,7 +1,10 @@
import fs from "node:fs/promises";
import path from "node:path";
-import { enqueueSystemEvent, resetSystemEventsForTest } from "openclaw/plugin-sdk/infra-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/memory-core";
+import {
+ enqueueSystemEvent,
+ resetSystemEventsForTest,
+} from "openclaw/plugin-sdk/system-event-runtime";
import { afterEach, describe, expect, it, vi } from "vitest";
import {
__testing,
diff --git a/extensions/memory-core/src/dreaming.ts b/extensions/memory-core/src/dreaming.ts
index e985cad2244..3023b2e2533 100644
--- a/extensions/memory-core/src/dreaming.ts
+++ b/extensions/memory-core/src/dreaming.ts
@@ -1,5 +1,4 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import { peekSystemEventEntries } from "openclaw/plugin-sdk/infra-runtime";
import {
DEFAULT_MEMORY_DREAMING_FREQUENCY as DEFAULT_MEMORY_DREAMING_CRON_EXPR,
DEFAULT_MEMORY_DEEP_DREAMING_LIMIT as DEFAULT_MEMORY_DREAMING_LIMIT,
@@ -21,6 +20,7 @@ import {
resolveMemoryDreamingWorkspaces,
} from "openclaw/plugin-sdk/memory-core-host-status";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
+import { peekSystemEventEntries } from "openclaw/plugin-sdk/system-event-runtime";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
import { writeDeepDreamingReport } from "./dreaming-markdown.js";
import { generateAndAppendDreamNarrative, type NarrativePhaseData } from "./dreaming-narrative.js";
diff --git a/extensions/openshell/src/fs-bridge.ts b/extensions/openshell/src/fs-bridge.ts
index fbfa1c5ce68..d858b8c69b0 100644
--- a/extensions/openshell/src/fs-bridge.ts
+++ b/extensions/openshell/src/fs-bridge.ts
@@ -2,7 +2,7 @@ import fs from "node:fs";
import fsPromises from "node:fs/promises";
import type { FileHandle } from "node:fs/promises";
import path from "node:path";
-import { writeFileWithinRoot } from "openclaw/plugin-sdk/infra-runtime";
+import { writeFileWithinRoot } from "openclaw/plugin-sdk/file-access-runtime";
import type {
SandboxFsBridge,
SandboxFsStat,
diff --git a/extensions/qqbot/src/exec-approvals.ts b/extensions/qqbot/src/exec-approvals.ts
index 821cfb6741a..effedd16234 100644
--- a/extensions/qqbot/src/exec-approvals.ts
+++ b/extensions/qqbot/src/exec-approvals.ts
@@ -5,8 +5,11 @@ import {
matchesApprovalRequestFilters,
} from "openclaw/plugin-sdk/approval-client-runtime";
import { resolveApprovalRequestChannelAccountId } from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
import {
normalizeLowercaseStringOrEmpty,
diff --git a/extensions/signal/src/monitor.tool-result.test-harness.ts b/extensions/signal/src/monitor.tool-result.test-harness.ts
index a1eae592c74..0f569e5c83b 100644
--- a/extensions/signal/src/monitor.tool-result.test-harness.ts
+++ b/extensions/signal/src/monitor.tool-result.test-harness.ts
@@ -196,9 +196,9 @@ vi.mock("./daemon.js", async () => {
};
});
-vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
- const actual = await vi.importActual(
- "openclaw/plugin-sdk/infra-runtime",
+vi.mock("openclaw/plugin-sdk/system-event-runtime", async () => {
+ const actual = await vi.importActual(
+ "openclaw/plugin-sdk/system-event-runtime",
);
return {
...actual,
@@ -206,15 +206,18 @@ vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
enqueueSystemEventMock(...args);
return actual.enqueueSystemEvent(...args);
},
- waitForTransportReady: (...args: unknown[]) => waitForTransportReadyMock(...args),
};
});
+vi.mock("openclaw/plugin-sdk/transport-ready-runtime", () => ({
+ waitForTransportReady: (...args: unknown[]) => waitForTransportReadyMock(...args),
+}));
+
export function installSignalToolResultTestHooks() {
beforeEach(async () => {
const [{ resetInboundDedupe }, { resetSystemEventsForTest }] = await Promise.all([
import("openclaw/plugin-sdk/reply-runtime"),
- import("openclaw/plugin-sdk/infra-runtime"),
+ import("openclaw/plugin-sdk/system-event-runtime"),
]);
resetInboundDedupe();
config = {
diff --git a/extensions/signal/src/monitor.ts b/extensions/signal/src/monitor.ts
index ca037d473b9..985e370c7e3 100644
--- a/extensions/signal/src/monitor.ts
+++ b/extensions/signal/src/monitor.ts
@@ -1,6 +1,5 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import type { SignalReactionNotificationMode } from "openclaw/plugin-sdk/config-types";
-import { waitForTransportReady } from "openclaw/plugin-sdk/infra-runtime";
import {
detectMime,
estimateBase64DecodedBytes,
@@ -33,6 +32,7 @@ import {
normalizeOptionalString,
normalizeStringEntries,
} from "openclaw/plugin-sdk/text-runtime";
+import { waitForTransportReady } from "openclaw/plugin-sdk/transport-ready-runtime";
import { resolveSignalAccount } from "./accounts.js";
import { signalCheck, signalRpcRequest } from "./client.js";
import { formatSignalDaemonExit, spawnSignalDaemon, type SignalDaemonHandle } from "./daemon.js";
diff --git a/extensions/signal/src/monitor/event-handler.ts b/extensions/signal/src/monitor/event-handler.ts
index 747c6c68f4f..7b234832f2d 100644
--- a/extensions/signal/src/monitor/event-handler.ts
+++ b/extensions/signal/src/monitor/event-handler.ts
@@ -25,7 +25,6 @@ import {
toInternalMessageReceivedContext,
triggerInternalHook,
} from "openclaw/plugin-sdk/hook-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { kindFromMime } from "openclaw/plugin-sdk/media-runtime";
import {
buildPendingHistoryContextFromMap,
@@ -42,6 +41,7 @@ import {
resolvePinnedMainDmOwnerFromAllowlist,
} from "openclaw/plugin-sdk/security-runtime";
import { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { normalizeE164, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import {
formatSignalPairingIdLine,
diff --git a/extensions/slack/src/approval-handler.runtime.ts b/extensions/slack/src/approval-handler.runtime.ts
index d54173226ad..500385d3108 100644
--- a/extensions/slack/src/approval-handler.runtime.ts
+++ b/extensions/slack/src/approval-handler.runtime.ts
@@ -8,11 +8,9 @@ import type {
} from "openclaw/plugin-sdk/approval-handler-runtime";
import { createChannelApprovalNativeRuntimeAdapter } from "openclaw/plugin-sdk/approval-handler-runtime";
import { buildChannelApprovalNativeTargetKey } from "openclaw/plugin-sdk/approval-native-runtime";
+import { buildApprovalInteractiveReplyFromActionDescriptors } from "openclaw/plugin-sdk/approval-reply-runtime";
+import type { ExecApprovalRequest } from "openclaw/plugin-sdk/approval-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import {
- buildApprovalInteractiveReplyFromActionDescriptors,
- type ExecApprovalRequest,
-} from "openclaw/plugin-sdk/infra-runtime";
import { logError, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import {
isSlackExecApprovalClientEnabled,
diff --git a/extensions/slack/src/approval-native.ts b/extensions/slack/src/approval-native.ts
index 06b252b19ec..de22b19cb06 100644
--- a/extensions/slack/src/approval-native.ts
+++ b/extensions/slack/src/approval-native.ts
@@ -9,8 +9,11 @@ import {
createChannelNativeOriginTargetResolver,
resolveApprovalRequestSessionConversation,
} from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { ChannelApprovalCapability } from "openclaw/plugin-sdk/channel-contract";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
diff --git a/extensions/slack/src/client-options.ts b/extensions/slack/src/client-options.ts
index b69245bb63e..47848aed437 100644
--- a/extensions/slack/src/client-options.ts
+++ b/extensions/slack/src/client-options.ts
@@ -1,6 +1,6 @@
import type { RetryOptions, WebClientOptions } from "@slack/web-api";
import { HttpsProxyAgent } from "https-proxy-agent";
-import { resolveEnvHttpProxyUrl } from "openclaw/plugin-sdk/infra-runtime";
+import { resolveEnvHttpProxyUrl } from "openclaw/plugin-sdk/fetch-runtime";
export const SLACK_DEFAULT_RETRY_OPTIONS: RetryOptions = {
retries: 2,
diff --git a/extensions/slack/src/monitor/context.ts b/extensions/slack/src/monitor/context.ts
index 6b1b9a1ceb0..8cc542b6744 100644
--- a/extensions/slack/src/monitor/context.ts
+++ b/extensions/slack/src/monitor/context.ts
@@ -6,8 +6,8 @@ import type {
} from "openclaw/plugin-sdk/config-types";
import type { SessionScope } from "openclaw/plugin-sdk/config-types";
import type { DmPolicy, GroupPolicy } from "openclaw/plugin-sdk/config-types";
+import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { createDedupeCache } from "openclaw/plugin-sdk/infra-runtime";
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-history";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
diff --git a/extensions/slack/src/monitor/events/channels.test.ts b/extensions/slack/src/monitor/events/channels.test.ts
index 0bde970937e..32eaa13664c 100644
--- a/extensions/slack/src/monitor/events/channels.test.ts
+++ b/extensions/slack/src/monitor/events/channels.test.ts
@@ -4,10 +4,10 @@ const enqueueSystemEventMock = vi.hoisted(() => vi.fn());
let registerSlackChannelEvents: typeof import("./channels.js").registerSlackChannelEvents;
let createSlackSystemEventTestHarness: typeof import("./system-event-test-harness.js").createSlackSystemEventTestHarness;
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime", () => ({
enqueueSystemEvent: (...args: unknown[]) => enqueueSystemEventMock(...args),
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime.js", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime.js", () => ({
enqueueSystemEvent: (...args: unknown[]) => enqueueSystemEventMock(...args),
}));
vi.mock("openclaw/plugin-sdk/security-runtime", () => ({
diff --git a/extensions/slack/src/monitor/events/channels.ts b/extensions/slack/src/monitor/events/channels.ts
index 25d98ce8afd..ce719164202 100644
--- a/extensions/slack/src/monitor/events/channels.ts
+++ b/extensions/slack/src/monitor/events/channels.ts
@@ -2,9 +2,9 @@ import type { SlackEventMiddlewareArgs } from "@slack/bolt";
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
import { replaceConfigFile } from "openclaw/plugin-sdk/config-mutation";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
import { danger, warn } from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { migrateSlackChannelConfig } from "../../channel-migration.js";
import { resolveSlackChannelLabel } from "../channel-config.js";
import type { SlackMonitorContext } from "../context.js";
diff --git a/extensions/slack/src/monitor/events/interactions.block-actions.ts b/extensions/slack/src/monitor/events/interactions.block-actions.ts
index a4d800cd6ee..ff4c02cba98 100644
--- a/extensions/slack/src/monitor/events/interactions.block-actions.ts
+++ b/extensions/slack/src/monitor/events/interactions.block-actions.ts
@@ -1,10 +1,8 @@
import type { SlackActionMiddlewareArgs } from "@slack/bolt";
import type { Block, KnownBlock } from "@slack/web-api";
import { resolveApprovalOverGateway } from "openclaw/plugin-sdk/approval-gateway-runtime";
-import {
- enqueueSystemEvent,
- parseExecApprovalCommandText,
-} from "openclaw/plugin-sdk/infra-runtime";
+import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import {
isSlackExecApprovalApprover,
diff --git a/extensions/slack/src/monitor/events/interactions.modal.ts b/extensions/slack/src/monitor/events/interactions.modal.ts
index fab8a7aa5ba..71b71c34400 100644
--- a/extensions/slack/src/monitor/events/interactions.modal.ts
+++ b/extensions/slack/src/monitor/events/interactions.modal.ts
@@ -1,4 +1,4 @@
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { parseSlackModalPrivateMetadata } from "../../modal-metadata.js";
import { authorizeSlackSystemEventSender } from "../auth.js";
import type { SlackMonitorContext } from "../context.js";
diff --git a/extensions/slack/src/monitor/events/interactions.test.ts b/extensions/slack/src/monitor/events/interactions.test.ts
index 637bf3f357f..066ebb36914 100644
--- a/extensions/slack/src/monitor/events/interactions.test.ts
+++ b/extensions/slack/src/monitor/events/interactions.test.ts
@@ -16,8 +16,8 @@ const resolveApprovalOverGatewayMock = vi.hoisted(() =>
let registerSlackInteractionEvents: typeof import("./interactions.js").registerSlackInteractionEvents;
-vi.mock("openclaw/plugin-sdk/infra-runtime", async (importOriginal) => {
- const actual = await importOriginal();
+vi.mock("openclaw/plugin-sdk/system-event-runtime", async (importOriginal) => {
+ const actual = await importOriginal();
return {
...actual,
enqueueSystemEvent: (...args: unknown[]) => enqueueSystemEventMock(...args),
diff --git a/extensions/slack/src/monitor/events/members.test.ts b/extensions/slack/src/monitor/events/members.test.ts
index c13bc64a70b..61127b12b97 100644
--- a/extensions/slack/src/monitor/events/members.test.ts
+++ b/extensions/slack/src/monitor/events/members.test.ts
@@ -7,10 +7,10 @@ let registerSlackMemberEvents: typeof import("./members.js").registerSlackMember
let initSlackHarness: typeof import("./system-event-test-harness.js").createSlackSystemEventTestHarness;
type MemberOverrides = import("./system-event-test-harness.js").SlackSystemEventTestOverrides;
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime", () => ({
enqueueSystemEvent: (...args: unknown[]) => memberMocks.enqueue(...args),
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime.js", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime.js", () => ({
enqueueSystemEvent: (...args: unknown[]) => memberMocks.enqueue(...args),
}));
vi.mock("openclaw/plugin-sdk/security-runtime", () => ({
diff --git a/extensions/slack/src/monitor/events/members.ts b/extensions/slack/src/monitor/events/members.ts
index 1d5e12ce8bd..974baa714f9 100644
--- a/extensions/slack/src/monitor/events/members.ts
+++ b/extensions/slack/src/monitor/events/members.ts
@@ -1,7 +1,7 @@
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import type { SlackMonitorContext } from "../context.js";
import type { SlackMemberChannelEvent } from "../types.js";
import { authorizeAndResolveSlackSystemEventContext } from "./system-event-context.js";
diff --git a/extensions/slack/src/monitor/events/messages.test.ts b/extensions/slack/src/monitor/events/messages.test.ts
index 8b60e0a1cc5..4b0d407011e 100644
--- a/extensions/slack/src/monitor/events/messages.test.ts
+++ b/extensions/slack/src/monitor/events/messages.test.ts
@@ -9,10 +9,10 @@ const { messageQueueMock, messageAllowMock } = vi.hoisted(() => ({
messageAllowMock: vi.fn(),
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime", () => ({
enqueueSystemEvent: (...args: unknown[]) => messageQueueMock(...args),
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime.js", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime.js", () => ({
enqueueSystemEvent: (...args: unknown[]) => messageQueueMock(...args),
}));
vi.mock("openclaw/plugin-sdk/security-runtime", () => ({
diff --git a/extensions/slack/src/monitor/events/messages.ts b/extensions/slack/src/monitor/events/messages.ts
index 91e792f8c3e..ebdc7d35e69 100644
--- a/extensions/slack/src/monitor/events/messages.ts
+++ b/extensions/slack/src/monitor/events/messages.ts
@@ -1,7 +1,7 @@
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import type { SlackAppMentionEvent, SlackMessageEvent } from "../../types.js";
import { normalizeSlackChannelType } from "../channel-type.js";
import type { SlackMonitorContext } from "../context.js";
diff --git a/extensions/slack/src/monitor/events/pins.test.ts b/extensions/slack/src/monitor/events/pins.test.ts
index b08b3712bf7..a42c1988016 100644
--- a/extensions/slack/src/monitor/events/pins.test.ts
+++ b/extensions/slack/src/monitor/events/pins.test.ts
@@ -5,10 +5,10 @@ let registerSlackPinEvents: typeof import("./pins.js").registerSlackPinEvents;
let buildPinHarness: typeof import("./system-event-test-harness.js").createSlackSystemEventTestHarness;
type PinOverrides = import("./system-event-test-harness.js").SlackSystemEventTestOverrides;
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime", () => ({
enqueueSystemEvent: (...args: unknown[]) => pinEnqueueMock(...args),
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime.js", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime.js", () => ({
enqueueSystemEvent: (...args: unknown[]) => pinEnqueueMock(...args),
}));
vi.mock("openclaw/plugin-sdk/security-runtime", () => ({
diff --git a/extensions/slack/src/monitor/events/pins.ts b/extensions/slack/src/monitor/events/pins.ts
index 6708487fe78..65dacdcc24d 100644
--- a/extensions/slack/src/monitor/events/pins.ts
+++ b/extensions/slack/src/monitor/events/pins.ts
@@ -1,7 +1,7 @@
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import type { SlackMonitorContext } from "../context.js";
import type { SlackPinEvent } from "../types.js";
import { authorizeAndResolveSlackSystemEventContext } from "./system-event-context.js";
diff --git a/extensions/slack/src/monitor/events/reactions.test.ts b/extensions/slack/src/monitor/events/reactions.test.ts
index 4895b73e78c..6df579dee1d 100644
--- a/extensions/slack/src/monitor/events/reactions.test.ts
+++ b/extensions/slack/src/monitor/events/reactions.test.ts
@@ -6,10 +6,10 @@ let createSlackSystemEventTestHarness: typeof import("./system-event-test-harnes
type SlackSystemEventTestOverrides =
import("./system-event-test-harness.js").SlackSystemEventTestOverrides;
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime", () => ({
enqueueSystemEvent: (...args: unknown[]) => reactionQueueMock(...args),
}));
-vi.mock("openclaw/plugin-sdk/infra-runtime.js", () => ({
+vi.mock("openclaw/plugin-sdk/system-event-runtime.js", () => ({
enqueueSystemEvent: (...args: unknown[]) => reactionQueueMock(...args),
}));
vi.mock("openclaw/plugin-sdk/security-runtime", () => ({
diff --git a/extensions/slack/src/monitor/events/reactions.ts b/extensions/slack/src/monitor/events/reactions.ts
index 3cb57fedcf0..79840eb3df6 100644
--- a/extensions/slack/src/monitor/events/reactions.ts
+++ b/extensions/slack/src/monitor/events/reactions.ts
@@ -1,7 +1,7 @@
import type { SlackEventMiddlewareArgs } from "@slack/bolt";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { danger } from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import type { SlackMonitorContext } from "../context.js";
import type { SlackReactionEvent } from "../types.js";
import { authorizeAndResolveSlackSystemEventContext } from "./system-event-context.js";
diff --git a/extensions/slack/src/monitor/external-arg-menu-store.ts b/extensions/slack/src/monitor/external-arg-menu-store.ts
index c3327ee88c6..76b692318c5 100644
--- a/extensions/slack/src/monitor/external-arg-menu-store.ts
+++ b/extensions/slack/src/monitor/external-arg-menu-store.ts
@@ -1,4 +1,4 @@
-import { generateSecureToken } from "openclaw/plugin-sdk/infra-runtime";
+import { generateSecureToken } from "openclaw/plugin-sdk/secure-random-runtime";
const SLACK_EXTERNAL_ARG_MENU_TOKEN_BYTES = 18;
const SLACK_EXTERNAL_ARG_MENU_TOKEN_LENGTH = Math.ceil(
diff --git a/extensions/slack/src/monitor/media.runtime.ts b/extensions/slack/src/monitor/media.runtime.ts
index fd4d2a7d5e2..457db077373 100644
--- a/extensions/slack/src/monitor/media.runtime.ts
+++ b/extensions/slack/src/monitor/media.runtime.ts
@@ -1,4 +1,4 @@
-export { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/infra-runtime";
+export { fetchWithRuntimeDispatcher } from "openclaw/plugin-sdk/runtime-fetch";
export type { FetchLike, SavedMedia } from "openclaw/plugin-sdk/media-runtime";
export { fetchRemoteMedia, saveMediaBuffer } from "openclaw/plugin-sdk/media-runtime";
export { logVerbose } from "openclaw/plugin-sdk/runtime-env";
diff --git a/extensions/slack/src/monitor/message-handler/prepare-content.ts b/extensions/slack/src/monitor/message-handler/prepare-content.ts
index 47079dd65ba..7e07b6afdc6 100644
--- a/extensions/slack/src/monitor/message-handler/prepare-content.ts
+++ b/extensions/slack/src/monitor/message-handler/prepare-content.ts
@@ -1,4 +1,4 @@
-import { runTasksWithConcurrency } from "openclaw/plugin-sdk/infra-runtime";
+import { runTasksWithConcurrency } from "openclaw/plugin-sdk/concurrency-runtime";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import { formatSlackFileReference } from "../../file-reference.js";
diff --git a/extensions/slack/src/monitor/message-handler/prepare.ts b/extensions/slack/src/monitor/message-handler/prepare.ts
index 0fd87538907..06327a6a790 100644
--- a/extensions/slack/src/monitor/message-handler/prepare.ts
+++ b/extensions/slack/src/monitor/message-handler/prepare.ts
@@ -16,7 +16,6 @@ import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-gating";
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/command-surface";
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-dispatch-runtime";
import {
buildPendingHistoryContextFromMap,
@@ -25,6 +24,7 @@ import {
import type { FinalizedMsgContext } from "openclaw/plugin-sdk/reply-runtime";
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
import { resolvePinnedMainDmOwnerFromAllowlist } from "openclaw/plugin-sdk/security-runtime";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
diff --git a/extensions/slack/src/sent-thread-cache.ts b/extensions/slack/src/sent-thread-cache.ts
index f09732345f1..0e896283fb4 100644
--- a/extensions/slack/src/sent-thread-cache.ts
+++ b/extensions/slack/src/sent-thread-cache.ts
@@ -1,4 +1,4 @@
-import { resolveGlobalDedupeCache } from "openclaw/plugin-sdk/infra-runtime";
+import { resolveGlobalDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
/**
* In-memory cache of Slack threads the bot has participated in.
diff --git a/extensions/telegram/src/approval-handler.runtime.ts b/extensions/telegram/src/approval-handler.runtime.ts
index 2ef9fef9e1b..1ae907abf58 100644
--- a/extensions/telegram/src/approval-handler.runtime.ts
+++ b/extensions/telegram/src/approval-handler.runtime.ts
@@ -8,10 +8,12 @@ import { buildPluginApprovalPendingReplyPayload } from "openclaw/plugin-sdk/appr
import {
buildApprovalInteractiveReplyFromActionDescriptors,
buildExecApprovalPendingReplyPayload,
- type ExecApprovalPendingReplyParams,
- type ExecApprovalRequest,
- type PluginApprovalRequest,
-} from "openclaw/plugin-sdk/infra-runtime";
+} from "openclaw/plugin-sdk/approval-reply-runtime";
+import type { ExecApprovalPendingReplyParams } from "openclaw/plugin-sdk/approval-reply-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
import { resolveTelegramInlineButtons } from "./button-types.js";
diff --git a/extensions/telegram/src/approval-native.ts b/extensions/telegram/src/approval-native.ts
index 57576b19224..56a0a82a5e4 100644
--- a/extensions/telegram/src/approval-native.ts
+++ b/extensions/telegram/src/approval-native.ts
@@ -8,8 +8,11 @@ import {
createChannelApproverDmTargetResolver,
createChannelNativeOriginTargetResolver,
} from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { ChannelApprovalCapability } from "openclaw/plugin-sdk/channel-contract";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import {
normalizeLowercaseStringOrEmpty,
normalizeOptionalString,
diff --git a/extensions/telegram/src/bot-deps.ts b/extensions/telegram/src/bot-deps.ts
index fc60f12fc4d..ef052594462 100644
--- a/extensions/telegram/src/bot-deps.ts
+++ b/extensions/telegram/src/bot-deps.ts
@@ -1,13 +1,13 @@
import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
import { readChannelAllowFromStore } from "openclaw/plugin-sdk/conversation-runtime";
import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
import { buildModelsProviderData } from "openclaw/plugin-sdk/models-provider-runtime";
import { dispatchReplyWithBufferedBlockDispatcher } from "openclaw/plugin-sdk/reply-dispatch-runtime";
import { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
import { resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
import { loadSessionStore } from "openclaw/plugin-sdk/session-store-runtime";
import { listSkillCommandsForAgents } from "openclaw/plugin-sdk/skill-commands-runtime";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
import { syncTelegramMenuCommands } from "./bot-native-command-menu.js";
import { deliverReplies, emitInternalMessageSentHook } from "./bot/delivery.js";
diff --git a/extensions/telegram/src/bot-handlers.runtime.ts b/extensions/telegram/src/bot-handlers.runtime.ts
index 7c533b9485e..383728497ca 100644
--- a/extensions/telegram/src/bot-handlers.runtime.ts
+++ b/extensions/telegram/src/bot-handlers.runtime.ts
@@ -1,4 +1,5 @@
import type { Message, ReactionTypeEmoji } from "@grammyjs/types";
+import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-helpers";
import { shouldDebounceTextInbound } from "openclaw/plugin-sdk/channel-inbound";
import {
@@ -19,7 +20,6 @@ import {
parsePluginBindingApprovalCustomId,
resolvePluginConversationBindingApproval,
} from "openclaw/plugin-sdk/conversation-runtime";
-import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/infra-runtime";
import { applyModelOverrideToSessionEntry } from "openclaw/plugin-sdk/model-session-runtime";
import { formatModelsAvailableHeader } from "openclaw/plugin-sdk/models-provider-runtime";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
diff --git a/extensions/telegram/src/bot-message-context.runtime.ts b/extensions/telegram/src/bot-message-context.runtime.ts
index 197ad8bdf37..de4b2aeb1f1 100644
--- a/extensions/telegram/src/bot-message-context.runtime.ts
+++ b/extensions/telegram/src/bot-message-context.runtime.ts
@@ -1,4 +1,4 @@
export { createStatusReactionController } from "openclaw/plugin-sdk/channel-feedback";
-export { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
+export { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
export { getRuntimeConfig } from "openclaw/plugin-sdk/runtime-config-snapshot";
export { ensureConfiguredBindingRouteReady } from "openclaw/plugin-sdk/conversation-runtime";
diff --git a/extensions/telegram/src/bot-updates.ts b/extensions/telegram/src/bot-updates.ts
index 68d714e21e2..696d3affa15 100644
--- a/extensions/telegram/src/bot-updates.ts
+++ b/extensions/telegram/src/bot-updates.ts
@@ -1,5 +1,5 @@
import type { Message } from "@grammyjs/types";
-import { createDedupeCache } from "openclaw/plugin-sdk/infra-runtime";
+import { createDedupeCache } from "openclaw/plugin-sdk/dedupe-runtime";
import type { TelegramContext } from "./bot/types.js";
const MEDIA_GROUP_TIMEOUT_MS = 500;
diff --git a/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts b/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts
index 2d6ba93c66d..05618177af3 100644
--- a/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts
+++ b/extensions/telegram/src/bot/delivery.resolve-media-retry.test.ts
@@ -8,7 +8,7 @@ const saveMediaBuffer = vi.fn();
const fetchRemoteMedia = vi.fn();
const readFileWithinRoot = vi.fn();
-vi.mock("openclaw/plugin-sdk/infra-runtime", () => ({
+vi.mock("openclaw/plugin-sdk/file-access-runtime", () => ({
readFileWithinRoot: (...args: unknown[]) => readFileWithinRoot(...args),
}));
diff --git a/extensions/telegram/src/bot/delivery.resolve-media.ts b/extensions/telegram/src/bot/delivery.resolve-media.ts
index 174831bd392..84b54d9a1f5 100644
--- a/extensions/telegram/src/bot/delivery.resolve-media.ts
+++ b/extensions/telegram/src/bot/delivery.resolve-media.ts
@@ -1,6 +1,6 @@
import path from "node:path";
import { GrammyError } from "grammy";
-import { readFileWithinRoot } from "openclaw/plugin-sdk/infra-runtime";
+import { readFileWithinRoot } from "openclaw/plugin-sdk/file-access-runtime";
import type { TelegramTransport } from "../fetch.js";
import { cacheSticker, getCachedSticker } from "../sticker-cache.js";
import {
diff --git a/extensions/telegram/src/exec-approval-forwarding.ts b/extensions/telegram/src/exec-approval-forwarding.ts
index 91b5a6e3751..03b5e91ec0c 100644
--- a/extensions/telegram/src/exec-approval-forwarding.ts
+++ b/extensions/telegram/src/exec-approval-forwarding.ts
@@ -3,8 +3,8 @@ import {
resolveExecApprovalRequestAllowedDecisions,
resolveExecApprovalCommandDisplay,
} from "openclaw/plugin-sdk/approval-reply-runtime";
+import type { ExecApprovalRequest } from "openclaw/plugin-sdk/approval-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import type { ExecApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import { normalizeMessageChannel } from "openclaw/plugin-sdk/routing";
import { isTelegramExecApprovalClientEnabled } from "./exec-approvals.js";
diff --git a/extensions/telegram/src/exec-approval-resolver.test.ts b/extensions/telegram/src/exec-approval-resolver.test.ts
index 5f73feeebe0..fe847e48121 100644
--- a/extensions/telegram/src/exec-approval-resolver.test.ts
+++ b/extensions/telegram/src/exec-approval-resolver.test.ts
@@ -1,4 +1,4 @@
-import type { ExecApprovalReplyDecision } from "openclaw/plugin-sdk/infra-runtime";
+import type { ExecApprovalReplyDecision } from "openclaw/plugin-sdk/approval-reply-runtime";
import { beforeEach, describe, expect, it, vi } from "vitest";
const approvalGatewayRuntimeHoisted = vi.hoisted(() => ({
diff --git a/extensions/telegram/src/exec-approval-resolver.ts b/extensions/telegram/src/exec-approval-resolver.ts
index e8a36728c1c..c8874f94e98 100644
--- a/extensions/telegram/src/exec-approval-resolver.ts
+++ b/extensions/telegram/src/exec-approval-resolver.ts
@@ -1,6 +1,6 @@
import { resolveApprovalOverGateway } from "openclaw/plugin-sdk/approval-gateway-runtime";
+import type { ExecApprovalReplyDecision } from "openclaw/plugin-sdk/approval-reply-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
-import type { ExecApprovalReplyDecision } from "openclaw/plugin-sdk/infra-runtime";
export type ResolveTelegramExecApprovalParams = {
cfg: OpenClawConfig;
diff --git a/extensions/telegram/src/exec-approvals.ts b/extensions/telegram/src/exec-approvals.ts
index ba059a5cc1d..187f59840c8 100644
--- a/extensions/telegram/src/exec-approvals.ts
+++ b/extensions/telegram/src/exec-approvals.ts
@@ -6,9 +6,12 @@ import {
matchesApprovalRequestFilters,
} from "openclaw/plugin-sdk/approval-client-runtime";
import { resolveApprovalRequestChannelAccountId } from "openclaw/plugin-sdk/approval-native-runtime";
+import type {
+ ExecApprovalRequest,
+ PluginApprovalRequest,
+} from "openclaw/plugin-sdk/approval-runtime";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
import type { TelegramExecApprovalConfig } from "openclaw/plugin-sdk/config-types";
-import type { ExecApprovalRequest, PluginApprovalRequest } from "openclaw/plugin-sdk/infra-runtime";
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
import {
diff --git a/extensions/telegram/src/send.ts b/extensions/telegram/src/send.ts
index 7d13eadd71b..a4b4b7493d0 100644
--- a/extensions/telegram/src/send.ts
+++ b/extensions/telegram/src/send.ts
@@ -1,9 +1,9 @@
import type { ReactionType, ReactionTypeEmoji } from "@grammyjs/types";
import * as grammy from "grammy";
import { type ApiClientOptions, Bot, HttpError } from "grammy";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import { isDiagnosticFlagEnabled } from "openclaw/plugin-sdk/diagnostic-runtime";
import { formatUncaughtError } from "openclaw/plugin-sdk/error-runtime";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { createTelegramRetryRunner, type RetryConfig } from "openclaw/plugin-sdk/retry-runtime";
import { createSubsystemLogger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { formatErrorMessage } from "openclaw/plugin-sdk/ssrf-runtime";
diff --git a/extensions/telegram/src/sequential-key.ts b/extensions/telegram/src/sequential-key.ts
index 14be5fda490..0d78e3c6b4a 100644
--- a/extensions/telegram/src/sequential-key.ts
+++ b/extensions/telegram/src/sequential-key.ts
@@ -1,4 +1,5 @@
import type { Message, UserFromGetMe } from "@grammyjs/types";
+import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/approval-reply-runtime";
import {
listChatCommands,
maybeResolveTextAlias,
@@ -8,7 +9,6 @@ import {
isAbortRequestText,
isBtwRequestText,
} from "openclaw/plugin-sdk/command-primitives-runtime";
-import { parseExecApprovalCommandText } from "openclaw/plugin-sdk/infra-runtime";
import { resolveTelegramForumThreadId } from "./bot/helpers.js";
export type TelegramSequentialKeyContext = {
diff --git a/extensions/whatsapp/src/auto-reply/heartbeat-runner.runtime.ts b/extensions/whatsapp/src/auto-reply/heartbeat-runner.runtime.ts
index fe05639ec3c..ed8cf20c642 100644
--- a/extensions/whatsapp/src/auto-reply/heartbeat-runner.runtime.ts
+++ b/extensions/whatsapp/src/auto-reply/heartbeat-runner.runtime.ts
@@ -11,7 +11,7 @@ export {
emitHeartbeatEvent,
resolveHeartbeatVisibility,
resolveIndicatorType,
-} from "openclaw/plugin-sdk/infra-runtime";
+} from "openclaw/plugin-sdk/heartbeat-runtime";
export {
hasOutboundReplyContent,
resolveSendableOutboundReplyParts,
diff --git a/extensions/whatsapp/src/auto-reply/monitor.ts b/extensions/whatsapp/src/auto-reply/monitor.ts
index aa0e7c59f36..2811b8c3a41 100644
--- a/extensions/whatsapp/src/auto-reply/monitor.ts
+++ b/extensions/whatsapp/src/auto-reply/monitor.ts
@@ -2,8 +2,7 @@ import { resolveAccountEntry } from "openclaw/plugin-sdk/account-core";
import { resolveInboundDebounceMs } from "openclaw/plugin-sdk/channel-inbound-debounce";
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
-import { drainPendingDeliveries } from "openclaw/plugin-sdk/infra-runtime";
-import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
+import { drainPendingDeliveries } from "openclaw/plugin-sdk/delivery-queue-runtime";
import { DEFAULT_GROUP_HISTORY_LIMIT } from "openclaw/plugin-sdk/reply-history";
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
@@ -14,6 +13,7 @@ import {
formatDurationPrecise,
type RuntimeEnv,
} from "openclaw/plugin-sdk/runtime-env";
+import { enqueueSystemEvent } from "openclaw/plugin-sdk/system-event-runtime";
import { resolveWhatsAppAccount, resolveWhatsAppMediaMaxBytes } from "../accounts.js";
import { WHATSAPP_AUTH_UNSTABLE_CODE, WhatsAppAuthUnstableError } from "../auth-store.js";
import {
diff --git a/extensions/whatsapp/src/inbound/monitor.ts b/extensions/whatsapp/src/inbound/monitor.ts
index 1926904e19d..4b193854091 100644
--- a/extensions/whatsapp/src/inbound/monitor.ts
+++ b/extensions/whatsapp/src/inbound/monitor.ts
@@ -5,9 +5,9 @@ import type {
WAMessage,
WASocket,
} from "@whiskeysockets/baileys";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import { formatLocationText } from "openclaw/plugin-sdk/channel-inbound";
import { createInboundDebouncer } from "openclaw/plugin-sdk/channel-inbound-debounce";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
import { defaultRuntime } from "openclaw/plugin-sdk/runtime-env";
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
import { getChildLogger } from "openclaw/plugin-sdk/text-runtime";
diff --git a/extensions/whatsapp/src/inbound/send-api.test.ts b/extensions/whatsapp/src/inbound/send-api.test.ts
index b76779bc78b..af84691a3dc 100644
--- a/extensions/whatsapp/src/inbound/send-api.test.ts
+++ b/extensions/whatsapp/src/inbound/send-api.test.ts
@@ -3,10 +3,10 @@ import { createWebSendApi } from "./send-api.js";
const recordChannelActivity = vi.hoisted(() => vi.fn());
-vi.mock("openclaw/plugin-sdk/infra-runtime", async () => {
- const actual = await vi.importActual(
- "openclaw/plugin-sdk/infra-runtime",
- );
+vi.mock("openclaw/plugin-sdk/channel-activity-runtime", async () => {
+ const actual = await vi.importActual<
+ typeof import("openclaw/plugin-sdk/channel-activity-runtime")
+ >("openclaw/plugin-sdk/channel-activity-runtime");
return {
...actual,
recordChannelActivity: (...args: unknown[]) => recordChannelActivity(...args),
diff --git a/extensions/whatsapp/src/inbound/send-api.ts b/extensions/whatsapp/src/inbound/send-api.ts
index 69aefcf9f8e..8b39c193213 100644
--- a/extensions/whatsapp/src/inbound/send-api.ts
+++ b/extensions/whatsapp/src/inbound/send-api.ts
@@ -3,7 +3,7 @@ import type {
MiscMessageGenerationOptions,
WAPresence,
} from "@whiskeysockets/baileys";
-import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
+import { recordChannelActivity } from "openclaw/plugin-sdk/channel-activity-runtime";
import { buildQuotedMessageOptions } from "../quoted-message.js";
import { toWhatsappJid } from "../text-runtime.js";
import type { ActiveWebSendOptions } from "./types.js";
diff --git a/extensions/whatsapp/src/session.ts b/extensions/whatsapp/src/session.ts
index bee5f91521e..bd7a53d0931 100644
--- a/extensions/whatsapp/src/session.ts
+++ b/extensions/whatsapp/src/session.ts
@@ -7,7 +7,7 @@ import { VERSION } from "openclaw/plugin-sdk/cli-runtime";
import {
resolveEnvHttpProxyUrl,
shouldUseEnvHttpProxyForUrl,
-} from "openclaw/plugin-sdk/infra-runtime";
+} from "openclaw/plugin-sdk/fetch-runtime";
import { danger, success } from "openclaw/plugin-sdk/runtime-env";
import { getChildLogger, toPinoLikeLogger } from "openclaw/plugin-sdk/runtime-env";
import { ensureDir, resolveUserPath } from "openclaw/plugin-sdk/text-runtime";
diff --git a/package.json b/package.json
index c05cee34e2e..3c792daf730 100644
--- a/package.json
+++ b/package.json
@@ -274,6 +274,50 @@
"types": "./dist/plugin-sdk/poll-runtime.d.ts",
"default": "./dist/plugin-sdk/poll-runtime.js"
},
+ "./plugin-sdk/async-lock-runtime": {
+ "types": "./dist/plugin-sdk/async-lock-runtime.d.ts",
+ "default": "./dist/plugin-sdk/async-lock-runtime.js"
+ },
+ "./plugin-sdk/channel-activity-runtime": {
+ "types": "./dist/plugin-sdk/channel-activity-runtime.d.ts",
+ "default": "./dist/plugin-sdk/channel-activity-runtime.js"
+ },
+ "./plugin-sdk/concurrency-runtime": {
+ "types": "./dist/plugin-sdk/concurrency-runtime.d.ts",
+ "default": "./dist/plugin-sdk/concurrency-runtime.js"
+ },
+ "./plugin-sdk/dedupe-runtime": {
+ "types": "./dist/plugin-sdk/dedupe-runtime.d.ts",
+ "default": "./dist/plugin-sdk/dedupe-runtime.js"
+ },
+ "./plugin-sdk/delivery-queue-runtime": {
+ "types": "./dist/plugin-sdk/delivery-queue-runtime.d.ts",
+ "default": "./dist/plugin-sdk/delivery-queue-runtime.js"
+ },
+ "./plugin-sdk/file-access-runtime": {
+ "types": "./dist/plugin-sdk/file-access-runtime.d.ts",
+ "default": "./dist/plugin-sdk/file-access-runtime.js"
+ },
+ "./plugin-sdk/heartbeat-runtime": {
+ "types": "./dist/plugin-sdk/heartbeat-runtime.d.ts",
+ "default": "./dist/plugin-sdk/heartbeat-runtime.js"
+ },
+ "./plugin-sdk/number-runtime": {
+ "types": "./dist/plugin-sdk/number-runtime.d.ts",
+ "default": "./dist/plugin-sdk/number-runtime.js"
+ },
+ "./plugin-sdk/secure-random-runtime": {
+ "types": "./dist/plugin-sdk/secure-random-runtime.d.ts",
+ "default": "./dist/plugin-sdk/secure-random-runtime.js"
+ },
+ "./plugin-sdk/system-event-runtime": {
+ "types": "./dist/plugin-sdk/system-event-runtime.d.ts",
+ "default": "./dist/plugin-sdk/system-event-runtime.js"
+ },
+ "./plugin-sdk/transport-ready-runtime": {
+ "types": "./dist/plugin-sdk/transport-ready-runtime.d.ts",
+ "default": "./dist/plugin-sdk/transport-ready-runtime.js"
+ },
"./plugin-sdk/infra-runtime": {
"types": "./dist/plugin-sdk/infra-runtime.d.ts",
"default": "./dist/plugin-sdk/infra-runtime.js"
diff --git a/packages/plugin-sdk/package.json b/packages/plugin-sdk/package.json
index 72f1feabb2a..2c82f027859 100644
--- a/packages/plugin-sdk/package.json
+++ b/packages/plugin-sdk/package.json
@@ -12,6 +12,50 @@
"types": "./dist/src/plugin-sdk/acp-runtime.d.ts",
"default": "./src/acp-runtime.ts"
},
+ "./async-lock-runtime": {
+ "types": "./dist/src/plugin-sdk/async-lock-runtime.d.ts",
+ "default": "./src/async-lock-runtime.ts"
+ },
+ "./channel-activity-runtime": {
+ "types": "./dist/src/plugin-sdk/channel-activity-runtime.d.ts",
+ "default": "./src/channel-activity-runtime.ts"
+ },
+ "./concurrency-runtime": {
+ "types": "./dist/src/plugin-sdk/concurrency-runtime.d.ts",
+ "default": "./src/concurrency-runtime.ts"
+ },
+ "./dedupe-runtime": {
+ "types": "./dist/src/plugin-sdk/dedupe-runtime.d.ts",
+ "default": "./src/dedupe-runtime.ts"
+ },
+ "./delivery-queue-runtime": {
+ "types": "./dist/src/plugin-sdk/delivery-queue-runtime.d.ts",
+ "default": "./src/delivery-queue-runtime.ts"
+ },
+ "./file-access-runtime": {
+ "types": "./dist/src/plugin-sdk/file-access-runtime.d.ts",
+ "default": "./src/file-access-runtime.ts"
+ },
+ "./heartbeat-runtime": {
+ "types": "./dist/src/plugin-sdk/heartbeat-runtime.d.ts",
+ "default": "./src/heartbeat-runtime.ts"
+ },
+ "./number-runtime": {
+ "types": "./dist/src/plugin-sdk/number-runtime.d.ts",
+ "default": "./src/number-runtime.ts"
+ },
+ "./secure-random-runtime": {
+ "types": "./dist/src/plugin-sdk/secure-random-runtime.d.ts",
+ "default": "./src/secure-random-runtime.ts"
+ },
+ "./system-event-runtime": {
+ "types": "./dist/src/plugin-sdk/system-event-runtime.d.ts",
+ "default": "./src/system-event-runtime.ts"
+ },
+ "./transport-ready-runtime": {
+ "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"
diff --git a/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts b/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts
index 0c10cf4b6c7..880ef262ec8 100644
--- a/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts
+++ b/scripts/check-no-monolithic-plugin-sdk-entry-imports.ts
@@ -16,6 +16,10 @@ const LEGACY_BROAD_SUBPATH_PATTERNS = [
pattern: /["']openclaw\/plugin-sdk\/config-runtime["']/,
label: "openclaw/plugin-sdk/config-runtime",
},
+ {
+ pattern: /["']openclaw\/plugin-sdk\/infra-runtime["']/,
+ label: "openclaw/plugin-sdk/infra-runtime",
+ },
] as const;
function hasMonolithicRootImport(content: string): boolean {
diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json
index 62b4df85330..d362fa059d8 100644
--- a/scripts/lib/plugin-sdk-entrypoints.json
+++ b/scripts/lib/plugin-sdk-entrypoints.json
@@ -52,6 +52,17 @@
"outbound-send-deps",
"outbound-runtime",
"poll-runtime",
+ "async-lock-runtime",
+ "channel-activity-runtime",
+ "concurrency-runtime",
+ "dedupe-runtime",
+ "delivery-queue-runtime",
+ "file-access-runtime",
+ "heartbeat-runtime",
+ "number-runtime",
+ "secure-random-runtime",
+ "system-event-runtime",
+ "transport-ready-runtime",
"infra-runtime",
"runtime-config-snapshot",
"runtime-group-policy",
diff --git a/src/plugin-sdk/approval-reply-runtime.ts b/src/plugin-sdk/approval-reply-runtime.ts
index cb3e1513420..d3216df45de 100644
--- a/src/plugin-sdk/approval-reply-runtime.ts
+++ b/src/plugin-sdk/approval-reply-runtime.ts
@@ -4,6 +4,7 @@ export {
buildExecApprovalPendingReplyPayload,
getExecApprovalApproverDmNoticeText,
getExecApprovalReplyMetadata,
+ parseExecApprovalCommandText,
type ExecApprovalActionDescriptor,
type ExecApprovalPendingReplyParams,
type ExecApprovalReplyDecision,
diff --git a/src/plugin-sdk/async-lock-runtime.ts b/src/plugin-sdk/async-lock-runtime.ts
new file mode 100644
index 00000000000..2370e7ce74d
--- /dev/null
+++ b/src/plugin-sdk/async-lock-runtime.ts
@@ -0,0 +1,3 @@
+// Process-local async lock helper for small runtime state files.
+
+export { createAsyncLock } from "../infra/json-files.js";
diff --git a/src/plugin-sdk/channel-activity-runtime.ts b/src/plugin-sdk/channel-activity-runtime.ts
new file mode 100644
index 00000000000..9744d649e8c
--- /dev/null
+++ b/src/plugin-sdk/channel-activity-runtime.ts
@@ -0,0 +1,3 @@
+// Channel activity telemetry helpers without the broad infra-runtime barrel.
+
+export { recordChannelActivity } from "../infra/channel-activity.js";
diff --git a/src/plugin-sdk/concurrency-runtime.ts b/src/plugin-sdk/concurrency-runtime.ts
new file mode 100644
index 00000000000..06c908b92cd
--- /dev/null
+++ b/src/plugin-sdk/concurrency-runtime.ts
@@ -0,0 +1,3 @@
+// Small concurrency helpers for plugin runtime work.
+
+export { runTasksWithConcurrency } from "../utils/run-with-concurrency.js";
diff --git a/src/plugin-sdk/dedupe-runtime.ts b/src/plugin-sdk/dedupe-runtime.ts
new file mode 100644
index 00000000000..e5a11624247
--- /dev/null
+++ b/src/plugin-sdk/dedupe-runtime.ts
@@ -0,0 +1,3 @@
+// In-memory dedupe helpers for plugin runtime hot paths.
+
+export { createDedupeCache, resolveGlobalDedupeCache } from "../infra/dedupe.js";
diff --git a/src/plugin-sdk/infra-runtime.test.ts b/src/plugin-sdk/delivery-queue-runtime.test.ts
similarity index 84%
rename from src/plugin-sdk/infra-runtime.test.ts
rename to src/plugin-sdk/delivery-queue-runtime.test.ts
index ff16efabfff..2c8dac0602d 100644
--- a/src/plugin-sdk/infra-runtime.test.ts
+++ b/src/plugin-sdk/delivery-queue-runtime.test.ts
@@ -13,9 +13,9 @@ vi.mock("../infra/outbound/deliver-runtime.js", () => ({
deliverOutboundPayloads: mocks.deliverOutboundPayloads,
}));
-type InfraRuntimeModule = typeof import("./infra-runtime.js");
+type DeliveryQueueRuntimeModule = typeof import("./delivery-queue-runtime.js");
-let drainPendingDeliveries: InfraRuntimeModule["drainPendingDeliveries"];
+let drainPendingDeliveries: DeliveryQueueRuntimeModule["drainPendingDeliveries"];
const log = {
info: vi.fn(),
@@ -24,7 +24,7 @@ const log = {
};
beforeAll(async () => {
- ({ drainPendingDeliveries } = await import("./infra-runtime.js"));
+ ({ drainPendingDeliveries } = await import("./delivery-queue-runtime.js"));
});
beforeEach(() => {
@@ -35,7 +35,7 @@ beforeEach(() => {
log.error.mockClear();
});
-describe("plugin-sdk drainPendingDeliveries", () => {
+describe("plugin-sdk delivery queue drainPendingDeliveries", () => {
it("injects the lazy outbound deliver runtime when no deliver fn is provided", async () => {
await drainPendingDeliveries({
drainKey: "demo:test",
diff --git a/src/plugin-sdk/delivery-queue-runtime.ts b/src/plugin-sdk/delivery-queue-runtime.ts
new file mode 100644
index 00000000000..c9e5f65d850
--- /dev/null
+++ b/src/plugin-sdk/delivery-queue-runtime.ts
@@ -0,0 +1,27 @@
+import {
+ drainPendingDeliveries as coreDrainPendingDeliveries,
+ type DeliverFn,
+} from "../infra/outbound/delivery-queue.js";
+
+type OutboundDeliverRuntimeModule = typeof import("../infra/outbound/deliver-runtime.js");
+type DrainPendingDeliveriesOptions = Omit<
+ Parameters[0],
+ "deliver"
+> & {
+ deliver?: DeliverFn;
+};
+
+let outboundDeliverRuntimePromise: Promise | null = null;
+
+async function loadOutboundDeliverRuntime(): Promise {
+ outboundDeliverRuntimePromise ??= import("../infra/outbound/deliver-runtime.js");
+ return await outboundDeliverRuntimePromise;
+}
+
+export async function drainPendingDeliveries(opts: DrainPendingDeliveriesOptions): Promise {
+ const deliver = opts.deliver ?? (await loadOutboundDeliverRuntime()).deliverOutboundPayloads;
+ await coreDrainPendingDeliveries({
+ ...opts,
+ deliver,
+ });
+}
diff --git a/src/plugin-sdk/fetch-runtime.ts b/src/plugin-sdk/fetch-runtime.ts
index 29a31634003..ea991387eed 100644
--- a/src/plugin-sdk/fetch-runtime.ts
+++ b/src/plugin-sdk/fetch-runtime.ts
@@ -2,7 +2,11 @@
export { resolveFetch, wrapFetchWithAbortSignal } from "../infra/fetch.js";
export { withTrustedEnvProxyGuardedFetchMode } from "../infra/net/fetch-guard.ts";
-export { hasEnvHttpProxyConfigured } from "../infra/net/proxy-env.js";
+export {
+ hasEnvHttpProxyConfigured,
+ resolveEnvHttpProxyUrl,
+ shouldUseEnvHttpProxyForUrl,
+} from "../infra/net/proxy-env.js";
export { getProxyUrlFromFetch, makeProxyFetch } from "../infra/net/proxy-fetch.js";
export { createPinnedLookup } from "../infra/net/ssrf.js";
export type { PinnedDispatcherPolicy } from "../infra/net/ssrf.js";
diff --git a/src/plugin-sdk/file-access-runtime.ts b/src/plugin-sdk/file-access-runtime.ts
new file mode 100644
index 00000000000..3f1188e25b4
--- /dev/null
+++ b/src/plugin-sdk/file-access-runtime.ts
@@ -0,0 +1,4 @@
+// Safe local-file helpers for plugin runtime media and bridge code.
+
+export { readFileWithinRoot, writeFileWithinRoot } from "../infra/fs-safe.js";
+export { basenameFromMediaSource, safeFileURLToPath } from "../infra/local-file-access.js";
diff --git a/src/plugin-sdk/heartbeat-runtime.ts b/src/plugin-sdk/heartbeat-runtime.ts
new file mode 100644
index 00000000000..15199157655
--- /dev/null
+++ b/src/plugin-sdk/heartbeat-runtime.ts
@@ -0,0 +1,4 @@
+// Heartbeat event and visibility helpers without the broad infra-runtime barrel.
+
+export * from "../infra/heartbeat-events.js";
+export * from "../infra/heartbeat-visibility.js";
diff --git a/src/plugin-sdk/infra-runtime.ts b/src/plugin-sdk/infra-runtime.ts
index 5f8d654bbd0..a2d11a73391 100644
--- a/src/plugin-sdk/infra-runtime.ts
+++ b/src/plugin-sdk/infra-runtime.ts
@@ -1,32 +1,10 @@
-import {
- drainPendingDeliveries as coreDrainPendingDeliveries,
- type DeliverFn,
-} from "../infra/outbound/delivery-queue.js";
+/**
+ * @deprecated Compatibility shim only. Keep old plugins working, but do not
+ * add new imports here and do not use this subpath from repo code.
+ * Prefer focused openclaw/plugin-sdk/ runtime subpaths instead.
+ */
-// Public runtime/transport helpers for plugins that need shared infra behavior.
-
-type OutboundDeliverRuntimeModule = typeof import("../infra/outbound/deliver-runtime.js");
-type DrainPendingDeliveriesOptions = Omit<
- Parameters[0],
- "deliver"
-> & {
- deliver?: DeliverFn;
-};
-
-let outboundDeliverRuntimePromise: Promise | null = null;
-
-async function loadOutboundDeliverRuntime(): Promise {
- outboundDeliverRuntimePromise ??= import("../infra/outbound/deliver-runtime.js");
- return await outboundDeliverRuntimePromise;
-}
-
-export async function drainPendingDeliveries(opts: DrainPendingDeliveriesOptions): Promise {
- const deliver = opts.deliver ?? (await loadOutboundDeliverRuntime()).deliverOutboundPayloads;
- await coreDrainPendingDeliveries({
- ...opts,
- deliver,
- });
-}
+export * from "./delivery-queue-runtime.js";
export * from "../infra/backoff.js";
export * from "../infra/channel-activity.js";
diff --git a/src/plugin-sdk/number-runtime.ts b/src/plugin-sdk/number-runtime.ts
new file mode 100644
index 00000000000..988913c1adf
--- /dev/null
+++ b/src/plugin-sdk/number-runtime.ts
@@ -0,0 +1,3 @@
+// Numeric coercion helpers for plugin runtime inputs.
+
+export { parseFiniteNumber } from "../infra/parse-finite-number.js";
diff --git a/src/plugin-sdk/secure-random-runtime.ts b/src/plugin-sdk/secure-random-runtime.ts
new file mode 100644
index 00000000000..f621243ce3c
--- /dev/null
+++ b/src/plugin-sdk/secure-random-runtime.ts
@@ -0,0 +1,3 @@
+// Secure random token helpers for plugin runtime state.
+
+export { generateSecureToken, generateSecureUuid } from "../infra/secure-random.js";
diff --git a/src/plugin-sdk/system-event-runtime.ts b/src/plugin-sdk/system-event-runtime.ts
new file mode 100644
index 00000000000..53de97d4769
--- /dev/null
+++ b/src/plugin-sdk/system-event-runtime.ts
@@ -0,0 +1,7 @@
+// System event queue helpers without the broad infra-runtime barrel.
+
+export {
+ enqueueSystemEvent,
+ peekSystemEventEntries,
+ resetSystemEventsForTest,
+} from "../infra/system-events.js";
diff --git a/src/plugin-sdk/transport-ready-runtime.ts b/src/plugin-sdk/transport-ready-runtime.ts
new file mode 100644
index 00000000000..176f762a311
--- /dev/null
+++ b/src/plugin-sdk/transport-ready-runtime.ts
@@ -0,0 +1,3 @@
+// Transport readiness wait helper for channel plugins.
+
+export { waitForTransportReady } from "../infra/transport-ready.js";
diff --git a/src/plugins/contracts/plugin-sdk-subpaths.test.ts b/src/plugins/contracts/plugin-sdk-subpaths.test.ts
index 553aad87c0a..d504c424897 100644
--- a/src/plugins/contracts/plugin-sdk-subpaths.test.ts
+++ b/src/plugins/contracts/plugin-sdk-subpaths.test.ts
@@ -1137,8 +1137,8 @@ describe("plugin-sdk subpath exports", () => {
expect(typeof textRuntimeSdk.createScopedExpiringIdCache).toBe("function");
expect(typeof textRuntimeSdk.resolveGlobalMap).toBe("function");
expect(typeof textRuntimeSdk.resolveGlobalSingleton).toBe("function");
- expectSourceMentions("infra-runtime", ["createRuntimeOutboundDelegates"]);
- expectSourceContains("infra-runtime", "../infra/outbound/send-deps.js");
+ expectSourceMentions("delivery-queue-runtime", ["drainPendingDeliveries"]);
+ expectSourceContains("delivery-queue-runtime", "../infra/outbound/deliver-runtime.js");
expectSourceMentions("error-runtime", ["formatUncaughtError", "isApprovalNotFoundError"]);
expect(typeof channelLifecycleSdk.createDraftStreamLoop).toBe("function");
diff --git a/src/plugins/loader-sdk-import-guardrails.test.ts b/src/plugins/loader-sdk-import-guardrails.test.ts
index 6cf8018e728..99ad4e85c0b 100644
--- a/src/plugins/loader-sdk-import-guardrails.test.ts
+++ b/src/plugins/loader-sdk-import-guardrails.test.ts
@@ -7,8 +7,8 @@ const ALLOWED_PLUGIN_SDK_FIXTURE_IMPORTS = new Set([
'src/plugins/loader.test.ts:configSchema: (require("openclaw/plugin-sdk").emptyPluginConfigSchema)(),',
'src/plugins/loader.test.ts:const { onDiagnosticEvent } = require("openclaw/plugin-sdk");',
// Intentional jiti alias regression test.
- 'src/plugins/loader.git-path-regression.test.ts:`import { resolveOutboundSendDep } from "openclaw/plugin-sdk/infra-runtime";',
- 'src/plugins/loader.git-path-regression.test.ts: "openclaw/plugin-sdk/infra-runtime": ${JSON.stringify(copiedChannelRuntimeShim)},',
+ 'src/plugins/loader.git-path-regression.test.ts:`import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps";',
+ 'src/plugins/loader.git-path-regression.test.ts: "openclaw/plugin-sdk/outbound-send-deps": ${JSON.stringify(copiedChannelRuntimeShim)},',
// Intentional packaged bundled-plugin SDK alias regression tests.
'src/plugins/loader.test.ts:`import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";`,',
]);
diff --git a/src/plugins/loader.git-path-regression.test.ts b/src/plugins/loader.git-path-regression.test.ts
index 76076f96f86..39726395bd2 100644
--- a/src/plugins/loader.git-path-regression.test.ts
+++ b/src/plugins/loader.git-path-regression.test.ts
@@ -21,7 +21,7 @@ afterEach(() => {
});
describe("plugin loader git path regression", () => {
- it("loads git-style package extension entries when they import plugin-sdk infra-runtime (#49806)", async () => {
+ it("loads git-style package extension entries when they import plugin-sdk subpaths (#49806)", async () => {
const copiedExtensionRoot = path.join(makeTempDir(), "extensions", "imessage");
const copiedSourceDir = path.join(copiedExtensionRoot, "src");
const copiedPluginSdkDir = path.join(copiedExtensionRoot, "plugin-sdk");
@@ -31,7 +31,7 @@ describe("plugin loader git path regression", () => {
fs.writeFileSync(jitiBaseFile, "export {};\n", "utf-8");
fs.writeFileSync(
path.join(copiedSourceDir, "channel.runtime.ts"),
- `import { resolveOutboundSendDep } from "openclaw/plugin-sdk/infra-runtime";
+ `import { resolveOutboundSendDep } from "openclaw/plugin-sdk/outbound-send-deps";
import { PAIRING_APPROVED_MESSAGE } from "../runtime-api.js";
export const copiedRuntimeMarker = {
@@ -47,7 +47,7 @@ export const copiedRuntimeMarker = {
`,
"utf-8",
);
- const copiedChannelRuntimeShim = path.join(copiedPluginSdkDir, "infra-runtime.ts");
+ const copiedChannelRuntimeShim = path.join(copiedPluginSdkDir, "outbound-send-deps.ts");
fs.writeFileSync(
copiedChannelRuntimeShim,
`export function resolveOutboundSendDep() {
@@ -75,7 +75,7 @@ export const copiedRuntimeMarker = {
tryNative: false,
extensions: [".ts", ".tsx", ".mts", ".cts", ".mtsx", ".ctsx", ".js", ".mjs", ".cjs", ".json"],
alias: {
- "openclaw/plugin-sdk/infra-runtime": ${JSON.stringify(copiedChannelRuntimeShim)},
+ "openclaw/plugin-sdk/outbound-send-deps": ${JSON.stringify(copiedChannelRuntimeShim)},
},
});
const mod = withAlias(${JSON.stringify(copiedChannelRuntime)});
diff --git a/src/plugins/sdk-alias.test.ts b/src/plugins/sdk-alias.test.ts
index 91fa35ed920..2b233c96f17 100644
--- a/src/plugins/sdk-alias.test.ts
+++ b/src/plugins/sdk-alias.test.ts
@@ -1063,7 +1063,7 @@ describe("plugin sdk alias helpers", () => {
fs.writeFileSync(jitiBaseFile, "export {};\n", "utf-8");
fs.writeFileSync(
path.join(copiedSourceDir, "channel.runtime.ts"),
- `import { resolveOutboundSendDep } from "@openclaw/plugin-sdk/infra-runtime";
+ `import { resolveOutboundSendDep } from "@openclaw/plugin-sdk/outbound-send-deps";
export const syntheticRuntimeMarker = {
resolveOutboundSendDep,
@@ -1071,7 +1071,7 @@ export const syntheticRuntimeMarker = {
`,
"utf-8",
);
- const copiedChannelRuntimeShim = path.join(copiedPluginSdkDir, "infra-runtime.ts");
+ const copiedChannelRuntimeShim = path.join(copiedPluginSdkDir, "outbound-send-deps.ts");
fs.writeFileSync(
copiedChannelRuntimeShim,
`export function resolveOutboundSendDep() {
@@ -1092,8 +1092,8 @@ export const syntheticRuntimeMarker = {
const withAlias = createJiti(jitiBaseUrl, {
...buildPluginLoaderJitiOptions({
- "openclaw/plugin-sdk/infra-runtime": copiedChannelRuntimeShim,
- "@openclaw/plugin-sdk/infra-runtime": copiedChannelRuntimeShim,
+ "openclaw/plugin-sdk/outbound-send-deps": copiedChannelRuntimeShim,
+ "@openclaw/plugin-sdk/outbound-send-deps": copiedChannelRuntimeShim,
}),
tryNative: false,
});