refactor(channels): make built-in channels self-contained (#4908)

* refactor(channels): own setup and instance contracts

* refactor(channels): isolate management contracts

* refactor(channels): normalize activation contracts

* fix(channels): enforce management contracts

* refactor(channels): finish setup ownership migration

* fix(channels): harden management contracts

* fix(channels): enforce lazy loading and runtime ownership

* fix(feishu): make multi-instance startup idempotent

* fix(webui): render channel setup contracts cleanly

* fix(feishu): stop websocket clients cleanly

* fix(channels): enforce persistence and activation gates

* fix(channels): preserve global feature action scope

* fix(channels): apply defaults for single plugins

* fix(channels): enforce management contract boundaries

* refactor(feishu): remove identity helper indirection

* fix(channels): preserve management setup contracts

* refactor(channels): generalize instance settings UI

* refactor(channels): package channel plugins with web UI metadata

* refactor(channels): make built-ins self-contained packages

* test(channels): colocate tests with channel packages

* fix(dingtalk): use official brand icon

* feat(channels): colocate webui translations

* docs(channels): clarify plugin ownership

* test(exec): remove output wait race

* refactor(channels): unify plugin descriptors

* fix(channels): enforce descriptor-owned contracts

* refactor(channels): finish package-owned plugin setup

* refactor(channels): use repository-owned packages only

* fix(channels): self-describe dependencies and runtime state

* fix(channels): warn about legacy entry points
This commit is contained in:
chengyongru
2026-07-19 23:30:49 +08:00
committed by GitHub
parent 7aaac37bca
commit 462a0dfb0f
388 changed files with 17093 additions and 5110 deletions
+21
View File
@@ -0,0 +1,21 @@
import type { ChannelUiContribution } from "@/channel-plugins/types";
import { chatAppGuideUrl } from "@/components/settings/channels/catalog";
export default {
presentation: {
displayName: "DingTalk",
initials: "DT",
color: "#1677FF",
logoUrl:
"https://img.alicdn.com/imgextra/i3/O1CN01WMvMRG1ks3Ixc9x1v_!!6000000004738-55-tps-32-32.svg",
setup: {
mode: "credentials",
docsUrl: chatAppGuideUrl("dingtalk"),
fields: [
{ key: "channels.dingtalk.clientId" },
{ key: "channels.dingtalk.clientSecret" },
{ key: "channels.dingtalk.allowFrom" },
],
},
},
} satisfies ChannelUiContribution;
@@ -0,0 +1,31 @@
{
"description": "Use nanobot from DingTalk groups.",
"requirements": "DingTalk app credentials and gateway",
"setup": {
"docsLabel": "Open DingTalk setup",
"officialLabel": "Open DingTalk console",
"tryIt": "Send a test message from the DingTalk group where the app is installed.",
"summary": "DingTalk needs app credentials from Stream mode.",
"steps": [
"Create or choose a DingTalk app with Stream mode enabled.",
"Add Client ID and Client Secret.",
"Save and enable DingTalk, then send a test message."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "DingTalk client ID",
"help": "Copy it from DingTalk app credentials."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "Copy it from the same DingTalk app credentials page."
},
"allowFrom": {
"label": "Allowed users",
"placeholder": "User IDs, comma separated"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "Usa nanobot desde grupos de DingTalk.",
"requirements": "Credenciales de la app de DingTalk y gateway",
"setup": {
"docsLabel": "Abrir guía de DingTalk",
"officialLabel": "Abrir consola de DingTalk",
"tryIt": "Envía un mensaje de prueba desde el grupo de DingTalk donde está instalada la app.",
"summary": "DingTalk necesita credenciales de una app en modo Stream.",
"steps": [
"Crea o elige una app de DingTalk con el modo Stream activado.",
"Añade el Client ID y el Client Secret.",
"Guarda y activa DingTalk; después envía un mensaje de prueba."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "Client ID de DingTalk",
"help": "Cópialo de las credenciales de la app de DingTalk."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "Cópialo de la misma página de credenciales."
},
"allowFrom": {
"label": "Usuarios permitidos",
"placeholder": "ID de usuario separados por comas"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "Utilisez nanobot depuis les groupes DingTalk.",
"requirements": "Identifiants dapplication DingTalk et passerelle",
"setup": {
"docsLabel": "Ouvrir le guide DingTalk",
"officialLabel": "Ouvrir la console DingTalk",
"tryIt": "Envoyez un message test dans le groupe DingTalk où lapplication est installée.",
"summary": "DingTalk nécessite les identifiants dune application en mode Stream.",
"steps": [
"Créez ou choisissez une application DingTalk avec le mode Stream activé.",
"Ajoutez le Client ID et le Client Secret.",
"Enregistrez et activez DingTalk, puis envoyez un message test."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "Client ID DingTalk",
"help": "Copiez-le depuis les identifiants de lapplication DingTalk."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "Copiez-le depuis la même page didentifiants DingTalk."
},
"allowFrom": {
"label": "Utilisateurs autorisés",
"placeholder": "ID utilisateur séparés par des virgules"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "Gunakan nanobot dari grup DingTalk.",
"requirements": "Kredensial aplikasi DingTalk dan gateway",
"setup": {
"docsLabel": "Buka panduan DingTalk",
"officialLabel": "Buka konsol DingTalk",
"tryIt": "Kirim pesan uji dari grup DingTalk tempat aplikasi dipasang.",
"summary": "DingTalk memerlukan kredensial aplikasi dari mode Stream.",
"steps": [
"Buat atau pilih aplikasi DingTalk dengan mode Stream aktif.",
"Tambahkan Client ID dan Client Secret.",
"Simpan dan aktifkan DingTalk, lalu kirim pesan uji."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "Client ID DingTalk",
"help": "Salin dari kredensial aplikasi DingTalk."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "Salin dari halaman kredensial yang sama."
},
"allowFrom": {
"label": "Pengguna yang diizinkan",
"placeholder": "ID pengguna, dipisahkan koma"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "DingTalk グループから nanobot を利用します。",
"requirements": "DingTalk アプリの認証情報とゲートウェイ",
"setup": {
"docsLabel": "DingTalk 設定ガイドを開く",
"officialLabel": "DingTalk コンソールを開く",
"tryIt": "アプリをインストールした DingTalk グループからテストメッセージを送信します。",
"summary": "DingTalk には Stream モードのアプリ認証情報が必要です。",
"steps": [
"Stream モードを有効にした DingTalk アプリを作成または選択します。",
"Client ID と Client Secret を追加します。",
"保存して DingTalk を有効にし、テストメッセージを送信します。"
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "DingTalk Client ID",
"help": "DingTalk アプリの認証情報からコピーします。"
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "同じ認証情報ページからコピーします。"
},
"allowFrom": {
"label": "許可するユーザー",
"placeholder": "ユーザー ID(カンマ区切り)"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "DingTalk 그룹에서 nanobot을 사용합니다.",
"requirements": "DingTalk 앱 자격 증명 및 게이트웨이",
"setup": {
"docsLabel": "DingTalk 설정 가이드 열기",
"officialLabel": "DingTalk 콘솔 열기",
"tryIt": "앱이 설치된 DingTalk 그룹에서 테스트 메시지를 보내세요.",
"summary": "DingTalk에는 Stream 모드 앱 자격 증명이 필요합니다.",
"steps": [
"Stream 모드가 활성화된 DingTalk 앱을 만들거나 선택하세요.",
"Client ID와 Client Secret을 추가하세요.",
"저장하고 DingTalk을 활성화한 다음 테스트 메시지를 보내세요."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "DingTalk Client ID",
"help": "DingTalk 앱 자격 증명에서 복사하세요."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "같은 자격 증명 페이지에서 복사하세요."
},
"allowFrom": {
"label": "허용된 사용자",
"placeholder": "사용자 ID, 쉼표로 구분"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "Use o nanobot em grupos do DingTalk.",
"requirements": "Credenciais do app DingTalk e gateway",
"setup": {
"docsLabel": "Abrir guia do DingTalk",
"officialLabel": "Abrir console do DingTalk",
"tryIt": "Envie uma mensagem de teste no grupo do DingTalk onde o app está instalado.",
"summary": "O DingTalk precisa das credenciais de um app no modo Stream.",
"steps": [
"Crie ou escolha um app do DingTalk com o modo Stream ativado.",
"Adicione o Client ID e o Client Secret.",
"Salve e ative o DingTalk; depois, envie uma mensagem de teste."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "Client ID do DingTalk",
"help": "Copie das credenciais do app DingTalk."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "Copie da mesma página de credenciais."
},
"allowFrom": {
"label": "Usuários permitidos",
"placeholder": "IDs de usuário separados por vírgulas"
}
}
}
}
@@ -0,0 +1,31 @@
{
"description": "Sử dụng nanobot trong các nhóm DingTalk.",
"requirements": "Thông tin xác thực ứng dụng DingTalk và gateway",
"setup": {
"docsLabel": "Mở hướng dẫn DingTalk",
"officialLabel": "Mở bảng điều khiển DingTalk",
"tryIt": "Gửi tin nhắn thử từ nhóm DingTalk đã cài ứng dụng.",
"summary": "DingTalk cần thông tin xác thực ứng dụng ở chế độ Stream.",
"steps": [
"Tạo hoặc chọn ứng dụng DingTalk đã bật chế độ Stream.",
"Thêm Client ID và Client Secret.",
"Lưu và bật DingTalk, sau đó gửi tin nhắn thử."
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "Client ID DingTalk",
"help": "Sao chép từ thông tin xác thực ứng dụng DingTalk."
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "Sao chép từ cùng trang thông tin xác thực."
},
"allowFrom": {
"label": "Người dùng được phép",
"placeholder": "ID người dùng, phân tách bằng dấu phẩy"
}
}
}
}
@@ -0,0 +1,32 @@
{
"displayName": "钉钉",
"description": "在钉钉群中使用 nanobot。",
"requirements": "钉钉应用凭据和网关",
"setup": {
"docsLabel": "打开钉钉配置指南",
"officialLabel": "打开钉钉开发者后台",
"tryIt": "在已安装应用的钉钉群中发送一条测试消息。",
"summary": "钉钉需要 Stream 模式的应用凭据。",
"steps": [
"创建或选择一个已启用 Stream 模式的钉钉应用。",
"填写 Client ID 和 Client Secret。",
"保存并启用钉钉,然后发送一条测试消息。"
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "钉钉 Client ID",
"help": "从钉钉应用凭据页面复制。"
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "从同一个钉钉应用凭据页面复制。"
},
"allowFrom": {
"label": "允许的用户",
"placeholder": "用户 ID,用逗号分隔"
}
}
}
}
@@ -0,0 +1,32 @@
{
"displayName": "釘釘",
"description": "在釘釘群組中使用 nanobot。",
"requirements": "釘釘應用程式憑證和閘道",
"setup": {
"docsLabel": "開啟釘釘設定指南",
"officialLabel": "開啟釘釘開發者後台",
"tryIt": "在已安裝應用程式的釘釘群組中傳送一則測試訊息。",
"summary": "釘釘需要 Stream 模式的應用程式憑證。",
"steps": [
"建立或選擇一個已啟用 Stream 模式的釘釘應用程式。",
"填入 Client ID 和 Client Secret。",
"儲存並啟用釘釘,然後傳送一則測試訊息。"
],
"fields": {
"clientId": {
"label": "Client ID",
"placeholder": "釘釘 Client ID",
"help": "從釘釘應用程式憑證頁面複製。"
},
"clientSecret": {
"label": "Client Secret",
"placeholder": "••••••",
"help": "從同一個釘釘應用程式憑證頁面複製。"
},
"allowFrom": {
"label": "允許的使用者",
"placeholder": "使用者 ID,以逗號分隔"
}
}
}
}