DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Bluebubbles — DeepSeek Harness 插件(DSH Plugin)
← Plugins
B

dsh-bluebubbles

Bluebubbles

用于 DeepSeek Harness 的 BlueBubbles (iMessage) 桥接插件:提供 REST 工具,并将 webhook 推送路由到已绑定的工作区。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:vINyLogY/dsh-bluebubbles#754f7abe497eb7251320bc263813f3be96cf886c
README兼容性版本

兼容性与来源证明

Bluebubbles 以 dsh-bluebubbles 发布,当前版本为 0.1.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
any
发布来源
github
Registry 更新时间
2026/8/27

版本

0.1.0stable
2026/8/27

相关插件

正在加载相关插件…

最新版
0.1.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
any
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/9/15
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录

相关插件

继续浏览 integrations-communication 分类下经过校验的插件。

Acp App@deepseek-ai/dsh-acp-appdsh ACP 配置文件包:基于 dsh-base 的仅限自动化的 JSON-RPC stdio 和进程生命周期管理Im@xmanrui/dsh-im将十一种 IM 渠道和一个公网 AI Office 接入本地 DeepSeek Harness。Pocketdsh-pocket把 DeepSeek Harness 装进你的口袋:一个包、一个设置页,手机扫码即同步访问电脑上的 DSH(局域网 + 公网,实时同屏)。DSCODE@toddzheng024/dscode-bundle完整的 DeepSeek 编码代理,支持持久化 shell、Ultra 协作和自动权限审查。

README

dsh-bluebubbles

Bridges a local BlueBubbles server (the macOS iMessage bridge) into DeepSeek Harness.

Design principle (Unix philosophy): the host plugin keeps only passive capabilities (webhook receive + binding resolution + message injection) and two high-frequency model tools (send text / send attachment); everything else converges into the bb-channel CLI — agents call it via bash, humans and automation scripts use it directly.

Components

ComponentLocationRole
bluebubbles-bridgesrc/index.tswebhook route + message injection + 2 send tools + the bluebubbles service
dsh-heartbeatsrc/heartbeat.tsgeneric periodic wake-up (reads heartbeat-targets.json)
dsh-cronsrc/cron.tscron-time tasks (reads cron-jobs.json)
bb-channelbin/bb-channel.mjsCLI: chats/messages/send/bind/contacts/webhook/configure…

Model tools (deliberately only two)

ToolRole
bluebubbles_send_textsend a text message
bluebubbles_send_attachmentsend an attachment (image/file)

Everything else goes through the CLI (agents call it via bash — equivalent capability):

~/.local/bin/bb-channel chats [--limit N] [--all]      # list chats (placeholder/pairing-code noise hidden by default)
~/.local/bin/bb-channel messages <chatGuid> [--limit N] # read history (with sender display names)
~/.local/bin/bb-channel send <chatGuid> <text...>       # send text
~/.local/bin/bb-channel send-attachment <chatGuid> <file>
~/.local/bin/bb-channel attachment <guid> [--dir D]     # download an attachment
~/.local/bin/bb-channel bind <chatGuid> (--workspace PATH | --session ID)
~/.local/bin/bb-channel unbind <chatGuid>
~/.local/bin/bb-channel bindings                        # show the binding table
~/.local/bin/bb-channel contacts / set-contact <address> <name>
~/.local/bin/bb-channel webhook [--url URL]             # check/self-register the webhook
~/.local/bin/bb-channel ping / configure                # connectivity / write ~/.dsh/.env
  • Output is always pretty JSON (jq-friendly); errors go to stderr with exit 1.
  • Credential chain matches the plugin: process.env → ~/.dsh/.env → ~/.zshenv; nothing to fill in by hand.
  • The CLI edits ~/.dsh/bluebubbles-bindings.json / bluebubbles-contacts.json directly; the plugin hot re-reads both files before every inbound message — edits take effect immediately, no reload.

Push path (webhook)

BlueBubbles server (new message)
   │  POST {type:"new-message", data:{...}}
   ▼
DSH webServer route  /bluebubbles/webhook  (loopback only)
   │  hot re-read bindings/contacts → look up chatGuid → workspacePath/sessionId
   ▼
workspace.sessionIds[0] → agents.get(sessionId).send(userMessage, 'next-step', true)
   ▼
The workspace's model wakes up and sees a message annotated
"📱 iMessage · <chat name> · 来自 <name> (<number>)"

