惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
博客园 - 司徒正美
博客园 - 【当耐特】
爱范儿
爱范儿
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
人人都是产品经理
人人都是产品经理
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
大猫的无限游戏
大猫的无限游戏
月光博客
月光博客
宝玉的分享
宝玉的分享
V
V2EX
S
SegmentFault 最新的问题
V
Visual Studio Blog
阮一峰的网络日志
阮一峰的网络日志
Martin Fowler
Martin Fowler
Jina AI
Jina AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
L
LangChain Blog
D
Docker
腾讯CDC

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
refactor(hooks): centralize live plugin config lookup · o...
vincentkoc · 2026-04-23 · via Recent Commits to openclaw:main
Original file line numberDiff line numberDiff line change

@@ -1,2 +1,2 @@

1-

475eafc1885c69203ac690a0ef3c1d1ddf6879d904a6980cf5f172c29ed70868 plugin-sdk-api-baseline.json

2-

906bb0b167b155d2f766bd13f720c8c6ed8f349769d39f57ff5070045b96ef4c plugin-sdk-api-baseline.jsonl

1+

452cf5257df597bb0062c4478aca3afdbda6909fbaaf9ade214c27e8885935b1 plugin-sdk-api-baseline.json

2+

30117bdbd814978ad04be54e80b72385cabb0c726de1abcbad319c9d0b3ed101 plugin-sdk-api-baseline.jsonl

Original file line numberDiff line numberDiff line change

@@ -192,7 +192,7 @@ explicitly promotes one as public.

192192

| `plugin-sdk/process-runtime` | Process exec helpers |

193193

| `plugin-sdk/cli-runtime` | CLI formatting, wait, and version helpers |

194194

| `plugin-sdk/gateway-runtime` | Gateway client and channel-status patch helpers |

195-

| `plugin-sdk/config-runtime` | Config load/write helpers |

195+

| `plugin-sdk/config-runtime` | Config load/write helpers and plugin-config lookup helpers |

196196

| `plugin-sdk/telegram-command-config` | Telegram command-name/description normalization and duplicate/conflict checks, even when the bundled Telegram contract surface is unavailable |

197197

| `plugin-sdk/text-autolink-runtime` | File-reference autolink detection without the broad text-runtime barrel |

198198

| `plugin-sdk/approval-runtime` | Exec/plugin approval helpers, approval-capability builders, auth/profile helpers, native routing/runtime helpers |

Original file line numberDiff line numberDiff line change

@@ -9,6 +9,7 @@ import {

99

resolveAgentWorkspaceDir,

1010

} from "openclaw/plugin-sdk/agent-runtime";

1111

