Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Openclaw/src/plugins/   (KI Agentensystem Version 22©)  Datei vom 26.3.2026 mit Größe 39 kB image not shown  

Quelle  channel-plugin-ids.test.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

import { beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../config/config.js";

const listPotentialConfiguredChannelIds = vi.hoisted(() => vi.fn());
const listPotentialConfiguredChannelPresenceSignals = vi.hoisted(() => vi.fn());
const hasPotentialConfiguredChannels = vi.hoisted(() => vi.fn());
const hasMeaningfulChannelConfig = vi.hoisted(() =>
  vi.fn((value: unknown) => {
    return (
      !!value &&
      typeof value === "object" &&
      !Array.isArray(value) &&
      Object.keys(value).some((key) => key !== "enabled")
    );
  }),
);
const loadPluginManifestRegistry = vi.hoisted(() => vi.fn());

vi.mock("../channels/config-presence.js", () => ({
  listPotentialConfiguredChannelIds,
  listPotentialConfiguredChannelPresenceSignals,
  hasPotentialConfiguredChannels,
  hasMeaningfulChannelConfig,
}));

vi.mock("./manifest-registry.js", async (importOriginal) => {
  const actual = await importOriginal<typeof import("./manifest-registry.js")>();
  return {
    ...actual,
    loadPluginManifestRegistry,
  };
});

import {
  hasConfiguredChannelsForReadOnlyScope,
  listConfiguredAnnounceChannelIdsForConfig,
  listConfiguredChannelIdsForReadOnlyScope,
  listExplicitConfiguredChannelIdsForConfig,
  resolveConfiguredChannelPresencePolicy,
  resolveConfiguredDeferredChannelPluginIds,
  resolveConfiguredChannelPluginIds,
  resolveGatewayStartupPluginIds,
} from "./channel-plugin-ids.js";

function createManifestRegistryFixture() {
  return {
    plugins: [
      {
        id: "demo-channel",
        channels: ["demo-channel"],
        origin: "bundled",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "demo-other-channel",
        channels: ["demo-other-channel"],
        origin: "bundled",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "browser",
        channels: [],
        origin: "bundled",
        enabledByDefault: true,
        providers: [],
        cliBackends: [],
      },
      {
        id: "demo-provider-plugin",
        channels: [],
        origin: "bundled",
        enabledByDefault: undefined,
        providers: ["demo-provider"],
        cliBackends: ["demo-cli"],
      },
      {
        id: "codex",
        channels: [],
        activation: {
          onAgentHarnesses: ["codex"],
        },
        origin: "bundled",
        enabledByDefault: undefined,
        providers: ["codex"],
        cliBackends: [],
      },
      {
        id: "activation-only-channel-plugin",
        channels: [],
        activation: {
          onChannels: ["activation-only-channel"],
        },
        origin: "bundled",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "workspace-activation-channel-plugin",
        channels: [],
        activation: {
          onChannels: ["workspace-activation-channel"],
        },
        origin: "workspace",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "global-activation-channel-plugin",
        channels: [],
        activation: {
          onChannels: ["global-activation-channel"],
        },
        origin: "global",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "external-env-channel-plugin",
        channels: ["external-env-channel"],
        channelEnvVars: {
          "external-env-channel": ["EXTERNAL_ENV_CHANNEL_TOKEN"],
        },
        origin: "config",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "ambient-env-channel-plugin",
        channels: ["ambient-env-channel"],
        channelEnvVars: {
          "ambient-env-channel": ["HOME", "PATH"],
        },
        origin: "config",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "voice-call",
        channels: [],
        origin: "bundled",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "memory-core",
        kind: "memory",
        channels: [],
        origin: "bundled",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "memory-lancedb",
        kind: "memory",
        channels: [],
        origin: "bundled",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
      {
        id: "demo-global-sidecar",
        channels: [],
        origin: "global",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
    ],
    diagnostics: [],
  };
}

function createManifestRegistryFixtureWithWorkspaceDemoChannel() {
  const fixture = createManifestRegistryFixture();
  return {
    ...fixture,
    plugins: [
      ...fixture.plugins,
      {
        id: "workspace-demo-channel-plugin",
        channels: ["demo-channel"],
        startupDeferConfiguredChannelFullLoadUntilAfterListen: true,
        origin: "workspace",
        enabledByDefault: undefined,
        providers: [],
        cliBackends: [],
      },
    ],
  };
}

function expectStartupPluginIds(params: {
  config: OpenClawConfig;
  activationSourceConfig?: OpenClawConfig;
  env?: NodeJS.ProcessEnv;
  expected: readonly string[];
}) {
  expect(
    resolveGatewayStartupPluginIds({
      config: params.config,
      ...(params.activationSourceConfig !== undefined
        ? { activationSourceConfig: params.activationSourceConfig }
        : {}),
      workspaceDir: "/tmp",
      env: params.env ?? process.env,
    }),
  ).toEqual(params.expected);
  expect(loadPluginManifestRegistry).toHaveBeenCalled();
}

function expectStartupPluginIdsCase(params: {
  config: OpenClawConfig;
  activationSourceConfig?: OpenClawConfig;
  env?: NodeJS.ProcessEnv;
  expected: readonly string[];
}) {
  expectStartupPluginIds(params);
}

function createStartupConfig(params: {
  enabledPluginIds?: string[];
  providerIds?: string[];
  modelId?: string;
  embeddedHarnessRuntime?: string;
  agentEmbeddedHarnessRuntimes?: string[];
  channelIds?: string[];
  allowPluginIds?: string[];
  noConfiguredChannels?: boolean;
  memorySlot?: string;
}) {
  return {
    ...(params.noConfiguredChannels
      ? {
          channels: {},
        }
      : params.channelIds?.length
        ? {
            channels: Object.fromEntries(
              params.channelIds.map((channelId) => [channelId, { enabled: true }]),
            ),
          }
        : {}),
    ...(params.enabledPluginIds?.length
      ? {
          plugins: {
            ...(params.allowPluginIds?.length ? { allow: params.allowPluginIds } : {}),
            ...(params.memorySlot ? { slots: { memory: params.memorySlot } } : {}),
            entries: Object.fromEntries(
              params.enabledPluginIds.map((pluginId) => [pluginId, { enabled: true }]),
            ),
          },
        }
      : params.allowPluginIds?.length
        ? {
            plugins: {
              allow: params.allowPluginIds,
            },
          }
        : params.memorySlot
          ? {
              plugins: {
                slots: {
                  memory: params.memorySlot,
                },
              },
            }
          : {}),
    ...(params.providerIds?.length
      ? {
          models: {
            providers: Object.fromEntries(
              params.providerIds.map((providerId) => [
                providerId,
                {
                  baseUrl: "https://example.com",
                  models: [],
                },
              ]),
            ),
          },
        }
      : {}),
    ...(params.modelId
      ? {
          agents: {
            defaults: {
              model: { primary: params.modelId },
              ...(params.embeddedHarnessRuntime
                ? {
                    embeddedHarness: {
                      runtime: params.embeddedHarnessRuntime,
                      fallback: "none",
                    },
                  }
                : {}),
              models: {
                [params.modelId]: {},
              },
            },
            ...(params.agentEmbeddedHarnessRuntimes?.length
              ? {
                  list: params.agentEmbeddedHarnessRuntimes.map((runtime, index) => ({
                    id: `agent-${index + 1}`,
                    embeddedHarness: { runtime },
                  })),
                }
              : {}),
          },
        }
      : params.embeddedHarnessRuntime || params.agentEmbeddedHarnessRuntimes?.length
        ? {
            agents: {
              defaults: params.embeddedHarnessRuntime
                ? {
                    embeddedHarness: {
                      runtime: params.embeddedHarnessRuntime,
                      fallback: "none",
                    },
                  }
                : {},
              ...(params.agentEmbeddedHarnessRuntimes?.length
                ? {
                    list: params.agentEmbeddedHarnessRuntimes.map((runtime, index) => ({
                      id: `agent-${index + 1}`,
                      embeddedHarness: { runtime },
                    })),
                  }
                : {}),
            },
          }
        : {}),
  } as OpenClawConfig;
}

describe("resolveGatewayStartupPluginIds", () => {
  beforeEach(() => {
    listPotentialConfiguredChannelIds.mockReset().mockImplementation((config: OpenClawConfig) => {
      if (Object.prototype.hasOwnProperty.call(config, "channels")) {
        return Object.keys(config.channels ?? {});
      }
      return ["demo-channel"];
    });
    listPotentialConfiguredChannelPresenceSignals
      .mockReset()
      .mockImplementation((config: OpenClawConfig) => {
        return listPotentialConfiguredChannelIds(config).map((channelId: string) => ({
          channelId,
          source: "config",
        }));
      });
    hasPotentialConfiguredChannels.mockReset().mockImplementation((config: OpenClawConfig) => {
      if (Object.prototype.hasOwnProperty.call(config, "channels")) {
        return Object.keys(config.channels ?? {}).length > 0;
      }
      return true;
    });
    loadPluginManifestRegistry.mockReset().mockReturnValue(createManifestRegistryFixture());
  });

  it.each([
    [
      "includes only configured channel plugins at idle startup",
      createStartupConfig({
        enabledPluginIds: ["voice-call"],
        modelId: "demo-cli/demo-model",
      }),
      ["demo-channel", "browser", "voice-call"],
    ],
    [
      "keeps bundled startup sidecars with enabledByDefault at idle startup",
      {} as OpenClawConfig,
      ["demo-channel", "browser"],
    ],
    [
      "keeps provider plugins out of idle startup when only provider config references them",
      createStartupConfig({
        providerIds: ["demo-provider"],
      }),
      ["demo-channel", "browser"],
    ],
    [
      "includes explicitly enabled non-channel sidecars in startup scope",
      createStartupConfig({
        enabledPluginIds: ["demo-global-sidecar", "voice-call"],
      }),
      ["demo-channel", "browser", "voice-call", "demo-global-sidecar"],
    ],
    [
      "keeps default-enabled startup sidecars when a restrictive allowlist permits them",
      createStartupConfig({
        allowPluginIds: ["browser"],
        noConfiguredChannels: true,
      }),
      ["browser"],
    ],
    [
      "includes every configured channel plugin and excludes other channels",
      createStartupConfig({
        channelIds: ["demo-channel", "demo-other-channel"],
      }),
      ["demo-channel", "demo-other-channel", "browser"],
    ],
  ] as const)("%s", (_name, config, expected) => {
    expectStartupPluginIdsCase({ config, expected });
  });

  it("keeps effective-only bundled sidecars behind restrictive allowlists", () => {
    const rawConfig = createStartupConfig({
      allowPluginIds: ["browser"],
    });
    const effectiveConfig = {
      ...rawConfig,
      plugins: {
        allow: ["browser"],
        entries: {
          "voice-call": {
            enabled: true,
          },
          "memory-core": {
            enabled: true,
          },
        },
      },
    } as OpenClawConfig;

    expectStartupPluginIdsCase({
      config: effectiveConfig,
      activationSourceConfig: rawConfig,
      expected: ["browser"],
    });
  });

  it("does not let weak channel presence start untrusted workspace channel owners", () => {
    loadPluginManifestRegistry
      .mockReset()
      .mockReturnValue(createManifestRegistryFixtureWithWorkspaceDemoChannel());
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
    ]);

    const config = {} as OpenClawConfig;

    expectStartupPluginIdsCase({
      config,
      env: {
        DEMO_CHANNEL_ANYTHING: "1",
      } as NodeJS.ProcessEnv,
      expected: ["demo-channel", "browser"],
    });
    expect(
      resolveConfiguredDeferredChannelPluginIds({
        config,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_ANYTHING: "1",
        } as NodeJS.ProcessEnv,
      }),
    ).toEqual([]);
  });

  it("keeps explicitly trusted deferred channel owners eligible at startup", () => {
    loadPluginManifestRegistry
      .mockReset()
      .mockReturnValue(createManifestRegistryFixtureWithWorkspaceDemoChannel());
    expect(
      resolveConfiguredDeferredChannelPluginIds({
        config: {
          channels: {
            "demo-channel": {
              token: "configured",
            },
          },
          plugins: {
            allow: ["workspace-demo-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
      }),
    ).toEqual(["workspace-demo-channel-plugin"]);
  });

  it("preserves explicit bundled channel config under restrictive allowlists", () => {
    expectStartupPluginIdsCase({
      config: {
        channels: {
          "demo-channel": {
            token: "configured",
          },
        },
        plugins: {
          allow: ["browser"],
        },
      } as OpenClawConfig,
      env: {},
      expected: ["demo-channel", "browser"],
    });
  });

  it("does not treat explicitly disabled stale channel config as startup intent", () => {
    expectStartupPluginIdsCase({
      config: {
        channels: {
          "demo-channel": {
            enabled: false,
            token: "stale",
          },
        },
      } as OpenClawConfig,
      env: {},
      expected: ["browser"],
    });
  });

  it("does not treat explicitly disabled stale channel config as deferred startup intent", () => {
    loadPluginManifestRegistry
      .mockReset()
      .mockReturnValue(createManifestRegistryFixtureWithWorkspaceDemoChannel());

    expect(
      resolveConfiguredDeferredChannelPluginIds({
        config: {
          channels: {
            "demo-channel": {
              enabled: false,
              token: "stale",
            },
          },
          plugins: {
            allow: ["workspace-demo-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
      }),
    ).toEqual([]);
  });

  it("includes the explicitly selected memory slot plugin in startup scope", () => {
    expectStartupPluginIdsCase({
      config: createStartupConfig({
        enabledPluginIds: ["memory-lancedb"],
        memorySlot: "memory-lancedb",
      }),
      expected: ["demo-channel", "browser", "memory-lancedb"],
    });
  });

  it("normalizes the raw memory slot id before startup filtering", () => {
    expectStartupPluginIdsCase({
      config: createStartupConfig({
        enabledPluginIds: ["memory-core"],
        memorySlot: "Memory-Core",
      }),
      expected: ["demo-channel", "browser", "memory-core"],
    });
  });

  it("does not include non-selected memory plugins only because they are enabled", () => {
    expectStartupPluginIdsCase({
      config: createStartupConfig({
        enabledPluginIds: ["memory-lancedb"],
      }),
      expected: ["demo-channel", "browser"],
    });
  });

  it("includes required agent harness owner plugins when the default runtime is forced", () => {
    expectStartupPluginIdsCase({
      config: createStartupConfig({
        embeddedHarnessRuntime: "codex",
        enabledPluginIds: ["codex"],
      }),
      expected: ["demo-channel", "browser", "codex"],
    });
  });

  it("includes required agent harness owner plugins when an agent override forces the runtime", () => {
    expectStartupPluginIdsCase({
      config: createStartupConfig({
        agentEmbeddedHarnessRuntimes: ["codex"],
        enabledPluginIds: ["codex"],
      }),
      expected: ["demo-channel", "browser", "codex"],
    });
  });

  it("includes required agent harness owner plugins when env forces the runtime", () => {
    expectStartupPluginIdsCase({
      config: createStartupConfig({
        enabledPluginIds: ["codex"],
      }),
      env: { OPENCLAW_AGENT_RUNTIME: "codex" },
      expected: ["demo-channel", "browser", "codex"],
    });
  });

  it("does not include required agent harness owner plugins when they are explicitly disabled", () => {
    expectStartupPluginIdsCase({
      config: {
        agents: {
          defaults: {
            embeddedHarness: {
              runtime: "codex",
              fallback: "none",
            },
          },
        },
        plugins: {
          entries: {
            codex: {
              enabled: false,
            },
          },
        },
      } as OpenClawConfig,
      expected: ["demo-channel", "browser"],
    });
  });
});

describe("resolveConfiguredChannelPluginIds", () => {
  beforeEach(() => {
    listPotentialConfiguredChannelIds.mockReset().mockImplementation((config: OpenClawConfig) => {
      if (Object.prototype.hasOwnProperty.call(config, "channels")) {
        return Object.keys(config.channels ?? {});
      }
      return [];
    });
    listPotentialConfiguredChannelPresenceSignals
      .mockReset()
      .mockImplementation((config: OpenClawConfig) => {
        return listPotentialConfiguredChannelIds(config).map((channelId: string) => ({
          channelId,
          source: "config",
        }));
      });
    hasPotentialConfiguredChannels.mockReset().mockImplementation((config: OpenClawConfig) => {
      if (Object.prototype.hasOwnProperty.call(config, "channels")) {
        return Object.keys(config.channels ?? {}).length > 0;
      }
      return false;
    });
    loadPluginManifestRegistry.mockReset().mockReturnValue(createManifestRegistryFixture());
  });

  it("uses manifest activation channel ownership before falling back to direct channel lists", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: createStartupConfig({
          channelIds: ["activation-only-channel"],
        }),
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual(["activation-only-channel-plugin"]);
  });

  it("keeps bundled activation owners behind restrictive allowlists", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: createStartupConfig({
          channelIds: ["activation-only-channel"],
          allowPluginIds: ["browser"],
        }),
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });

  it("keeps explicitly configured bundled channel owners under restrictive allowlists", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: {
          channels: {
            "demo-channel": {
              token: "configured",
            },
          },
          plugins: {
            allow: ["browser"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
      }),
    ).toEqual(["demo-channel"]);
  });

  it("blocks bundled activation owners when explicitly denied", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: {
          channels: {
            "activation-only-channel": { enabled: true },
          },
          plugins: {
            deny: ["activation-only-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });

  it("blocks bundled activation owners when plugins are globally disabled", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: {
          channels: {
            "activation-only-channel": { enabled: true },
          },
          plugins: {
            enabled: false,
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });

  it("filters untrusted workspace activation owners from configured-channel runtime planning", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: createStartupConfig({
          channelIds: ["workspace-activation-channel"],
        }),
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });

  it("filters untrusted global activation owners from configured-channel runtime planning", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: createStartupConfig({
          channelIds: ["global-activation-channel"],
        }),
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });

  it("keeps explicitly enabled global activation owners eligible for configured-channel runtime planning", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: createStartupConfig({
          channelIds: ["global-activation-channel"],
          enabledPluginIds: ["global-activation-channel-plugin"],
        }),
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual(["global-activation-channel-plugin"]);
  });

  it("does not treat auto-enabled non-bundled channel owners as explicitly trusted", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: createStartupConfig({
          channelIds: ["global-activation-channel"],
          enabledPluginIds: ["global-activation-channel-plugin"],
        }),
        activationSourceConfig: createStartupConfig({
          channelIds: ["global-activation-channel"],
        }),
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });

  it("includes trusted external channel owners configured only by manifest env vars", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: {
          plugins: {
            allow: ["external-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
      }),
    ).toEqual(["external-env-channel-plugin"]);
  });

  it("blocks bundled activation owners when explicitly disabled", () => {
    expect(
      resolveConfiguredChannelPluginIds({
        config: {
          channels: {
            "activation-only-channel": { enabled: true },
          },
          plugins: {
            entries: {
              "activation-only-channel-plugin": {
                enabled: false,
              },
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: process.env,
      }),
    ).toEqual([]);
  });
});

describe("listConfiguredChannelIdsForReadOnlyScope", () => {
  beforeEach(() => {
    listPotentialConfiguredChannelIds.mockReset().mockReturnValue([]);
    listPotentialConfiguredChannelPresenceSignals.mockReset().mockReturnValue([]);
    hasPotentialConfiguredChannels.mockReset().mockReturnValue(false);
    hasMeaningfulChannelConfig.mockClear();
    loadPluginManifestRegistry.mockReset().mockReturnValue(createManifestRegistryFixture());
  });

  it("filters bundled ambient channel triggers through effective activation", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
    ]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["memory-core"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([]);

    expect(
      hasConfiguredChannelsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["memory-core"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toBe(false);
  });

  it("returns reason-rich policy entries for blocked ambient channel triggers", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
    ]);

    expect(
      resolveConfiguredChannelPresencePolicy({
        config: {
          plugins: {
            allow: ["memory-core"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([
      {
        channelId: "demo-channel",
        sources: ["env"],
        effective: false,
        pluginIds: [],
        blockedReasons: ["not-in-allowlist"],
      },
    ]);
  });

  it("keeps explicitly enabled bundled ambient channel triggers", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
    ]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          plugins: {
            entries: {
              "demo-channel": {
                enabled: true,
              },
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual(["demo-channel"]);
  });

  it("treats enabled-only channel config as explicit read-only intent", () => {
    expect(
      resolveConfiguredChannelPresencePolicy({
        config: {
          channels: {
            "demo-channel": {
              enabled: true,
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual([
      {
        channelId: "demo-channel",
        sources: ["explicit-config"],
        effective: true,
        pluginIds: ["demo-channel"],
        blockedReasons: [],
      },
    ]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          channels: {
            "demo-channel": {
              enabled: true,
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual(["demo-channel"]);
  });

  it("does not treat disabled stale channel config as explicit read-only intent", () => {
    const config = {
      channels: {
        "demo-channel": {
          enabled: false,
          token: "stale-token",
        },
      },
    } as OpenClawConfig;

    expect(listExplicitConfiguredChannelIdsForConfig(config)).toEqual([]);
    expect(
      resolveConfiguredChannelPresencePolicy({
        config,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
  });

  it("treats disabled channel config as a hard read-only env suppressor", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
    ]);

    const config = {
      channels: {
        "Demo-Channel": {
          enabled: false,
          token: "stale-token",
        },
      },
      plugins: {
        entries: {
          "demo-channel": {
            enabled: true,
          },
        },
      },
    } as OpenClawConfig;

    expect(
      resolveConfiguredChannelPresencePolicy({
        config,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "ambient",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "ambient",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
  });

  it("treats disabled channel config as a hard persisted-auth suppressor", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "persisted-auth" },
    ]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          channels: {
            "demo-channel": {
              enabled: false,
            },
          },
          plugins: {
            entries: {
              "demo-channel": {
                enabled: true,
              },
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
      }),
    ).toEqual([]);
  });

  it("treats disabled channel config as a hard manifest-env suppressor", () => {
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          channels: {
            "external-env-channel": {
              enabled: false,
            },
          },
          plugins: {
            allow: ["external-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
  });

  it("lets explicit bundled channel config bypass restrictive allowlists", () => {
    const config = {
      channels: {
        "demo-channel": {
          token: "configured",
        },
      },
      plugins: {
        allow: ["browser"],
      },
    } as OpenClawConfig;

    expect(
      resolveConfiguredChannelPresencePolicy({
        config,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual([
      {
        channelId: "demo-channel",
        sources: ["explicit-config"],
        effective: true,
        pluginIds: ["demo-channel"],
        blockedReasons: [],
      },
    ]);
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual(["demo-channel"]);
  });

  it("keeps explicitly configured bundled channels discovered from potential ids", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "config" },
    ]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          channels: {
            "demo-channel": {
              token: "configured",
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual(["demo-channel"]);
  });

  it("blocks explicitly configured bundled channels when plugins are disabled or denied", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "config" },
    ]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          channels: {
            "demo-channel": {
              token: "configured",
            },
          },
          plugins: {
            enabled: false,
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual([]);

    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          channels: {
            "demo-channel": {
              token: "configured",
            },
          },
          plugins: {
            deny: ["demo-channel"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {},
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
  });

  it("lists explicit configured channels without ambient env triggers", () => {
    expect(
      listExplicitConfiguredChannelIdsForConfig({
        channels: {
          defaults: {
            model: "sonnet-4.6",
          },
          "demo-channel": {
            token: "configured",
          },
          "demo-other-channel": {
            enabled: false,
          },
        },
      } as OpenClawConfig),
    ).toEqual(["demo-channel"]);
  });

  it("does not let disabled mixed-case channel config announce ambient matches", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
    ]);

    expect(
      listConfiguredAnnounceChannelIdsForConfig({
        config: {
          channels: {
            "Demo-Channel": {
              enabled: false,
              token: "stale-token",
            },
          },
          plugins: {
            entries: {
              "demo-channel": {
                enabled: true,
              },
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "ambient",
        } as NodeJS.ProcessEnv,
      }),
    ).toEqual([]);
  });

  it("uses effective read-only channel policy for announce channels", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["demo-channel", "demo-other-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "demo-channel", source: "env" },
      { channelId: "demo-other-channel", source: "config" },
    ]);

    expect(
      listConfiguredAnnounceChannelIdsForConfig({
        config: {
          channels: {
            "demo-other-channel": {
              token: "configured",
            },
          },
          plugins: {
            allow: ["demo-other-channel"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          DEMO_CHANNEL_TOKEN: "ambient",
        } as NodeJS.ProcessEnv,
      }),
    ).toEqual(["demo-other-channel"]);
  });

  it("does not treat activation-only declarations as channel ownership", () => {
    listPotentialConfiguredChannelIds.mockReturnValue(["activation-only-channel"]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([
      { channelId: "activation-only-channel", source: "env" },
    ]);

    expect(
      resolveConfiguredChannelPresencePolicy({
        config: {
          plugins: {
            entries: {
              "activation-only-channel-plugin": {
                enabled: true,
              },
            },
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          ACTIVATION_ONLY_CHANNEL_TOKEN: "ambient",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([
      {
        channelId: "activation-only-channel",
        sources: ["env"],
        effective: false,
        pluginIds: [],
        blockedReasons: ["no-channel-owner"],
      },
    ]);
  });

  it("uses manifest env vars as read-only configured channel triggers", () => {
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["external-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual(["external-env-channel"]);
  });

  it("ignores manifest env vars from untrusted external plugins", () => {
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {} as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([]);

    expect(
      hasConfiguredChannelsForReadOnlyScope({
        config: {} as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toBe(false);
  });

  it("ignores ambient or malformed manifest env vars as read-only configured channel triggers", () => {
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["ambient-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          HOME: "/tmp/user",
          PATH: "/usr/bin",
          lowercase_token: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toEqual([]);
  });

  it("accepts lowercase or mixed-case manifest env vars as read-only configured channel triggers", () => {
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["external-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          external_env_channel_token: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
        manifestRecords: [
          {
            id: "external-env-channel-plugin",
            channels: ["external-env-channel"],
            channelEnvVars: {
              "external-env-channel": ["external_env_channel_token"],
            },
            origin: "config",
            enabledByDefault: undefined,
            providers: [],
            cliBackends: [],
          } as never,
        ],
      }),
    ).toEqual(["external-env-channel"]);
  });

  it("matches uppercase process env entries for lowercase manifest env var declarations", () => {
    expect(
      listConfiguredChannelIdsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["external-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
        manifestRecords: [
          {
            id: "external-env-channel-plugin",
            channels: ["external-env-channel"],
            channelEnvVars: {
              "external-env-channel": ["external_env_channel_token"],
            },
            origin: "config",
            enabledByDefault: undefined,
            providers: [],
            cliBackends: [],
          } as never,
        ],
      }),
    ).toEqual(["external-env-channel"]);
  });

  it("uses manifest env vars for read-only channel presence checks", () => {
    listPotentialConfiguredChannelIds.mockReturnValue([]);
    listPotentialConfiguredChannelPresenceSignals.mockReturnValue([]);
    hasPotentialConfiguredChannels.mockReturnValue(false);

    expect(
      hasConfiguredChannelsForReadOnlyScope({
        config: {
          plugins: {
            allow: ["external-env-channel-plugin"],
          },
        } as OpenClawConfig,
        workspaceDir: "/tmp",
        env: {
          EXTERNAL_ENV_CHANNEL_TOKEN: "token",
        } as NodeJS.ProcessEnv,
        includePersistedAuthState: false,
      }),
    ).toBe(true);
  });
});

¤ Dauer der Verarbeitung: 0.5 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.