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

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
罗磊的独立博客
博客园 - 【当耐特】
M
MIT News - Artificial intelligence
月光博客
月光博客
博客园_首页
博客园 - 叶小钗
T
Tailwind CSS Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
I
InfoQ
量子位
小众软件
小众软件
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
IT之家
IT之家
Jina AI
Jina AI
阮一峰的网络日志
阮一峰的网络日志
G
Google Developers Blog
WordPress大学
WordPress大学
人人都是产品经理
人人都是产品经理
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
云风的 BLOG
云风的 BLOG
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报

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
perf: reuse gateway runtime metadata · openclaw/openclaw@...
steipete · 2026-05-30 · via Recent Commits to openclaw:main

@@ -4,6 +4,7 @@ import type { PluginAutoEnableResult } from "../config/plugin-auto-enable.js";

44

import { sortUniqueStrings } from "../shared/string-normalization.js";

55

import type { PluginManifestRecord } from "./manifest-registry.js";

66

import type { OpenClawPackageManifest } from "./manifest.js";

7+

import type { PluginMetadataSnapshot } from "./plugin-metadata-snapshot.types.js";

78

import type { PluginRegistrySnapshot } from "./plugin-registry.js";

89

import { createEmptyPluginRegistry } from "./registry-empty.js";

910

import type { ProviderPlugin } from "./types.js";

@@ -29,6 +30,7 @@ const loadOpenClawPluginsMock = vi.fn<LoadOpenClawPlugins>();

2930

const isPluginRegistryLoadInFlightMock = vi.fn<IsPluginRegistryLoadInFlight>((_) => false);

3031

const loadPluginManifestRegistryMock = vi.fn<LoadPluginManifestRegistry>();

3132

const loadPluginMetadataSnapshotMock = vi.fn<LoadPluginMetadataSnapshot>();

33+

const getCurrentPluginMetadataSnapshotMock = vi.fn();

3234

const applyPluginAutoEnableMock = vi.fn<ApplyPluginAutoEnable>();

33353436

let resolveOwningPluginIdsForProvider: typeof import("./providers.js").resolveOwningPluginIdsForProvider;

@@ -180,6 +182,45 @@ function createProviderRegistrySnapshotFixture(): PluginRegistrySnapshot {

180182

};

181183

}

182184185+

function createMetadataSnapshotFixture(

186+

plugins: PluginManifestRecord[],

187+

): Pick<PluginMetadataSnapshot, "owners" | "manifestRegistry" | "byPluginId"> {

188+

const ownerMap = (entries: Array<[string, readonly string[]]>) => new Map(entries);

189+

return {

190+

manifestRegistry: {

191+

plugins,

192+

diagnostics: [],

193+

},

194+

byPluginId: new Map(plugins.map((plugin) => [plugin.id, plugin])),

195+

owners: {

196+

channels: ownerMap([]),

197+

channelConfigs: ownerMap([]),

198+

providers: ownerMap(

199+

plugins.flatMap((plugin) =>

200+

plugin.providers.map((providerId) => [providerId, [plugin.id]] as const),

201+

),

202+

),

203+

modelCatalogProviders: ownerMap(

204+

plugins.flatMap((plugin) =>

205+

Object.keys(plugin.modelCatalog?.aliases ?? {}).map(

206+

(providerId) => [providerId, [plugin.id]] as const,

207+

),

208+

),

209+

),

210+

cliBackends: ownerMap(

211+

plugins.flatMap((plugin) =>

212+

[...plugin.cliBackends, ...(plugin.setup?.cliBackends ?? [])].map(

213+

(backendId) => [backendId, [plugin.id]] as const,

214+

),

215+

),

216+

),

217+

setupProviders: ownerMap([]),

218+

commandAliases: ownerMap([]),

219+

contracts: ownerMap([]),

220+

},

221+

};

222+

}

223+183224

function normalizeProviderForFixture(value: string): string {

184225

return value.trim().toLowerCase();

185226

}

@@ -475,6 +516,10 @@ describe("resolvePluginProviders", () => {

475516

};

476517

},

477518

}));

519+

vi.doMock("./current-plugin-metadata-snapshot.js", () => ({

520+

getCurrentPluginMetadataSnapshot: (...args: unknown[]) =>

521+

getCurrentPluginMetadataSnapshotMock(...args),

522+

}));

478523

