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

Quelle  exec-approvals.test.ts

  Sprache: JAVA
 

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

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { afterEach, describe, expect, it } from "vitest";
import {
  getMatrixExecApprovalApprovers,
  isMatrixExecApprovalApprover,
  isMatrixExecApprovalAuthorizedSender,
  isMatrixExecApprovalClientEnabled,
  isMatrixExecApprovalTargetRecipient,
  normalizeMatrixApproverId,
  resolveMatrixExecApprovalTarget,
  shouldHandleMatrixExecApprovalRequest,
  shouldSuppressLocalMatrixExecApprovalPrompt,
} from "./exec-approvals.js";
import type { MatrixAccountConfig, MatrixExecApprovalConfig } from "./types.js";

const tempDirs: string[] = [];
type MatrixExecApprovalRequest = Parameters<
  typeof shouldHandleMatrixExecApprovalRequest
>[0]["request"];

afterEach(() => {
  for (const dir of tempDirs.splice(0)) {
    fs.rmSync(dir, { recursive: true, force: true });
  }
});

function createTempDir(): string {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-matrix-exec-approvals-"));
  tempDirs.push(dir);
  return dir;
}

function buildConfig(
  execApprovals?: NonNullable<NonNullable<OpenClawConfig["channels"]>["matrix"]>["execApprovals"],
  channelOverrides?: Partial<NonNullable<NonNullable<OpenClawConfig["channels"]>["matrix"]>>,
): OpenClawConfig {
  return {
    channels: {
      matrix: {
        homeserver: "https://matrix.example.org",
        userId: "@bot:example.org",
        accessToken: "tok",
        ...channelOverrides,
        execApprovals,
      },
    },
  } as OpenClawConfig;
}

function matrixAccount(
  accountId: string,
  execApprovals: MatrixExecApprovalConfig,
  overrides: Partial<MatrixAccountConfig> = {},
): MatrixAccountConfig {
  return {
    homeserver: "https://matrix.example.org",
    userId: `@bot-${accountId}:example.org`,
    accessToken: `tok-${accountId}`,
    ...overrides,
    execApprovals,
  };
}

function buildMultiAccountMatrixConfig(params: {
  sessionStorePath?: string;
  defaultExecApprovals?: MatrixExecApprovalConfig;
  opsExecApprovals?: MatrixExecApprovalConfig;
  defaultOverrides?: Partial<MatrixAccountConfig>;
  opsOverrides?: Partial<MatrixAccountConfig>;
}): OpenClawConfig {
  return {
    ...(params.sessionStorePath ? { session: { store: params.sessionStorePath } } : {}),
    channels: {
      matrix: {
        accounts: {
          default: matrixAccount(
            "default",
            params.defaultExecApprovals ?? {
              enabled: true,
              approvers: ["@owner:example.org"],
            },
            params.defaultOverrides,
          ),
          ops: matrixAccount(
            "ops",
            params.opsExecApprovals ?? {
              enabled: true,
              approvers: ["@owner:example.org"],
            },
            params.opsOverrides,
          ),
        },
      },
    },
  } as OpenClawConfig;
}

function makeForeignChannelApprovalRequest(params: {
  id: string;
  sessionKey?: string;
  agentId?: string;
}): MatrixExecApprovalRequest {
  return {
    id: params.id,
    request: {
      command: "echo hi",
      agentId: params.agentId ?? "ops-agent",
      sessionKey: params.sessionKey ?? "agent:ops-agent:missing",
      turnSourceChannel: "slack",
      turnSourceTo: "channel:C123",
    },
    createdAtMs: 0,
    expiresAtMs: 1000,
  };
}

