





















@@ -277,7 +277,19 @@ function installToolManifestSnapshots(params: {
277277policyHash: "test",
278278generatedAtMs: 0,
279279installRecords: {},
280-plugins: [],
280+plugins: plugins.map((plugin) => ({
281+pluginId: String(plugin.id),
282+origin: plugin.origin,
283+enabled: true,
284+enabledByDefault: plugin.enabledByDefault,
285+startup: {
286+sidecar: false,
287+memory: false,
288+deferConfiguredChannelFullLoadUntilAfterListen: false,
289+agentHarnesses: [],
290+},
291+compat: [],
292+})),
281293diagnostics: [],
282294},
283295registryDiagnostics: [],
@@ -301,7 +313,7 @@ function installToolManifestSnapshots(params: {
301313manifestRegistryMs: 0,
302314ownerMapsMs: 0,
303315totalMs: 0,
304-indexPluginCount: 0,
316+indexPluginCount: plugins.length,
305317manifestPluginCount: plugins.length,
306318},
307319} as never,
@@ -491,16 +503,28 @@ describe("resolvePluginTools optional tools", () => {
491503);
492504});
493505494-it("auto-loads cold registry for path-based (bundled-origin) plugins without pre-warming (#76598)", () => {
495-const config = createContext().config;
506+it("auto-loads cold registry for path-based config-origin plugins without pre-warming (#76598)", () => {
507+const context = {
508+ ...createContext(),
509+config: {
510+ ...createContext().config,
511+plugins: {
512+ ...createContext().config.plugins,
513+entries: {
514+"optional-demo": { enabled: true },
515+},
516+},
517+},
518+};
519+const config = context.config;
496520const registry = createToolRegistry([createOptionalDemoEntry()]);
497521loadOpenClawPluginsMock.mockReturnValue(registry);
498522installToolManifestSnapshot({
499523 config,
500524plugin: {
501525id: "optional-demo",
502-origin: "bundled",
503-enabledByDefault: true,
526+origin: "config",
527+enabledByDefault: undefined,
504528channels: [],
505529providers: [],
506530contracts: {
@@ -514,6 +538,7 @@ describe("resolvePluginTools optional tools", () => {
514538// This is the regression path from PR #76004 where path-based plugin tools disappeared.
515539const tools = resolvePluginTools(
516540createResolveToolsParams({
541+ context,
517542toolAllowlist: ["optional_tool"],
518543}),
519544);
@@ -528,6 +553,50 @@ describe("resolvePluginTools optional tools", () => {
528553);
529554});
530555556+it("warns when cold registry load still does not provide the selected plugin tools", () => {
557+const context = {
558+ ...createContext(),
559+config: {
560+ ...createContext().config,
561+plugins: {
562+ ...createContext().config.plugins,
563+entries: {
564+"optional-demo": { enabled: true },
565+},
566+},
567+},
568+};
569+const config = context.config;
570+const registry = createToolRegistry([]);
571+loadOpenClawPluginsMock.mockReturnValue(registry);
572+installToolManifestSnapshot({
573+ config,
574+plugin: {
575+id: "optional-demo",
576+origin: "config",
577+enabledByDefault: undefined,
578+channels: [],
579+providers: [],
580+contracts: {
581+tools: ["optional_tool"],
582+},
583+},
584+});
585+586+const tools = resolvePluginTools(
587+createResolveToolsParams({
588+ context,
589+toolAllowlist: ["optional_tool"],
590+}),
591+);
592+593+expect(tools).toEqual([]);
594+expectSingleDiagnosticMessage(
595+registry.diagnostics,
596+"plugin tool registry did not include selected plugin tools after cold load (optional-demo)",
597+);
598+});
599+531600it("does not reuse a pinned gateway registry for manifest-unavailable tools", () => {
532601const config = createContext().config;
533602installToolManifestSnapshot({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。