Anti-loop (two layers, v22+):

  1. pendingSent queue: the plugin records (chatGuid, normalized text) before every send; webhook echoes with isFromMe=true matching an entry are dropped (60s TTL, unicode NFC-normalized comparison);
  2. seenGuids: after a successful send the real guid returned by the API joins a dedup set (BlueBubbles occasionally pushes the same event twice — second-layer backstop).

A blanket isFromMe drop is not an option: phones on the same Apple ID also produce isFromMe=true in a self-chat DM, and dropping all of them would kill real user messages.

Sender display name: payload.handle.displayName → ~/.dsh/bluebubbles-contacts.json (address→name, maintained via bb-channel set-contact) → bare number.

Relay auto-delivery (same mode for inbound and cron)

With relay: true on a binding, the bridge registers a reply trigger for the woken session (persisted to bluebubbles-relay-state.json, 10min TTL, cleared on turn/end; an exact NO_REPLY reply suppresses delivery). During that turn, every assistant message containing text parts is sent back to the chat immediately — thinking and tool results are never delivered.

When dsh-cron fires a job whose target session has a relay: true binding, it arms the same mechanism through the bluebubbles service's armRelay. Cron task prompts must not tell the model to call send tools itself — that would double-send.

Configuration

Credentials

MethodTakes effect
bb-channel configure --password <pw> (writes ~/.dsh/.env)after DSH restart or bridge reload
env var BLUEBUBBLES_PASSWORD (optionally BLUEBUBBLES_BASE_URL)after DSH restart

Never put DSH_-prefixed variables in .env — the DSH bootstrap refuses to start. That is why heartbeat/cron config keys are HEARTBEAT_INTERVAL / HEARTBEAT_TARGETS / CRON_JOBS.

State files ($DSH_HOME, default ~/.dsh)

PathContentWriter
bluebubbles-bindings.json{ "chat:<guid>": { workspacePath | sessionId } }bb-channel bind/unbind
bluebubbles-contacts.json{ "address": "display name" }bb-channel set-contact
bluebubbles-media/inbound attachments (<guid>-<filename>)bridge auto-download
heartbeat-targets.jsonheartbeat targetshand-edited
cron-jobs.jsoncron jobshand-edited

Session resolution chain: sessionId direct → otherwise workspacePath → that workspace's sessionIds[0] (most recent session) → verify a live agent. With no live agent the message is dropped and logged (no fallback, no queue).

Updating the code

  1. Edit src/*.ts → npm run typecheck → git commit
  2. In ~/.dsh/profiles/web/cordis.patch.yml, bump the corresponding row's ?v=N by 1 and save
  3. In-process HMR does not reliably hot-replace the bridge module (stale fiber routes survive), so restarting DSH is the reliable load path; verify the version marker with curl -X POST -d '{}' http://127.0.0.1:3080/bluebubbles/webhook (ok-vN).

Diagnostics

With BLUEBUBBLES_DEBUG=1 (env or .env), inbound events and drop reasons go to ~/.dsh/bluebubbles-debug.log (serialized appends, no lost lines).

Security

  • The webhook route only accepts loopback sources; BlueBubbles webhooks have no signing mechanism.
  • Injected content is plain text messages and triggers no tools; outbound sends always happen through explicit model tool calls.
  • Neither the repository nor the patch file contains credentials.

Installation

As a profile bundle (consumers):

dsh plugin --profile web add github:vINyLogY/dsh-bluebubbles

dsh plugin add forwards to pnpm and, because this package declares dsh.bundle.patch, automatically joins the profile's bundle stack — the shipped cordis.patch.yml inserts rows for all three plugins (bluebubbles-bridge, dsh-heartbeat, dsh-cron, resolved through the package exports map). A DSH restart loads them. The bb-channel CLI lands on the profile's node_modules/.bin via the package bin entry.

For local development, insert absolute-path rows with a ?v=N cache-buster into the profile's own cordis.patch.yml instead (see below).

Tech stack

  • TypeScript (erasable syntax only), types from @deepseek-ai/dsh-* devDeps (0.1.0-rc.7 / cordis 4.0.1).
  • Zero build: Node ≥ 23.6 native type stripping; composition rows point straight at src/index.ts.
  • The CLI is plain Node ESM (bin/bb-channel.mjs), zero dependencies, global fetch/FormData — deliberately .mjs so it runs on any modern Node and stays ESM wherever it is symlinked.
  • Bootstrap: npm install --cache ./.npm-cache && npm run typecheck.