diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e1bb73e9fc..b335edc2460 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,6 +111,7 @@ Docs: https://docs.openclaw.ai - Skill Workshop: keep the tool plus `before_prompt_build` / `agent_end` hooks wired while the plugin is disabled at startup, so turning the plugin back on in live config starts guidance and capture without waiting for a restart. Thanks @vincentkoc. - Active Memory: stop reviving removed live `active-memory` config from startup snapshots, so removing the plugin entry turns the hook off immediately instead of waiting for a restart. Thanks @vincentkoc. - GitHub Copilot: re-read plugin discovery config from the live runtime snapshot, so toggling `plugins.entries.github-copilot.config.discovery.enabled` takes effect without a restart. Thanks @vincentkoc. +- Ollama: re-read plugin discovery config from the live runtime snapshot, so toggling `plugins.entries.ollama.config.discovery.enabled` takes effect without a restart. Thanks @vincentkoc. - Agents/subagents: drop bare `NO_REPLY` from the parent turn when the session still has pending spawned children, so direct-conversation surfaces such as Telegram DMs no longer rewrite the sentinel into visible fallback chatter while waiting for the child completion event. (#69942) Thanks @neeravmakwana. - Plugins/install: keep bundled plugin dependencies off npm install while repairing them when plugins activate from a packaged install, including Feishu/Lark, Browser, and direct bundled channel setup-entry loads. - CLI/channels: skip and cache bundled channel plugin, setup, and secrets load failures during read-only discovery, so one broken unused bundled channel cannot crash `openclaw status` or bootstrap secret scans. diff --git a/extensions/ollama/index.test.ts b/extensions/ollama/index.test.ts index 43a86220371..9253ff70b21 100644 --- a/extensions/ollama/index.test.ts +++ b/extensions/ollama/index.test.ts @@ -185,7 +185,17 @@ describe("ollama plugin", () => { const provider = registerProviderWithPluginConfig({ discovery: { enabled: false } }); const result = await provider.discovery.run({ - config: {}, + config: { + plugins: { + entries: { + ollama: { + config: { + discovery: { enabled: false }, + }, + }, + }, + }, + }, env: {}, resolveProviderApiKey: () => ({ apiKey: "", discoveryApiKey: "" }), } as never); @@ -194,6 +204,41 @@ describe("ollama plugin", () => { expect(buildOllamaProviderMock).not.toHaveBeenCalled(); }); + it("uses live plugin config to re-enable discovery after startup disable", async () => { + const provider = registerProviderWithPluginConfig({ discovery: { enabled: false } }); + buildOllamaProviderMock.mockResolvedValueOnce({ + baseUrl: "http://127.0.0.1:11434", + api: "ollama", + models: [{ id: "llama3.2", name: "Llama 3.2" }], + }); + + const result = await provider.discovery.run({ + config: { + plugins: { + entries: { + ollama: { + config: { + discovery: { enabled: true }, + }, + }, + }, + }, + }, + env: { OLLAMA_API_KEY: "ollama-live" }, + resolveProviderApiKey: () => ({ apiKey: "ollama-live", discoveryApiKey: "ollama-live" }), + } as never); + + expect(buildOllamaProviderMock).toHaveBeenCalledOnce(); + expect(result).toEqual({ + provider: { + baseUrl: "http://127.0.0.1:11434", + api: "ollama", + models: [{ id: "llama3.2", name: "Llama 3.2" }], + apiKey: "OLLAMA_API_KEY", + }, + }); + }); + it("keeps empty default-ish provider stubs quiet", async () => { const provider = registerProvider(); buildOllamaProviderMock.mockResolvedValueOnce({ diff --git a/extensions/ollama/index.ts b/extensions/ollama/index.ts index 29d77050f40..0e399201aab 100644 --- a/extensions/ollama/index.ts +++ b/extensions/ollama/index.ts @@ -1,3 +1,7 @@ +import { + resolvePluginConfigObject, + type OpenClawConfig, +} from "openclaw/plugin-sdk/config-runtime"; import { definePluginEntry, type OpenClawPluginApi, @@ -57,7 +61,14 @@ export default definePluginEntry({ register(api: OpenClawPluginApi) { api.registerMemoryEmbeddingProvider(ollamaMemoryEmbeddingProviderAdapter); api.registerMediaUnderstandingProvider(ollamaMediaUnderstandingProvider); - const pluginConfig = (api.pluginConfig ?? {}) as OllamaPluginConfig; + const startupPluginConfig = (api.pluginConfig ?? {}) as OllamaPluginConfig; + const resolveCurrentPluginConfig = (config?: OpenClawConfig): OllamaPluginConfig => { + const runtimePluginConfig = resolvePluginConfigObject(config, "ollama"); + if (runtimePluginConfig) { + return runtimePluginConfig as OllamaPluginConfig; + } + return config ? {} : startupPluginConfig; + }; api.registerWebSearchProvider(createOllamaWebSearchProvider()); api.registerProvider({ id: OLLAMA_PROVIDER_ID, @@ -117,7 +128,7 @@ export default definePluginEntry({ run: async (ctx: ProviderDiscoveryContext) => await resolveOllamaDiscoveryResult({ ctx, - pluginConfig, + pluginConfig: resolveCurrentPluginConfig(ctx.config), buildProvider: buildOllamaProvider, }), },