diff --git a/docs.json b/docs.json index 5c92ad2cc..ec40b98fb 100644 --- a/docs.json +++ b/docs.json @@ -560,6 +560,7 @@ "en/usage/platforms/discord", "en/usage/platforms/telegram", "en/usage/platforms/slack", + "en/usage/platforms/mattermost", "en/usage/platforms/line", "en/usage/platforms/webpage", "en/usage/platforms/http-bot", @@ -892,6 +893,7 @@ "zh/usage/platforms/discord", "zh/usage/platforms/telegram", "zh/usage/platforms/slack", + "zh/usage/platforms/mattermost", "zh/usage/platforms/line", "zh/usage/platforms/webpage", "zh/usage/platforms/http-bot" @@ -1159,6 +1161,7 @@ "ja/usage/platforms/discord", "ja/usage/platforms/telegram", "ja/usage/platforms/slack", + "ja/usage/platforms/mattermost", "ja/usage/platforms/line", "ja/usage/platforms/webpage", "ja/usage/platforms/http-bot", diff --git a/en/usage/platforms/mattermost.mdx b/en/usage/platforms/mattermost.mdx new file mode 100644 index 000000000..586fed532 --- /dev/null +++ b/en/usage/platforms/mattermost.mdx @@ -0,0 +1,48 @@ +--- +title: "Mattermost" +description: "Connect a Mattermost bot to LangBot and bring agents and workflows to your Mattermost server in minutes." +icon: "/images/platforms/mattermost.svg" +--- + + +The screenshots below use the Chinese interface. Follow the corresponding menu items and fields described in the text. + + +## Create a bot account + +Log in to your Mattermost instance (self-hosted or hosted by Mattermost). Click the `Mattermost icon` in the upper-left corner and select `Integrations` from the menu. + +![Open Integrations from the Mattermost menu](/images/zh/deploy/bots/mattermost/Mattermost_main_page.png) + +On the Integrations page, select `Bot Accounts` in the left menu, then click `Add Bot Account` in the upper-right corner. + +![Open Bot Accounts and add a bot account](/images/zh/deploy/bots/mattermost/Mattermost_bot_account.png) + +Choose a username for the bot. + +![Enter the bot username](/images/zh/deploy/bots/mattermost/Mattermost_bot_add_new.png) + +Set the role to `Member` (administrator-related features are not currently supported). Select `post:all` if you need direct messages, or select only `post:channels` if you only need public channels. Then click `Create Bot Account` in the lower-right corner. + +![Select the bot role and posting permissions](/images/zh/deploy/bots/mattermost/Mattermost_bot_deploy.png) + +Click the button to copy the token. It is shown only once, so save it securely. Then click `Done` in the lower-right corner. + +![Copy the bot token before completing account creation](/images/zh/deploy/bots/mattermost/Mattermost_bot_token.png) + +## Configure the bot in LangBot + +Open LangBot Cloud or your self-hosted LangBot instance and follow the red arrows in the screenshot below: + +- Hover over the `Bots` tab on the left and click the `+` icon that appears. +- Enter a name in the `Bot Name` field. +- Open the platform adapter dropdown and select `Mattermost`. +- Enter the address of your Mattermost instance and the token for the bot account you just created. +- (Optional) Disable streaming output if your pipeline or AI provider does not support it. +- Click `Submit` in the upper-right corner to open the bot editing page. + +![Add a Mattermost bot and enter the instance address and token in LangBot](/images/zh/deploy/bots/mattermost/Mattermost_langbot_add_new.png) + +Bind an existing pipeline, configure routing if needed, and click `Save` in the upper-right corner. + +![Bind a pipeline and save the Mattermost bot configuration](/images/zh/deploy/bots/mattermost/Mattermost_langbot_deploy.png) diff --git a/en/usage/platforms/readme.mdx b/en/usage/platforms/readme.mdx index 6661a3bad..4e905d3cb 100644 --- a/en/usage/platforms/readme.mdx +++ b/en/usage/platforms/readme.mdx @@ -13,6 +13,7 @@ Bots are used to receive message events from messaging platforms and call pipeli | Discord | ✅ | | [Tutorial](/en/usage/platforms/discord) | | Telegram | ✅ | | [Tutorial](/en/usage/platforms/telegram) | | Slack | ✅ | | [Tutorial](/en/usage/platforms/slack) | +| Mattermost | ✅ | Supports the open-source, Free, Professional, and Enterprise editions | [Tutorial](/en/usage/platforms/mattermost) | | LINE | ✅ | | [Tutorial](/en/usage/platforms/line) | | KOOK | ✅ | | [Tutorial](/en/usage/platforms/kook) | | Lark | ✅ | | [Tutorial](/en/usage/platforms/lark) | diff --git a/images/platforms/mattermost.svg b/images/platforms/mattermost.svg new file mode 100644 index 000000000..d185ef27d --- /dev/null +++ b/images/platforms/mattermost.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/zh/deploy/bots/mattermost/Mattermost_bot_account.png b/images/zh/deploy/bots/mattermost/Mattermost_bot_account.png new file mode 100644 index 000000000..dd2f5dc2b Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_bot_account.png differ diff --git a/images/zh/deploy/bots/mattermost/Mattermost_bot_add_new.png b/images/zh/deploy/bots/mattermost/Mattermost_bot_add_new.png new file mode 100644 index 000000000..ea6de9643 Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_bot_add_new.png differ diff --git a/images/zh/deploy/bots/mattermost/Mattermost_bot_deploy.png b/images/zh/deploy/bots/mattermost/Mattermost_bot_deploy.png new file mode 100644 index 000000000..ea6643e93 Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_bot_deploy.png differ diff --git a/images/zh/deploy/bots/mattermost/Mattermost_bot_token.png b/images/zh/deploy/bots/mattermost/Mattermost_bot_token.png new file mode 100644 index 000000000..763dae316 Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_bot_token.png differ diff --git a/images/zh/deploy/bots/mattermost/Mattermost_langbot_add_new.png b/images/zh/deploy/bots/mattermost/Mattermost_langbot_add_new.png new file mode 100644 index 000000000..9a48ebc3b Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_langbot_add_new.png differ diff --git a/images/zh/deploy/bots/mattermost/Mattermost_langbot_deploy.png b/images/zh/deploy/bots/mattermost/Mattermost_langbot_deploy.png new file mode 100644 index 000000000..d375b2172 Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_langbot_deploy.png differ diff --git a/images/zh/deploy/bots/mattermost/Mattermost_main_page.png b/images/zh/deploy/bots/mattermost/Mattermost_main_page.png new file mode 100644 index 000000000..d50dc365f Binary files /dev/null and b/images/zh/deploy/bots/mattermost/Mattermost_main_page.png differ diff --git a/ja/usage/platforms/mattermost.mdx b/ja/usage/platforms/mattermost.mdx new file mode 100644 index 000000000..cd20a64d9 --- /dev/null +++ b/ja/usage/platforms/mattermost.mdx @@ -0,0 +1,48 @@ +--- +title: "Mattermost" +description: "LangBot に Mattermost ボットを接続し、エージェントやワークフローを数分で Mattermost サーバーに導入します。" +icon: "/images/platforms/mattermost.svg" +--- + + +以下のスクリーンショットは中国語の画面です。本文で説明する対応するメニューや入力欄を参照して操作してください。 + + +## ボットアカウントの作成 + +Mattermost インスタンス(セルフホスト版または Mattermost が提供するホスト版)にログインします。左上の `Mattermost アイコン`をクリックし、メニューから「統合機能(Integrations)」を選択します。 + +![Mattermost メニューから統合機能を開く](/images/zh/deploy/bots/mattermost/Mattermost_main_page.png) + +統合機能のページで、左側のメニューから「ボットアカウント(Bot Accounts)」を選択し、右上の「ボットアカウントを追加(Add Bot Account)」をクリックします。 + +![ボットアカウントの一覧から新しいアカウントを追加する](/images/zh/deploy/bots/mattermost/Mattermost_bot_account.png) + +ボットのユーザー名を入力します。 + +![ボットのユーザー名を入力する](/images/zh/deploy/bots/mattermost/Mattermost_bot_add_new.png) + +ロールは「メンバー(Member)」を選択します(管理者向けの機能には現在対応していません)。ダイレクトメッセージが必要な場合は `post:all`、公開チャンネルのみを使用する場合は `post:channels` だけを選択します。右下の「ボットアカウントを作成(Create Bot Account)」をクリックします。 + +![ボットのロールと投稿権限を選択する](/images/zh/deploy/bots/mattermost/Mattermost_bot_deploy.png) + +ボタンをクリックしてトークンをコピーします。トークンは一度しか表示されないため、安全な場所に保存してください。右下の「完了(Done)」をクリックします。 + +![アカウント作成を完了する前にボットのトークンをコピーする](/images/zh/deploy/bots/mattermost/Mattermost_bot_token.png) + +## LangBot でのボット設定 + +LangBot Cloud またはセルフホストの LangBot インスタンスを開き、以下の画像の赤い矢印の順に操作します。 + +- 左側の「ボット」タブにカーソルを合わせ、表示される `+` アイコンをクリックします。 +- 「ボット名」欄にボットの名前を入力します。 +- プラットフォームアダプターのドロップダウンを開き、`Mattermost` を選択します。 +- Mattermost インスタンスのアドレスと、先ほど作成したボットアカウントのトークンを入力します。 +- (任意)パイプラインまたは AI プロバイダーがストリーミング出力に対応していない場合は、このオプションを無効にします。 +- 右上の「送信(Submit)」をクリックすると、ボットの編集画面が開きます。 + +![LangBot に Mattermost ボットを追加し、インスタンスのアドレスとトークンを入力する](/images/zh/deploy/bots/mattermost/Mattermost_langbot_add_new.png) + +既存のパイプラインを紐付け、必要に応じてルーティングを設定し、右上の「保存(Save)」をクリックします。 + +![パイプラインを紐付けて Mattermost ボットの設定を保存する](/images/zh/deploy/bots/mattermost/Mattermost_langbot_deploy.png) diff --git a/ja/usage/platforms/readme.mdx b/ja/usage/platforms/readme.mdx index 453761c54..347291929 100644 --- a/ja/usage/platforms/readme.mdx +++ b/ja/usage/platforms/readme.mdx @@ -13,6 +13,7 @@ description: "LangBot を各メッセージングプラットフォームに接 | Discord | ✅ | | [チュートリアル](/ja/usage/platforms/discord) | | Telegram | ✅ | | [チュートリアル](/ja/usage/platforms/telegram) | | Slack | ✅ | | [チュートリアル](/ja/usage/platforms/slack) | +| Mattermost | ✅ | オープンソース版・無料版・Professional 版・Enterprise 版に対応 | [チュートリアル](/ja/usage/platforms/mattermost) | | LINE | ✅ | | [チュートリアル](/ja/usage/platforms/line) | | KOOK | ✅ | | [チュートリアル](/ja/usage/platforms/kook) | | Lark | ✅ | | [チュートリアル](/ja/usage/platforms/lark) | diff --git a/tests/fumapress-migration.test.mjs b/tests/fumapress-migration.test.mjs index 47ec0ad60..7738db42c 100644 --- a/tests/fumapress-migration.test.mjs +++ b/tests/fumapress-migration.test.mjs @@ -170,8 +170,8 @@ test("MDX compatibility normalization removes internal .html route suffixes", () test("canonical MDX and nested OpenAPI sources are discovered", async () => { const docs = JSON.parse(await readFile(path.join(root, "docs.json"), "utf8")); const pages = await collectMdxDocuments(root); - assert.equal(pages.length, 302); - assert.deepEqual(Object.fromEntries([...pages.reduce((acc, page) => acc.set(page.split("/", 1)[0], (acc.get(page.split("/", 1)[0]) ?? 0) + 1), new Map()).entries()]), { en: 96, zh: 110, ja: 96 }); + assert.equal(pages.length, 305); + assert.deepEqual(Object.fromEntries([...pages.reduce((acc, page) => acc.set(page.split("/", 1)[0], (acc.get(page.split("/", 1)[0]) ?? 0) + 1), new Map()).entries()]), { en: 97, zh: 111, ja: 97 }); assert.deepEqual(collectOpenApiSources(docs), [ { locale: "en", source: "openapi/service-api-en.json", directory: "en/api-reference" }, { locale: "zh", source: "openapi/service-api-zh.json", directory: "zh/api-reference" }, @@ -216,7 +216,7 @@ test("prebuild is deterministic and preserves local assets and SEO files", async const first = await prepareFumapress({ root, outRoot: temp }); const second = await prepareFumapress({ root, outRoot: temp }); assert.deepEqual(first, second); - assert.equal(first.documents, 302); + assert.equal(first.documents, 305); assert.equal(first.fallbackDefaults, 0); assert.equal(first.localeOnlyDocuments, 14); assert.equal(first.redirects, 103); diff --git a/tests/test_mattermost_docs.py b/tests/test_mattermost_docs.py new file mode 100644 index 000000000..936f711c7 --- /dev/null +++ b/tests/test_mattermost_docs.py @@ -0,0 +1,78 @@ +"""Read-only contracts for Mattermost documentation translations; no network access.""" + +import json +from pathlib import Path +import re +import unittest + + +ROOT = Path(__file__).resolve().parents[1] +LOCALES = {"en": "en", "cn": "zh", "jp": "ja"} +GUIDE = "usage/platforms/mattermost" +IMAGE = re.compile(r"!\[([^\]]*)\]\((/images/[^)]+)\)") + + +class MattermostDocsTests(unittest.TestCase): + def test_each_site_locale_has_a_guide_and_support_table_entry(self): + docs = json.loads((ROOT / "docs.json").read_text(encoding="utf-8")) + for language in docs["navigation"]["languages"]: + locale = LOCALES[language["language"]] + with self.subTest(locale=locale): + guide = ROOT / f"{locale}/{GUIDE}.mdx" + self.assertTrue(guide.is_file(), f"Missing translated guide: {guide}") + readme = (guide.parent / "readme.mdx").read_text(encoding="utf-8") + rows = [line for line in readme.splitlines() if line.startswith("| Mattermost |")] + self.assertEqual(len(rows), 1) + self.assertIn("✅", rows[0]) + self.assertIn(f"](/{locale}/{GUIDE})", rows[0]) + self.assertTrue(rows[0].split("|")[3].strip(), "Edition support notes missing") + + def test_each_site_locale_lists_mattermost_in_bot_navigation(self): + docs = json.loads((ROOT / "docs.json").read_text(encoding="utf-8")) + + def page_lists(value): + if isinstance(value, dict): + if "pages" in value: + yield value["pages"] + for child in value.values(): + yield from page_lists(child) + elif isinstance(value, list): + for child in value: + yield from page_lists(child) + + for language in docs["navigation"]["languages"]: + locale = LOCALES[language["language"]] + with self.subTest(locale=locale): + groups = [pages for pages in page_lists(language) + if f"{locale}/usage/platforms/slack" in pages] + self.assertEqual(len(groups), 1) + self.assertEqual(groups[0].count(f"{locale}/{GUIDE}"), 1) + + def test_translations_preserve_source_steps_permissions_and_assets(self): + source = (ROOT / f"zh/{GUIDE}.mdx").read_text(encoding="utf-8") + source_images = [url for _, url in IMAGE.findall(source)] + for locale, screenshot_note in (("en", "Chinese"), ("ja", "中国語")): + with self.subTest(locale=locale): + path = ROOT / f"{locale}/{GUIDE}.mdx" + self.assertTrue(path.is_file(), f"Missing translated guide: {path}") + text = path.read_text(encoding="utf-8") + self.assertTrue(text.startswith('---\ntitle: "Mattermost"\n')) + self.assertRegex(text, r'(?m)^description: ".+"$') + self.assertIn('icon: "/images/platforms/mattermost.svg"', text) + self.assertTrue((ROOT / "images/platforms/mattermost.svg").is_file()) + for permission in ("`post:all`", "`post:channels`"): + self.assertIn(permission, text) + self.assertEqual(len(re.findall(r"^## ", text, re.M)), + len(re.findall(r"^## ", source, re.M))) + self.assertEqual(len(re.findall(r"^- ", text, re.M)), + len(re.findall(r"^- ", source, re.M))) + self.assertIn(screenshot_note, text) + images = IMAGE.findall(text) + self.assertEqual([url for _, url in images], source_images) + for alt, url in images: + self.assertTrue(alt.strip(), "Translated screenshot alt text missing") + self.assertTrue((ROOT / url.lstrip("/")).is_file(), url) + + +if __name__ == "__main__": + unittest.main() diff --git a/zh/usage/platforms/mattermost.mdx b/zh/usage/platforms/mattermost.mdx new file mode 100644 index 000000000..6c461e77e --- /dev/null +++ b/zh/usage/platforms/mattermost.mdx @@ -0,0 +1,44 @@ +--- +title: "Mattermost" +description: "用 LangBot 接入 Mattermost 机器人,几分钟内将 智能体/工作流 接入 Mattermost 服务器。" +icon: "/images/platforms/mattermost.svg" +--- + +## 创建机器人账号 + +登录Mattermost实例(自部署/官方皆可),点击左上角的`Mattermost图标`,在下拉菜单中选择`集成`。 + +![](/images/zh/deploy/bots/mattermost/Mattermost_main_page.png) + +进入集成页面后,在左侧菜单中选择`机器人账号`,点击右上角的添加机器人账号。 + +![](/images/zh/deploy/bots/mattermost/Mattermost_bot_account.png) + +为机器人起一个用户名。 + +![](/images/zh/deploy/bots/mattermost/Mattermost_bot_add_new.png) + +身份选择`成员`即可(暂不支持管理员相关功能),需要私聊选`post:all`,仅需要公共频道就只勾选`post:channels`,然后点击右下角的`创建机器人账号`。 + +![](/images/zh/deploy/bots/mattermost/Mattermost_bot_deploy.png) + +点击按钮复制令牌(只显示一次,记得保存),点右下角`完成`。 + +![](/images/zh/deploy/bots/mattermost/Mattermost_bot_token.png) + +## 配置LangBot机器人 + +进入LangBot官网或自部署实例,按下图中红箭头指示的顺序操作: + +- 光标移到左侧`机器人`选项卡上,会显示一个加号`+`,点击加号 +- 给机器人起一个名字,输进`机器人名称`的文本框 +- 点击平台适配器选择的选项框,在下拉菜单中选择`Mattermost` +- 输入`Mattermost`实例的地址和刚才创建的机器人账号的令牌 +- (可选)如果你的流水线/AI供应商不支持流式输出,则关闭该选项 +- 点击右上角的提交后会进入编辑该机器人的界面 + +![](/images/zh/deploy/bots/mattermost/Mattermost_langbot_add_new.png) + +绑定现有的流水线,以及配置路由(如果有需求的话),并点击右上角的保存。 + +![](/images/zh/deploy/bots/mattermost/Mattermost_langbot_deploy.png) diff --git a/zh/usage/platforms/readme.mdx b/zh/usage/platforms/readme.mdx index 21f6f1e76..6e85b13ef 100644 --- a/zh/usage/platforms/readme.mdx +++ b/zh/usage/platforms/readme.mdx @@ -21,6 +21,7 @@ description: "将 LangBot 接入各消息平台:Discord、Telegram、Slack、 | Discord | ✅ | | [教程](/zh/usage/platforms/discord) | | Telegram | ✅ | | [教程](/zh/usage/platforms/telegram) | | Slack | ✅ | | [教程](/zh/usage/platforms/slack) | +| Mattermost | ✅ | 适用于开源版、免费版、专业版、企业版 | [教程](/zh/usage/platforms/mattermost) | | LINE | ✅ | | [教程](/zh/usage/platforms/line) | | KOOK | ✅ | | [教程](/zh/usage/platforms/kook) | | 页面机器人 | ✅ | 将聊天组件嵌入网站 | [教程](/zh/usage/platforms/webpage) |