diff --git a/CHANGELOG.md b/CHANGELOG.md index d0bb16bcdef..893cf928c97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai - Outbound adapters/plugins: add shared `sendPayload` support across direct-text-media, Discord, Slack, WhatsApp, Zalo, and Zalouser with multi-media iteration and chunk-aware text fallback. (#30144) Thanks @nohat. - Media understanding/audio echo: add optional `tools.media.audio.echoTranscript` + `echoFormat` to send a pre-agent transcript confirmation message to the originating chat, with echo disabled by default. (#32150) Thanks @AytuncYildizli. - Plugin runtime/STT: add `api.runtime.stt.transcribeAudioFile(...)` so extensions can transcribe local audio files through OpenClaw's configured media-understanding audio providers. (#22402) Thanks @benthecarman. +- Plugin SDK/channel extensibility: expose `channelRuntime` on `ChannelGatewayContext` so external channel plugins can access shared runtime helpers (reply/routing/session/text/media/commands) without internal imports. (#25462) Thanks @guxiaobo. - Sessions/Attachments: add inline file attachment support for `sessions_spawn` (subagent runtime only) with base64/utf8 encoding, transcript content redaction, lifecycle cleanup, and configurable limits via `tools.sessions_spawn.attachments`. (#16761) Thanks @napetrov. - Tools/PDF analysis: add a first-class `pdf` tool with native Anthropic and Google PDF provider support, extraction fallback for non-native models, configurable defaults (`agents.defaults.pdfModel`, `pdfMaxBytesMb`, `pdfMaxPages`), and docs/tests covering routing, validation, and registration. (#31319) Thanks @tyler6204. - Zalo Personal plugin (`@openclaw/zalouser`): rebuilt channel runtime to use native `zca-js` integration in-process, removing external CLI transport usage and keeping QR/login + send/listen flows fully inside OpenClaw. diff --git a/src/gateway/server-channels.test.ts b/src/gateway/server-channels.test.ts index 54d880b8b6e..c442c142417 100644 --- a/src/gateway/server-channels.test.ts +++ b/src/gateway/server-channels.test.ts @@ -7,6 +7,7 @@ import { } from "../logging/subsystem.js"; import { createEmptyPluginRegistry, type PluginRegistry } from "../plugins/registry.js"; import { getActivePluginRegistry, setActivePluginRegistry } from "../plugins/runtime.js"; +import type { PluginRuntime } from "../plugins/runtime/types.js"; import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js"; import type { RuntimeEnv } from "../runtime.js"; import { createChannelManager } from "./server-channels.js"; @@ -87,7 +88,7 @@ function installTestRegistry(plugin: ChannelPlugin) { setActivePluginRegistry(registry); } -function createManager() { +function createManager(options?: { channelRuntime?: PluginRuntime["channel"] }) { const log = createSubsystemLogger("gateway/server-channels-test"); const channelLogs = { discord: log } as Record; const runtime = runtimeForLogger(log); @@ -96,6 +97,7 @@ function createManager() { loadConfig: () => ({}), channelLogs, channelRuntimeEnvs, + ...(options?.channelRuntime ? { channelRuntime: options.channelRuntime } : {}), }); } @@ -165,4 +167,17 @@ describe("server-channels auto restart", () => { expect(account?.enabled).toBe(true); expect(account?.configured).toBe(true); }); + + it("passes channelRuntime through channel gateway context when provided", async () => { + const channelRuntime = { marker: "channel-runtime" } as unknown as PluginRuntime["channel"]; + const startAccount = vi.fn(async (ctx) => { + expect(ctx.channelRuntime).toBe(channelRuntime); + }); + + installTestRegistry(createTestPlugin({ startAccount })); + const manager = createManager({ channelRuntime }); + + await manager.startChannels(); + expect(startAccount).toHaveBeenCalledTimes(1); + }); });