feat: gate legacy startup sidecar fallback

This commit is contained in:
Shakker
2026-04-28 06:31:48 +01:00
parent 583b419827
commit d48c3e12a5
5 changed files with 49 additions and 1 deletions

View File

@@ -32,6 +32,7 @@ Docs: https://docs.openclaw.ai
- Channels/Yuanbao: register the Tencent Yuanbao external channel plugin (`openclaw-plugin-yuanbao`) in the official channel catalog, contract suites, and community plugin docs, with a new `docs/channels/yuanbao.md` quick-start guide for WebSocket bot DMs and group chats. (#72756) Thanks @loongfay.
- Channels/QQBot: add full group chat support (history tracking, @-mention gating, activation modes, per-group config, FIFO message queue with deliver debounce), C2C `stream_messages` streaming with a `StreamingController` lifecycle manager, unified `sendMedia` with chunked upload for large files, and refactor the engine into pipeline stages, focused outbound submodules, builtin slash-command modules, and explicit DI ports via `createEngineAdapters()`. (#70624) Thanks @cxyhhhhh.
- Plugins/startup: migrate bundled plugin manifests to explicit `activation.onStartup` declarations so Gateway startup imports only the bundled plugins that intentionally register startup-time runtime surfaces. Thanks @shakkernerd.
- Plugins/startup: add an opt-in future-mode gate for disabling deprecated implicit startup sidecar loading while preserving explicit startup and narrower activation triggers. Thanks @shakkernerd.
- Plugins/startup: add plugin compatibility warnings for deprecated implicit startup loading so authors can migrate to explicit `activation.onStartup` metadata. Thanks @shakkernerd.
- Plugins/runtime: load bundled agent tool-result middleware from manifest contracts on demand so tokenjuice stays startup-lazy without losing Pi/Codex tool-output compaction. Thanks @shakkernerd.
- Plugins/startup: add explicit `activation.onStartup` metadata so plugins can declare Gateway startup import behavior while the deprecated implicit sidecar fallback remains for legacy plugins. Thanks @shakkernerd.

View File

@@ -136,7 +136,8 @@ Current compatibility records include:
move to `openclaw/plugin-sdk/channel-route`
- activation hints that are being replaced by manifest contribution ownership
- deprecated implicit startup sidecar loading for plugins that have not declared
`activation.onStartup`
`activation.onStartup`; maintainers can test the future stricter behavior with
`OPENCLAW_DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS=1`
- `setup-api` runtime fallback while setup descriptors move to cold
`setup.requiresRuntime: false` metadata
- provider `discovery` hooks while provider catalog hooks move to

View File

@@ -268,6 +268,12 @@ plugins unless they declare `activation.onStartup: true`. Plugin status and
compatibility reports warn with `legacy-implicit-startup-sidecar` when a plugin
still relies on that fallback.
For migration testing, set
`OPENCLAW_DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS=1` to disable only that
deprecated fallback. This opt-in mode does not block explicit
`activation.onStartup: true` plugins or plugins loaded by channel, config,
agent-harness, memory, or other narrower activation triggers.
```json
{
"activation": {

View File

@@ -662,6 +662,22 @@ describe("resolveGatewayStartupPluginIds", () => {
});
});
it("can disable deprecated implicit startup sidecar fallback for future-mode testing", () => {
expectStartupPluginIdsCase({
config: createStartupConfig({
enabledPluginIds: ["demo-global-sidecar"],
allowPluginIds: ["demo-global-sidecar"],
noConfiguredChannels: true,
memorySlot: "none",
}),
env: {
...process.env,
OPENCLAW_DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS: "1",
},
expected: [],
});
});
it("skips deprecated implicit startup sidecar fallback when activation.onStartup is false", () => {
expectStartupPluginIdsCase({
config: createStartupConfig({
@@ -682,6 +698,10 @@ describe("resolveGatewayStartupPluginIds", () => {
noConfiguredChannels: true,
memorySlot: "none",
}),
env: {
...process.env,
OPENCLAW_DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS: "1",
},
expected: ["demo-global-explicit-startup"],
});
});

View File

@@ -20,6 +20,18 @@ import {
} from "./plugin-registry-contributions.js";
import { loadPluginRegistrySnapshot } from "./plugin-registry-snapshot.js";
const DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS_ENV =
"OPENCLAW_DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS";
function isTruthyEnvValue(value: string | undefined): boolean {
const normalized = value?.trim().toLowerCase();
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
}
function shouldDisableLegacyImplicitStartupSidecars(env: NodeJS.ProcessEnv): boolean {
return isTruthyEnvValue(env[DISABLE_LEGACY_IMPLICIT_STARTUP_SIDECARS_ENV]);
}
function listDisabledChannelIds(config: OpenClawConfig): Set<string> {
const channels = config.channels;
if (!channels || typeof channels !== "object" || Array.isArray(channels)) {
@@ -117,6 +129,7 @@ function resolveMemorySlotStartupPluginId(params: {
function shouldConsiderForGatewayStartup(params: {
plugin: InstalledPluginIndexRecord;
manifest: PluginManifestRecord | undefined;
disableLegacyImplicitStartupSidecars: boolean;
startupDreamingPluginIds: ReadonlySet<string>;
memorySlotStartupPluginId?: string;
}): boolean {
@@ -127,6 +140,9 @@ function shouldConsiderForGatewayStartup(params: {
if (params.manifest?.activation?.onStartup === false) {
return false;
}
if (params.disableLegacyImplicitStartupSidecars) {
return false;
}
// Deprecated compatibility fallback: plugins without explicit startup
// activation metadata may still need startup import to register hooks or
// services. All plugins should declare activation.onStartup explicitly as
@@ -383,6 +399,9 @@ export function resolveGatewayStartupPluginIdsFromRegistry(params: {
collectConfiguredAgentHarnessRuntimes(activationSourceConfig, params.env),
);
const startupDreamingPluginIds = resolveGatewayStartupDreamingPluginIds(params.config);
const disableLegacyImplicitStartupSidecars = shouldDisableLegacyImplicitStartupSidecars(
params.env,
);
const memorySlotStartupPluginId = resolveMemorySlotStartupPluginId({
activationSourceConfig,
activationSourcePlugins,
@@ -436,6 +455,7 @@ export function resolveGatewayStartupPluginIdsFromRegistry(params: {
!shouldConsiderForGatewayStartup({
plugin,
manifest,
disableLegacyImplicitStartupSidecars,
startupDreamingPluginIds,
memorySlotStartupPluginId,
})