mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:20:43 +00:00
fix(plugins): honor descriptor-only setup flag
Honor explicit setup.requiresRuntime: false as a descriptor-only setup contract while preserving omitted values as the legacy setup-api fallback path.
This commit is contained in:
@@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Changes
|
||||
|
||||
- Gradium: add a bundled text-to-speech provider with voice-note and telephony output support. (#64958) Thanks @LaurentMazare.
|
||||
- Plugins/setup: honor explicit `setup.requiresRuntime: false` as a descriptor-only setup contract while keeping omitted values on the legacy setup-api fallback path. Thanks @vincentkoc.
|
||||
- TUI/dependencies: remove direct `cli-highlight` usage from the OpenClaw TUI code-block renderer, keeping themed code coloring without the extra root dependency. Thanks @vincentkoc.
|
||||
- Diagnostics/OTEL: export run, model-call, and tool-execution diagnostic lifecycle events as OTEL spans without retaining live span state. Thanks @vincentkoc.
|
||||
- Plugins/activation: expose activation plan reasons and a richer plan API so callers can inspect why a plugin was selected while preserving existing id-list activation behavior. (#70943) Thanks @vincentkoc.
|
||||
|
||||
@@ -71,10 +71,12 @@ or fallback behavior without changing runtime loading semantics.
|
||||
|
||||
Setup discovery now prefers descriptor-owned ids such as `setup.providers` and
|
||||
`setup.cliBackends` to narrow candidate plugins before it falls back to
|
||||
`setup-api` for plugins that still need setup-time runtime hooks. If more than
|
||||
one discovered plugin claims the same normalized setup provider or CLI backend
|
||||
id, setup lookup refuses the ambiguous owner instead of relying on discovery
|
||||
order.
|
||||
`setup-api` for plugins that still need setup-time runtime hooks. Explicit
|
||||
`setup.requiresRuntime: false` is a descriptor-only cutoff; omitted
|
||||
`requiresRuntime` keeps the legacy setup-api fallback for compatibility. If more
|
||||
than one discovered plugin claims the same normalized setup provider or CLI
|
||||
backend id, setup lookup refuses the ambiguous owner instead of relying on
|
||||
discovery order.
|
||||
|
||||
### What the loader caches
|
||||
|
||||
|
||||
@@ -327,6 +327,12 @@ narrows the candidate plugin and setup still needs richer setup-time runtime
|
||||
hooks, set `requiresRuntime: true` and keep `setup-api` in place as the
|
||||
fallback execution path.
|
||||
|
||||
Set `requiresRuntime: false` only when those descriptors are sufficient for the
|
||||
setup surface. OpenClaw treats explicit `false` as a descriptor-only contract
|
||||
and will not execute `setup-api` for setup lookup. Omitted `requiresRuntime`
|
||||
keeps legacy fallback behavior so existing plugins that added descriptors
|
||||
without the flag do not break.
|
||||
|
||||
Because setup lookup can execute plugin-owned `setup-api` code, normalized
|
||||
`setup.providers[].id` and `setup.cliBackends[]` values must stay unique across
|
||||
discovered plugins. Ambiguous ownership fails closed instead of picking a
|
||||
|
||||
@@ -349,6 +349,39 @@ describe("setup-registry getJiti", () => {
|
||||
expect(mocks.createJiti.mock.calls[0]?.[0]).toBe(path.join(pluginRoot, "setup-api.js"));
|
||||
});
|
||||
|
||||
it("treats explicit descriptor-only setup as a runtime cutoff", () => {
|
||||
const pluginRoot = makeTempDir();
|
||||
fs.writeFileSync(
|
||||
path.join(pluginRoot, "setup-api.js"),
|
||||
"export default { register(api) { api.registerProvider({ id: 'openai', label: 'OpenAI', auth: [] }); api.registerCliBackend({ id: 'codex-cli', config: { command: 'codex' } }); } };\n",
|
||||
"utf-8",
|
||||
);
|
||||
mocks.loadPluginManifestRegistry.mockReturnValue({
|
||||
plugins: [
|
||||
{
|
||||
id: "openai",
|
||||
rootDir: pluginRoot,
|
||||
setup: {
|
||||
providers: [{ id: "openai" }],
|
||||
cliBackends: ["codex-cli"],
|
||||
requiresRuntime: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
diagnostics: [],
|
||||
});
|
||||
|
||||
expect(resolvePluginSetupProvider({ provider: "openai", env: {} })).toBeUndefined();
|
||||
expect(resolvePluginSetupCliBackend({ backend: "codex-cli", env: {} })).toBeUndefined();
|
||||
expect(resolvePluginSetupRegistry({ env: {} })).toEqual({
|
||||
providers: [],
|
||||
cliBackends: [],
|
||||
configMigrations: [],
|
||||
autoEnableProbes: [],
|
||||
});
|
||||
expect(mocks.createJiti).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not load setup-api modules from the current working directory", () => {
|
||||
const pluginRoot = makeTempDir();
|
||||
const workspaceRoot = makeTempDir();
|
||||
|
||||
@@ -272,6 +272,9 @@ function resolveSetupRegistration(record: PluginManifestRecord): {
|
||||
setupSource: string;
|
||||
register: (api: ReturnType<typeof buildPluginApi>) => void | Promise<void>;
|
||||
} | null {
|
||||
if (record.setup?.requiresRuntime === false) {
|
||||
return null;
|
||||
}
|
||||
const setupSource = record.setupSource ?? resolveSetupApiPath(record.rootDir);
|
||||
if (!setupSource) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user