Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  actions.ts

  Sprache: JAVA
 

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

import {
  createActionGate,
  readNumberParam,
  readStringParam,
  ToolAuthorizationError,
} from "openclaw/plugin-sdk/channel-actions";
import type {
  ChannelMessageActionAdapter,
  ChannelMessageActionContext,
  ChannelMessageActionName,
  ChannelMessageToolDiscovery,
} from "openclaw/plugin-sdk/channel-contract";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
import { Type } from "typebox";
import { requiresExplicitMatrixDefaultAccount } from "./account-selection.js";
import { resolveDefaultMatrixAccountId, resolveMatrixAccount } from "./matrix/accounts.js";
import type { CoreConfig } from "./types.js";

const MATRIX_PLUGIN_HANDLED_ACTIONS = new Set<ChannelMessageActionName>([
  "send",
  "poll-vote",
  "react",
  "reactions",
  "read",
  "edit",
  "delete",
  "pin",
  "unpin",
  "list-pins",
  "set-profile",
  "member-info",
  "channel-info",
  "permissions",
]);
const MATRIX_PROFILE_MEDIA_PROPERTIES = {
  avatarUrl: Type.Optional(
    Type.String({
      description:
        "Profile avatar URL for Matrix self-profile update actions. Matrix accepts mxc:// and http(s) URLs.",
    }),
  ),
  avatar_url: Type.Optional(
    Type.String({
      description:
        "snake_case alias of avatarUrl for Matrix self-profile update actions. Matrix accepts mxc:// and http(s) URLs.",
    }),
  ),
  avatarPath: Type.Optional(
    Type.String({
      description:
        "Local avatar file path for Matrix self-profile update actions. Matrix uploads this file and sets the resulting MXC URI.",
    }),
  ),
  avatar_path: Type.Optional(
    Type.String({
      description:
        "snake_case alias of avatarPath for Matrix self-profile update actions. Matrix uploads this file and sets the resulting MXC URI.",
    }),
  ),
} as const;
const MATRIX_PROFILE_MEDIA_SOURCE_PARAMS = Object.freeze(["avatarUrl", "avatarPath"]);

function createMatrixExposedActions(params: {
  gate: ReturnType<typeof createActionGate>;
  encryptionEnabled: boolean;
  senderIsOwner?: boolean;
}) {
  const actions = new Set<ChannelMessageActionName>(["poll", "poll-vote"]);
  if (params.gate("messages")) {
    actions.add("send");
    actions.add("read");
    actions.add("edit");
    actions.add("delete");
  }
  if (params.gate("reactions")) {
    actions.add("react");
    actions.add("reactions");
  }
  if (params.gate("pins")) {
    actions.add("pin");
    actions.add("unpin");
    actions.add("list-pins");
  }
  if (params.gate("profile") && params.senderIsOwner === true) {
    actions.add("set-profile");
  }
  if (params.gate("memberInfo")) {
    actions.add("member-info");
  }
  if (params.gate("channelInfo")) {
    actions.add("channel-info");
  }
  if (params.encryptionEnabled && params.gate("verification")) {
    actions.add("permissions");
  }
  return actions;
}

function buildMatrixProfileToolSchema(): NonNullable<ChannelMessageToolDiscovery["schema"]> {
  return {
    actions: ["set-profile"],
    properties: {
      displayName: Type.Optional(
        Type.String({
          description: "Profile display name for Matrix self-profile update actions.",
        }),
      ),
      display_name: Type.Optional(
        Type.String({
          description: "snake_case alias of displayName for Matrix self-profile update actions.",
        }),
      ),
      ...MATRIX_PROFILE_MEDIA_PROPERTIES,
    },
  };
}

