前言¶
dsh 跑在家裏或公司的一臺機器上,人在外面,想看某個會話走到哪一步,或者臨時給某個工作區派個活。常規做法是 SSH 端口轉發,或者把 web UI 暴露到公網——前者要求你能路由到那臺機器,後者要求公網 IP 或反向代理,再不然就是掛一個隧道服務,而隧道服務手裏握着你機器的鑰匙。
dsh-discord-bot 走的是另一條路:把 Discord 當作控制面。機器只向 Discord gateway 發起一條出站 WebSocket 並保持住,命令從這條既有連接進來。不監聽端口、不轉發端口、不引入新的入站攻擊面。下面介紹這個插件能做什麼、怎麼裝、開哪些開關之前要想清楚什麼。
這是什麼¶
dsh-discord-bot 是 DeepSeek Harness(下稱 dsh)的社區插件,由 Oliver0804 維護,MIT 許可證,當前版本 0.3.4,依賴 discord.js ^14.27.0,要求 Node >= 20。它把一個 dsh profile 投影到一個 Discord guild 上:一個分類(category)下,每個工作區對應一個文本頻道,再配一套 /dsh … 命令,可以在頻道里讀會話軌跡、看即時子代理、下發工作。dsh 的理念是「一切皆插件」,遠程訪問這件事在這裏也被做成了插件。
核心功能¶
只出站的連接¶
插件向 Discord gateway 打開一條 WebSocket 並保持。每條命令都經由這條既有連接送達,所以 harness 可以在 NAT、CGNAT、酒店網絡或公司防火牆後面應答——無需端口轉發、動態 DNS、反向代理,也不需要持有你機器密鑰的隧道服務。只要這臺機器訪問得了 discord.com,你就能用手機查它。沒有任何東西在監聽,也就沒有新增的入站攻擊面。
讀取與監視¶
讀取側覆蓋:sessions、trajectories、raw event timelines、subagents、lineage。在工作區頻道內用 /dsh … 命令可以讀會話軌跡(session trajectories)與即時子代理(live subagents)。
監視側是 mirror: true:harness 的每個回合——不管由 web UI、tui 還是 cron 發起——都會即時出現在對應工作區頻道里。默認關閉,因爲它意味着持續把會話內容導出到聊天平臺。
寫入與運行¶
寫入包括註冊工作區和切換 profile 配置:
/dsh workspace:註冊工作區/dsh model:切換默認模型/dsh preset:切換 agent preset/dsh permission:切換權限 preset
運行側只有一條 /dsh run <prompt>:向工作區 agent 交付提示詞,並流式回傳該回合。默認關閉(allowRun: false)——其餘命令都是在描述工作,只有這一條會讓工作真的發生在你的機器上。
頻道默認私有¶
分類與頻道拒絕 @everyone,只授予 bot 和 allowedUserIds 裏的用戶;名單爲空時只剩 guild owner。同一條規則也決定誰能運行命令,所以一個人能讀什麼和他能問什麼不會分叉。
隱私設置在每次同步時重新應用,而不是隻在創建時:已經存在的分類、或在此功能開啓之前建好的分類,同樣會被鎖上。如果 bot 缺少 Manage Channels,它做不了任何限制,會在日誌和 /dsh sync 裏明確說明,而不是讓你誤以爲已經鎖好。
另外,bot 以點擊者所用的語言回答。
安裝與啓用¶
先在 Discord 側準備 bot,再裝進 dsh profile。
1、創建 bot。在 Discord Developer Portal(https://discord.com/developers/applications)依次 New Application → Bot → Reset Token,複製 token。不需要任何特權 intents,Message Content 保持關閉。
2、邀請 bot 進服務器,scope 用 bot 和 applications.commands:
https://discord.com/oauth2/authorize?client_id=<APP_ID>&permissions=268487696&scope=bot+applications.commands
把 <APP_ID> 換成你的應用 ID。permissions=268487696 對應 View Channels、Send Messages、Embed Links、Attach Files、Manage Channels、Manage Roles。最後一個是容易漏的:寫頻道權限覆蓋——也就是讓頻道變私有的那件事——需要 Manage Roles,而 Discord 在缺少它時只報一句 Missing Access。缺了它 bot 仍能工作,但頻道保持全網可讀,並且每次同步都會提示。
3、安裝進 dsh profile:
npx dsh-discord-bot-setup --profile web
setup 腳本會安裝包、向 profile 註冊 bundle、把 token 寫入 $DSH_HOME/discord-bot.token(mode 600),並在 profile 的 patch 層追加一條配置覆蓋。沒傳的參數會交互式詢問;profile 裏已存在對應配置行時,腳本拒絕執行且不改動 profile。
非交互式寫法:
npx dsh-discord-bot-setup --profile web --guild 123456789012345678 --token "$TOKEN" --yes
加 --print 只預覽將寫入的行,不做任何更改。
4、重啓 dsh 並驗證:
dsh --profile web
打開新出現的 dsh 分類,運行 /dsh status。
手動安裝與配置¶
不想用 setup 腳本的話:
dsh plugin --profile web add dsh-discord-bot
這一步安裝包並把插件掛進 profile 的 bundle 層,插件自帶的 cordis.patch.yml 由此成爲組合配置樹的一層。此時插件會離線啓動並在日誌裏說明——因爲還沒有人告訴它綁定哪個 guild。在 profile 自己的 cordis.patch.yml 裏補一條 id 定向 override:
- id: discord-bot
config:
guildId: '123456789012345678'
tokenFile: '/Users/you/.dsh/discord-bot.token'
categoryName: 'dsh'
注意這是 override,不是第二個 insert。bundle 層已經掛載了這一行,兩層帶同一 id 不會合並,而是組合出兩個實例——同一個 guild 上兩個 bot,每條命令回答兩次。用下面的命令檢查組合後的配置樹,確認 id: discord-bot 只出現一次:
dsh --profile web --dump-config
順帶一提,這個插件屬於 host plane,不要放進 agent preset:它服務所有工作區和所有會話,按會話複製一份在第二個會話就會衝突。
從 0.3.1 或更早版本升級¶
0.3.1 及更早版本沒有 bundle 層,setup 腳本當時寫進 profile 的是完整的 insert: 行;現在包自己掛載,那行會組合出第二個 bot。把舊行替換成上面的 id 覆蓋行,保留你自己的值:
# 之前 # 之後
- insert: - id: discord-bot
- id: discord-bot config:
name: 'dsh-discord-bot' guildId: '…'
config: tokenFile: '…'
guildId: '…'
暫時不改也不會壞:bundle 的行沒有配置,只會記一條缺少 guildId 的日誌並保持離線,不會讓組合失敗。改完再用 --dump-config 確認只有一個 id: discord-bot。
典型用法¶
經過上面的步驟,guild 裏會出現一個 dsh 分類,結構大致是:
dsh ← 分類
├── dsh ← 工作區 /Users/you/Documents/dsh
├── sweepbot-home ← 工作區 /Users/you/code/game/godot/sweepbot_home
└── my-api ← 工作區 /Users/you/work/my-api
在對應頻道里發 /dsh run <prompt>,頻道里會出現一張運行卡片,標明當前在執行哪個工具,附 Trace、Timeline、Subagents、Todos、Export、Steer、Stop 等按鈕;Trace 裏是每一次工具調用與結果,底部附帶耗時、token 與緩存命中率。會話進行到哪一步、每一步做了什麼,都能在手機上直接看到。
安全邊界與兩個默認關閉的開關¶
mirror 和 allowRun 默認都是關的,原因相同:內容出口。
mirror: true會持續把會話內容導出到 Discord。allowRun: true之後,allowedUserIds內的任何人都能讓 agent 在 harness 機器上編輯文件、運行命令——從手機上。此時名單不再只是隱私邊界,而成了 shell 訪問名單。README 的建議是:名單隻留自己;開啓時權限 preset 優先選ask,而不是danger-full-access。
邊界方面,bot 不會削弱 dsh 自身的沙箱與審批策略:本地會被 harness 拒絕的操作,在這裏同樣被拒絕,它也無法代你批准。它也跨不過工作區邊界——訪問不了其他工作區頻道里的會話。
適用場景與注意¶
適合:
- dsh 跑在 NAT、CGNAT 或公司防火牆後面、沒有公網入口的機器上;
- 需要在手機或任何裝了 Discord 的設備上查看和驅動會話;
- 小範圍使用:把允許的人加進
allowedUserIds,頻道可讀範圍和命令權限保持一致。
不適合:
- 不接受會話內容經過 Discord 的情況——命令應答與 mirror 都經由 Discord 這條通道;
- 需要把訪問權開放給名單之外的人的場合,這套權限模型不爲此設計。
兩點提醒:插件以當前 dsh 進程的權限運行,它能觸達的範圍就是 dsh 進程能觸達的範圍;安裝任何第三方插件前,建議先讀一遍源碼、確認許可證(本項目爲 MIT)。
結尾¶
一句話回顧:一條出站 WebSocket,把工作區、會話軌跡和 harness 自己的命令帶到 Discord,全程不開放入站端口。項目地址與社區目錄頁:
- GitHub:https://github.com/Oliver0804/dsh-discord-bot
- 社區目錄頁:https://www.skillhub.cn/plugins/Oliver0804/dsh-discord-bot
社區目錄爲獨立站點,與 DeepSeek 或幻方無官方從屬關係。