diff --git a/CHANGELOG.md b/CHANGELOG.md index ecf4b9675b0..d05d33bc527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai - Discord/voice: apply per-channel Discord `systemPrompt` overrides to voice transcript turns by forwarding the trusted channel prompt through the voice agent run. Fixes #47095. Thanks @qearlyao. - Discord/voice: run voice-channel turns under a voice-output policy that hides the agent `tts` tool and asks for spoken reply text, so `/vc join` sessions synthesize and play agent replies instead of ending with `NO_REPLY`. Fixes #61536. Thanks @aounakram. - Plugins/runtime-deps: include packaged OpenClaw identity in bundled plugin loader cache keys, so same-path package upgrades stop reusing stale versioned runtime-deps mirrors. Fixes #75045. Thanks @sahilsatralkar. +- Plugin SDK: restore reply-prefix and reply-pipeline helpers on the deprecated root/compat SDK surface so external plugins still using `openclaw/plugin-sdk` do not fail message dispatch after update. Fixes #75171. Thanks @zhangxiliang. - Plugins/runtime-deps: prune inactive same-package versioned runtime-deps roots after bundled dependency repair, so upgrades do not leave old `openclaw--` package caches behind after doctor runs. Thanks @vincentkoc. - Plugins/runtime-deps: prune legacy version-scoped plugin runtime-deps roots during bundled dependency repair and cover the path in Package Acceptance's upgrade-survivor matrix, so upgrades from 2026.4.x no longer leave stale per-plugin runtime trees after doctor runs. Thanks @vincentkoc. - Plugins/runtime-deps: keep Gateway startup plugin imports and runtime plugin fallback loads verify-only after startup/config repair planning, so packaged installs no longer spawn package-manager repair from hot paths after readiness. Refs #75283 and #75069. Thanks @brokemac79 and @xiaohuaxi. diff --git a/src/plugin-sdk/compat.ts b/src/plugin-sdk/compat.ts index 62648b419d8..508fc74b881 100644 --- a/src/plugin-sdk/compat.ts +++ b/src/plugin-sdk/compat.ts @@ -4,6 +4,21 @@ * instead. */ +import { + createChannelReplyPipeline as createChannelReplyPipelineCompat, + createReplyPrefixContext as createReplyPrefixContextCompat, + createReplyPrefixOptions as createReplyPrefixOptionsCompat, + createTypingCallbacks as createTypingCallbacksCompat, + resolveChannelSourceReplyDeliveryMode as resolveChannelSourceReplyDeliveryModeCompat, + type ChannelReplyPipeline as ChannelReplyPipelineCompat, + type CreateTypingCallbacksParams as CreateTypingCallbacksParamsCompat, + type ReplyPrefixContext as ReplyPrefixContextCompat, + type ReplyPrefixContextBundle as ReplyPrefixContextBundleCompat, + type ReplyPrefixOptions as ReplyPrefixOptionsCompat, + type SourceReplyDeliveryMode as SourceReplyDeliveryModeCompat, + type TypingCallbacks as TypingCallbacksCompat, +} from "./channel-reply-pipeline.js"; + const shouldWarnCompatImport = process.env.VITEST !== "true" && process.env.NODE_ENV !== "test" && @@ -69,6 +84,31 @@ export * from "./reply-history.js"; export * from "./directory-runtime.js"; export { mapAllowlistResolutionInputs } from "./allow-from.js"; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export const createChannelReplyPipeline = createChannelReplyPipelineCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export const createReplyPrefixContext = createReplyPrefixContextCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export const createReplyPrefixOptions = createReplyPrefixOptionsCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export const createTypingCallbacks = createTypingCallbacksCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export const resolveChannelSourceReplyDeliveryMode = resolveChannelSourceReplyDeliveryModeCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type ChannelReplyPipeline = ChannelReplyPipelineCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type CreateTypingCallbacksParams = CreateTypingCallbacksParamsCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type ReplyPrefixContext = ReplyPrefixContextCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type ReplyPrefixContextBundle = ReplyPrefixContextBundleCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type ReplyPrefixOptions = ReplyPrefixOptionsCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type SourceReplyDeliveryMode = SourceReplyDeliveryModeCompat; +/** @deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`. */ +export type TypingCallbacks = TypingCallbacksCompat; + export { resolveBlueBubblesGroupRequireMention, resolveBlueBubblesGroupToolPolicy, diff --git a/src/plugins/compat/registry.test.ts b/src/plugins/compat/registry.test.ts index 4b25ceceb16..a314093f9bd 100644 --- a/src/plugins/compat/registry.test.ts +++ b/src/plugins/compat/registry.test.ts @@ -130,6 +130,11 @@ const knownDeprecatedSurfaceMarkers = [ file: "src/plugin-sdk/testing.ts", marker: "@deprecated Broad compatibility barrel", }, + { + code: "legacy-root-sdk-import", + file: "src/plugin-sdk/compat.ts", + marker: "@deprecated Use `openclaw/plugin-sdk/channel-reply-pipeline`.", + }, { code: "channel-route-key-aliases", file: "src/plugin-sdk/channel-route.ts", diff --git a/src/plugins/compat/registry.ts b/src/plugins/compat/registry.ts index a5eddfaaf6e..0a8966c95f3 100644 --- a/src/plugins/compat/registry.ts +++ b/src/plugins/compat/registry.ts @@ -48,6 +48,7 @@ export const PLUGIN_COMPAT_RECORDS = [ diagnostics: ["OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED"], tests: [ "src/plugins/contracts/plugin-sdk-index.test.ts", + "src/plugins/contracts/plugin-sdk-root-alias.test.ts", "src/plugins/contracts/plugin-sdk-subpaths.test.ts", ], }, diff --git a/src/plugins/contracts/plugin-sdk-root-alias.test.ts b/src/plugins/contracts/plugin-sdk-root-alias.test.ts index fa20417892f..6f5fde93fe2 100644 --- a/src/plugins/contracts/plugin-sdk-root-alias.test.ts +++ b/src/plugins/contracts/plugin-sdk-root-alias.test.ts @@ -468,6 +468,11 @@ describe("plugin-sdk root alias", () => { expect(typeof rootSdk.stringEnum).toBe("function"); expect(typeof rootSdk.buildChannelConfigSchema).toBe("function"); expect(typeof rootSdk.normalizeAccountId).toBe("function"); + expect(typeof rootSdk.createReplyPrefixContext).toBe("function"); + expect(typeof rootSdk.createReplyPrefixOptions).toBe("function"); + expect(typeof rootSdk.createTypingCallbacks).toBe("function"); + expect(typeof rootSdk.createChannelReplyPipeline).toBe("function"); + expect(typeof rootSdk.resolveChannelSourceReplyDeliveryMode).toBe("function"); expect(typeof rootSdk.resolvePreferredOpenClawTmpDir).toBe("function"); expect(typeof rootSdk.default).toBe("object"); expect(rootSdk.default).toBe(rootSdk); diff --git a/src/plugins/contracts/plugin-sdk-subpaths.test.ts b/src/plugins/contracts/plugin-sdk-subpaths.test.ts index e04e7e3cc1e..0cdc5bdc203 100644 --- a/src/plugins/contracts/plugin-sdk-subpaths.test.ts +++ b/src/plugins/contracts/plugin-sdk-subpaths.test.ts @@ -643,6 +643,8 @@ describe("plugin-sdk subpath exports", () => { "collectOpenGroupPolicyConfiguredRouteWarnings", "resolveControlCommandGate", "delegateCompactionToRuntime", + "createReplyPrefixContext", + "createChannelReplyPipeline", ]); expectSourceMentions("device-bootstrap", [ "approveDevicePairing",