import {

12+

resolvePluginConfigObject,

1213

resolveSessionStoreEntry,

1314

updateSessionStore,

1415

type OpenClawConfig,

@@ -573,14 +574,10 @@ function isActiveMemoryGloballyEnabled(cfg: OpenClawConfig): boolean {

573574

if (entry?.enabled === false) {

574575

return false;

575576

}

576-

const pluginConfig = asRecord(entry?.config);

577+

const pluginConfig = resolvePluginConfigObject(cfg, "active-memory");

577578

return pluginConfig?.enabled !== false;

578579

}

579580
580-

function resolveActiveMemoryPluginConfigFromConfig(cfg: OpenClawConfig): unknown {

581-

return asRecord(cfg.plugins?.entries?.["active-memory"])?.config;

582-

}

583-
584581

function updateActiveMemoryGlobalEnabledInConfig(

585582

cfg: OpenClawConfig,

586583

enabled: boolean,

@@ -1887,7 +1884,7 @@ export default definePluginEntry({

18871884

warnDeprecatedModelFallbackPolicy(api.pluginConfig);

18881885

const refreshLiveConfigFromRuntime = () => {

18891886

const livePluginConfig =

1890-

resolveActiveMemoryPluginConfigFromConfig(api.runtime.config.loadConfig()) ??

1887+

resolvePluginConfigObject(api.runtime.config.loadConfig(), "active-memory") ??

18911888

api.pluginConfig;

18921889

config = normalizePluginConfig(livePluginConfig);

18931890

warnDeprecatedModelFallbackPolicy(livePluginConfig);

Original file line numberDiff line numberDiff line change

@@ -10,6 +10,7 @@ import { randomUUID } from "node:crypto";

1010

import type * as LanceDB from "@lancedb/lancedb";

1111

import { Type } from "@sinclair/typebox";

1212

import OpenAI from "openai";

13+

import { resolvePluginConfigObject } from "openclaw/plugin-sdk/config-runtime";

1314

import { ensureGlobalUndiciEnvProxyDispatcher } from "openclaw/plugin-sdk/runtime-env";

1415

import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";

1516

import { definePluginEntry, type OpenClawPluginApi } from "./api.js";

@@ -311,9 +312,7 @@ export default definePluginEntry({

311312

const embeddings = new Embeddings(apiKey, model, baseUrl, dimensions);

312313

const resolveCurrentHookConfig = () => {

313314

const runtimeConfig = api.runtime.config?.loadConfig?.();

314-

const runtimePlugins = asRecord(asRecord(runtimeConfig)?.plugins);

315-

const runtimeEntries = asRecord(runtimePlugins?.entries);

316-

const runtimePluginConfig = asRecord(runtimeEntries?.["memory-lancedb"])?.config;

315+

const runtimePluginConfig = resolvePluginConfigObject(runtimeConfig, "memory-lancedb");

317316

if (!runtimePluginConfig) {

318317

return cfg;

319318

}

Original file line numberDiff line numberDiff line change

@@ -1,3 +1,4 @@

1+

import { resolvePluginConfigObject } from "openclaw/plugin-sdk/config-runtime";

12

import { definePluginEntry, resolveDefaultAgentId } from "./api.js";

23

import { resolveConfig } from "./src/config.js";

34

import { buildWorkshopGuidance } from "./src/prompt.js";

@@ -6,12 +7,6 @@ import { createProposalFromMessages } from "./src/signals.js";

67

import { createSkillWorkshopTool } from "./src/tool.js";

78

import { applyOrStoreProposal, createStoreForContext } from "./src/workshop.js";

89
9-

function asRecord(value: unknown): Record<string, unknown> | undefined {

10-

return value && typeof value === "object" && !Array.isArray(value)

11-

? (value as Record<string, unknown>)

12-

: undefined;

13-

}

14-
1510

export default definePluginEntry({

1611

id: "skill-workshop",

1712

name: "Skill Workshop",

@@ -24,10 +19,8 @@ export default definePluginEntry({

2419

}

2520

const resolveCurrentConfig = () => {

2621

const runtimeConfig = api.runtime.config?.loadConfig?.();

27-

const runtimePlugins = asRecord(asRecord(runtimeConfig)?.plugins);

28-

const runtimeEntries = asRecord(runtimePlugins?.entries);

2922

const runtimePluginConfig =

30-

asRecord(runtimeEntries?.["skill-workshop"])?.config ?? api.pluginConfig;

23+

resolvePluginConfigObject(runtimeConfig, "skill-workshop") ?? api.pluginConfig;

3124

return resolveConfig(runtimePluginConfig);

3225

};

3326
Original file line numberDiff line numberDiff line change

@@ -1,3 +1,4 @@

1+

import { resolvePluginConfigObject } from "openclaw/plugin-sdk/config-runtime";

12

import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";

23

import {

34

definePluginEntry,

@@ -72,20 +73,6 @@ function resolveOwnershipAgent(config: OpenClawConfig): { id: string; name: stri

7273

return { id, name };

7374

}

7475
75-

function asRecord(value: unknown): Record<string, unknown> | undefined {

76-

return value && typeof value === "object" && !Array.isArray(value)

77-

? (value as Record<string, unknown>)

78-

: undefined;

79-

}

80-
81-

function resolveThreadOwnershipPluginConfigFromConfig(

82-

config: OpenClawConfig,

83-

): ThreadOwnershipConfig | undefined {

84-

return asRecord(asRecord(config.plugins?.entries)?.["thread-ownership"])?.config as

85-

| ThreadOwnershipConfig

86-

| undefined;

87-

}

88-
8976

export default definePluginEntry({

9077

id: "thread-ownership",

9178

name: "Thread Ownership",

@@ -94,7 +81,7 @@ export default definePluginEntry({

9481

const resolveCurrentState = () => {

9582

const currentConfig = api.runtime.config?.loadConfig?.() ?? api.config;

9683

const pluginCfg =

97-

resolveThreadOwnershipPluginConfigFromConfig(currentConfig) ||

84+

resolvePluginConfigObject(currentConfig, "thread-ownership") ||

9885

((api.pluginConfig ?? {}) as ThreadOwnershipConfig);

9986

return {

10087

currentConfig,

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,47 @@

1+

import { describe, expect, it } from "vitest";

2+

import { resolvePluginConfigObject, type OpenClawConfig } from "./config-runtime.js";

3+
4+

describe("resolvePluginConfigObject", () => {

5+

it("returns the plugin config object for a configured plugin entry", () => {

6+

const config = {

7+

plugins: {

8+

entries: {

9+

"demo-plugin": {

10+

enabled: true,

11+

config: {

12+

enabled: false,

13+

mode: "strict",

14+

},

15+

},

16+

},

17+

},

18+

} as OpenClawConfig;

19+
20+

expect(resolvePluginConfigObject(config, "demo-plugin")).toEqual({

21+

enabled: false,

22+

mode: "strict",

23+

});

24+

});

25+
26+

it("returns undefined for missing or non-object plugin configs", () => {

27+

const config = {

28+

plugins: {

29+

entries: {

30+

"demo-plugin": {

31+

enabled: true,

32+

config: "bad-shape",

33+

},

34+

"array-plugin": {

35+

enabled: true,

36+

config: ["bad-shape"],

37+

},

38+

},

39+

},

40+

} as OpenClawConfig;

41+
42+

expect(resolvePluginConfigObject(config, "missing-plugin")).toBeUndefined();

43+

expect(resolvePluginConfigObject(config, "demo-plugin")).toBeUndefined();

44+

expect(resolvePluginConfigObject(config, "array-plugin")).toBeUndefined();

45+

expect(resolvePluginConfigObject(undefined, "demo-plugin")).toBeUndefined();

46+

});

47+

});

Original file line numberDiff line numberDiff line change

@@ -12,6 +12,28 @@ export function requireRuntimeConfig(config: OpenClawConfig, context: string): O

1212

);

1313

}

1414
15+

export function resolvePluginConfigObject(

16+

config: OpenClawConfig | undefined,

17+

pluginId: string,

18+

): Record<string, unknown> | undefined {

19+

const plugins =

20+

config?.plugins && typeof config.plugins === "object" && !Array.isArray(config.plugins)

21+

? (config.plugins as Record<string, unknown>)

22+

: undefined;

23+

const entries =

24+

plugins?.entries && typeof plugins.entries === "object" && !Array.isArray(plugins.entries)

25+

? (plugins.entries as Record<string, unknown>)

26+

: undefined;

27+

const entry = entries?.[pluginId];

28+

if (!entry || typeof entry !== "object" || Array.isArray(entry)) {

29+

return undefined;

30+

}

31+

const pluginConfig = (entry as { config?: unknown }).config;

32+

return pluginConfig && typeof pluginConfig === "object" && !Array.isArray(pluginConfig)

33+

? (pluginConfig as Record<string, unknown>)

34+

: undefined;

35+

}

36+
1537

export { resolveDefaultAgentId } from "../agents/agent-scope.js";

1638

export {

1739

clearRuntimeConfigSnapshot,