durar-ai 2026.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5497 -0
- package/LICENSE +21 -0
- package/README.md +614 -0
- package/assets/avatar-placeholder.svg +19 -0
- package/assets/chrome-extension/icons/icon128.png +0 -0
- package/assets/chrome-extension/icons/icon16.png +0 -0
- package/assets/chrome-extension/icons/icon32.png +0 -0
- package/assets/chrome-extension/icons/icon48.png +0 -0
- package/assets/dmg-background-small.png +0 -0
- package/assets/dmg-background.png +0 -0
- package/docs/.i18n/README.md +72 -0
- package/docs/.i18n/ar-navigation.json +18 -0
- package/docs/.i18n/de-navigation.json +18 -0
- package/docs/.i18n/es-navigation.json +18 -0
- package/docs/.i18n/fr-navigation.json +18 -0
- package/docs/.i18n/glossary.ar.json +5 -0
- package/docs/.i18n/glossary.de.json +5 -0
- package/docs/.i18n/glossary.es.json +5 -0
- package/docs/.i18n/glossary.fr.json +5 -0
- package/docs/.i18n/glossary.id.json +5 -0
- package/docs/.i18n/glossary.it.json +5 -0
- package/docs/.i18n/glossary.ja-JP.json +14 -0
- package/docs/.i18n/glossary.ko.json +5 -0
- package/docs/.i18n/glossary.pl.json +5 -0
- package/docs/.i18n/glossary.pt-BR.json +5 -0
- package/docs/.i18n/glossary.tr.json +5 -0
- package/docs/.i18n/glossary.zh-CN.json +358 -0
- package/docs/.i18n/id-navigation.json +18 -0
- package/docs/.i18n/it-navigation.json +18 -0
- package/docs/.i18n/ja-navigation.json +18 -0
- package/docs/.i18n/ko-navigation.json +18 -0
- package/docs/.i18n/pl-navigation.json +18 -0
- package/docs/.i18n/pt-BR-navigation.json +18 -0
- package/docs/.i18n/tr-navigation.json +18 -0
- package/docs/.i18n/zh-Hans-navigation.json +544 -0
- package/docs/assets/install-script.svg +1 -0
- package/docs/assets/macos-onboarding/01-macos-warning.jpeg +0 -0
- package/docs/assets/macos-onboarding/02-local-networks.jpeg +0 -0
- package/docs/assets/macos-onboarding/03-security-notice.png +0 -0
- package/docs/assets/macos-onboarding/04-choose-gateway.png +0 -0
- package/docs/assets/macos-onboarding/05-permissions.png +0 -0
- package/docs/assets/openclaw-logo-text-dark.png +0 -0
- package/docs/assets/openclaw-logo-text-dark.svg +418 -0
- package/docs/assets/openclaw-logo-text.png +0 -0
- package/docs/assets/openclaw-logo-text.svg +418 -0
- package/docs/assets/pixel-lobster.svg +60 -0
- package/docs/assets/showcase/agents-ui.jpg +0 -0
- package/docs/assets/showcase/bambu-cli.png +0 -0
- package/docs/assets/showcase/codexmonitor.png +0 -0
- package/docs/assets/showcase/gohome-grafana.png +0 -0
- package/docs/assets/showcase/ios-testflight.jpg +0 -0
- package/docs/assets/showcase/oura-health.png +0 -0
- package/docs/assets/showcase/padel-cli.svg +11 -0
- package/docs/assets/showcase/padel-screenshot.jpg +0 -0
- package/docs/assets/showcase/papla-tts.jpg +0 -0
- package/docs/assets/showcase/pr-review-telegram.jpg +0 -0
- package/docs/assets/showcase/roborock-screenshot.jpg +0 -0
- package/docs/assets/showcase/roborock-status.svg +13 -0
- package/docs/assets/showcase/roof-camera-sky.jpg +0 -0
- package/docs/assets/showcase/snag.png +0 -0
- package/docs/assets/showcase/tesco-shop.jpg +0 -0
- package/docs/assets/showcase/wienerlinien.png +0 -0
- package/docs/assets/showcase/wine-cellar-skill.jpg +0 -0
- package/docs/assets/showcase/winix-air-purifier.jpg +0 -0
- package/docs/assets/showcase/xuezh-pronunciation.jpeg +0 -0
- package/docs/assets/sponsors/blacksmith-light.svg +14 -0
- package/docs/assets/sponsors/blacksmith.svg +14 -0
- package/docs/assets/sponsors/convex-light.svg +16 -0
- package/docs/assets/sponsors/convex.svg +16 -0
- package/docs/assets/sponsors/github-light.svg +3 -0
- package/docs/assets/sponsors/github.svg +3 -0
- package/docs/assets/sponsors/nvidia-dark.svg +9 -0
- package/docs/assets/sponsors/nvidia.svg +9 -0
- package/docs/assets/sponsors/openai-light.svg +3 -0
- package/docs/assets/sponsors/openai.svg +3 -0
- package/docs/assets/sponsors/vercel-light.svg +5 -0
- package/docs/assets/sponsors/vercel.svg +5 -0
- package/docs/auth-credential-semantics.md +80 -0
- package/docs/automation/auth-monitoring.md +8 -0
- package/docs/automation/clawflow.md +8 -0
- package/docs/automation/cron-jobs.md +410 -0
- package/docs/automation/cron-vs-heartbeat.md +8 -0
- package/docs/automation/gmail-pubsub.md +8 -0
- package/docs/automation/hooks.md +303 -0
- package/docs/automation/index.md +115 -0
- package/docs/automation/poll.md +8 -0
- package/docs/automation/standing-orders.md +254 -0
- package/docs/automation/taskflow.md +82 -0
- package/docs/automation/tasks.md +323 -0
- package/docs/automation/troubleshooting.md +8 -0
- package/docs/automation/webhook.md +8 -0
- package/docs/brave-search.md +103 -0
- package/docs/channels/bluebubbles.md +435 -0
- package/docs/channels/broadcast-groups.md +442 -0
- package/docs/channels/channel-routing.md +139 -0
- package/docs/channels/discord.md +1254 -0
- package/docs/channels/feishu.md +793 -0
- package/docs/channels/googlechat.md +270 -0
- package/docs/channels/group-messages.md +84 -0
- package/docs/channels/groups.md +410 -0
- package/docs/channels/imessage.md +427 -0
- package/docs/channels/index.md +50 -0
- package/docs/channels/irc.md +252 -0
- package/docs/channels/line.md +225 -0
- package/docs/channels/location.md +56 -0
- package/docs/channels/matrix.md +869 -0
- package/docs/channels/mattermost.md +472 -0
- package/docs/channels/msteams.md +805 -0
- package/docs/channels/nextcloud-talk.md +149 -0
- package/docs/channels/nostr.md +252 -0
- package/docs/channels/pairing.md +129 -0
- package/docs/channels/qqbot.md +193 -0
- package/docs/channels/signal.md +337 -0
- package/docs/channels/slack.md +681 -0
- package/docs/channels/synology-chat.md +185 -0
- package/docs/channels/telegram.md +1072 -0
- package/docs/channels/tlon.md +290 -0
- package/docs/channels/troubleshooting.md +133 -0
- package/docs/channels/twitch.md +394 -0
- package/docs/channels/whatsapp.md +488 -0
- package/docs/channels/zalo.md +254 -0
- package/docs/channels/zalouser.md +195 -0
- package/docs/ci.md +66 -0
- package/docs/cli/acp.md +316 -0
- package/docs/cli/agent.md +57 -0
- package/docs/cli/agents.md +220 -0
- package/docs/cli/approvals.md +136 -0
- package/docs/cli/backup.md +84 -0
- package/docs/cli/browser.md +233 -0
- package/docs/cli/channels.md +131 -0
- package/docs/cli/clawbot.md +21 -0
- package/docs/cli/completion.md +35 -0
- package/docs/cli/config.md +353 -0
- package/docs/cli/configure.md +70 -0
- package/docs/cli/cron.md +167 -0
- package/docs/cli/daemon.md +57 -0
- package/docs/cli/dashboard.md +22 -0
- package/docs/cli/devices.md +171 -0
- package/docs/cli/directory.md +63 -0
- package/docs/cli/dns.md +48 -0
- package/docs/cli/docs.md +28 -0
- package/docs/cli/doctor.md +63 -0
- package/docs/cli/flows.md +18 -0
- package/docs/cli/gateway.md +307 -0
- package/docs/cli/health.md +36 -0
- package/docs/cli/hooks.md +337 -0
- package/docs/cli/index.md +1836 -0
- package/docs/cli/logs.md +59 -0
- package/docs/cli/mcp.md +505 -0
- package/docs/cli/memory.md +139 -0
- package/docs/cli/message.md +300 -0
- package/docs/cli/models.md +136 -0
- package/docs/cli/node.md +137 -0
- package/docs/cli/nodes.md +66 -0
- package/docs/cli/onboard.md +171 -0
- package/docs/cli/pairing.md +65 -0
- package/docs/cli/plugins.md +305 -0
- package/docs/cli/qr.md +52 -0
- package/docs/cli/reset.md +35 -0
- package/docs/cli/sandbox.md +197 -0
- package/docs/cli/secrets.md +197 -0
- package/docs/cli/security.md +86 -0
- package/docs/cli/sessions.md +113 -0
- package/docs/cli/setup.md +45 -0
- package/docs/cli/skills.md +59 -0
- package/docs/cli/status.md +35 -0
- package/docs/cli/system.md +71 -0
- package/docs/cli/tui.md +30 -0
- package/docs/cli/uninstall.md +39 -0
- package/docs/cli/update.md +113 -0
- package/docs/cli/voicecall.md +34 -0
- package/docs/cli/webhooks.md +91 -0
- package/docs/concepts/agent-loop.md +168 -0
- package/docs/concepts/agent-workspace.md +246 -0
- package/docs/concepts/agent.md +129 -0
- package/docs/concepts/architecture.md +156 -0
- package/docs/concepts/compaction.md +122 -0
- package/docs/concepts/context-engine.md +274 -0
- package/docs/concepts/context.md +179 -0
- package/docs/concepts/delegate-architecture.md +307 -0
- package/docs/concepts/dreaming.md +173 -0
- package/docs/concepts/features.md +76 -0
- package/docs/concepts/markdown-formatting.md +130 -0
- package/docs/concepts/memory-builtin.md +105 -0
- package/docs/concepts/memory-honcho.md +140 -0
- package/docs/concepts/memory-qmd.md +163 -0
- package/docs/concepts/memory-search.md +141 -0
- package/docs/concepts/memory.md +121 -0
- package/docs/concepts/messages.md +161 -0
- package/docs/concepts/model-failover.md +349 -0
- package/docs/concepts/model-providers.md +799 -0
- package/docs/concepts/models.md +255 -0
- package/docs/concepts/multi-agent.md +615 -0
- package/docs/concepts/oauth.md +225 -0
- package/docs/concepts/presence.md +102 -0
- package/docs/concepts/queue.md +89 -0
- package/docs/concepts/retry.md +69 -0
- package/docs/concepts/session-pruning.md +92 -0
- package/docs/concepts/session-tool.md +141 -0
- package/docs/concepts/session.md +116 -0
- package/docs/concepts/soul.md +110 -0
- package/docs/concepts/streaming.md +161 -0
- package/docs/concepts/system-prompt.md +182 -0
- package/docs/concepts/timezone.md +97 -0
- package/docs/concepts/typebox.md +307 -0
- package/docs/concepts/typing-indicators.md +69 -0
- package/docs/concepts/usage-tracking.md +59 -0
- package/docs/date-time.md +128 -0
- package/docs/debug/node-issue.md +85 -0
- package/docs/diagnostics/flags.md +91 -0
- package/docs/docs.json +1601 -0
- package/docs/gateway/authentication.md +218 -0
- package/docs/gateway/background-process.md +131 -0
- package/docs/gateway/bonjour.md +179 -0
- package/docs/gateway/bridge-protocol.md +89 -0
- package/docs/gateway/cli-backends.md +310 -0
- package/docs/gateway/configuration-examples.md +631 -0
- package/docs/gateway/configuration-reference.md +3618 -0
- package/docs/gateway/configuration.md +698 -0
- package/docs/gateway/discovery.md +141 -0
- package/docs/gateway/doctor.md +494 -0
- package/docs/gateway/gateway-lock.md +37 -0
- package/docs/gateway/health.md +61 -0
- package/docs/gateway/heartbeat.md +443 -0
- package/docs/gateway/index.md +367 -0
- package/docs/gateway/local-models.md +163 -0
- package/docs/gateway/logging.md +113 -0
- package/docs/gateway/multiple-gateways.md +120 -0
- package/docs/gateway/network-model.md +25 -0
- package/docs/gateway/openai-http-api.md +280 -0
- package/docs/gateway/openresponses-http-api.md +340 -0
- package/docs/gateway/openshell.md +307 -0
- package/docs/gateway/pairing.md +138 -0
- package/docs/gateway/protocol.md +588 -0
- package/docs/gateway/remote-gateway-readme.md +164 -0
- package/docs/gateway/remote.md +251 -0
- package/docs/gateway/sandbox-vs-tool-policy-vs-elevated.md +141 -0
- package/docs/gateway/sandboxing.md +473 -0
- package/docs/gateway/secrets-plan-contract.md +116 -0
- package/docs/gateway/secrets.md +541 -0
- package/docs/gateway/security/index.md +1362 -0
- package/docs/gateway/tailscale.md +136 -0
- package/docs/gateway/tools-invoke-http-api.md +161 -0
- package/docs/gateway/troubleshooting.md +451 -0
- package/docs/gateway/trusted-proxy-auth.md +399 -0
- package/docs/help/debugging.md +168 -0
- package/docs/help/environment.md +165 -0
- package/docs/help/faq.md +3244 -0
- package/docs/help/index.md +28 -0
- package/docs/help/scripts.md +27 -0
- package/docs/help/testing.md +640 -0
- package/docs/help/troubleshooting.md +372 -0
- package/docs/images/configure-model-picker-unsearchable.png +0 -0
- package/docs/images/feishu-step2-create-app.png +0 -0
- package/docs/images/feishu-step3-credentials.png +0 -0
- package/docs/images/feishu-step4-permissions.png +0 -0
- package/docs/images/feishu-step5-bot-capability.png +0 -0
- package/docs/images/feishu-step6-event-subscription.png +0 -0
- package/docs/images/feishu-verification-token.png +0 -0
- package/docs/images/groups-flow.svg +52 -0
- package/docs/images/mobile-ui-screenshot.png +0 -0
- package/docs/index.md +196 -0
- package/docs/install/ansible.md +230 -0
- package/docs/install/azure.md +311 -0
- package/docs/install/bun.md +55 -0
- package/docs/install/clawdock.md +106 -0
- package/docs/install/development-channels.md +131 -0
- package/docs/install/digitalocean.md +129 -0
- package/docs/install/docker-vm-runtime.md +142 -0
- package/docs/install/docker.md +412 -0
- package/docs/install/exe-dev.md +133 -0
- package/docs/install/fly.md +504 -0
- package/docs/install/gcp.md +412 -0
- package/docs/install/hetzner.md +259 -0
- package/docs/install/index.md +212 -0
- package/docs/install/installer.md +443 -0
- package/docs/install/kubernetes.md +192 -0
- package/docs/install/macos-vm.md +281 -0
- package/docs/install/migrating-matrix.md +349 -0
- package/docs/install/migrating.md +112 -0
- package/docs/install/nix.md +89 -0
- package/docs/install/node.md +144 -0
- package/docs/install/northflank.mdx +42 -0
- package/docs/install/oracle.md +158 -0
- package/docs/install/podman.md +210 -0
- package/docs/install/railway.mdx +90 -0
- package/docs/install/raspberry-pi.md +159 -0
- package/docs/install/render.mdx +165 -0
- package/docs/install/uninstall.md +128 -0
- package/docs/install/updating.md +142 -0
- package/docs/logging.md +389 -0
- package/docs/nav-tabs-underline.js +100 -0
- package/docs/network.md +69 -0
- package/docs/nodes/audio.md +191 -0
- package/docs/nodes/camera.md +162 -0
- package/docs/nodes/images.md +73 -0
- package/docs/nodes/index.md +408 -0
- package/docs/nodes/location-command.md +98 -0
- package/docs/nodes/media-understanding.md +432 -0
- package/docs/nodes/talk.md +92 -0
- package/docs/nodes/troubleshooting.md +123 -0
- package/docs/nodes/voicewake.md +66 -0
- package/docs/perplexity.md +181 -0
- package/docs/pi-dev.md +80 -0
- package/docs/pi.md +570 -0
- package/docs/platforms/android.md +244 -0
- package/docs/platforms/digitalocean.md +266 -0
- package/docs/platforms/index.md +55 -0
- package/docs/platforms/ios.md +223 -0
- package/docs/platforms/linux.md +100 -0
- package/docs/platforms/mac/bundled-gateway.md +75 -0
- package/docs/platforms/mac/canvas.md +125 -0
- package/docs/platforms/mac/child-process.md +69 -0
- package/docs/platforms/mac/dev-setup.md +107 -0
- package/docs/platforms/mac/health.md +34 -0
- package/docs/platforms/mac/icon.md +31 -0
- package/docs/platforms/mac/logging.md +57 -0
- package/docs/platforms/mac/menu-bar.md +81 -0
- package/docs/platforms/mac/peekaboo.md +65 -0
- package/docs/platforms/mac/permissions.md +50 -0
- package/docs/platforms/mac/remote.md +84 -0
- package/docs/platforms/mac/signing.md +47 -0
- package/docs/platforms/mac/skills.md +40 -0
- package/docs/platforms/mac/voice-overlay.md +60 -0
- package/docs/platforms/mac/voicewake.md +67 -0
- package/docs/platforms/mac/webchat.md +51 -0
- package/docs/platforms/mac/xpc.md +61 -0
- package/docs/platforms/macos.md +229 -0
- package/docs/platforms/oracle.md +305 -0
- package/docs/platforms/raspberry-pi.md +420 -0
- package/docs/platforms/windows.md +241 -0
- package/docs/plugins/agent-tools.md +10 -0
- package/docs/plugins/architecture.md +1609 -0
- package/docs/plugins/building-extensions.md +10 -0
- package/docs/plugins/building-plugins.md +319 -0
- package/docs/plugins/bundles.md +292 -0
- package/docs/plugins/community.md +149 -0
- package/docs/plugins/manifest.md +412 -0
- package/docs/plugins/sdk-channel-plugins.md +508 -0
- package/docs/plugins/sdk-entrypoints.md +210 -0
- package/docs/plugins/sdk-migration.md +359 -0
- package/docs/plugins/sdk-overview.md +475 -0
- package/docs/plugins/sdk-provider-plugins.md +712 -0
- package/docs/plugins/sdk-runtime.md +381 -0
- package/docs/plugins/sdk-setup.md +516 -0
- package/docs/plugins/sdk-testing.md +263 -0
- package/docs/plugins/voice-call.md +466 -0
- package/docs/plugins/zalouser.md +78 -0
- package/docs/prose.md +134 -0
- package/docs/providers/anthropic.md +402 -0
- package/docs/providers/bedrock-mantle.md +91 -0
- package/docs/providers/bedrock.md +273 -0
- package/docs/providers/chutes.md +103 -0
- package/docs/providers/claude-max-api-proxy.md +163 -0
- package/docs/providers/cloudflare-ai-gateway.md +71 -0
- package/docs/providers/deepgram.md +93 -0
- package/docs/providers/deepseek.md +53 -0
- package/docs/providers/fireworks.md +69 -0
- package/docs/providers/github-copilot.md +80 -0
- package/docs/providers/glm.md +68 -0
- package/docs/providers/google.md +149 -0
- package/docs/providers/groq.md +105 -0
- package/docs/providers/huggingface.md +193 -0
- package/docs/providers/index.md +81 -0
- package/docs/providers/kilocode.md +89 -0
- package/docs/providers/litellm.md +159 -0
- package/docs/providers/minimax.md +281 -0
- package/docs/providers/mistral.md +68 -0
- package/docs/providers/models.md +56 -0
- package/docs/providers/moonshot.md +224 -0
- package/docs/providers/nvidia.md +58 -0
- package/docs/providers/ollama.md +379 -0
- package/docs/providers/openai.md +472 -0
- package/docs/providers/opencode-go.md +45 -0
- package/docs/providers/opencode.md +68 -0
- package/docs/providers/openrouter.md +59 -0
- package/docs/providers/perplexity-provider.md +62 -0
- package/docs/providers/qianfan.md +90 -0
- package/docs/providers/qwen.md +128 -0
- package/docs/providers/qwen_modelstudio.md +137 -0
- package/docs/providers/sglang.md +115 -0
- package/docs/providers/stepfun.md +152 -0
- package/docs/providers/synthetic.md +101 -0
- package/docs/providers/together.md +70 -0
- package/docs/providers/venice.md +282 -0
- package/docs/providers/vercel-ai-gateway.md +60 -0
- package/docs/providers/vllm.md +103 -0
- package/docs/providers/volcengine.md +94 -0
- package/docs/providers/xai.md +94 -0
- package/docs/providers/xiaomi.md +89 -0
- package/docs/providers/zai.md +75 -0
- package/docs/reference/AGENTS.default.md +126 -0
- package/docs/reference/RELEASING.md +138 -0
- package/docs/reference/api-usage-costs.md +198 -0
- package/docs/reference/credits.md +30 -0
- package/docs/reference/device-models.md +47 -0
- package/docs/reference/memory-config.md +421 -0
- package/docs/reference/prompt-caching.md +344 -0
- package/docs/reference/rpc.md +43 -0
- package/docs/reference/secretref-credential-surface.md +148 -0
- package/docs/reference/secretref-user-supplied-credentials-matrix.json +607 -0
- package/docs/reference/session-management-compaction.md +352 -0
- package/docs/reference/templates/AGENTS.dev.md +84 -0
- package/docs/reference/templates/AGENTS.md +219 -0
- package/docs/reference/templates/BOOT.md +12 -0
- package/docs/reference/templates/BOOTSTRAP.md +62 -0
- package/docs/reference/templates/CLAUDE.md +1 -0
- package/docs/reference/templates/HEARTBEAT.md +14 -0
- package/docs/reference/templates/IDENTITY.dev.md +48 -0
- package/docs/reference/templates/IDENTITY.md +30 -0
- package/docs/reference/templates/SOUL.dev.md +77 -0
- package/docs/reference/templates/SOUL.md +45 -0
- package/docs/reference/templates/TOOLS.dev.md +25 -0
- package/docs/reference/templates/TOOLS.md +47 -0
- package/docs/reference/templates/USER.dev.md +19 -0
- package/docs/reference/templates/USER.md +24 -0
- package/docs/reference/test.md +119 -0
- package/docs/reference/token-use.md +197 -0
- package/docs/reference/transcript-hygiene.md +151 -0
- package/docs/reference/wizard.md +245 -0
- package/docs/security/CONTRIBUTING-THREAT-MODEL.md +98 -0
- package/docs/security/THREAT-MODEL-ATLAS.md +608 -0
- package/docs/security/formal-verification.md +167 -0
- package/docs/snippets/plugin-publish/minimal-openclaw.plugin.json +9 -0
- package/docs/snippets/plugin-publish/minimal-package.json +16 -0
- package/docs/start/bootstrapping.md +41 -0
- package/docs/start/docs-directory.md +67 -0
- package/docs/start/getting-started.md +148 -0
- package/docs/start/hubs.md +199 -0
- package/docs/start/lore.md +219 -0
- package/docs/start/onboarding-overview.md +69 -0
- package/docs/start/onboarding.md +92 -0
- package/docs/start/openclaw.md +225 -0
- package/docs/start/quickstart.md +22 -0
- package/docs/start/setup.md +172 -0
- package/docs/start/showcase.md +418 -0
- package/docs/start/wizard-cli-automation.md +233 -0
- package/docs/start/wizard-cli-reference.md +324 -0
- package/docs/start/wizard.md +127 -0
- package/docs/style.css +37 -0
- package/docs/tools/acp-agents.md +837 -0
- package/docs/tools/agent-send.md +100 -0
- package/docs/tools/apply-patch.md +52 -0
- package/docs/tools/brave-search.md +107 -0
- package/docs/tools/browser-linux-troubleshooting.md +145 -0
- package/docs/tools/browser-login.md +73 -0
- package/docs/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md +221 -0
- package/docs/tools/browser.md +890 -0
- package/docs/tools/btw.md +142 -0
- package/docs/tools/capability-cookbook.md +119 -0
- package/docs/tools/clawhub.md +348 -0
- package/docs/tools/code-execution.md +90 -0
- package/docs/tools/creating-skills.md +119 -0
- package/docs/tools/diffs.md +434 -0
- package/docs/tools/duckduckgo-search.md +102 -0
- package/docs/tools/elevated.md +116 -0
- package/docs/tools/exa-search.md +127 -0
- package/docs/tools/exec-approvals.md +635 -0
- package/docs/tools/exec.md +237 -0
- package/docs/tools/firecrawl.md +147 -0
- package/docs/tools/gemini-search.md +98 -0
- package/docs/tools/grok-search.md +102 -0
- package/docs/tools/image-generation.md +139 -0
- package/docs/tools/index.md +174 -0
- package/docs/tools/kimi-search.md +98 -0
- package/docs/tools/llm-task.md +119 -0
- package/docs/tools/lobster.md +348 -0
- package/docs/tools/loop-detection.md +100 -0
- package/docs/tools/minimax-search.md +99 -0
- package/docs/tools/multi-agent-sandbox-tools.md +373 -0
- package/docs/tools/ollama-search.md +100 -0
- package/docs/tools/pdf.md +176 -0
- package/docs/tools/perplexity-search.md +185 -0
- package/docs/tools/plugin.md +348 -0
- package/docs/tools/reactions.md +78 -0
- package/docs/tools/searxng-search.md +132 -0
- package/docs/tools/skills-config.md +133 -0
- package/docs/tools/skills.md +377 -0
- package/docs/tools/slash-commands.md +322 -0
- package/docs/tools/subagents.md +341 -0
- package/docs/tools/tavily.md +129 -0
- package/docs/tools/thinking.md +102 -0
- package/docs/tools/tts.md +452 -0
- package/docs/tools/web-fetch.md +159 -0
- package/docs/tools/web.md +417 -0
- package/docs/tts.md +452 -0
- package/docs/vps.md +115 -0
- package/docs/web/control-ui.md +318 -0
- package/docs/web/dashboard.md +93 -0
- package/docs/web/index.md +126 -0
- package/docs/web/tui.md +176 -0
- package/docs/web/webchat.md +77 -0
- package/docs/whatsapp-openclaw-ai-zh.jpg +0 -0
- package/docs/whatsapp-openclaw.jpg +0 -0
- package/durar.mjs +180 -0
- package/package.json +1259 -0
- package/scripts/npm-runner.mjs +111 -0
- package/scripts/postinstall-bundled-plugins.mjs +188 -0
- package/skills/1password/SKILL.md +70 -0
- package/skills/1password/references/cli-examples.md +29 -0
- package/skills/1password/references/get-started.md +17 -0
- package/skills/apple-notes/SKILL.md +77 -0
- package/skills/apple-reminders/SKILL.md +118 -0
- package/skills/bear-notes/SKILL.md +107 -0
- package/skills/blogwatcher/SKILL.md +69 -0
- package/skills/blucli/SKILL.md +47 -0
- package/skills/bluebubbles/SKILL.md +131 -0
- package/skills/camsnap/SKILL.md +45 -0
- package/skills/canvas/SKILL.md +199 -0
- package/skills/clawhub/SKILL.md +77 -0
- package/skills/coding-agent/SKILL.md +316 -0
- package/skills/discord/SKILL.md +197 -0
- package/skills/eightctl/SKILL.md +50 -0
- package/skills/gemini/SKILL.md +43 -0
- package/skills/gh-issues/SKILL.md +885 -0
- package/skills/gifgrep/SKILL.md +79 -0
- package/skills/github/SKILL.md +163 -0
- package/skills/gog/SKILL.md +116 -0
- package/skills/goplaces/SKILL.md +52 -0
- package/skills/healthcheck/SKILL.md +245 -0
- package/skills/himalaya/SKILL.md +257 -0
- package/skills/himalaya/references/configuration.md +184 -0
- package/skills/himalaya/references/message-composition.md +199 -0
- package/skills/imsg/SKILL.md +122 -0
- package/skills/mcporter/SKILL.md +61 -0
- package/skills/model-usage/SKILL.md +69 -0
- package/skills/model-usage/references/codexbar-cli.md +33 -0
- package/skills/model-usage/scripts/model_usage.py +320 -0
- package/skills/model-usage/scripts/test_model_usage.py +40 -0
- package/skills/nano-pdf/SKILL.md +38 -0
- package/skills/node-connect/SKILL.md +142 -0
- package/skills/notion/SKILL.md +174 -0
- package/skills/obsidian/SKILL.md +81 -0
- package/skills/openai-whisper/SKILL.md +38 -0
- package/skills/openai-whisper-api/SKILL.md +62 -0
- package/skills/openai-whisper-api/scripts/transcribe.sh +88 -0
- package/skills/openhue/SKILL.md +112 -0
- package/skills/oracle/SKILL.md +125 -0
- package/skills/ordercli/SKILL.md +78 -0
- package/skills/peekaboo/SKILL.md +190 -0
- package/skills/sag/SKILL.md +87 -0
- package/skills/session-logs/SKILL.md +151 -0
- package/skills/sherpa-onnx-tts/SKILL.md +109 -0
- package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
- package/skills/skill-creator/SKILL.md +372 -0
- package/skills/skill-creator/license.txt +202 -0
- package/skills/skill-creator/scripts/init_skill.py +378 -0
- package/skills/skill-creator/scripts/package_skill.py +139 -0
- package/skills/skill-creator/scripts/quick_validate.py +159 -0
- package/skills/skill-creator/scripts/test_package_skill.py +160 -0
- package/skills/skill-creator/scripts/test_quick_validate.py +72 -0
- package/skills/slack/SKILL.md +144 -0
- package/skills/songsee/SKILL.md +49 -0
- package/skills/sonoscli/SKILL.md +65 -0
- package/skills/spotify-player/SKILL.md +64 -0
- package/skills/summarize/SKILL.md +87 -0
- package/skills/taskflow/SKILL.md +149 -0
- package/skills/taskflow/examples/inbox-triage.lobster +33 -0
- package/skills/taskflow/examples/pr-intake.lobster +32 -0
- package/skills/taskflow-inbox-triage/SKILL.md +119 -0
- package/skills/things-mac/SKILL.md +86 -0
- package/skills/tmux/SKILL.md +170 -0
- package/skills/tmux/scripts/find-sessions.sh +112 -0
- package/skills/tmux/scripts/wait-for-text.sh +83 -0
- package/skills/trello/SKILL.md +108 -0
- package/skills/video-frames/SKILL.md +46 -0
- package/skills/video-frames/scripts/frame.sh +81 -0
- package/skills/voice-call/SKILL.md +45 -0
- package/skills/wacli/SKILL.md +72 -0
- package/skills/weather/SKILL.md +129 -0
- package/skills/xurl/SKILL.md +461 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Building Channel Plugins"
|
|
3
|
+
sidebarTitle: "Channel Plugins"
|
|
4
|
+
summary: "Step-by-step guide to building a messaging channel plugin for Durar"
|
|
5
|
+
read_when:
|
|
6
|
+
- You are building a new messaging channel plugin
|
|
7
|
+
- You want to connect Durar to a messaging platform
|
|
8
|
+
- You need to understand the ChannelPlugin adapter surface
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Building Channel Plugins
|
|
12
|
+
|
|
13
|
+
This guide walks through building a channel plugin that connects Durar to a
|
|
14
|
+
messaging platform. By the end you will have a working channel with DM security,
|
|
15
|
+
pairing, reply threading, and outbound messaging.
|
|
16
|
+
|
|
17
|
+
<Info>
|
|
18
|
+
If you have not built any Durar plugin before, read
|
|
19
|
+
[Getting Started](/plugins/building-plugins) first for the basic package
|
|
20
|
+
structure and manifest setup.
|
|
21
|
+
</Info>
|
|
22
|
+
|
|
23
|
+
## How channel plugins work
|
|
24
|
+
|
|
25
|
+
Channel plugins do not need their own send/edit/react tools. Durar keeps one
|
|
26
|
+
shared `message` tool in core. Your plugin owns:
|
|
27
|
+
|
|
28
|
+
- **Config** — account resolution and setup wizard
|
|
29
|
+
- **Security** — DM policy and allowlists
|
|
30
|
+
- **Pairing** — DM approval flow
|
|
31
|
+
- **Session grammar** — how provider-specific conversation ids map to base chats, thread ids, and parent fallbacks
|
|
32
|
+
- **Outbound** — sending text, media, and polls to the platform
|
|
33
|
+
- **Threading** — how replies are threaded
|
|
34
|
+
|
|
35
|
+
Core owns the shared message tool, prompt wiring, the outer session-key shape,
|
|
36
|
+
generic `:thread:` bookkeeping, and dispatch.
|
|
37
|
+
|
|
38
|
+
If your platform stores extra scope inside conversation ids, keep that parsing
|
|
39
|
+
in the plugin with `messaging.resolveSessionConversation(...)`. That is the
|
|
40
|
+
canonical hook for mapping `rawId` to the base conversation id, optional thread
|
|
41
|
+
id, explicit `baseConversationId`, and any `parentConversationCandidates`.
|
|
42
|
+
When you return `parentConversationCandidates`, keep them ordered from the
|
|
43
|
+
narrowest parent to the broadest/base conversation.
|
|
44
|
+
|
|
45
|
+
Bundled plugins that need the same parsing before the channel registry boots
|
|
46
|
+
can also expose a top-level `session-key-api.ts` file with a matching
|
|
47
|
+
`resolveSessionConversation(...)` export. Core uses that bootstrap-safe surface
|
|
48
|
+
only when the runtime plugin registry is not available yet.
|
|
49
|
+
|
|
50
|
+
`messaging.resolveParentConversationCandidates(...)` remains available as a
|
|
51
|
+
legacy compatibility fallback when a plugin only needs parent fallbacks on top
|
|
52
|
+
of the generic/raw id. If both hooks exist, core uses
|
|
53
|
+
`resolveSessionConversation(...).parentConversationCandidates` first and only
|
|
54
|
+
falls back to `resolveParentConversationCandidates(...)` when the canonical hook
|
|
55
|
+
omits them.
|
|
56
|
+
|
|
57
|
+
## Approvals and channel capabilities
|
|
58
|
+
|
|
59
|
+
Most channel plugins do not need approval-specific code.
|
|
60
|
+
|
|
61
|
+
- Core owns same-chat `/approve`, shared approval button payloads, and generic fallback delivery.
|
|
62
|
+
- Prefer one `approvalCapability` object on the channel plugin when the channel needs approval-specific behavior.
|
|
63
|
+
- `approvalCapability.authorizeActorAction` and `approvalCapability.getActionAvailabilityState` are the canonical approval-auth seam.
|
|
64
|
+
- Use `outbound.shouldSuppressLocalPayloadPrompt` or `outbound.beforeDeliverPayload` for channel-specific payload lifecycle behavior such as hiding duplicate local approval prompts or sending typing indicators before delivery.
|
|
65
|
+
- Use `approvalCapability.delivery` only for native approval routing or fallback suppression.
|
|
66
|
+
- Use `approvalCapability.render` only when a channel truly needs custom approval payloads instead of the shared renderer.
|
|
67
|
+
- If a channel can infer stable owner-like DM identities from existing config, use `createResolvedApproverActionAuthAdapter` from `Durar/plugin-sdk/approval-runtime` to restrict same-chat `/approve` without adding approval-specific core logic.
|
|
68
|
+
- If a channel needs native approval delivery, keep channel code focused on target normalization and transport hooks. Use `createChannelExecApprovalProfile`, `createChannelNativeOriginTargetResolver`, `createChannelApproverDmTargetResolver`, `createApproverRestrictedNativeApprovalCapability`, and `createChannelNativeApprovalRuntime` from `Durar/plugin-sdk/approval-runtime` so core owns request filtering, routing, dedupe, expiry, and gateway subscription.
|
|
69
|
+
- Native approval channels must route both `accountId` and `approvalKind` through those helpers. `accountId` keeps multi-account approval policy scoped to the right bot account, and `approvalKind` keeps exec vs plugin approval behavior available to the channel without hardcoded branches in core.
|
|
70
|
+
- Preserve the delivered approval id kind end-to-end. Native clients should not
|
|
71
|
+
guess or rewrite exec vs plugin approval routing from channel-local state.
|
|
72
|
+
- Different approval kinds can intentionally expose different native surfaces.
|
|
73
|
+
Current bundled examples:
|
|
74
|
+
- Slack keeps native approval routing available for both exec and plugin ids.
|
|
75
|
+
- Matrix keeps native DM/channel routing for exec approvals only and leaves
|
|
76
|
+
plugin approvals on the shared same-chat `/approve` path.
|
|
77
|
+
- `createApproverRestrictedNativeApprovalAdapter` still exists as a compatibility wrapper, but new code should prefer the capability builder and expose `approvalCapability` on the plugin.
|
|
78
|
+
|
|
79
|
+
For hot channel entrypoints, prefer the narrower runtime subpaths when you only
|
|
80
|
+
need one part of that family:
|
|
81
|
+
|
|
82
|
+
- `Durar/plugin-sdk/approval-auth-runtime`
|
|
83
|
+
- `Durar/plugin-sdk/approval-client-runtime`
|
|
84
|
+
- `Durar/plugin-sdk/approval-delivery-runtime`
|
|
85
|
+
- `Durar/plugin-sdk/approval-native-runtime`
|
|
86
|
+
- `Durar/plugin-sdk/approval-reply-runtime`
|
|
87
|
+
|
|
88
|
+
Likewise, prefer `Durar/plugin-sdk/setup-runtime`,
|
|
89
|
+
`Durar/plugin-sdk/setup-adapter-runtime`,
|
|
90
|
+
`Durar/plugin-sdk/reply-runtime`,
|
|
91
|
+
`Durar/plugin-sdk/reply-dispatch-runtime`,
|
|
92
|
+
`Durar/plugin-sdk/reply-reference`, and
|
|
93
|
+
`Durar/plugin-sdk/reply-chunking` when you do not need the broader umbrella
|
|
94
|
+
surface.
|
|
95
|
+
|
|
96
|
+
For setup specifically:
|
|
97
|
+
|
|
98
|
+
- `Durar/plugin-sdk/setup-runtime` covers the runtime-safe setup helpers:
|
|
99
|
+
import-safe setup patch adapters (`createPatchedAccountSetupAdapter`,
|
|
100
|
+
`createEnvPatchedAccountSetupAdapter`,
|
|
101
|
+
`createSetupInputPresenceValidator`), lookup-note output,
|
|
102
|
+
`promptResolvedAllowFrom`, `splitSetupEntries`, and the delegated
|
|
103
|
+
setup-proxy builders
|
|
104
|
+
- `Durar/plugin-sdk/setup-adapter-runtime` is the narrow env-aware adapter
|
|
105
|
+
seam for `createEnvPatchedAccountSetupAdapter`
|
|
106
|
+
- `Durar/plugin-sdk/channel-setup` covers the optional-install setup
|
|
107
|
+
builders plus a few setup-safe primitives:
|
|
108
|
+
`createOptionalChannelSetupSurface`, `createOptionalChannelSetupAdapter`,
|
|
109
|
+
`createOptionalChannelSetupWizard`, `DEFAULT_ACCOUNT_ID`,
|
|
110
|
+
`createTopLevelChannelDmPolicy`, `setSetupChannelEnabled`, and
|
|
111
|
+
`splitSetupEntries`
|
|
112
|
+
- use the broader `Durar/plugin-sdk/setup` seam only when you also need the
|
|
113
|
+
heavier shared setup/config helpers such as
|
|
114
|
+
`moveSingleAccountChannelSectionToDefaultAccount(...)`
|
|
115
|
+
|
|
116
|
+
If your channel only wants to advertise "install this plugin first" in setup
|
|
117
|
+
surfaces, prefer `createOptionalChannelSetupSurface(...)`. The generated
|
|
118
|
+
adapter/wizard fail closed on config writes and finalization, and they reuse
|
|
119
|
+
the same install-required message across validation, finalize, and docs-link
|
|
120
|
+
copy.
|
|
121
|
+
|
|
122
|
+
For other hot channel paths, prefer the narrow helpers over broader legacy
|
|
123
|
+
surfaces:
|
|
124
|
+
|
|
125
|
+
- `Durar/plugin-sdk/account-core`,
|
|
126
|
+
`Durar/plugin-sdk/account-id`,
|
|
127
|
+
`Durar/plugin-sdk/account-resolution`, and
|
|
128
|
+
`Durar/plugin-sdk/account-helpers` for multi-account config and
|
|
129
|
+
default-account fallback
|
|
130
|
+
- `Durar/plugin-sdk/inbound-envelope` and
|
|
131
|
+
`Durar/plugin-sdk/inbound-reply-dispatch` for inbound route/envelope and
|
|
132
|
+
record-and-dispatch wiring
|
|
133
|
+
- `Durar/plugin-sdk/messaging-targets` for target parsing/matching
|
|
134
|
+
- `Durar/plugin-sdk/outbound-media` and
|
|
135
|
+
`Durar/plugin-sdk/outbound-runtime` for media loading plus outbound
|
|
136
|
+
identity/send delegates
|
|
137
|
+
- `Durar/plugin-sdk/thread-bindings-runtime` for thread-binding lifecycle
|
|
138
|
+
and adapter registration
|
|
139
|
+
- `Durar/plugin-sdk/agent-media-payload` only when a legacy agent/media
|
|
140
|
+
payload field layout is still required
|
|
141
|
+
- `Durar/plugin-sdk/telegram-command-config` for Telegram custom-command
|
|
142
|
+
normalization, duplicate/conflict validation, and a fallback-stable command
|
|
143
|
+
config contract
|
|
144
|
+
|
|
145
|
+
Auth-only channels can usually stop at the default path: core handles approvals and the plugin just exposes outbound/auth capabilities. Native approval channels such as Matrix, Slack, Telegram, and custom chat transports should use the shared native helpers instead of rolling their own approval lifecycle.
|
|
146
|
+
|
|
147
|
+
## Walkthrough
|
|
148
|
+
|
|
149
|
+
<Steps>
|
|
150
|
+
<a id="step-1-package-and-manifest"></a>
|
|
151
|
+
<Step title="Package and manifest">
|
|
152
|
+
Create the standard plugin files. The `channel` field in `package.json` is
|
|
153
|
+
what makes this a channel plugin. For the full package-metadata surface,
|
|
154
|
+
see [Plugin Setup and Config](/plugins/sdk-setup#Durarchannel):
|
|
155
|
+
|
|
156
|
+
<CodeGroup>
|
|
157
|
+
```json package.json
|
|
158
|
+
{
|
|
159
|
+
"name": "@myorg/Durar-acme-chat",
|
|
160
|
+
"version": "1.0.0",
|
|
161
|
+
"type": "module",
|
|
162
|
+
"Durar": {
|
|
163
|
+
"extensions": ["./index.ts"],
|
|
164
|
+
"setupEntry": "./setup-entry.ts",
|
|
165
|
+
"channel": {
|
|
166
|
+
"id": "acme-chat",
|
|
167
|
+
"label": "Acme Chat",
|
|
168
|
+
"blurb": "Connect Durar to Acme Chat."
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```json Durar.plugin.json
|
|
175
|
+
{
|
|
176
|
+
"id": "acme-chat",
|
|
177
|
+
"kind": "channel",
|
|
178
|
+
"channels": ["acme-chat"],
|
|
179
|
+
"name": "Acme Chat",
|
|
180
|
+
"description": "Acme Chat channel plugin",
|
|
181
|
+
"configSchema": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"additionalProperties": false,
|
|
184
|
+
"properties": {
|
|
185
|
+
"acme-chat": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"properties": {
|
|
188
|
+
"token": { "type": "string" },
|
|
189
|
+
"allowFrom": {
|
|
190
|
+
"type": "array",
|
|
191
|
+
"items": { "type": "string" }
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
</CodeGroup>
|
|
200
|
+
|
|
201
|
+
</Step>
|
|
202
|
+
|
|
203
|
+
<Step title="Build the channel plugin object">
|
|
204
|
+
The `ChannelPlugin` interface has many optional adapter surfaces. Start with
|
|
205
|
+
the minimum — `id` and `setup` — and add adapters as you need them.
|
|
206
|
+
|
|
207
|
+
Create `src/channel.ts`:
|
|
208
|
+
|
|
209
|
+
```typescript src/channel.ts
|
|
210
|
+
import {
|
|
211
|
+
createChatChannelPlugin,
|
|
212
|
+
createChannelPluginBase,
|
|
213
|
+
} from "Durar/plugin-sdk/channel-core";
|
|
214
|
+
import type { DurarConfig } from "Durar/plugin-sdk/channel-core";
|
|
215
|
+
import { acmeChatApi } from "./client.js"; // your platform API client
|
|
216
|
+
|
|
217
|
+
type ResolvedAccount = {
|
|
218
|
+
accountId: string | null;
|
|
219
|
+
token: string;
|
|
220
|
+
allowFrom: string[];
|
|
221
|
+
dmPolicy: string | undefined;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
function resolveAccount(
|
|
225
|
+
cfg: DurarConfig,
|
|
226
|
+
accountId?: string | null,
|
|
227
|
+
): ResolvedAccount {
|
|
228
|
+
const section = (cfg.channels as Record<string, any>)?.["acme-chat"];
|
|
229
|
+
const token = section?.token;
|
|
230
|
+
if (!token) throw new Error("acme-chat: token is required");
|
|
231
|
+
return {
|
|
232
|
+
accountId: accountId ?? null,
|
|
233
|
+
token,
|
|
234
|
+
allowFrom: section?.allowFrom ?? [],
|
|
235
|
+
dmPolicy: section?.dmSecurity,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const acmeChatPlugin = createChatChannelPlugin<ResolvedAccount>({
|
|
240
|
+
base: createChannelPluginBase({
|
|
241
|
+
id: "acme-chat",
|
|
242
|
+
setup: {
|
|
243
|
+
resolveAccount,
|
|
244
|
+
inspectAccount(cfg, accountId) {
|
|
245
|
+
const section =
|
|
246
|
+
(cfg.channels as Record<string, any>)?.["acme-chat"];
|
|
247
|
+
return {
|
|
248
|
+
enabled: Boolean(section?.token),
|
|
249
|
+
configured: Boolean(section?.token),
|
|
250
|
+
tokenStatus: section?.token ? "available" : "missing",
|
|
251
|
+
};
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
}),
|
|
255
|
+
|
|
256
|
+
// DM security: who can message the bot
|
|
257
|
+
security: {
|
|
258
|
+
dm: {
|
|
259
|
+
channelKey: "acme-chat",
|
|
260
|
+
resolvePolicy: (account) => account.dmPolicy,
|
|
261
|
+
resolveAllowFrom: (account) => account.allowFrom,
|
|
262
|
+
defaultPolicy: "allowlist",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
// Pairing: approval flow for new DM contacts
|
|
267
|
+
pairing: {
|
|
268
|
+
text: {
|
|
269
|
+
idLabel: "Acme Chat username",
|
|
270
|
+
message: "Send this code to verify your identity:",
|
|
271
|
+
notify: async ({ target, code }) => {
|
|
272
|
+
await acmeChatApi.sendDm(target, `Pairing code: ${code}`);
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
// Threading: how replies are delivered
|
|
278
|
+
threading: { topLevelReplyToMode: "reply" },
|
|
279
|
+
|
|
280
|
+
// Outbound: send messages to the platform
|
|
281
|
+
outbound: {
|
|
282
|
+
attachedResults: {
|
|
283
|
+
sendText: async (params) => {
|
|
284
|
+
const result = await acmeChatApi.sendMessage(
|
|
285
|
+
params.to,
|
|
286
|
+
params.text,
|
|
287
|
+
);
|
|
288
|
+
return { messageId: result.id };
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
base: {
|
|
292
|
+
sendMedia: async (params) => {
|
|
293
|
+
await acmeChatApi.sendFile(params.to, params.filePath);
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
<Accordion title="What createChatChannelPlugin does for you">
|
|
301
|
+
Instead of implementing low-level adapter interfaces manually, you pass
|
|
302
|
+
declarative options and the builder composes them:
|
|
303
|
+
|
|
304
|
+
| Option | What it wires |
|
|
305
|
+
| --- | --- |
|
|
306
|
+
| `security.dm` | Scoped DM security resolver from config fields |
|
|
307
|
+
| `pairing.text` | Text-based DM pairing flow with code exchange |
|
|
308
|
+
| `threading` | Reply-to-mode resolver (fixed, account-scoped, or custom) |
|
|
309
|
+
| `outbound.attachedResults` | Send functions that return result metadata (message IDs) |
|
|
310
|
+
|
|
311
|
+
You can also pass raw adapter objects instead of the declarative options
|
|
312
|
+
if you need full control.
|
|
313
|
+
</Accordion>
|
|
314
|
+
|
|
315
|
+
</Step>
|
|
316
|
+
|
|
317
|
+
<Step title="Wire the entry point">
|
|
318
|
+
Create `index.ts`:
|
|
319
|
+
|
|
320
|
+
```typescript index.ts
|
|
321
|
+
import { defineChannelPluginEntry } from "Durar/plugin-sdk/channel-core";
|
|
322
|
+
import { acmeChatPlugin } from "./src/channel.js";
|
|
323
|
+
|
|
324
|
+
export default defineChannelPluginEntry({
|
|
325
|
+
id: "acme-chat",
|
|
326
|
+
name: "Acme Chat",
|
|
327
|
+
description: "Acme Chat channel plugin",
|
|
328
|
+
plugin: acmeChatPlugin,
|
|
329
|
+
registerCliMetadata(api) {
|
|
330
|
+
api.registerCli(
|
|
331
|
+
({ program }) => {
|
|
332
|
+
program
|
|
333
|
+
.command("acme-chat")
|
|
334
|
+
.description("Acme Chat management");
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
descriptors: [
|
|
338
|
+
{
|
|
339
|
+
name: "acme-chat",
|
|
340
|
+
description: "Acme Chat management",
|
|
341
|
+
hasSubcommands: false,
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
);
|
|
346
|
+
},
|
|
347
|
+
registerFull(api) {
|
|
348
|
+
api.registerGatewayMethod(/* ... */);
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Put channel-owned CLI descriptors in `registerCliMetadata(...)` so Durar
|
|
354
|
+
can show them in root help without activating the full channel runtime,
|
|
355
|
+
while normal full loads still pick up the same descriptors for real command
|
|
356
|
+
registration. Keep `registerFull(...)` for runtime-only work.
|
|
357
|
+
If `registerFull(...)` registers gateway RPC methods, use a
|
|
358
|
+
plugin-specific prefix. Core admin namespaces (`config.*`,
|
|
359
|
+
`exec.approvals.*`, `wizard.*`, `update.*`) stay reserved and always
|
|
360
|
+
resolve to `operator.admin`.
|
|
361
|
+
`defineChannelPluginEntry` handles the registration-mode split automatically. See
|
|
362
|
+
[Entry Points](/plugins/sdk-entrypoints#definechannelpluginentry) for all
|
|
363
|
+
options.
|
|
364
|
+
|
|
365
|
+
</Step>
|
|
366
|
+
|
|
367
|
+
<Step title="Add a setup entry">
|
|
368
|
+
Create `setup-entry.ts` for lightweight loading during onboarding:
|
|
369
|
+
|
|
370
|
+
```typescript setup-entry.ts
|
|
371
|
+
import { defineSetupPluginEntry } from "Durar/plugin-sdk/channel-core";
|
|
372
|
+
import { acmeChatPlugin } from "./src/channel.js";
|
|
373
|
+
|
|
374
|
+
export default defineSetupPluginEntry(acmeChatPlugin);
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Durar loads this instead of the full entry when the channel is disabled
|
|
378
|
+
or unconfigured. It avoids pulling in heavy runtime code during setup flows.
|
|
379
|
+
See [Setup and Config](/plugins/sdk-setup#setup-entry) for details.
|
|
380
|
+
|
|
381
|
+
</Step>
|
|
382
|
+
|
|
383
|
+
<Step title="Handle inbound messages">
|
|
384
|
+
Your plugin needs to receive messages from the platform and forward them to
|
|
385
|
+
Durar. The typical pattern is a webhook that verifies the request and
|
|
386
|
+
dispatches it through your channel's inbound handler:
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
registerFull(api) {
|
|
390
|
+
api.registerHttpRoute({
|
|
391
|
+
path: "/acme-chat/webhook",
|
|
392
|
+
auth: "plugin", // plugin-managed auth (verify signatures yourself)
|
|
393
|
+
handler: async (req, res) => {
|
|
394
|
+
const event = parseWebhookPayload(req);
|
|
395
|
+
|
|
396
|
+
// Your inbound handler dispatches the message to Durar.
|
|
397
|
+
// The exact wiring depends on your platform SDK —
|
|
398
|
+
// see a real example in the bundled Microsoft Teams or Google Chat plugin package.
|
|
399
|
+
await handleAcmeChatInbound(api, event);
|
|
400
|
+
|
|
401
|
+
res.statusCode = 200;
|
|
402
|
+
res.end("ok");
|
|
403
|
+
return true;
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
<Note>
|
|
410
|
+
Inbound message handling is channel-specific. Each channel plugin owns
|
|
411
|
+
its own inbound pipeline. Look at bundled channel plugins
|
|
412
|
+
(for example the Microsoft Teams or Google Chat plugin package) for real patterns.
|
|
413
|
+
</Note>
|
|
414
|
+
|
|
415
|
+
</Step>
|
|
416
|
+
|
|
417
|
+
<a id="step-6-test"></a>
|
|
418
|
+
<Step title="Test">
|
|
419
|
+
Write colocated tests in `src/channel.test.ts`:
|
|
420
|
+
|
|
421
|
+
```typescript src/channel.test.ts
|
|
422
|
+
import { describe, it, expect } from "vitest";
|
|
423
|
+
import { acmeChatPlugin } from "./channel.js";
|
|
424
|
+
|
|
425
|
+
describe("acme-chat plugin", () => {
|
|
426
|
+
it("resolves account from config", () => {
|
|
427
|
+
const cfg = {
|
|
428
|
+
channels: {
|
|
429
|
+
"acme-chat": { token: "test-token", allowFrom: ["user1"] },
|
|
430
|
+
},
|
|
431
|
+
} as any;
|
|
432
|
+
const account = acmeChatPlugin.setup!.resolveAccount(cfg, undefined);
|
|
433
|
+
expect(account.token).toBe("test-token");
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
it("inspects account without materializing secrets", () => {
|
|
437
|
+
const cfg = {
|
|
438
|
+
channels: { "acme-chat": { token: "test-token" } },
|
|
439
|
+
} as any;
|
|
440
|
+
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
|
|
441
|
+
expect(result.configured).toBe(true);
|
|
442
|
+
expect(result.tokenStatus).toBe("available");
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it("reports missing config", () => {
|
|
446
|
+
const cfg = { channels: {} } as any;
|
|
447
|
+
const result = acmeChatPlugin.setup!.inspectAccount!(cfg, undefined);
|
|
448
|
+
expect(result.configured).toBe(false);
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
pnpm test -- <bundled-plugin-root>/acme-chat/
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
For shared test helpers, see [Testing](/plugins/sdk-testing).
|
|
458
|
+
|
|
459
|
+
</Step>
|
|
460
|
+
</Steps>
|
|
461
|
+
|
|
462
|
+
## File structure
|
|
463
|
+
|
|
464
|
+
```
|
|
465
|
+
<bundled-plugin-root>/acme-chat/
|
|
466
|
+
├── package.json # Durar.channel metadata
|
|
467
|
+
├── Durar.plugin.json # Manifest with config schema
|
|
468
|
+
├── index.ts # defineChannelPluginEntry
|
|
469
|
+
├── setup-entry.ts # defineSetupPluginEntry
|
|
470
|
+
├── api.ts # Public exports (optional)
|
|
471
|
+
├── runtime-api.ts # Internal runtime exports (optional)
|
|
472
|
+
└── src/
|
|
473
|
+
├── channel.ts # ChannelPlugin via createChatChannelPlugin
|
|
474
|
+
├── channel.test.ts # Tests
|
|
475
|
+
├── client.ts # Platform API client
|
|
476
|
+
└── runtime.ts # Runtime store (if needed)
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Advanced topics
|
|
480
|
+
|
|
481
|
+
<CardGroup cols={2}>
|
|
482
|
+
<Card title="Threading options" icon="git-branch" href="/plugins/sdk-entrypoints#registration-mode">
|
|
483
|
+
Fixed, account-scoped, or custom reply modes
|
|
484
|
+
</Card>
|
|
485
|
+
<Card title="Message tool integration" icon="puzzle" href="/plugins/architecture#channel-plugins-and-the-shared-message-tool">
|
|
486
|
+
describeMessageTool and action discovery
|
|
487
|
+
</Card>
|
|
488
|
+
<Card title="Target resolution" icon="crosshair" href="/plugins/architecture#channel-target-resolution">
|
|
489
|
+
inferTargetChatType, looksLikeId, resolveTarget
|
|
490
|
+
</Card>
|
|
491
|
+
<Card title="Runtime helpers" icon="settings" href="/plugins/sdk-runtime">
|
|
492
|
+
TTS, STT, media, subagent via api.runtime
|
|
493
|
+
</Card>
|
|
494
|
+
</CardGroup>
|
|
495
|
+
|
|
496
|
+
<Note>
|
|
497
|
+
Some bundled helper seams still exist for bundled-plugin maintenance and
|
|
498
|
+
compatibility. They are not the recommended pattern for new channel plugins;
|
|
499
|
+
prefer the generic channel/setup/reply/runtime subpaths from the common SDK
|
|
500
|
+
surface unless you are maintaining that bundled plugin family directly.
|
|
501
|
+
</Note>
|
|
502
|
+
|
|
503
|
+
## Next steps
|
|
504
|
+
|
|
505
|
+
- [Provider Plugins](/plugins/sdk-provider-plugins) — if your plugin also provides models
|
|
506
|
+
- [SDK Overview](/plugins/sdk-overview) — full subpath import reference
|
|
507
|
+
- [SDK Testing](/plugins/sdk-testing) — test utilities and contract tests
|
|
508
|
+
- [Plugin Manifest](/plugins/manifest) — full manifest schema
|