
Security News
Rust 1.100 Will Add Dependency Cooldowns to Cargo
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.
dsh-ringcentral
Advanced tools
RingCentral Team Messaging IM channel plugin for deepseek-harness (dsh). It turns a RingCentral Bot Add-in into a first-class frontend for a dsh agent: inbound posts from RingCentral chats drive the agent loop, and assistant replies flow back as threaded RingCentral posts.
English | 中文说明
RingCentral user ──▶ WebSocket (PostAdded) ──▶ im-ringcentral ──▶ ctx.agents ──▶ dsh agent loop ──▶ LLM
│ │
└── admission / session / event ◀────┘
(assistant reply ──▶ RingCentral post, threaded)
The plugin is a pure Cordis plugin following the dsh "Plugins, not loop changes" principle. It speaks the RingCentral Team Messaging v1 REST API + WebSocket subscription stream directly (no external SDK) and reuses the host dsh services for agents, sessions, models, compaction, and tool presentation.
# install into a profile
npx @deepseek-ai/dsh plugin --profile ringcentral add dsh-ringcentral
# start
export RC_BOT_TOKEN="your-bot-jwt"
export DEEPSEEK_API_KEY="your-deepseek-key"
npx @deepseek-ai/dsh --profile ringcentral
Or run the bundled installer: sh install.sh.
cd /path/to/dsh-ringcentral
pnpm install && pnpm build
npx @deepseek-ai/dsh plugin --profile ringcentral add /path/to/dsh-ringcentral
export RC_BOT_TOKEN="your-bot-jwt"
npx @deepseek-ai/dsh --profile ringcentral
The --patch overlay loads the plugin from a local absolute path without
installing it into a profile. Generate the machine-local patch first, then
boot:
cd /path/to/dsh-ringcentral
pnpm install && pnpm build # dist entry (npx dsh cannot resolve .js -> .ts)
node scripts/gen-dev-patch.mjs # writes cordis.local.yml with the real path
export RC_BOT_TOKEN="your-bot-jwt"
npx @deepseek-ai/dsh web --patch ./cordis.local.yml
Use pnpm dev (tsc --watch) while iterating: the loader hot-reloads the
plugin whenever dist/ changes. Pointing the patch at src/index.ts only
works inside a deepseek-harness source tree (pnpm dsh), not with the
npx-installed package.
TeamMessaging, ReadAccounts, WebSocketsSubscription.RC_BOT_TOKEN.Optional owner credentials (JWT REST API app for your own account, with
TeamMessaging + WebSocketsSubscription + ReadMessages) give
ringcentral_get_recent_messages owner read fallback and outbound owner
fallback. The history tool always reads through the bot client
(RC_BOT_TOKEN) first; without owner credentials it uses only the bot
client (chats the bot is a member of).
Config follows dsh practice: the cordis config tree is the single source
(profile cordis.patch.yml / cordis.yml), with Schema defaults applied
automatically. Secrets (RC_BOT_TOKEN, RC_USER_CLIENT_ID,
RC_USER_CLIENT_SECRET, RC_USER_JWT_TOKEN) resolve through the host
credentials domain — an explicit config value wins, then environment →
managed $DSH_HOME/.credentials.yaml → project/user .env, with the plain
process environment as the final fallback. RC_SERVER_URL works the other
way for operational overrides (e.g. sandbox): the environment value wins over
the configured/default server. Secrets are never persisted into profile YAML.
To drive any other setting from an environment variable, use the cordis
loader's !!js tag (double bang — a single !js is not evaluated), e.g.
access.groupMode: !!js process.env.RC_GROUP_MODE ?? 'open'.
The access-control block mirrors @tencent-connect/dsh-qqbot exactly
(QQ's c2c surface is dm here). RingCentral's three non-DM chat types
(Team / Everyone / Group) are all governed by the group surface.
| Config | Type | Default | Description |
|---|---|---|---|
botToken | string | required | Bot static JWT (env: RC_BOT_TOKEN) |
ownerCredentials.clientId / clientSecret / jwt | string | - | Owner JWT (env: RC_USER_*) |
server | string | https://platform.ringcentral.com | API server (env: RC_SERVER_URL) |
access.dmMode | enum | open | DM handling: disabled, allowlist, open |
access.dmAllow | string[] | [] | Person ids allowed in DMs; empty or ["*"] = allow all |
access.groupMode | enum | open | Group handling: disabled, allowlist, open |
access.groupAllow | string[] | [] | Chat ids allowed in groups; empty or ["*"] = allow all |
requireMention | boolean | true | Require @-mention in group chats |
groupPrompt | string | - | Extra system prompt for group chats |
directPrompt | string | - | Extra system prompt for DMs |
processingPlaceholder.enabled | boolean | false | Post 👀 → ⏳ while the agent works (texts/delay are fixed) |
historyMessageLimit | number | 250 | Default record count for the history tool |
homeChannel | string | - | Fallback target for the history tool |
textChunkLimit | number | 4000 | Max chars per outgoing post |
provider / model | string | host default | LLM route (fallback chain: per-peer prefs → config → host agentDefaultModel) |
preset | string | - | Agent preset id |
cwd | string | process.cwd() | Agent working directory |
sessionIdleTimeout | number | 1800000 | Idle session eviction (ms) |
showToolResults | boolean | false | Show successful tool results (errors always show) |
debug | boolean | false | Debug logging (includes inbound message logs) |
Every row except the secret entries is editable from the Web GUI card described below.
Installed into a web profile (dsh plugin --profile web add dsh-ringcentral),
the plugin registers a settings namespace and a configuration card under
Settings → Plugins → Plugin configuration. The card:
RC_BOT_TOKEN, RC_USER_*) as write-only
controls: it reports only whether each is configured and writes through the
host credentials domain ($DSH_HOME/.credentials.yaml); secret values are
never sent back to the page. Rotated credentials still take effect after a
plugin restart (see Design principles).Without a settings service (a bare custom cordis.yml), the card simply does
not mount and the plugin behaves exactly as before.
| Command | Description |
|---|---|
/new (/reset, /clear) | Start a new session (clear context) |
/compact | Compress session history (summary replaces old records) |
/model | Show or switch the model |
/stop | Abort the current generation |
/rc-ping | Connectivity test |
/rc-version | Plugin version |
/rc-status | Current session status |
/rc-help | List all commands |
sessionKey: ringcentral:<accountScopeKey>:<scope>:<peerId> where scope is
direct (peer = person id), group (peer = Group DM chat id), or
channel (peer = Team/Everyone chat id), and accountScopeKey is a
SHA-256 fingerprint of server + bot token. The SessionId is derived
deterministically (SHA-256), so the same user/chat always routes to the same
session and survives restarts. Resolution order: in-process reuse → persisted
resume → fresh create.
When the agent calls ask_user_question, the plugin renders the question
into the chat (thread-anchored) and waits for the user to reply in the same
session:
multi_select
accepts "1, 3"), or type a free-text answer.Note: the provider registers on the userQuestions service seam. In a web
profile the GUI provider takes precedence — questions then appear in the web
UI, not in RingCentral. Use a dedicated profile for IM-only operation.
inject = ['agents']; tools/compaction/presets are optional seams.pnpm install
pnpm build # or: pnpm dev (watch)
pnpm test
pnpm typecheck
# run against the npx-installed dsh
export RC_BOT_TOKEN="xxx"
node scripts/gen-dev-patch.mjs
npx @deepseek-ai/dsh web --patch ./cordis.local.yml
scripts/gen-dev-patch.mjs emits the gitignored cordis.local.yml directly,
with the entry resolved to an absolute path on the machine (default
dist/index.js; pass src/index.ts to point at the TypeScript entry).
| Symptom | Likely cause | Fix |
|---|---|---|
| Plugin not starting | RC_BOT_TOKEN missing | Set RC_BOT_TOKEN (env or $DSH_HOME/.credentials.yaml) or botToken in config |
| Bot never replies in a group chat | access.groupMode: disabled, not allowlisted, or no mention | Check access.groupMode / access.groupAllow and @-mention the bot |
| DM ignored | access.dmMode: disabled or sender not in access.dmAllow | Check access.dmMode / access.dmAllow |
| History tool returns nothing | Chat not visible to bot or owner | Reads try the bot first, then the owner; pass a bare chat id or channel:<chatId> and make sure one client is a member |
| Agent question not answered from RingCentral | Web GUI provider registered (web profile) | Questions go to the web UI; use a dedicated profile or answer in the web UI |
FAQs
RingCentral Team Messaging IM channel plugin for deepseek-harness (dsh)
The npm package dsh-ringcentral receives a total of 0 weekly downloads. As such, dsh-ringcentral popularity was classified as not popular.
We found that dsh-ringcentral demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.