vi.doMock("./plugin-registry.js", async () => {

479524

const actual =

480525

await vi.importActual<typeof import("./plugin-registry.js")>("./plugin-registry.js");

@@ -560,6 +605,96 @@ describe("resolvePluginProviders", () => {

560605

expectOwningPluginIds("moonshot-ai", ["moonshot"]);

561606

});

562607608+

it("uses the current metadata owner maps before loading plugin metadata", () => {

609+

const plugins = [

610+

createManifestProviderPlugin({

611+

id: "openai",

612+

providerIds: ["openai", "openai-codex"],

613+

}),

614+

];

615+

getCurrentPluginMetadataSnapshotMock.mockReturnValue(createMetadataSnapshotFixture(plugins));

616+617+

expectOwningPluginIds("openai-codex", ["openai"]);

618+619+

expect(loadPluginMetadataSnapshotMock).not.toHaveBeenCalled();

620+

expect(getCurrentPluginMetadataSnapshotMock).toHaveBeenCalledWith({

621+

config: undefined,

622+

env: undefined,

623+

allowWorkspaceScopedSnapshot: true,

624+

});

625+

});

626+627+

it("uses current metadata owner maps for cli backend provider refs", () => {

628+

const plugins = [

629+

createManifestProviderPlugin({

630+

id: "anthropic",

631+

providerIds: [],

632+

cliBackends: ["claude-cli"],

633+

}),

634+

];

635+

getCurrentPluginMetadataSnapshotMock.mockReturnValue(createMetadataSnapshotFixture(plugins));

636+637+

expect(resolveOwningPluginIdsForProviderRef({ provider: "claude-cli" })).toEqual(["anthropic"]);

638+639+

expect(loadPluginMetadataSnapshotMock).not.toHaveBeenCalled();

640+

});

641+642+

it("keeps normalized case-variant owners from current metadata maps", () => {

643+

const plugins = [

644+

createManifestProviderPlugin({

645+

id: "exact-owner",

646+

providerIds: ["codex-cli"],

647+

cliBackends: ["codex-cli"],

648+

}),

649+

createManifestProviderPlugin({

650+

id: "case-owner",

651+

providerIds: ["CODEX-CLI"],

652+

cliBackends: ["CODEX-CLI"],

653+

}),

654+

];

655+

getCurrentPluginMetadataSnapshotMock.mockReturnValue(createMetadataSnapshotFixture(plugins));

656+657+

expect(resolveOwningPluginIdsForProvider({ provider: "codex-cli" })).toEqual([

658+

"case-owner",

659+

"exact-owner",

660+

]);

661+

expect(resolveOwningPluginIdsForProviderRef({ provider: "codex-cli" })).toEqual([

662+

"case-owner",

663+

"exact-owner",

664+

]);

665+

});

666+667+

it("keeps explicit manifest registries ahead of current metadata owner maps", () => {

668+

getCurrentPluginMetadataSnapshotMock.mockReturnValue(

669+

createMetadataSnapshotFixture([

670+

createManifestProviderPlugin({

671+

id: "stale-owner",

672+

providerIds: ["dynamic-provider"],

673+

cliBackends: ["dynamic-cli"],

674+

}),

675+

]),

676+

);

677+

const manifestRegistry = {

678+

diagnostics: [],

679+

plugins: [

680+

createManifestProviderPlugin({

681+

id: "fresh-owner",

682+

providerIds: ["dynamic-provider"],

683+

cliBackends: ["dynamic-cli"],

684+

}),

685+

],

686+

};

687+688+

expect(

689+

resolveOwningPluginIdsForProvider({ provider: "dynamic-provider", manifestRegistry }),

690+

).toEqual(["fresh-owner"]);

691+

expect(

692+

resolveOwningPluginIdsForProviderRef({ provider: "dynamic-cli", manifestRegistry }),

693+

).toEqual(["fresh-owner"]);

694+695+

expect(getCurrentPluginMetadataSnapshotMock).not.toHaveBeenCalled();

696+

});

697+563698

it("reflects provider ownership manifest changes on the next lookup", () => {

564699

setManifestPlugins([

565700

createManifestProviderPlugin({

@@ -588,6 +723,8 @@ describe("resolvePluginProviders", () => {

588723

isPluginRegistryLoadInFlightMock.mockReset();

589724

isPluginRegistryLoadInFlightMock.mockReturnValue(false);

590725

loadPluginMetadataSnapshotMock.mockReset();

726+

getCurrentPluginMetadataSnapshotMock.mockReset();

727+

getCurrentPluginMetadataSnapshotMock.mockReturnValue(undefined);

591728

const provider: ProviderPlugin = {

592729

id: "demo-provider",

593730

label: "Demo Provider",

@@ -665,6 +802,28 @@ describe("resolvePluginProviders", () => {

665802

]);

666803

});

667804805+

it("does not answer explicit registry lookups from current metadata snapshots", () => {

806+

setOwningProviderManifestPlugins();

807+

getCurrentPluginMetadataSnapshotMock.mockReturnValue(

808+

createMetadataSnapshotFixture([

809+

createManifestProviderPlugin({

810+

id: "stale-owner",

811+

providerIds: ["stale-provider"],

812+

}),

813+

]),

814+

);

815+816+

expect(

817+

resolveEnabledProviderPluginIds({

818+

config: {},

819+

env: {} as NodeJS.ProcessEnv,

820+

registry: createProviderRegistrySnapshotFixture(),

821+

}),

822+

).toEqual([]);

823+824+

expect(getCurrentPluginMetadataSnapshotMock).not.toHaveBeenCalled();

825+

});

826+668827

it("loads catalog augment hooks only for declarative runtime catalog manifests", () => {

669828

setManifestPlugins([

670829

createManifestProviderPlugin({