mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-05 22:32:12 +00:00
fix(matrix): migrate room allow aliases to enabled (#60690)
* fix(matrix): migrate room allow aliases to enabled * test(matrix): keep migration coverage on the channel seam * chore(config): refresh baselines after matrix alias cleanup
This commit is contained in:
@@ -13821,16 +13821,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.groups.*.allow",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.groups.*.allowBots",
|
||||
"kind": "channel",
|
||||
@@ -14200,16 +14190,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.rooms.*.allow",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.rooms.*.allowBots",
|
||||
"kind": "channel",
|
||||
|
||||
@@ -1704,7 +1704,7 @@
|
||||
"tags": [
|
||||
"automation"
|
||||
],
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: telegram, whatsapp, discord, irc, googlechat, slack, signal, imessage, line, bluebubbles, feishu, matrix, mattermost, msteams, nextcloud-talk, nostr, qqbot, synology-chat, tlon, twitch, zalo, zalouser.",
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: feishu, googlechat, nostr, msteams, mattermost, nextcloud-talk, matrix, bluebubbles, line, zalo, zalouser, synology-chat, tlon, discord, imessage, irc, qqbot, signal, slack, telegram, twitch, whatsapp.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -4532,7 +4532,7 @@
|
||||
"tags": [
|
||||
"automation"
|
||||
],
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: telegram, whatsapp, discord, irc, googlechat, slack, signal, imessage, line, bluebubbles, feishu, matrix, mattermost, msteams, nextcloud-talk, nostr, qqbot, synology-chat, tlon, twitch, zalo, zalouser.",
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: feishu, googlechat, nostr, msteams, mattermost, nextcloud-talk, matrix, bluebubbles, line, zalo, zalouser, synology-chat, tlon, discord, imessage, irc, qqbot, signal, slack, telegram, twitch, whatsapp.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -15426,6 +15426,16 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.models.*.contextTokens",
|
||||
"kind": "core",
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.models.*.contextWindow",
|
||||
"kind": "core",
|
||||
|
||||
@@ -1703,7 +1703,7 @@
|
||||
"tags": [
|
||||
"automation"
|
||||
],
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: telegram, whatsapp, discord, irc, googlechat, slack, signal, imessage, line, bluebubbles, feishu, matrix, mattermost, msteams, nextcloud-talk, nostr, qqbot, synology-chat, tlon, twitch, zalo, zalouser.",
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: feishu, googlechat, nostr, msteams, mattermost, nextcloud-talk, matrix, bluebubbles, line, zalo, zalouser, synology-chat, tlon, discord, imessage, irc, qqbot, signal, slack, telegram, twitch, whatsapp.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -4531,7 +4531,7 @@
|
||||
"tags": [
|
||||
"automation"
|
||||
],
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: telegram, whatsapp, discord, irc, googlechat, slack, signal, imessage, line, bluebubbles, feishu, matrix, mattermost, msteams, nextcloud-talk, nostr, qqbot, synology-chat, tlon, twitch, zalo, zalouser.",
|
||||
"help": "Delivery target (\"last\", \"none\", or a channel id). Known channels: feishu, googlechat, nostr, msteams, mattermost, nextcloud-talk, matrix, bluebubbles, line, zalo, zalouser, synology-chat, tlon, discord, imessage, irc, qqbot, signal, slack, telegram, twitch, whatsapp.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -15425,6 +15425,16 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.models.*.contextTokens",
|
||||
"kind": "core",
|
||||
"type": "integer",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.models.*.contextWindow",
|
||||
"kind": "core",
|
||||
@@ -41851,16 +41861,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.groups.*.allow",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.groups.*.allowBots",
|
||||
"kind": "channel",
|
||||
@@ -42230,16 +42230,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.rooms.*.allow",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.matrix.rooms.*.allowBots",
|
||||
"kind": "channel",
|
||||
@@ -65406,6 +65396,120 @@
|
||||
],
|
||||
"label": "@openclaw/memory-core Config",
|
||||
"help": "Plugin-defined config payload for memory-core.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.frequency",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Dreaming Frequency",
|
||||
"help": "Optional cron cadence override for managed dreaming runs.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.limit",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"performance"
|
||||
],
|
||||
"label": "Promotion Limit",
|
||||
"help": "Maximum short-term candidates promoted per dreaming run (set to 0 to skip promotions).",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.minRecallCount",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Promotion Min Recalls",
|
||||
"help": "Minimum recall count required for automatic promotion.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.minScore",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Promotion Min Score",
|
||||
"help": "Minimum weighted rank required for automatic promotion.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.minUniqueQueries",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Promotion Min Queries",
|
||||
"help": "Minimum unique query count required for automatic promotion.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.mode",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"enumValues": [
|
||||
"off",
|
||||
"core",
|
||||
"deep",
|
||||
"rem"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Dreaming Mode",
|
||||
"help": "Select dreaming mode: off, core, deep, or rem.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.timezone",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Dreaming Timezone",
|
||||
"help": "IANA timezone for the managed dreaming cron schedule.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -67287,6 +67391,21 @@
|
||||
],
|
||||
"label": "@openclaw/openai-provider Config",
|
||||
"help": "Plugin-defined config payload for openai.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.openai.config.personalityOverlay",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"friendly",
|
||||
"off"
|
||||
],
|
||||
"defaultValue": "friendly",
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -71224,6 +71343,199 @@
|
||||
"label": "Public Webhook URL",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable Realtime Voice",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.instructions",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Realtime Instructions",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.provider",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Realtime Voice Provider",
|
||||
"help": "Uses the first registered realtime voice provider when unset.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.providers",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Realtime Provider Config",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.providers.*",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.streamPath",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"storage"
|
||||
],
|
||||
"label": "Realtime Stream Path",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.description",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.name",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.properties",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.required",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.required.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.type",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"enumValues": [
|
||||
"object"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.type",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"enumValues": [
|
||||
"function"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.responseModel",
|
||||
"kind": "plugin",
|
||||
@@ -71235,6 +71547,7 @@
|
||||
"advanced"
|
||||
],
|
||||
"label": "Response Model",
|
||||
"help": "Optional override. Falls back to the runtime default model when unset.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -71423,21 +71736,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.openaiApiKey",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"auth",
|
||||
"security"
|
||||
],
|
||||
"label": "OpenAI Realtime API Key",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.preStartTimeoutMs",
|
||||
"kind": "plugin",
|
||||
@@ -71449,9 +71747,36 @@
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.silenceDurationMs",
|
||||
"path": "plugins.entries.voice-call.config.streaming.provider",
|
||||
"kind": "plugin",
|
||||
"type": "integer",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Streaming Provider",
|
||||
"help": "Uses the first registered realtime transcription provider when unset.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.providers",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Streaming Provider Config",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.providers.*",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
@@ -71472,76 +71797,6 @@
|
||||
"label": "Media Stream Path",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.sttModel",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "Realtime STT Model",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.sttProvider",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"openai-realtime"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.vadThreshold",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.stt",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.stt.model",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.stt.provider",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"openai"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.tailscale",
|
||||
"kind": "plugin",
|
||||
@@ -71839,7 +72094,11 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "TTS Provider Config",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -71994,12 +72253,10 @@
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"auth",
|
||||
"media",
|
||||
"security"
|
||||
],
|
||||
"label": "ElevenLabs API Key",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -72025,11 +72282,9 @@
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media",
|
||||
"url-secret"
|
||||
],
|
||||
"label": "ElevenLabs Base URL",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -72049,12 +72304,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media",
|
||||
"models"
|
||||
],
|
||||
"label": "ElevenLabs Model ID",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -72074,11 +72324,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "ElevenLabs Voice ID",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -72269,12 +72515,10 @@
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"auth",
|
||||
"media",
|
||||
"security"
|
||||
],
|
||||
"label": "OpenAI API Key",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -72307,12 +72551,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media",
|
||||
"models"
|
||||
],
|
||||
"label": "OpenAI TTS Model",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -72332,11 +72571,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "OpenAI TTS Voice",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -5731,6 +5731,120 @@
|
||||
],
|
||||
"label": "@openclaw/memory-core Config",
|
||||
"help": "Plugin-defined config payload for memory-core.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.frequency",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Dreaming Frequency",
|
||||
"help": "Optional cron cadence override for managed dreaming runs.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.limit",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"performance"
|
||||
],
|
||||
"label": "Promotion Limit",
|
||||
"help": "Maximum short-term candidates promoted per dreaming run (set to 0 to skip promotions).",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.minRecallCount",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Promotion Min Recalls",
|
||||
"help": "Minimum recall count required for automatic promotion.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.minScore",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Promotion Min Score",
|
||||
"help": "Minimum weighted rank required for automatic promotion.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.minUniqueQueries",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Promotion Min Queries",
|
||||
"help": "Minimum unique query count required for automatic promotion.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.mode",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"enumValues": [
|
||||
"off",
|
||||
"core",
|
||||
"deep",
|
||||
"rem"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Dreaming Mode",
|
||||
"help": "Select dreaming mode: off, core, deep, or rem.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.memory-core.config.dreaming.timezone",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Dreaming Timezone",
|
||||
"help": "IANA timezone for the managed dreaming cron schedule.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -7612,6 +7726,21 @@
|
||||
],
|
||||
"label": "@openclaw/openai-provider Config",
|
||||
"help": "Plugin-defined config payload for openai.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.openai.config.personalityOverlay",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"friendly",
|
||||
"off"
|
||||
],
|
||||
"defaultValue": "friendly",
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -11549,6 +11678,199 @@
|
||||
"label": "Public Webhook URL",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable Realtime Voice",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.instructions",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Realtime Instructions",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.provider",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Realtime Voice Provider",
|
||||
"help": "Uses the first registered realtime voice provider when unset.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.providers",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Realtime Provider Config",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.providers.*",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.streamPath",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"storage"
|
||||
],
|
||||
"label": "Realtime Stream Path",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.description",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.name",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.properties",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.required",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.required.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.parameters.type",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"enumValues": [
|
||||
"object"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.realtime.tools.*.type",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"enumValues": [
|
||||
"function"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.responseModel",
|
||||
"kind": "plugin",
|
||||
@@ -11560,6 +11882,7 @@
|
||||
"advanced"
|
||||
],
|
||||
"label": "Response Model",
|
||||
"help": "Optional override. Falls back to the runtime default model when unset.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -11748,21 +12071,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.openaiApiKey",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"auth",
|
||||
"security"
|
||||
],
|
||||
"label": "OpenAI Realtime API Key",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.preStartTimeoutMs",
|
||||
"kind": "plugin",
|
||||
@@ -11774,9 +12082,36 @@
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.silenceDurationMs",
|
||||
"path": "plugins.entries.voice-call.config.streaming.provider",
|
||||
"kind": "plugin",
|
||||
"type": "integer",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Streaming Provider",
|
||||
"help": "Uses the first registered realtime transcription provider when unset.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.providers",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Streaming Provider Config",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.providers.*",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
@@ -11797,76 +12132,6 @@
|
||||
"label": "Media Stream Path",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.sttModel",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "Realtime STT Model",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.sttProvider",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"openai-realtime"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.streaming.vadThreshold",
|
||||
"kind": "plugin",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.stt",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.stt.model",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.stt.provider",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"openai"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.voice-call.config.tailscale",
|
||||
"kind": "plugin",
|
||||
@@ -12164,7 +12429,11 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "TTS Provider Config",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -12319,12 +12588,10 @@
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"auth",
|
||||
"media",
|
||||
"security"
|
||||
],
|
||||
"label": "ElevenLabs API Key",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -12350,11 +12617,9 @@
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media",
|
||||
"url-secret"
|
||||
],
|
||||
"label": "ElevenLabs Base URL",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -12374,12 +12639,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media",
|
||||
"models"
|
||||
],
|
||||
"label": "ElevenLabs Model ID",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -12399,11 +12659,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "ElevenLabs Voice ID",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -12594,12 +12850,10 @@
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"auth",
|
||||
"media",
|
||||
"security"
|
||||
],
|
||||
"label": "OpenAI API Key",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -12632,12 +12886,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media",
|
||||
"models"
|
||||
],
|
||||
"label": "OpenAI TTS Model",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -12657,11 +12906,7 @@
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"media"
|
||||
],
|
||||
"label": "OpenAI TTS Voice",
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -37,7 +37,7 @@ describe("MatrixConfigSchema SecretInput", () => {
|
||||
accessToken: "token",
|
||||
groups: {
|
||||
"!room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "axis",
|
||||
},
|
||||
},
|
||||
@@ -55,7 +55,7 @@ describe("MatrixConfigSchema SecretInput", () => {
|
||||
accessToken: "token",
|
||||
rooms: {
|
||||
"!room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "axis",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -45,7 +45,6 @@ const matrixRoomSchema = z
|
||||
.object({
|
||||
account: z.string().optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
allow: z.boolean().optional(),
|
||||
requireMention: z.boolean().optional(),
|
||||
allowBots: z.union([z.boolean(), z.literal("mentions")]).optional(),
|
||||
tools: ToolPolicySchema,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
collectMatrixInstallPathWarnings,
|
||||
formatMatrixLegacyCryptoPreview,
|
||||
formatMatrixLegacyStatePreview,
|
||||
matrixDoctor,
|
||||
runMatrixDoctorSequence,
|
||||
} from "./doctor.js";
|
||||
|
||||
@@ -125,4 +126,50 @@ describe("matrix doctor", () => {
|
||||
});
|
||||
expect(sequence.changeNotes.join("\n")).toContain("Matrix migration snapshot");
|
||||
});
|
||||
|
||||
it("normalizes legacy Matrix room allow aliases to enabled", () => {
|
||||
const normalize = matrixDoctor.normalizeCompatibilityConfig;
|
||||
expect(normalize).toBeDefined();
|
||||
if (!normalize) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = normalize({
|
||||
cfg: {
|
||||
channels: {
|
||||
matrix: {
|
||||
groups: {
|
||||
"!ops:example.org": {
|
||||
allow: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
work: {
|
||||
rooms: {
|
||||
"!legacy:example.org": {
|
||||
allow: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
});
|
||||
|
||||
expect(result.config.channels?.matrix?.groups?.["!ops:example.org"]).toEqual({
|
||||
enabled: true,
|
||||
});
|
||||
expect(result.config.channels?.matrix?.accounts?.work?.rooms?.["!legacy:example.org"]).toEqual(
|
||||
{
|
||||
enabled: false,
|
||||
},
|
||||
);
|
||||
expect(result.changes).toEqual(
|
||||
expect.arrayContaining([
|
||||
"Moved channels.matrix.groups.!ops:example.org.allow → channels.matrix.groups.!ops:example.org.enabled (true).",
|
||||
"Moved channels.matrix.accounts.work.rooms.!legacy:example.org.allow → channels.matrix.accounts.work.rooms.!legacy:example.org.enabled (false).",
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import type { ChannelDoctorAdapter } from "openclaw/plugin-sdk/channel-contract";
|
||||
import {
|
||||
type ChannelDoctorAdapter,
|
||||
type ChannelDoctorConfigMutation,
|
||||
type ChannelDoctorLegacyConfigRule,
|
||||
} from "openclaw/plugin-sdk/channel-contract";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import {
|
||||
detectPluginInstallPathIssue,
|
||||
@@ -19,6 +23,161 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function hasLegacyMatrixRoomAllowAlias(value: unknown): boolean {
|
||||
const room = isRecord(value) ? value : null;
|
||||
return Boolean(room && typeof room.allow === "boolean");
|
||||
}
|
||||
|
||||
function hasLegacyMatrixRoomMapAllowAliases(value: unknown): boolean {
|
||||
const rooms = isRecord(value) ? value : null;
|
||||
return Boolean(rooms && Object.values(rooms).some((room) => hasLegacyMatrixRoomAllowAlias(room)));
|
||||
}
|
||||
|
||||
function hasLegacyMatrixAccountRoomAllowAliases(value: unknown): boolean {
|
||||
const accounts = isRecord(value) ? value : null;
|
||||
if (!accounts) {
|
||||
return false;
|
||||
}
|
||||
return Object.values(accounts).some((account) => {
|
||||
if (!isRecord(account)) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
hasLegacyMatrixRoomMapAllowAliases(account.groups) ||
|
||||
hasLegacyMatrixRoomMapAllowAliases(account.rooms)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeMatrixRoomAllowAliases(params: {
|
||||
rooms: Record<string, unknown>;
|
||||
pathPrefix: string;
|
||||
changes: string[];
|
||||
}): { rooms: Record<string, unknown>; changed: boolean } {
|
||||
let changed = false;
|
||||
const nextRooms: Record<string, unknown> = { ...params.rooms };
|
||||
for (const [roomId, roomValue] of Object.entries(params.rooms)) {
|
||||
const room = isRecord(roomValue) ? roomValue : null;
|
||||
if (!room || typeof room.allow !== "boolean") {
|
||||
continue;
|
||||
}
|
||||
const nextRoom = { ...room };
|
||||
if (typeof nextRoom.enabled !== "boolean") {
|
||||
nextRoom.enabled = room.allow;
|
||||
}
|
||||
delete nextRoom.allow;
|
||||
nextRooms[roomId] = nextRoom;
|
||||
changed = true;
|
||||
params.changes.push(
|
||||
`Moved ${params.pathPrefix}.${roomId}.allow → ${params.pathPrefix}.${roomId}.enabled (${String(nextRoom.enabled)}).`,
|
||||
);
|
||||
}
|
||||
return { rooms: nextRooms, changed };
|
||||
}
|
||||
|
||||
function normalizeMatrixCompatibilityConfig(cfg: OpenClawConfig): ChannelDoctorConfigMutation {
|
||||
const channels = isRecord(cfg.channels) ? cfg.channels : null;
|
||||
const matrix = isRecord(channels?.matrix) ? channels.matrix : null;
|
||||
if (!matrix) {
|
||||
return { config: cfg, changes: [] };
|
||||
}
|
||||
|
||||
const changes: string[] = [];
|
||||
let updatedMatrix: Record<string, unknown> = matrix;
|
||||
let changed = false;
|
||||
|
||||
const normalizeTopLevelRoomScope = (key: "groups" | "rooms") => {
|
||||
const rooms = isRecord(updatedMatrix[key]) ? updatedMatrix[key] : null;
|
||||
if (!rooms) {
|
||||
return;
|
||||
}
|
||||
const normalized = normalizeMatrixRoomAllowAliases({
|
||||
rooms,
|
||||
pathPrefix: `channels.matrix.${key}`,
|
||||
changes,
|
||||
});
|
||||
if (normalized.changed) {
|
||||
updatedMatrix = { ...updatedMatrix, [key]: normalized.rooms };
|
||||
changed = true;
|
||||
}
|
||||
};
|
||||
|
||||
normalizeTopLevelRoomScope("groups");
|
||||
normalizeTopLevelRoomScope("rooms");
|
||||
|
||||
const accounts = isRecord(updatedMatrix.accounts) ? updatedMatrix.accounts : null;
|
||||
if (accounts) {
|
||||
let accountsChanged = false;
|
||||
const nextAccounts: Record<string, unknown> = { ...accounts };
|
||||
for (const [accountId, accountValue] of Object.entries(accounts)) {
|
||||
const account = isRecord(accountValue) ? accountValue : null;
|
||||
if (!account) {
|
||||
continue;
|
||||
}
|
||||
let nextAccount: Record<string, unknown> = account;
|
||||
let accountChanged = false;
|
||||
for (const key of ["groups", "rooms"] as const) {
|
||||
const rooms = isRecord(nextAccount[key]) ? nextAccount[key] : null;
|
||||
if (!rooms) {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeMatrixRoomAllowAliases({
|
||||
rooms,
|
||||
pathPrefix: `channels.matrix.accounts.${accountId}.${key}`,
|
||||
changes,
|
||||
});
|
||||
if (normalized.changed) {
|
||||
nextAccount = { ...nextAccount, [key]: normalized.rooms };
|
||||
accountChanged = true;
|
||||
}
|
||||
}
|
||||
if (accountChanged) {
|
||||
nextAccounts[accountId] = nextAccount;
|
||||
accountsChanged = true;
|
||||
}
|
||||
}
|
||||
if (accountsChanged) {
|
||||
updatedMatrix = { ...updatedMatrix, accounts: nextAccounts };
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
return { config: cfg, changes: [] };
|
||||
}
|
||||
return {
|
||||
config: {
|
||||
...cfg,
|
||||
channels: {
|
||||
...cfg.channels,
|
||||
matrix: updatedMatrix as OpenClawConfig["channels"]["matrix"],
|
||||
},
|
||||
},
|
||||
changes,
|
||||
};
|
||||
}
|
||||
|
||||
const MATRIX_LEGACY_CONFIG_RULES: ChannelDoctorLegacyConfigRule[] = [
|
||||
{
|
||||
path: ["channels", "matrix", "groups"],
|
||||
message:
|
||||
"channels.matrix.groups.<room>.allow is legacy; use channels.matrix.groups.<room>.enabled instead (auto-migrated on load).",
|
||||
match: hasLegacyMatrixRoomMapAllowAliases,
|
||||
},
|
||||
{
|
||||
path: ["channels", "matrix", "rooms"],
|
||||
message:
|
||||
"channels.matrix.rooms.<room>.allow is legacy; use channels.matrix.rooms.<room>.enabled instead (auto-migrated on load).",
|
||||
match: hasLegacyMatrixRoomMapAllowAliases,
|
||||
},
|
||||
{
|
||||
path: ["channels", "matrix", "accounts"],
|
||||
message:
|
||||
"channels.matrix.accounts.<id>.{groups,rooms}.<room>.allow is legacy; use channels.matrix.accounts.<id>.{groups,rooms}.<room>.enabled instead (auto-migrated on load).",
|
||||
match: hasLegacyMatrixAccountRoomAllowAliases,
|
||||
},
|
||||
];
|
||||
|
||||
function hasConfiguredMatrixChannel(cfg: OpenClawConfig): boolean {
|
||||
const channels = cfg.channels as Record<string, unknown> | undefined;
|
||||
return isRecord(channels?.matrix);
|
||||
@@ -259,6 +418,8 @@ export const matrixDoctor: ChannelDoctorAdapter = {
|
||||
groupModel: "sender",
|
||||
groupAllowFromFallbackToAllowFrom: false,
|
||||
warnOnEmptyGroupSenderAllowlist: true,
|
||||
legacyConfigRules: MATRIX_LEGACY_CONFIG_RULES,
|
||||
normalizeCompatibilityConfig: ({ cfg }) => normalizeMatrixCompatibilityConfig(cfg),
|
||||
runConfigSequence: async ({ cfg, env, shouldRepair }) =>
|
||||
await runMatrixDoctorSequence({ cfg, env, shouldRepair }),
|
||||
cleanStaleConfig: async ({ cfg }) => await cleanStaleMatrixPluginConfig(cfg),
|
||||
|
||||
@@ -476,15 +476,15 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
groups: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!axis-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "axis",
|
||||
},
|
||||
"!unassigned-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -503,20 +503,20 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "default" }).config.groups).toEqual({
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!unassigned-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "axis" }).config.groups).toEqual({
|
||||
"!axis-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "axis",
|
||||
},
|
||||
"!unassigned-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -529,15 +529,15 @@ describe("resolveMatrixAccount", () => {
|
||||
accessToken: "default-token",
|
||||
groups: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!ops-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "ops",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -552,20 +552,20 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "default" }).config.groups).toEqual({
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.groups).toEqual({
|
||||
"!ops-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "ops",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -576,15 +576,15 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
rooms: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!axis-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "axis",
|
||||
},
|
||||
"!unassigned-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -603,20 +603,20 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "default" }).config.rooms).toEqual({
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!unassigned-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "axis" }).config.rooms).toEqual({
|
||||
"!axis-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "axis",
|
||||
},
|
||||
"!unassigned-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -629,15 +629,15 @@ describe("resolveMatrixAccount", () => {
|
||||
accessToken: "default-token",
|
||||
rooms: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!ops-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "ops",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -652,20 +652,20 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "default" }).config.rooms).toEqual({
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.rooms).toEqual({
|
||||
"!ops-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "ops",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -683,15 +683,15 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
groups: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!ops-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "ops",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -700,11 +700,11 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "ops", env }).config.groups).toEqual({
|
||||
"!ops-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "ops",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -715,11 +715,11 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
groups: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -734,7 +734,7 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.groups).toEqual({
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -745,11 +745,11 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
rooms: {
|
||||
"!default-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
account: "default",
|
||||
},
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -764,7 +764,7 @@ describe("resolveMatrixAccount", () => {
|
||||
|
||||
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.rooms).toEqual({
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -775,7 +775,7 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
groups: {
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
@@ -798,7 +798,7 @@ describe("resolveMatrixAccount", () => {
|
||||
matrix: {
|
||||
rooms: {
|
||||
"!shared-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
|
||||
@@ -122,7 +122,7 @@ describe("updateMatrixAccountConfig", () => {
|
||||
policy: "pairing",
|
||||
},
|
||||
groups: {
|
||||
"!default:example.org": { allow: true },
|
||||
"!default:example.org": { enabled: true },
|
||||
},
|
||||
accounts: {
|
||||
ops: {
|
||||
@@ -145,14 +145,14 @@ describe("updateMatrixAccountConfig", () => {
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"!ops-room:example.org": { allow: true },
|
||||
"!ops-room:example.org": { enabled: true },
|
||||
},
|
||||
rooms: null,
|
||||
});
|
||||
|
||||
expect(updated.channels?.["matrix"]?.dm?.policy).toBe("pairing");
|
||||
expect(updated.channels?.["matrix"]?.groups).toEqual({
|
||||
"!default:example.org": { allow: true },
|
||||
"!default:example.org": { enabled: true },
|
||||
});
|
||||
expect(updated.channels?.["matrix"]?.accounts?.ops).toMatchObject({
|
||||
dm: {
|
||||
@@ -162,7 +162,7 @@ describe("updateMatrixAccountConfig", () => {
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"!ops-room:example.org": { allow: true },
|
||||
"!ops-room:example.org": { enabled: true },
|
||||
},
|
||||
});
|
||||
expect(updated.channels?.["matrix"]?.accounts?.ops?.rooms).toBeUndefined();
|
||||
|
||||
@@ -39,13 +39,13 @@ describe("resolveMatrixMonitorConfig", () => {
|
||||
);
|
||||
|
||||
const roomsConfig: MatrixRoomsConfig = {
|
||||
"*": { allow: true },
|
||||
"*": { enabled: true },
|
||||
"room:!ops:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
users: ["Dana", "user:@Erin:Example.org"],
|
||||
},
|
||||
General: {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -62,13 +62,13 @@ describe("resolveMatrixMonitorConfig", () => {
|
||||
expect(result.allowFrom).toEqual(["@alice:example.org", "@bob:example.org"]);
|
||||
expect(result.groupAllowFrom).toEqual(["@carol:example.org"]);
|
||||
expect(result.roomsConfig).toEqual({
|
||||
"*": { allow: true },
|
||||
"*": { enabled: true },
|
||||
"!ops:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
users: ["@dana:example.org", "@erin:example.org"],
|
||||
},
|
||||
"!general:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
expect(resolveTargets).toHaveBeenCalledTimes(3);
|
||||
@@ -116,7 +116,7 @@ describe("resolveMatrixMonitorConfig", () => {
|
||||
groupAllowFrom: ["matrix:@known:example.org"],
|
||||
roomsConfig: {
|
||||
"channel:Project X": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
users: ["matrix:Ghost"],
|
||||
},
|
||||
},
|
||||
@@ -174,7 +174,7 @@ describe("resolveMatrixMonitorConfig", () => {
|
||||
accountId: "ops",
|
||||
roomsConfig: {
|
||||
"#allowed:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
runtime,
|
||||
@@ -183,7 +183,7 @@ describe("resolveMatrixMonitorConfig", () => {
|
||||
|
||||
expect(result.roomsConfig).toEqual({
|
||||
"!allowed-room:example.org": {
|
||||
allow: true,
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
expect(resolveTargets).toHaveBeenCalledWith(
|
||||
|
||||
@@ -4,9 +4,9 @@ import { resolveMatrixRoomConfig } from "./rooms.js";
|
||||
describe("resolveMatrixRoomConfig", () => {
|
||||
it("matches room IDs and aliases, not names", () => {
|
||||
const rooms = {
|
||||
"!room:example.org": { allow: true },
|
||||
"#alias:example.org": { allow: true },
|
||||
"Project Room": { allow: true },
|
||||
"!room:example.org": { enabled: true },
|
||||
"#alias:example.org": { enabled: true },
|
||||
"Project Room": { enabled: true },
|
||||
};
|
||||
|
||||
const byId = resolveMatrixRoomConfig({
|
||||
@@ -26,7 +26,7 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
expect(byAlias.matchKey).toBe("#alias:example.org");
|
||||
|
||||
const byName = resolveMatrixRoomConfig({
|
||||
rooms: { "Project Room": { allow: true } },
|
||||
rooms: { "Project Room": { enabled: true } },
|
||||
roomId: "!different:example.org",
|
||||
aliases: [],
|
||||
});
|
||||
@@ -37,7 +37,7 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
describe("matchSource classification", () => {
|
||||
it('returns matchSource="direct" for exact room ID match', () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: { "!room:example.org": { allow: true } },
|
||||
rooms: { "!room:example.org": { enabled: true } },
|
||||
roomId: "!room:example.org",
|
||||
aliases: [],
|
||||
});
|
||||
@@ -47,7 +47,7 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
|
||||
it('returns matchSource="direct" for alias match', () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: { "#alias:example.org": { allow: true } },
|
||||
rooms: { "#alias:example.org": { enabled: true } },
|
||||
roomId: "!room:example.org",
|
||||
aliases: ["#alias:example.org"],
|
||||
});
|
||||
@@ -57,7 +57,7 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
|
||||
it('returns matchSource="wildcard" for wildcard match', () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: { "*": { allow: true } },
|
||||
rooms: { "*": { enabled: true } },
|
||||
roomId: "!any:example.org",
|
||||
aliases: [],
|
||||
});
|
||||
@@ -67,7 +67,7 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
|
||||
it("returns undefined matchSource when no match", () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: { "!other:example.org": { allow: true } },
|
||||
rooms: { "!other:example.org": { enabled: true } },
|
||||
roomId: "!room:example.org",
|
||||
aliases: [],
|
||||
});
|
||||
@@ -78,8 +78,8 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
it("direct match takes priority over wildcard", () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: {
|
||||
"!room:example.org": { allow: true, systemPrompt: "room-specific" },
|
||||
"*": { allow: true, systemPrompt: "generic" },
|
||||
"!room:example.org": { enabled: true, systemPrompt: "room-specific" },
|
||||
"*": { enabled: true, systemPrompt: "generic" },
|
||||
},
|
||||
roomId: "!room:example.org",
|
||||
aliases: [],
|
||||
@@ -96,7 +96,7 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
|
||||
it("wildcard config should NOT be usable to override DM classification", () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: { "*": { allow: true, skills: ["general"] } },
|
||||
rooms: { "*": { enabled: true, skills: ["general"] } },
|
||||
roomId: "!dm-room:example.org",
|
||||
aliases: [],
|
||||
});
|
||||
@@ -108,8 +108,8 @@ describe("resolveMatrixRoomConfig", () => {
|
||||
it("explicitly configured room should be usable to override DM classification", () => {
|
||||
const result = resolveMatrixRoomConfig({
|
||||
rooms: {
|
||||
"!configured-room:example.org": { allow: true },
|
||||
"*": { allow: true },
|
||||
"!configured-room:example.org": { enabled: true },
|
||||
"*": { enabled: true },
|
||||
},
|
||||
roomId: "!configured-room:example.org",
|
||||
aliases: [],
|
||||
|
||||
@@ -9,6 +9,11 @@ export type MatrixRoomConfigResolved = {
|
||||
matchSource?: "direct" | "wildcard";
|
||||
};
|
||||
|
||||
function readLegacyRoomAllowAlias(room: MatrixRoomConfig | undefined): boolean | undefined {
|
||||
const rawRoom = room as Record<string, unknown> | undefined;
|
||||
return typeof rawRoom?.allow === "boolean" ? rawRoom.allow : undefined;
|
||||
}
|
||||
|
||||
export function resolveMatrixRoomConfig(params: {
|
||||
rooms?: Record<string, MatrixRoomConfig>;
|
||||
roomId: string;
|
||||
@@ -33,7 +38,8 @@ export function resolveMatrixRoomConfig(params: {
|
||||
wildcardKey: "*",
|
||||
});
|
||||
const resolved = matched ?? wildcardEntry;
|
||||
const allowed = resolved ? resolved.enabled !== false && resolved.allow !== false : false;
|
||||
const legacyAllow = readLegacyRoomAllowAlias(resolved);
|
||||
const allowed = resolved ? resolved.enabled !== false && legacyAllow !== false : false;
|
||||
const matchKey = matchedKey ?? wildcardKey;
|
||||
const matchSource = matched ? "direct" : wildcardEntry ? "wildcard" : undefined;
|
||||
return {
|
||||
|
||||
@@ -308,7 +308,7 @@ describe("matrix onboarding", () => {
|
||||
},
|
||||
groupPolicy: "allowlist",
|
||||
groups: {
|
||||
"!ops-room:example.org": { allow: true },
|
||||
"!ops-room:example.org": { enabled: true },
|
||||
},
|
||||
});
|
||||
expect(result.cfg.channels?.["matrix"]?.dm).toBeUndefined();
|
||||
|
||||
@@ -183,7 +183,7 @@ function setMatrixGroupPolicy(
|
||||
}
|
||||
|
||||
function setMatrixGroupRooms(cfg: CoreConfig, roomKeys: string[], accountId?: string) {
|
||||
const groups = Object.fromEntries(roomKeys.map((key) => [key, { allow: true }]));
|
||||
const groups = Object.fromEntries(roomKeys.map((key) => [key, { enabled: true }]));
|
||||
return updateMatrixAccountConfig(cfg, resolveMatrixOnboardingAccountId(cfg, accountId), {
|
||||
groups,
|
||||
rooms: null,
|
||||
|
||||
@@ -23,10 +23,8 @@ export type MatrixDmConfig = {
|
||||
export type MatrixRoomConfig = {
|
||||
/** Restrict this room entry to a specific Matrix account in multi-account setups. */
|
||||
account?: string;
|
||||
/** If false, disable the bot in this room (alias for allow: false). */
|
||||
/** If false, disable the bot in this room. */
|
||||
enabled?: boolean;
|
||||
/** Legacy room allow toggle; prefer enabled. */
|
||||
allow?: boolean;
|
||||
/** Require mentioning the bot to trigger replies. */
|
||||
requireMention?: boolean;
|
||||
/**
|
||||
|
||||
@@ -6856,9 +6856,6 @@ export const GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA = [
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
},
|
||||
allow: {
|
||||
type: "boolean",
|
||||
},
|
||||
requireMention: {
|
||||
type: "boolean",
|
||||
},
|
||||
@@ -6938,9 +6935,6 @@ export const GENERATED_BUNDLED_CHANNEL_CONFIG_METADATA = [
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
},
|
||||
allow: {
|
||||
type: "boolean",
|
||||
},
|
||||
requireMention: {
|
||||
type: "boolean",
|
||||
},
|
||||
|
||||
@@ -558,7 +558,7 @@ describe("legacy migrate nested channel enabled aliases", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("moves legacy allow toggles into enabled for slack, googlechat, and discord", () => {
|
||||
it("moves legacy allow toggles into enabled for slack, googlechat, discord, and matrix", () => {
|
||||
const res = migrateLegacyConfig({
|
||||
channels: {
|
||||
slack: {
|
||||
@@ -617,6 +617,22 @@ describe("legacy migrate nested channel enabled aliases", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
matrix: {
|
||||
groups: {
|
||||
"!ops:example.org": {
|
||||
allow: false,
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
work: {
|
||||
rooms: {
|
||||
"!legacy:example.org": {
|
||||
allow: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -638,6 +654,12 @@ describe("legacy migrate nested channel enabled aliases", () => {
|
||||
expect(res.changes).toContain(
|
||||
"Moved channels.discord.accounts.work.guilds.200.channels.help.allow → channels.discord.accounts.work.guilds.200.channels.help.enabled.",
|
||||
);
|
||||
expect(res.changes).toContain(
|
||||
"Moved channels.matrix.groups.!ops:example.org.allow → channels.matrix.groups.!ops:example.org.enabled (false).",
|
||||
);
|
||||
expect(res.changes).toContain(
|
||||
"Moved channels.matrix.accounts.work.rooms.!legacy:example.org.allow → channels.matrix.accounts.work.rooms.!legacy:example.org.enabled (true).",
|
||||
);
|
||||
expect(res.config?.channels?.slack?.channels?.ops).toEqual({
|
||||
enabled: false,
|
||||
});
|
||||
@@ -647,6 +669,12 @@ describe("legacy migrate nested channel enabled aliases", () => {
|
||||
expect(res.config?.channels?.discord?.guilds?.["100"]?.channels?.general).toEqual({
|
||||
enabled: false,
|
||||
});
|
||||
expect(res.config?.channels?.matrix?.groups?.["!ops:example.org"]).toEqual({
|
||||
enabled: false,
|
||||
});
|
||||
expect(res.config?.channels?.matrix?.accounts?.work?.rooms?.["!legacy:example.org"]).toEqual({
|
||||
enabled: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("drops legacy allow when enabled is already set", () => {
|
||||
|
||||
Reference in New Issue
Block a user