export const matrixMessageActions: ChannelMessageActionAdapter = {
  describeMessageTool: ({ cfg, accountId, senderIsOwner }) => {
    const resolvedCfg = cfg as CoreConfig;
    if (!accountId && requiresExplicitMatrixDefaultAccount(resolvedCfg)) {
      return { actions: [], capabilities: [] };
    }
    const account = resolveMatrixAccount({
      cfg: resolvedCfg,
      accountId: accountId ?? resolveDefaultMatrixAccountId(resolvedCfg),
    });
    if (!account.enabled || !account.configured) {
      return { actions: [], capabilities: [] };
    }
    const gate = createActionGate(account.config.actions);
    const actions = createMatrixExposedActions({
      gate,
      encryptionEnabled: account.config.encryption === true,
      senderIsOwner,
    });
    const listedActions = Array.from(actions);
    return {
      actions: listedActions,
      capabilities: [],
      schema: listedActions.includes("set-profile") ? buildMatrixProfileToolSchema() : null,
      mediaSourceParams: listedActions.includes("set-profile")
        ? { "set-profile": MATRIX_PROFILE_MEDIA_SOURCE_PARAMS }
        : null,
    };
  },
  supportsAction: ({ action }) => MATRIX_PLUGIN_HANDLED_ACTIONS.has(action),
  extractToolSend: ({ args }) => {
    return extractToolSend(args, "sendMessage");
  },
  handleAction: async (ctx: ChannelMessageActionContext) => {
    const { handleMatrixAction } = await import("./tool-actions.runtime.js");
    const { action, params, cfg, accountId, mediaLocalRoots } = ctx;
    const dispatch = async (actionParams: Record<string, unknown>) =>
      await handleMatrixAction(
        {
          ...actionParams,
          ...(accountId ? { accountId } : {}),
        },
        cfg as CoreConfig,
        { mediaLocalRoots },
      );
    const resolveRoomId = () =>
      readStringParam(params, "roomId") ??
      readStringParam(params, "channelId") ??
      readStringParam(params, "to", { required: true });

    if (action === "send") {
      const to = readStringParam(params, "to", { required: true });
      const mediaUrl =
        readStringParam(params, "media", { trim: false }) ??
        readStringParam(params, "mediaUrl", { trim: false }) ??
        readStringParam(params, "filePath", { trim: false }) ??
        readStringParam(params, "path", { trim: false });
      const content = readStringParam(params, "message", {
        required: !mediaUrl,
        allowEmpty: true,
      });
      const replyTo = readStringParam(params, "replyTo");
      const threadId = readStringParam(params, "threadId");
      const audioAsVoice =
        typeof params.asVoice === "boolean"
          ? params.asVoice
          : typeof params.audioAsVoice === "boolean"
            ? params.audioAsVoice
            : undefined;
      return await dispatch({
        action: "sendMessage",
        to,
        content,
        mediaUrl: mediaUrl ?? undefined,
        replyToId: replyTo ?? undefined,
        threadId: threadId ?? undefined,
        audioAsVoice,
      });
    }

    if (action === "poll-vote") {
      return await dispatch({
        ...params,
        action: "pollVote",
      });
    }

    if (action === "react") {
      const messageId = readStringParam(params, "messageId", { required: true });
      const emoji = readStringParam(params, "emoji", { allowEmpty: true });
      const remove = typeof params.remove === "boolean" ? params.remove : undefined;
      return await dispatch({
        action: "react",
        roomId: resolveRoomId(),
        messageId,
        emoji,
        remove,
      });
    }

    if (action === "reactions") {
      const messageId = readStringParam(params, "messageId", { required: true });
      const limit = readNumberParam(params, "limit", { integer: true });
      return await dispatch({
        action: "reactions",
        roomId: resolveRoomId(),
        messageId,
        limit,
      });
    }

    if (action === "read") {
      const limit = readNumberParam(params, "limit", { integer: true });
      return await dispatch({
        action: "readMessages",
        roomId: resolveRoomId(),
        limit,
        before: readStringParam(params, "before"),
        after: readStringParam(params, "after"),
      });
    }

    if (action === "edit") {
      const messageId = readStringParam(params, "messageId", { required: true });
      const content = readStringParam(params, "message", { required: true });
      return await dispatch({
        action: "editMessage",
        roomId: resolveRoomId(),
        messageId,
        content,
      });
    }

    if (action === "delete") {
      const messageId = readStringParam(params, "messageId", { required: true });
      return await dispatch({
        action: "deleteMessage",
        roomId: resolveRoomId(),
        messageId,
      });
    }

    if (action === "pin" || action === "unpin" || action === "list-pins") {
      const messageId =
        action === "list-pins"
          ? undefined
          : readStringParam(params, "messageId", { required: true });
      return await dispatch({
        action: action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
        roomId: resolveRoomId(),
        messageId,
      });
    }

    if (action === "set-profile") {
      if (ctx.senderIsOwner !== true) {
        throw new ToolAuthorizationError("Matrix profile updates require owner access.");
      }
      const avatarPath =
        readStringParam(params, "avatarPath") ??
        readStringParam(params, "path") ??
        readStringParam(params, "filePath");
      return await dispatch({
        action: "setProfile",
        displayName: readStringParam(params, "displayName") ?? readStringParam(params, "name"),
        avatarUrl: readStringParam(params, "avatarUrl"),
        avatarPath,
      });
    }

    if (action === "member-info") {
      const userId = readStringParam(params, "userId", { required: true });
      return await dispatch({
        action: "memberInfo",
        userId,
        roomId: readStringParam(params, "roomId") ?? readStringParam(params, "channelId"),
      });
    }

    if (action === "channel-info") {
      return await dispatch({
        action: "channelInfo",
        roomId: resolveRoomId(),
      });
    }

    if (action === "permissions") {
      const operation = normalizeLowercaseStringOrEmpty(
        readStringParam(params, "operation") ??
          readStringParam(params, "mode") ??
          "verification-list",
      );
      const operationToAction: Record<string, string> = {
        "encryption-status": "encryptionStatus",
        "verification-status": "verificationStatus",
        "verification-bootstrap": "verificationBootstrap",
        "verification-recovery-key": "verificationRecoveryKey",
        "verification-backup-status": "verificationBackupStatus",
        "verification-backup-restore": "verificationBackupRestore",
        "verification-list": "verificationList",
        "verification-request": "verificationRequest",
        "verification-accept": "verificationAccept",
        "verification-cancel": "verificationCancel",
        "verification-start": "verificationStart",
        "verification-generate-qr": "verificationGenerateQr",
        "verification-scan-qr": "verificationScanQr",
        "verification-sas": "verificationSas",
        "verification-confirm": "verificationConfirm",
        "verification-mismatch": "verificationMismatch",
        "verification-confirm-qr": "verificationConfirmQr",
      };
      const resolvedAction = operationToAction[operation];
      if (!resolvedAction) {
        throw new Error(
          `Unsupported Matrix permissions operation: ${operation}. Supported values: ${Object.keys(
            operationToAction,
          ).join(", ")}`,
        );
      }
      return await dispatch({
        ...params,
        action: resolvedAction,
      });
    }

    throw new Error(`Action ${action} is not supported for provider matrix.`);
  },
};

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






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge