Configuration
Configuration lives in the DSH profile patch (cordis.patch.yml) under the plugin's config:. dsh.shared.config.json in the project root (or its parent) can supply workspace/state defaults that take precedence for those keys.
dsh-connect (core)
| Key | Default | Description |
|---|
agentPreset | roster default | Agent preset id composed into each bound session. Resolution is best-effort: the configured id is tried, then standard (or the roster's first mountable row), and if neither composes the agent is built without a preset so the turn still runs. A stale id therefore degrades instead of failing every message — it is logged, not thrown. |
workDir | process cwd | Absolute working directory for each bound agent |
workspaces | [] | Extra workspaces offered by the /dir picker |
visionModel | auto-detected | { provider, model } used to describe images when the main model can't see them |
language | zh | User-facing message language: zh / en |
allowUsers | [] | Sender allowlist (open_id). Empty = allow all |
allowChats | [] | Chat allowlist (chat_id). Empty = allow all |
stateDir | .dsh-connect | Directory holding the bindings.json route store (env DSH_CONNECT_STATE_DIR overrides) |
autoMirror | true | Automatically create a Web GUI mirror for every new session |
streamHeartbeatMs | 60000 | Liveness heartbeat interval (ms) for the streaming card; 0 disables it |
notifyLevel | result | Default notification level: full (stream everything) / important (key milestones) / result (answer only, the default); per-chat override via settings menu or /notify |
progressTimeoutMs | 300000 | Proactive progress-notice interval (ms): when a turn has sent no standalone card/text for this long, a status card reports the latest milestone; 0 disables; per-chat override via settings menu or /progress |
Shared (all channels)
| Key | Default | Description |
|---|
channels | all built-in | Which channels to activate: feishu / telegram / dingtalk / web. Omit to activate all built-in channels. |
channelDefaults | {} | Keys applied to every channel that doesn't set its own (e.g. { language: "zh" }). |
settingsStatePath | /dsh-connect-settings.json | Where the web-settings pane mirrors non-secret config. Defaults to dsh-connect-settings.json inside stateDir, so it lands beside bindings.json and can never disagree with the stores; set it to override. Since 0.9.0 the pane's authoritative store is the dsh-connect section of $DSH_HOME/settings.yaml (see User settings), and this file is only the compatibility mirror the legacy /dsh-connect RPC reads and writes. |
feishu (Feishu / Lark channel)
| Key | Default | Description |
|---|
appId | env FEISHU_APP_ID | Feishu custom app id (secret) |
appSecret | env FEISHU_APP_SECRET | Feishu custom app secret (secret) |
transport | websocket | websocket = long connection (no public network); webhook needs public HTTPS |
verificationToken | — | Webhook verification token (secret) |
encryptKey | — | Webhook encrypt key (secret) |
webhookPort | 9000 | HTTP port for the built-in webhook server when transport: "webhook" |
webhookPath | / | URL path the Feishu event callback posts to (webhook transport) |
requireMention | true | Groups only respond when the bot is @mentioned |
dmMode | open | DM policy: open / allowlist / pair / disabled |
language | zh | User-facing message language: zh / en |
Environment variables
| Variable | Purpose |
|---|
FEISHU_APP_ID / FEISHU_APP_SECRET | Feishu credentials — preferred over putting secrets in config files |
DSH_CONNECT_STATE_DIR | Overrides stateDir for the binding store |
DSH_HOME | Overrides the ~/.dsh base for credential files |
Sensitive items — appSecret, verificationToken, encryptKey, and feishu-credentials.json. Prefer environment variables or one-click onboarding; keep them out of version control.
telegram (Telegram channel)
| Key | Default | Description |
|---|
botToken | env TELEGRAM_BOT_TOKEN | Telegram bot token from @BotFather (secret) |
requireMention | true | Groups only respond when the bot is @mentioned (or replying to the bot's own message) |
pollingTimeoutSeconds | 50 | getUpdates long-poll timeout in seconds |
baseUrl | — | Optional Bot API base URL override (e.g. a local Bot API server) |
language | zh | User-facing message language: zh / en |
dingtalk (DingTalk channel)
| Key | Default | Description |
|---|
webhookUrl | env DINGTALK_WEBHOOK_URL | Group custom-robot webhook URL (proactive push) |
secret | env DINGTALK_WEBHOOK_SECRET | Signing secret (SEC…) only when signing is enabled |
stream.clientId / stream.clientSecret | env DINGTALK_STREAM_CLIENT_ID / DINGTALK_STREAM_CLIENT_SECRET | Bidirectional stream-mode app credentials (secret, nested under stream) |
stream.requireMention | true | Group replies need an @-mention (stream mode) |
defaultAt | — | Default @-mentions merged into every push ({ mobiles, userIds, all }) |
language | zh | User-facing message language: zh / en |
web (Web mirror channel)
| Key | Default | Description |
|---|
pollIntervalMs | 1000 | Mirror-session polling interval (ms) |
Environment variables (FEISHU_*, TELEGRAM_*, DINGTALK_*, DSH_CONNECT_STATE_DIR, DSH_HOME) and the DSH credential store are the preferred way to supply per-channel secrets — the web settings pane writes them to the credential store and injectSecrets populates them on load.