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. AM 8:29

신중하게 설치하기

소스 코드, 권한, 수명 주기 스크립트, 의존성 및 네트워크 접근을 검토하고 신뢰하지 않는 플러그인은 격리 환경에서 테스트하세요.