ringclaw / dsh-ringcentral

已收录

Plugin for integrating RingCentral with DeepSeek Harness (dsh)

main其他 查看源代码

安装

npx @deepseek-ai/dsh plugin --profile ringcentral add dsh-ringcentral

此命令根据 GitHub 仓库地址生成。运行前请检查上游 README 与源代码;需要可复现安装时,请固定 release 或 commit。

README

维护者编写的文档快照。

在 GitHub 查看 ↗
提交版本 f9c3a2e同步于 2026年8月18日

最近一次目录同步未能刷新此 README 快照。

dsh-ringcentral

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 | 中文说明

Architecture

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

1. Via dsh plugin manager

# 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.

2. Local path

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

3. --patch development mode

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.

RingCentral bot setup

  1. Sign in at https://developers.ringcentral.com/.
  2. Create an app with the Bot platform type.
  3. Grant at least: TeamMessaging, ReadAccounts, WebSocketsSubscription.
  4. Install or publish the bot to your RingCentral account.
  5. Copy the bot JWT and use it as 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).

Configuration

Config follows dsh practice: the cordis config tree is the single source (profile cordis.patch.yml / cordis.yml), with Schema defaults applied automatically. The plugin reads environment variables directly only for secrets: RC_BOT_TOKEN, RC_SERVER_URL, RC_USER_CLIENT_ID, RC_USER_CLIENT_SECRET, RC_USER_JWT_TOKEN. To drive any other setting from an environment variable, use cordis ${VAR} interpolation in your config, e.g. dmPolicy: ${RC_DM_POLICY:-pairing}.

ConfigTypeDefaultDescription
botTokenstringrequiredBot static JWT (env: RC_BOT_TOKEN)
ownerCredentials.clientId / clientSecret / jwtstring-Owner JWT (env: RC_USER_*)
serverstringhttps://platform.ringcentral.comAPI server (env: RC_SERVER_URL)
botExtensionIdstringauto-detectedBot person id for mention/self-echo detection
dmPolicyenumpairingDM handling: disabled, allowlist, pairing, open
allowFromstring[][]Stable person ids allowed in DMs; open requires ["*"]
dangerouslyAllowEmailMatchingbooleanfalseMatch allowFrom against email aliases
groupPolicyenumdisabledTeam/Everyone handling: disabled, allowlist, open
teamsmap{}Per-chat Team config: allow, requireMention, systemPrompt, users
groupDmEnabledbooleanfalseEnable Group DM conversations
groupDmChannelsmap{}Per-chat Group DM allowlist
threadRequireMentionbooleantrueRequire mention for thread follow-ups
noThreadChannelsstring[][]Chat ids where replies are unthreaded
replyToModeenumfirstoff, first, or all
processingPlaceholder.enabledbooleanfalsePost 👀 while the agent works
processingPlaceholder.editDelaySecondsnumber2Delay before 👀 becomes
attachments.enabled / maxCount / maxBytes-true / 5 / 5242880Inbound attachment download
historyMessageLimitnumber250Default record count for the history tool
homeChannelstring-Fallback target for the history tool
requireMentionbooleantrueGlobal mention gate for Team/Everyone and Group DM (per-chat requireMention overrides)
textChunkLimitnumber4000Max chars per outgoing post
allowBotsbooleanfalseAdmit bot-authored inbound posts
provider / modelstringhost defaultLLM route (fallback chain: per-peer prefs → config → settings.yaml → host)
presetstring-Agent preset id
cwdstringprocess.cwd()Agent working directory
sessionIdleTimeoutnumber1800000Idle session eviction (ms)
showToolResultsbooleanfalseShow successful tool results (errors always show)
debugbooleanfalseDebug logging

Commands

CommandDescription
/new (/reset, /clear)Start a new session (clear context)
/compactCompress session history (summary replaces old records)
/modelShow or switch the model
/stopAbort the current generation
/rc-pingConnectivity test
/rc-versionPlugin version
/rc-statusCurrent session status
/rc-helpList all commands

Session routing

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.

Design principles

  • Pure Cordis plugin — follows dsh "Plugins, not loop changes".
  • Declarative depsinject = ['agents']; tools/compaction/presets are optional seams.
  • Session isolation — one agent per RingCentral peer.
  • Mini-Markdown outbound — replies are converted to RingCentral Mini-Markdown and chunked.
  • Threading — replies honor replyToMode with owner fallback and unthreaded retry.
  • Idle eviction — inactive agents are disposed automatically.
  • Defensive degradation — missing tools/presets/owner credentials never crash the plugin.

Not in v1 (planned follow-ups)

  • Adaptive Card / note / calendar / task artifact tools
  • Cron and out-of-process notification sender
  • Multi-account support
  • Native streaming (RingCentral has no stream API; the processing placeholder is the typing affordance)

Local development

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

cordis.dev.yml is the committed template; scripts/gen-dev-patch.mjs replaces the /path/to/dsh-ringcentral placeholder with the machine's absolute path and writes the gitignored cordis.local.yml.

Troubleshooting

SymptomLikely causeFix
Plugin not startingRC_BOT_TOKEN missingSet RC_BOT_TOKEN or botToken in cordis.patch.yml
Bot never replies in a TeamgroupPolicy: disabled or no mentionAllowlist the chat under teams and @-mention the bot
DM ignoreddmPolicy or pairing already claimedCheck dmPolicy / allowFrom; pairing is claimed by the first DM sender
History tool returns nothingChat not visible to bot or ownerReads try the bot first, then the owner; pass a bare chat id or channel:<chatId> and make sure one client is a member
Replies not threadedreplyToMode: off or noThreadChannelsCheck replyToMode and noThreadChannels
Legacy env rejectedRC_ALLOWED_USER_EMAILS etc.Behavioral config lives in the cordis config tree now — use allowFrom / teams (see migration errors in logs)

License

MIT

项目文件与信号

以下项目是目录快照中检测到的公开仓库信号。

测试已检测

仓库信息

开发语言
TypeScript
许可证
MIT
最新发布
v0.1.0
最后更新
2026年8月18日 08:29

谨慎安装

请检查源代码、权限、生命周期脚本、依赖与网络访问;不受信任的插件应先在隔离环境中测试。