describe("matrix exec approvals", () => {
  it("requires enablement and approvers before enabling the client", () => {
    expect(isMatrixExecApprovalClientEnabled({ cfg: buildConfig() })).toBe(false);
    expect(
      isMatrixExecApprovalClientEnabled({
        cfg: buildConfig(undefined, { dm: { allowFrom: ["@owner:example.org"] } }),
      }),
    ).toBe(false);
    expect(isMatrixExecApprovalClientEnabled({ cfg: buildConfig({ enabled: true }) })).toBe(false);
    expect(
      isMatrixExecApprovalClientEnabled({
        cfg: buildConfig({ enabled: true }, { dm: { allowFrom: ["@owner:example.org"] } }),
      }),
    ).toBe(true);
    expect(
      isMatrixExecApprovalClientEnabled({
        cfg: buildConfig({ enabled: true, approvers: ["@owner:example.org"] }),
      }),
    ).toBe(true);
  });

  it("prefers explicit approvers when configured", () => {
    const cfg = buildConfig(
      { enabled: true, approvers: ["user:@override:example.org"] },
      { dm: { allowFrom: ["@owner:example.org"] } },
    );

    expect(getMatrixExecApprovalApprovers({ cfg })).toEqual(["@override:example.org"]);
    expect(isMatrixExecApprovalApprover({ cfg, senderId: "@override:example.org" })).toBe(true);
    expect(isMatrixExecApprovalApprover({ cfg, senderId: "@owner:example.org" })).toBe(false);
  });

  it("ignores wildcard allowlist entries when inferring exec approvers", () => {
    const cfg = buildConfig({ enabled: true }, { dm: { allowFrom: ["*"] } });

    expect(getMatrixExecApprovalApprovers({ cfg })).toEqual([]);
    expect(isMatrixExecApprovalClientEnabled({ cfg })).toBe(false);
  });

  it("defaults target to dm", () => {
    expect(
      resolveMatrixExecApprovalTarget({
        cfg: buildConfig({ enabled: true, approvers: ["@owner:example.org"] }),
      }),
    ).toBe("dm");
  });

  it("matches matrix target recipients from generic approval forwarding targets", () => {
    const cfg = {
      channels: {
        matrix: {
          homeserver: "https://matrix.example.org",
          userId: "@bot:example.org",
          accessToken: "tok",
        },
      },
      approvals: {
        exec: {
          enabled: true,
          mode: "targets",
          targets: [
            { channel: "matrix", to: "user:@target:example.org" },
            { channel: "matrix", to: "room:!ops:example.org" },
          ],
        },
      },
    } as OpenClawConfig;

    expect(isMatrixExecApprovalTargetRecipient({ cfg, senderId: "@target:example.org" })).toBe(
      true,
    );
    expect(isMatrixExecApprovalTargetRecipient({ cfg, senderId: "@other:example.org" })).toBe(
      false,
    );
    expect(isMatrixExecApprovalAuthorizedSender({ cfg, senderId: "@target:example.org" })).toBe(
      true,
    );
  });

  it("suppresses local prompts only when the native client is enabled", () => {
    const payload = {
      channelData: {
        execApproval: {
          approvalId: "req-1",
          approvalSlug: "req-1",
          agentId: "ops-agent",
          sessionKey: "agent:ops-agent:matrix:channel:!ops:example.org",
        },
      },
    };

    expect(
      shouldSuppressLocalMatrixExecApprovalPrompt({
        cfg: buildConfig({ enabled: true, approvers: ["@owner:example.org"] }),
        payload,
      }),
    ).toBe(true);

    expect(
      shouldSuppressLocalMatrixExecApprovalPrompt({
        cfg: buildConfig(),
        payload,
      }),
    ).toBe(false);
  });

  it("keeps local prompts when filters exclude the request", () => {
    const payload = {
      channelData: {
        execApproval: {
          approvalId: "req-1",
          approvalSlug: "req-1",
          agentId: "other-agent",
          sessionKey: "agent:other-agent:matrix:channel:!ops:example.org",
        },
      },
    };

    expect(
      shouldSuppressLocalMatrixExecApprovalPrompt({
        cfg: buildConfig({
          enabled: true,
          approvers: ["@owner:example.org"],
          agentFilter: ["ops-agent"],
        }),
        payload,
      }),
    ).toBe(false);
  });

  it("suppresses local prompts for generic exec payloads when metadata matches filters", () => {
    const payload = {
      channelData: {
        execApproval: {
          approvalId: "req-1",
          approvalSlug: "req-1",
          approvalKind: "exec",
          agentId: "ops-agent",
          sessionKey: "agent:ops-agent:matrix:channel:!ops:example.org",
        },
      },
    };

    expect(
      shouldSuppressLocalMatrixExecApprovalPrompt({
        cfg: buildConfig({
          enabled: true,
          approvers: ["@owner:example.org"],
          agentFilter: ["ops-agent"],
          sessionFilter: ["matrix:channel:"],
        }),
        payload,
      }),
    ).toBe(true);
  });

  it("suppresses local prompts for plugin approval payloads when DM approvers are configured", () => {
    const payload = {
      channelData: {
        execApproval: {
          approvalId: "plugin:req-1",
          approvalSlug: "plugin:r",
          approvalKind: "plugin",
        },
      },
    };

    expect(
      shouldSuppressLocalMatrixExecApprovalPrompt({
        cfg: buildConfig(
          { enabled: true, approvers: ["@owner:example.org"] },
          { dm: { allowFrom: ["@owner:example.org"] } },
        ),
        payload,
      }),
    ).toBe(true);
  });

  it("normalizes prefixed approver ids", () => {
    expect(normalizeMatrixApproverId("matrix:@owner:example.org")).toBe("@owner:example.org");
    expect(normalizeMatrixApproverId("user:@owner:example.org")).toBe("@owner:example.org");
  });

  it("applies agent and session filters to request handling", () => {
    const cfg = buildConfig({
      enabled: true,
      approvers: ["@owner:example.org"],
      agentFilter: ["ops-agent"],
      sessionFilter: ["matrix:channel:", "ops$"],
    });

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        request: {
          id: "req-1",
          request: {
            command: "echo hi",
            agentId: "ops-agent",
            sessionKey: "agent:ops-agent:matrix:channel:!room:example.org:ops",
          },
          createdAtMs: 0,
          expiresAtMs: 1000,
        },
      }),
    ).toBe(true);

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        request: {
          id: "req-2",
          request: {
            command: "echo hi",
            agentId: "other-agent",
            sessionKey: "agent:other-agent:matrix:channel:!room:example.org:ops",
          },
          createdAtMs: 0,
          expiresAtMs: 1000,
        },
      }),
    ).toBe(false);
  });

  it("scopes non-matrix turn sources to the stored matrix account", () => {
    const tmpDir = createTempDir();
    const storePath = path.join(tmpDir, "sessions.json");
    fs.writeFileSync(
      storePath,
      JSON.stringify({
        "agent:ops-agent:matrix:channel:!room:example.org": {
          sessionId: "main",
          updatedAt: 1,
          origin: {
            provider: "matrix",
            accountId: "ops",
          },
          lastChannel: "slack",
          lastTo: "channel:C999",
          lastAccountId: "work",
        },
      }),
      "utf-8",
    );
    const cfg = buildMultiAccountMatrixConfig({ sessionStorePath: storePath });
    const request = makeForeignChannelApprovalRequest({
      id: "req-3",
      sessionKey: "agent:ops-agent:matrix:channel:!room:example.org",
    });

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "default",
        request,
      }),
    ).toBe(false);
    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "ops",
        request,
      }),
    ).toBe(true);
  });

  it("rejects unbound foreign-channel approvals in multi-account matrix configs", () => {
    const cfg = buildMultiAccountMatrixConfig({});
    const request = makeForeignChannelApprovalRequest({ id: "req-4" });

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "default",
        request,
      }),
    ).toBe(false);
    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "ops",
        request,
      }),
    ).toBe(false);
  });

  it("allows unbound foreign-channel approvals when only one matrix account can handle them", () => {
    const cfg = buildMultiAccountMatrixConfig({
      opsExecApprovals: {
        enabled: false,
        approvers: ["@owner:example.org"],
      },
    });
    const request = makeForeignChannelApprovalRequest({ id: "req-5" });

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "default",
        request,
      }),
    ).toBe(true);
    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "ops",
        request,
      }),
    ).toBe(false);
  });

  it("uses request filters when checking foreign-channel matrix ambiguity", () => {
    const cfg = buildMultiAccountMatrixConfig({
      defaultExecApprovals: {
        enabled: true,
        approvers: ["@owner:example.org"],
        agentFilter: ["ops-agent"],
      },
      opsExecApprovals: {
        enabled: true,
        approvers: ["@owner:example.org"],
        agentFilter: ["other-agent"],
      },
    });
    const request = makeForeignChannelApprovalRequest({ id: "req-6" });

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "default",
        request,
      }),
    ).toBe(true);
    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "ops",
        request,
      }),
    ).toBe(false);
  });

  it("ignores disabled matrix accounts when checking foreign-channel ambiguity", () => {
    const cfg = buildMultiAccountMatrixConfig({
      opsOverrides: { enabled: false },
    });
    const request = makeForeignChannelApprovalRequest({ id: "req-7" });

    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "default",
        request,
      }),
    ).toBe(true);
    expect(
      shouldHandleMatrixExecApprovalRequest({
        cfg,
        accountId: "ops",
        request,
      }),
    ).toBe(false);
  });
});

¤ Dauer der Verarbeitung: 0.1 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.