feat(channels): add Tlon config compatibility

This commit is contained in:
晴天
2026-05-24 02:03:55 +08:00
parent 7e3bb71fca
commit 7b32b533fb
8 changed files with 561 additions and 9 deletions

View File

@@ -18,6 +18,7 @@ export const CHANNEL_LABELS = {
imessage: 'iMessage',
line: 'LINE',
nostr: 'Nostr',
tlon: 'Tlon',
mattermost: 'Mattermost',
clickclack: 'ClickClack',
'nextcloud-talk': 'Nextcloud Talk',

View File

@@ -190,6 +190,28 @@ export default {
nostrDefaultAccountHint: _('上游当前通过根节点配置生成隐式账号,通常保持 default 即可。', 'Upstream currently derives an implicit account from the root config; default is usually enough.'),
nostrProfileAboutPh: _('可选,展示在 Nostr Profile 中的机器人介绍', 'Optional bot introduction shown in the Nostr profile'),
nostrProfileUrlHint: _('上游 Profile URL 字段要求使用 https:// 地址。', 'Upstream profile URL fields require https:// URLs.'),
tlonDesc: _('接入 Tlon / Urbit 消息网络,支持 Ship 登录、群组频道、私信白名单和邀请控制', 'Connect Tlon / Urbit messaging with ship login, group channels, DM allowlists, and invite controls'),
tlonGuide1: _('准备可访问的 Tlon Ship例如 <code>~sampel-palnet</code>,并确认 Gateway 网络可以访问该 Ship 的 URL', 'Prepare a reachable Tlon ship, for example <code>~sampel-palnet</code>, and make sure Gateway can access its URL'),
tlonGuide2: _('填写 Ship、URL 和登录 Code这是上游 Tlon 插件的最小可运行配置', 'Fill Ship, URL, and login Code; these are the minimum fields required by the upstream Tlon plugin'),
tlonGuide3: _('按需填写 Group Channels、DM Allowlist 与 Group Invite Allowlist限制机器人可响应和可接受邀请的范围', 'Set Group Channels, DM Allowlist, and Group Invite Allowlist as needed to limit where the bot can respond and accept invites'),
tlonGuide4: _('保存后面板会启用 Tlon 插件并重载 Gateway真实连通性以 Gateway 日志或 channels status --probe 为准', 'After saving, the panel enables the Tlon plugin and reloads Gateway; verify connectivity through Gateway logs or channels status --probe'),
tlonGuideFooter: _('<div style="margin-top:8px;font-size:var(--font-size-xs);color:var(--text-tertiary)">Tlon 最小配置需要 Ship、URL 与 Code命名账号会写入 <code>channels.tlon.accounts</code>,默认账号写入 <code>channels.tlon</code> 根节点。</div>', '<div style="margin-top:8px;font-size:var(--font-size-xs);color:var(--text-tertiary)">Tlon minimally requires Ship, URL, and Code; named accounts are written to <code>channels.tlon.accounts</code>, while the default account is written to the <code>channels.tlon</code> root.</div>'),
tlonShipHint: _('Ship 名通常以 ~ 开头,例如 ~sampel-palnet。', 'Ship names usually start with ~, for example ~sampel-palnet.'),
tlonUrlHint: _('Tlon 实例 URL建议使用 https://。如为内网地址,需确认 Gateway 可访问。', 'Tlon instance URL; https:// is recommended. For private addresses, make sure Gateway can reach it.'),
tlonCodeHint: _('Tlon 登录码;生产环境建议使用 SecretRef保持 SecretRef 占位不变即可保留引用。', 'Tlon login code; prefer SecretRef in production. Keep the SecretRef placeholder unchanged to preserve the reference.'),
tlonPrivateNetworkHint: _('仅在 Tlon URL 是可信内网地址时开启;该开关会写入 network.dangerouslyAllowPrivateNetwork。', 'Enable only for trusted private Tlon URLs; this writes network.dangerouslyAllowPrivateNetwork.'),
tlonGroupChannelsHint: _('群组频道 Nest多个值用逗号分隔例如 chat/~host-ship/general。', 'Group channel nests separated by commas, for example chat/~host-ship/general.'),
tlonDmAllowlistHint: _('允许发起私信的 Ship 列表,多个值用逗号分隔。', 'Ships allowed to start DMs, separated by commas.'),
tlonGroupInviteAllowlistHint: _('允许邀请机器人加入群组的 Ship 列表,留空表示按上游默认处理。', 'Ships allowed to invite the bot to groups; leave empty to use upstream defaults.'),
tlonAutoDiscoverChannels: _('自动发现频道', 'Auto-discover channels'),
tlonAutoDiscoverChannelsHint: _('开启后上游会尝试发现 Ship 可用频道;大型 Ship 上建议先显式填写 Group Channels。', 'When enabled, upstream tries to discover available channels; for large ships, explicitly setting Group Channels first is recommended.'),
tlonShowModelSignature: _('显示模型签名', 'Show model signature'),
tlonAutoAcceptDmInvites: _('自动接受私信邀请', 'Auto-accept DM invites'),
tlonAutoAcceptDmInvitesHint: _('通常仅配合 DM Allowlist 使用,避免接受未知 Ship。', 'Usually use this with DM Allowlist to avoid accepting unknown ships.'),
tlonAutoAcceptGroupInvites: _('自动接受群组邀请', 'Auto-accept group invites'),
tlonAutoAcceptGroupInvitesHint: _('建议同时配置 Group Invite Allowlist避免恶意群组邀请。', 'Configure Group Invite Allowlist as well to avoid malicious group invites.'),
tlonOwnerShipHint: _('用于审批请求的 Owner Ship可填写当前 Ship 或专门的管理 Ship。', 'Owner ship that receives approval requests; use the current ship or a dedicated management ship.'),
tlonDefaultAuthorizedShipsHint: _('默认授权 Ship 列表,多个值用逗号分隔。', 'Default authorized ships separated by commas.'),
ircDesc: _('接入 IRC 网络支持服务器账号、NickServ 登录、频道白名单和提及策略', 'Connect IRC networks with server accounts, NickServ login, channel allowlists, and mention policy'),
ircGuide1: _('准备 IRC 服务器地址,例如 <code>irc.libera.chat</code>,并确认 Gateway 网络可以连接', 'Prepare the IRC server host, for example <code>irc.libera.chat</code>, and make sure Gateway can connect'),
ircGuide2: _('填写机器人 Nick如服务器需要 SASL 或密码,可填写 Server Password 或文件路径', 'Fill the bot Nick; if the server requires SASL or a password, provide Server Password or a file path'),

View File

@@ -418,6 +418,39 @@ const PLATFORM_REGISTRY = {
pluginRequired: '@openclaw/nostr@latest',
pluginId: 'nostr',
},
tlon: {
label: 'Tlon',
iconName: 'globe',
desc: t('channels.tlonDesc'),
guide: [
t('channels.tlonGuide1'),
t('channels.tlonGuide2'),
t('channels.tlonGuide3'),
t('channels.tlonGuide4'),
],
guideFooter: t('channels.tlonGuideFooter'),
fields: [
{ key: 'name', label: t('channels.accountName'), placeholder: t('channels.optionalEg', { example: 'main-ship' }), required: false },
{ key: 'ship', label: 'Ship', placeholder: '~sampel-palnet', required: true, hint: t('channels.tlonShipHint') },
{ key: 'url', label: 'URL', placeholder: 'https://urbit.example.com', required: true, hint: t('channels.tlonUrlHint') },
{ key: 'code', label: 'Code', placeholder: 'lidlut-tabwed-pillex-ridrup', secret: true, required: true, hint: t('channels.tlonCodeHint') },
{ key: 'dangerouslyAllowPrivateNetwork', label: t('channels.mattermostPrivateNetwork'), type: 'select', options: BOOLEAN_OPTIONS, required: false, hint: t('channels.tlonPrivateNetworkHint') },
{ key: 'groupChannels', label: 'Group Channels', placeholder: 'chat/~host-ship/general, chat/~host-ship/support', required: false, hint: t('channels.tlonGroupChannelsHint') },
{ key: 'dmAllowlist', label: 'DM Allowlist', placeholder: '~zod, ~nec', required: false, hint: t('channels.tlonDmAllowlistHint') },
{ key: 'groupInviteAllowlist', label: 'Group Invite Allowlist', placeholder: '~zod, ~nec', required: false, hint: t('channels.tlonGroupInviteAllowlistHint') },
{ key: 'autoDiscoverChannels', label: t('channels.tlonAutoDiscoverChannels'), type: 'select', options: BOOLEAN_OPTIONS, required: false, hint: t('channels.tlonAutoDiscoverChannelsHint') },
{ key: 'showModelSignature', label: t('channels.tlonShowModelSignature'), type: 'select', options: BOOLEAN_OPTIONS, required: false },
{ key: 'responsePrefix', label: 'Response Prefix', placeholder: t('channels.optionalEg', { example: '[Tlon]' }), required: false },
{ key: 'autoAcceptDmInvites', label: t('channels.tlonAutoAcceptDmInvites'), type: 'select', options: BOOLEAN_OPTIONS, required: false, hint: t('channels.tlonAutoAcceptDmInvitesHint') },
{ key: 'autoAcceptGroupInvites', label: t('channels.tlonAutoAcceptGroupInvites'), type: 'select', options: BOOLEAN_OPTIONS, required: false, hint: t('channels.tlonAutoAcceptGroupInvitesHint') },
{ key: 'ownerShip', label: 'Owner Ship', placeholder: '~sampel-palnet', required: false, hint: t('channels.tlonOwnerShipHint') },
{ key: 'defaultAuthorizedShips', label: 'Default Authorized Ships', placeholder: '~zod, ~nec', required: false, hint: t('channels.tlonDefaultAuthorizedShipsHint') },
],
configKey: 'tlon',
pairingChannel: 'tlon',
pluginRequired: '@openclaw/tlon@latest',
pluginId: 'tlon',
},
irc: {
label: 'IRC',
iconName: 'hash',
@@ -993,7 +1026,7 @@ function applyRouteIntent(page, state) {
// ── 已配置平台渲染 ──
// ── 多账号支持的平台:与 OpenClaw 的 accounts/defaultAccount 配置模型保持一致 ──
const MULTI_INSTANCE_PLATFORMS = ['telegram', 'discord', 'slack', 'feishu', 'dingtalk', 'dingtalk-connector', 'qqbot', 'zalo', 'zalouser', 'line', 'mattermost', 'clickclack', 'nextcloud-talk', 'twitch', 'irc', 'synology-chat', 'googlechat', 'signal']
const MULTI_INSTANCE_PLATFORMS = ['telegram', 'discord', 'slack', 'feishu', 'dingtalk', 'dingtalk-connector', 'qqbot', 'zalo', 'zalouser', 'line', 'mattermost', 'clickclack', 'nextcloud-talk', 'twitch', 'tlon', 'irc', 'synology-chat', 'googlechat', 'signal']
function supportsMessagingMultiAccount(pid) {
return MULTI_INSTANCE_PLATFORMS.includes(pid)

View File

@@ -1149,6 +1149,18 @@ mark {
/* === 移动端响应式 === */
@media (max-width: 768px) {
.modal .btn {
min-height: 44px;
justify-content: center;
}
.modal .btn-sm,
.modal .btn-xs {
min-height: 40px;
padding: var(--space-sm) var(--space-md);
}
.modal-actions {
flex-wrap: wrap;
}
.stat-cards {
grid-template-columns: repeat(2, 1fr);
gap: var(--space-sm);