clawdbot-dingtalk 0.1.0

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.
Files changed (63) hide show
  1. package/README.md +164 -0
  2. package/clawdbot.plugin.json +11 -0
  3. package/dist/index.d.ts +10 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +15 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/accounts.d.ts +47 -0
  8. package/dist/src/accounts.d.ts.map +1 -0
  9. package/dist/src/accounts.js +152 -0
  10. package/dist/src/accounts.js.map +1 -0
  11. package/dist/src/channel.d.ts +10 -0
  12. package/dist/src/channel.d.ts.map +1 -0
  13. package/dist/src/channel.js +186 -0
  14. package/dist/src/channel.js.map +1 -0
  15. package/dist/src/config-schema.d.ts +279 -0
  16. package/dist/src/config-schema.d.ts.map +1 -0
  17. package/dist/src/config-schema.js +92 -0
  18. package/dist/src/config-schema.js.map +1 -0
  19. package/dist/src/monitor.d.ts +17 -0
  20. package/dist/src/monitor.d.ts.map +1 -0
  21. package/dist/src/monitor.js +183 -0
  22. package/dist/src/monitor.js.map +1 -0
  23. package/dist/src/probe.d.ts +15 -0
  24. package/dist/src/probe.d.ts.map +1 -0
  25. package/dist/src/probe.js +48 -0
  26. package/dist/src/probe.js.map +1 -0
  27. package/dist/src/runtime.d.ts +4 -0
  28. package/dist/src/runtime.d.ts.map +1 -0
  29. package/dist/src/runtime.js +11 -0
  30. package/dist/src/runtime.js.map +1 -0
  31. package/dist/src/send/chunker.d.ts +23 -0
  32. package/dist/src/send/chunker.d.ts.map +1 -0
  33. package/dist/src/send/chunker.js +149 -0
  34. package/dist/src/send/chunker.js.map +1 -0
  35. package/dist/src/send/index.d.ts +9 -0
  36. package/dist/src/send/index.d.ts.map +1 -0
  37. package/dist/src/send/index.js +7 -0
  38. package/dist/src/send/index.js.map +1 -0
  39. package/dist/src/send/markdown.d.ts +13 -0
  40. package/dist/src/send/markdown.d.ts.map +1 -0
  41. package/dist/src/send/markdown.js +44 -0
  42. package/dist/src/send/markdown.js.map +1 -0
  43. package/dist/src/send/reply.d.ts +35 -0
  44. package/dist/src/send/reply.d.ts.map +1 -0
  45. package/dist/src/send/reply.js +100 -0
  46. package/dist/src/send/reply.js.map +1 -0
  47. package/dist/src/stream/client.d.ts +11 -0
  48. package/dist/src/stream/client.d.ts.map +1 -0
  49. package/dist/src/stream/client.js +182 -0
  50. package/dist/src/stream/client.js.map +1 -0
  51. package/dist/src/stream/index.d.ts +7 -0
  52. package/dist/src/stream/index.d.ts.map +1 -0
  53. package/dist/src/stream/index.js +6 -0
  54. package/dist/src/stream/index.js.map +1 -0
  55. package/dist/src/stream/message-parser.d.ts +24 -0
  56. package/dist/src/stream/message-parser.d.ts.map +1 -0
  57. package/dist/src/stream/message-parser.js +211 -0
  58. package/dist/src/stream/message-parser.js.map +1 -0
  59. package/dist/src/stream/types.d.ts +92 -0
  60. package/dist/src/stream/types.d.ts.map +1 -0
  61. package/dist/src/stream/types.js +5 -0
  62. package/dist/src/stream/types.js.map +1 -0
  63. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # @clawdbot/dingtalk
2
+
3
+ DingTalk (钉钉) channel plugin for [Clawdbot](https://github.com/anthropics/claude-code) - enables AI agent messaging via DingTalk Stream API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # Install Clawdbot globally
9
+ npm install -g clawdbot
10
+
11
+ # Install DingTalk plugin
12
+ npm install -g @clawdbot/dingtalk
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ Edit `~/.clawdbot/clawdbot.json`:
18
+
19
+ ```json
20
+ {
21
+ "extensions": ["@clawdbot/dingtalk"],
22
+ "channels": {
23
+ "dingtalk": {
24
+ "enabled": true,
25
+ "clientId": "your-dingtalk-client-id",
26
+ "clientSecret": "your-dingtalk-client-secret"
27
+ }
28
+ },
29
+ "models": {
30
+ "providers": {
31
+ "dashscope": {
32
+ "baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1",
33
+ "apiKey": "sk-xxx",
34
+ "api": "openai-completions",
35
+ "models": [
36
+ { "id": "qwen3-coder-plus", "contextWindow": 1000000, "maxTokens": 65536 }
37
+ ]
38
+ }
39
+ }
40
+ },
41
+ "agents": {
42
+ "defaults": {
43
+ "model": { "primary": "dashscope/qwen3-coder-plus" }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Start Gateway
50
+
51
+ ```bash
52
+ clawdbot gateway
53
+ ```
54
+
55
+ ## Configuration Options
56
+
57
+ | Option | Type | Default | Description |
58
+ |--------|------|---------|-------------|
59
+ | `enabled` | boolean | `true` | Enable/disable the channel |
60
+ | `clientId` | string | - | DingTalk app Client ID (required) |
61
+ | `clientSecret` | string | - | DingTalk app Client Secret (required) |
62
+ | `clientSecretFile` | string | - | Path to file containing client secret |
63
+ | `replyMode` | `"text"` \| `"markdown"` | `"text"` | Message format |
64
+ | `maxChars` | number | `1800` | Max characters per message chunk |
65
+ | `allowFrom` | string[] | `[]` | Allowlist of sender IDs (empty = allow all) |
66
+ | `requirePrefix` | string | - | Require messages to start with prefix |
67
+ | `responsePrefix` | string | - | Prefix added to responses |
68
+ | `tableMode` | `"code"` \| `"off"` | `"code"` | Table rendering mode |
69
+ | `showToolStatus` | boolean | `false` | Show tool execution status |
70
+ | `showToolResult` | boolean | `false` | Show tool results |
71
+ | `thinking` | string | `"off"` | Thinking mode (off/minimal/low/medium/high) |
72
+
73
+ ### Multi-account Configuration
74
+
75
+ ```json
76
+ {
77
+ "channels": {
78
+ "dingtalk": {
79
+ "accounts": {
80
+ "bot1": {
81
+ "enabled": true,
82
+ "clientId": "client-id-1",
83
+ "clientSecret": "secret-1",
84
+ "name": "Support Bot"
85
+ },
86
+ "bot2": {
87
+ "enabled": true,
88
+ "clientId": "client-id-2",
89
+ "clientSecret": "secret-2",
90
+ "name": "Dev Bot"
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ### Message Coalescing
99
+
100
+ Control how streaming messages are batched before sending:
101
+
102
+ ```json
103
+ {
104
+ "channels": {
105
+ "dingtalk": {
106
+ "coalesce": {
107
+ "enabled": true,
108
+ "minChars": 800,
109
+ "maxChars": 1200,
110
+ "idleMs": 1000
111
+ }
112
+ }
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## Running as a Service
118
+
119
+ ### Using systemd (Linux)
120
+
121
+ Create `/etc/systemd/system/clawdbot.service`:
122
+
123
+ ```ini
124
+ [Unit]
125
+ Description=Clawdbot Gateway
126
+ After=network.target
127
+
128
+ [Service]
129
+ Type=simple
130
+ User=root
131
+ ExecStart=/usr/bin/clawdbot gateway
132
+ Restart=always
133
+ RestartSec=10
134
+ Environment=NODE_ENV=production
135
+
136
+ [Install]
137
+ WantedBy=multi-user.target
138
+ ```
139
+
140
+ ```bash
141
+ sudo systemctl enable clawdbot
142
+ sudo systemctl start clawdbot
143
+ ```
144
+
145
+ ### Using PM2
146
+
147
+ ```bash
148
+ npm install -g pm2
149
+ pm2 start "clawdbot gateway" --name clawdbot
150
+ pm2 save
151
+ pm2 startup
152
+ ```
153
+
154
+ ## DingTalk Setup
155
+
156
+ 1. Go to [DingTalk Open Platform](https://open.dingtalk.com/)
157
+ 2. Create an Enterprise Internal Application
158
+ 3. Enable "Robot" capability
159
+ 4. Get Client ID and Client Secret from "Credentials & Basic Info"
160
+ 5. Configure the robot's messaging subscription
161
+
162
+ ## License
163
+
164
+ MIT
@@ -0,0 +1,11 @@
1
+ {
2
+ "id": "dingtalk",
3
+ "channels": [
4
+ "dingtalk"
5
+ ],
6
+ "configSchema": {
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "properties": {}
10
+ }
11
+ }
@@ -0,0 +1,10 @@
1
+ import type { ClawdbotPluginApi } from "clawdbot/plugin-sdk";
2
+ declare const plugin: {
3
+ id: string;
4
+ name: string;
5
+ description: string;
6
+ configSchema: any;
7
+ register(api: ClawdbotPluginApi): void;
8
+ };
9
+ export default plugin;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAM7D,QAAA,MAAM,MAAM;;;;;kBAKI,iBAAiB;CAIhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,15 @@
1
+ import { emptyPluginConfigSchema } from "clawdbot/plugin-sdk";
2
+ import { dingtalkPlugin } from "./src/channel.js";
3
+ import { setDingTalkRuntime } from "./src/runtime.js";
4
+ const plugin = {
5
+ id: "dingtalk",
6
+ name: "DingTalk",
7
+ description: "DingTalk (钉钉) channel plugin for enterprise messaging",
8
+ configSchema: emptyPluginConfigSchema(),
9
+ register(api) {
10
+ setDingTalkRuntime(api.runtime);
11
+ api.registerChannel({ plugin: dingtalkPlugin });
12
+ },
13
+ };
14
+ export default plugin;
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,uDAAuD;IACpE,YAAY,EAAE,uBAAuB,EAAE;IACvC,QAAQ,CAAC,GAAsB;QAC7B,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;IAClD,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
2
+ import { type CoalesceConfig } from "./config-schema.js";
3
+ /**
4
+ * Resolved DingTalk account with normalized configuration.
5
+ */
6
+ export type ResolvedDingTalkAccount = {
7
+ accountId: string;
8
+ name?: string;
9
+ enabled: boolean;
10
+ clientId: string;
11
+ clientSecret: string;
12
+ credentialSource: "env" | "config" | "file" | "none";
13
+ apiBase: string;
14
+ openPath: string;
15
+ subscriptionsJson?: string;
16
+ replyMode: "text" | "markdown";
17
+ maxChars: number;
18
+ tableMode: "code" | "off";
19
+ coalesce: CoalesceConfig;
20
+ allowFrom: string[];
21
+ selfUserId?: string;
22
+ requirePrefix?: string;
23
+ responsePrefix?: string;
24
+ showToolStatus: boolean;
25
+ showToolResult: boolean;
26
+ thinking: "off" | "minimal" | "low" | "medium" | "high";
27
+ };
28
+ /**
29
+ * List all configured account IDs.
30
+ */
31
+ export declare function listDingTalkAccountIds(cfg: ClawdbotConfig): string[];
32
+ /**
33
+ * Resolve the default account ID.
34
+ */
35
+ export declare function resolveDefaultDingTalkAccountId(cfg: ClawdbotConfig): string;
36
+ /**
37
+ * Resolve a specific DingTalk account by ID.
38
+ */
39
+ export declare function resolveDingTalkAccount(params: {
40
+ cfg: ClawdbotConfig;
41
+ accountId?: string | null;
42
+ }): ResolvedDingTalkAccount;
43
+ /**
44
+ * Check if account has valid credentials
45
+ */
46
+ export declare function isDingTalkAccountConfigured(account: ResolvedDingTalkAccount): boolean;
47
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../../src/accounts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EACL,KAAK,cAAc,EAIpB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAGrD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,SAAS,EAAE,MAAM,GAAG,UAAU,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1B,QAAQ,EAAE,cAAc,CAAC;IAGzB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IAGxB,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACzD,CAAC;AAqBF;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,EAAE,CAuBpE;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAG3E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,GAAG,EAAE,cAAc,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,uBAAuB,CAiG1B;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAErF"}
@@ -0,0 +1,152 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { DEFAULT_ACCOUNT_ID, DEFAULT_COALESCE, } from "./config-schema.js";
3
+ /**
4
+ * Read DingTalk config section from ClawdbotConfig
5
+ */
6
+ function getDingTalkSection(cfg) {
7
+ return cfg.channels?.dingtalk;
8
+ }
9
+ /**
10
+ * Try to read secret from file
11
+ */
12
+ function readSecretFile(path) {
13
+ if (!path)
14
+ return undefined;
15
+ try {
16
+ return readFileSync(path, "utf-8").trim();
17
+ }
18
+ catch {
19
+ return undefined;
20
+ }
21
+ }
22
+ /**
23
+ * List all configured account IDs.
24
+ */
25
+ export function listDingTalkAccountIds(cfg) {
26
+ const section = getDingTalkSection(cfg);
27
+ if (!section)
28
+ return [];
29
+ const accountIds = [];
30
+ // Check for base-level credentials (default account)
31
+ const envClientId = process.env.DINGTALK_CLIENT_ID?.trim();
32
+ const hasBaseCredentials = Boolean(section.clientId || section.clientSecretFile || envClientId);
33
+ if (hasBaseCredentials) {
34
+ accountIds.push(DEFAULT_ACCOUNT_ID);
35
+ }
36
+ // Add named accounts
37
+ if (section.accounts) {
38
+ for (const id of Object.keys(section.accounts)) {
39
+ if (!accountIds.includes(id)) {
40
+ accountIds.push(id);
41
+ }
42
+ }
43
+ }
44
+ return accountIds;
45
+ }
46
+ /**
47
+ * Resolve the default account ID.
48
+ */
49
+ export function resolveDefaultDingTalkAccountId(cfg) {
50
+ const ids = listDingTalkAccountIds(cfg);
51
+ return ids.length > 0 ? ids[0] : DEFAULT_ACCOUNT_ID;
52
+ }
53
+ /**
54
+ * Resolve a specific DingTalk account by ID.
55
+ */
56
+ export function resolveDingTalkAccount(params) {
57
+ const { cfg, accountId: rawAccountId } = params;
58
+ const accountId = rawAccountId ?? DEFAULT_ACCOUNT_ID;
59
+ const section = getDingTalkSection(cfg);
60
+ // Merge base config with account-specific overrides
61
+ const accountConfig = accountId !== DEFAULT_ACCOUNT_ID ? section?.accounts?.[accountId] : undefined;
62
+ // Resolve credentials with priority: account > base > env
63
+ const envClientId = process.env.DINGTALK_CLIENT_ID?.trim() ?? "";
64
+ const envClientSecret = process.env.DINGTALK_CLIENT_SECRET?.trim() ?? "";
65
+ let clientId = "";
66
+ let clientSecret = "";
67
+ let credentialSource = "none";
68
+ // Try account-level first
69
+ if (accountConfig?.clientId) {
70
+ clientId = accountConfig.clientId;
71
+ if (accountConfig.clientSecret) {
72
+ clientSecret = accountConfig.clientSecret;
73
+ credentialSource = "config";
74
+ }
75
+ else if (accountConfig.clientSecretFile) {
76
+ clientSecret = readSecretFile(accountConfig.clientSecretFile) ?? "";
77
+ credentialSource = clientSecret ? "file" : "none";
78
+ }
79
+ }
80
+ // Fall back to base-level
81
+ if (!clientId && section?.clientId) {
82
+ clientId = section.clientId;
83
+ if (section.clientSecret) {
84
+ clientSecret = section.clientSecret;
85
+ credentialSource = "config";
86
+ }
87
+ else if (section.clientSecretFile) {
88
+ clientSecret = readSecretFile(section.clientSecretFile) ?? "";
89
+ credentialSource = clientSecret ? "file" : "none";
90
+ }
91
+ }
92
+ // Fall back to environment
93
+ if (!clientId && envClientId) {
94
+ clientId = envClientId;
95
+ clientSecret = envClientSecret;
96
+ credentialSource = clientId && clientSecret ? "env" : "none";
97
+ }
98
+ // Merge other settings with cascading priority
99
+ const enabled = accountConfig?.enabled ?? section?.enabled ?? true;
100
+ const name = accountConfig?.name ?? section?.name;
101
+ const apiBase = accountConfig?.apiBase ?? section?.apiBase ?? "https://api.dingtalk.com";
102
+ const openPath = accountConfig?.openPath ?? section?.openPath ?? "/v1.0/gateway/connections/open";
103
+ const subscriptionsJson = accountConfig?.subscriptionsJson ?? section?.subscriptionsJson;
104
+ const replyMode = accountConfig?.replyMode ?? section?.replyMode ?? "text";
105
+ const maxChars = accountConfig?.maxChars ?? section?.maxChars ?? 1800;
106
+ const tableMode = accountConfig?.tableMode ?? section?.tableMode ?? "code";
107
+ const allowFrom = accountConfig?.allowFrom ?? section?.allowFrom ?? [];
108
+ const selfUserId = accountConfig?.selfUserId ?? section?.selfUserId;
109
+ const requirePrefix = accountConfig?.requirePrefix ?? section?.requirePrefix;
110
+ const responsePrefix = accountConfig?.responsePrefix ?? section?.responsePrefix;
111
+ const showToolStatus = accountConfig?.showToolStatus ?? section?.showToolStatus ?? false;
112
+ const showToolResult = accountConfig?.showToolResult ?? section?.showToolResult ?? false;
113
+ const thinking = accountConfig?.thinking ?? section?.thinking ?? "off";
114
+ // Merge coalesce config
115
+ const baseCoalesce = section?.coalesce ?? DEFAULT_COALESCE;
116
+ const accountCoalesce = accountConfig?.coalesce;
117
+ const coalesce = {
118
+ enabled: accountCoalesce?.enabled ?? baseCoalesce.enabled,
119
+ minChars: accountCoalesce?.minChars ?? baseCoalesce.minChars,
120
+ maxChars: accountCoalesce?.maxChars ?? baseCoalesce.maxChars,
121
+ idleMs: accountCoalesce?.idleMs ?? baseCoalesce.idleMs,
122
+ };
123
+ return {
124
+ accountId,
125
+ name,
126
+ enabled,
127
+ clientId,
128
+ clientSecret,
129
+ credentialSource,
130
+ apiBase,
131
+ openPath,
132
+ subscriptionsJson,
133
+ replyMode,
134
+ maxChars,
135
+ tableMode,
136
+ coalesce,
137
+ allowFrom,
138
+ selfUserId,
139
+ requirePrefix,
140
+ responsePrefix,
141
+ showToolStatus,
142
+ showToolResult,
143
+ thinking,
144
+ };
145
+ }
146
+ /**
147
+ * Check if account has valid credentials
148
+ */
149
+ export function isDingTalkAccountConfigured(account) {
150
+ return Boolean(account.clientId?.trim() && account.clientSecret?.trim());
151
+ }
152
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../src/accounts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * DingTalk Channel Plugin for Clawdbot.
3
+ */
4
+ import type { ChannelPlugin } from "clawdbot/plugin-sdk";
5
+ import { type ResolvedDingTalkAccount } from "./accounts.js";
6
+ /**
7
+ * DingTalk channel plugin.
8
+ */
9
+ export declare const dingtalkPlugin: ChannelPlugin<ResolvedDingTalkAccount>;
10
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,aAAa,EAKd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,uBAAuB,EAK7B,MAAM,eAAe,CAAC;AAgCvB;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,uBAAuB,CA+KjE,CAAC"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * DingTalk Channel Plugin for Clawdbot.
3
+ */
4
+ import { listDingTalkAccountIds, resolveDingTalkAccount, resolveDefaultDingTalkAccountId, isDingTalkAccountConfigured, } from "./accounts.js";
5
+ import { DEFAULT_ACCOUNT_ID } from "./config-schema.js";
6
+ import { chunkMarkdownText } from "./send/chunker.js";
7
+ import { monitorDingTalkProvider } from "./monitor.js";
8
+ import { probeDingTalk } from "./probe.js";
9
+ /**
10
+ * Channel metadata.
11
+ */
12
+ const meta = {
13
+ id: "dingtalk",
14
+ label: "DingTalk",
15
+ selectionLabel: "钉钉 (DingTalk)",
16
+ blurb: "Enterprise messaging platform by Alibaba",
17
+ docsPath: "/docs/channels/dingtalk",
18
+ order: 50,
19
+ aliases: ["dingding", "钉钉"],
20
+ systemImage: "dingtalk",
21
+ };
22
+ /**
23
+ * Channel capabilities.
24
+ */
25
+ const capabilities = {
26
+ chatTypes: ["direct", "group"],
27
+ reactions: false,
28
+ threads: false,
29
+ media: false, // TODO: Add media support later
30
+ nativeCommands: false,
31
+ blockStreaming: true, // Use block-based streaming for DingTalk
32
+ };
33
+ /**
34
+ * DingTalk channel plugin.
35
+ */
36
+ export const dingtalkPlugin = {
37
+ id: "dingtalk",
38
+ meta,
39
+ capabilities,
40
+ reload: { configPrefixes: ["channels.dingtalk"] },
41
+ config: {
42
+ listAccountIds: (cfg) => listDingTalkAccountIds(cfg),
43
+ resolveAccount: (cfg, accountId) => resolveDingTalkAccount({ cfg, accountId }),
44
+ defaultAccountId: (cfg) => resolveDefaultDingTalkAccountId(cfg),
45
+ setAccountEnabled: ({ cfg, accountId, enabled }) => {
46
+ const dingtalk = cfg.channels?.dingtalk;
47
+ if (!dingtalk)
48
+ return cfg;
49
+ if (accountId === DEFAULT_ACCOUNT_ID) {
50
+ return {
51
+ ...cfg,
52
+ channels: {
53
+ ...cfg.channels,
54
+ dingtalk: { ...dingtalk, enabled },
55
+ },
56
+ };
57
+ }
58
+ const accounts = (dingtalk.accounts ?? {});
59
+ const account = (accounts[accountId] ?? {});
60
+ return {
61
+ ...cfg,
62
+ channels: {
63
+ ...cfg.channels,
64
+ dingtalk: {
65
+ ...dingtalk,
66
+ accounts: {
67
+ ...accounts,
68
+ [accountId]: { ...account, enabled },
69
+ },
70
+ },
71
+ },
72
+ };
73
+ },
74
+ deleteAccount: ({ cfg, accountId }) => {
75
+ const dingtalk = cfg.channels?.dingtalk;
76
+ if (!dingtalk)
77
+ return cfg;
78
+ if (accountId === DEFAULT_ACCOUNT_ID) {
79
+ // Clear base-level credentials
80
+ const { clientId, clientSecret, clientSecretFile, ...rest } = dingtalk;
81
+ return {
82
+ ...cfg,
83
+ channels: {
84
+ ...cfg.channels,
85
+ dingtalk: rest,
86
+ },
87
+ };
88
+ }
89
+ const accounts = { ...(dingtalk.accounts ?? {}) };
90
+ delete accounts[accountId];
91
+ return {
92
+ ...cfg,
93
+ channels: {
94
+ ...cfg.channels,
95
+ dingtalk: {
96
+ ...dingtalk,
97
+ accounts: Object.keys(accounts).length > 0 ? accounts : undefined,
98
+ },
99
+ },
100
+ };
101
+ },
102
+ isConfigured: (account) => isDingTalkAccountConfigured(account),
103
+ describeAccount: (account) => ({
104
+ accountId: account.accountId,
105
+ name: account.name,
106
+ enabled: account.enabled,
107
+ configured: isDingTalkAccountConfigured(account),
108
+ credentialSource: account.credentialSource,
109
+ }),
110
+ resolveAllowFrom: ({ cfg, accountId }) => {
111
+ const account = resolveDingTalkAccount({ cfg, accountId });
112
+ return account.allowFrom;
113
+ },
114
+ formatAllowFrom: ({ allowFrom }) => allowFrom
115
+ .map((entry) => String(entry).trim())
116
+ .filter(Boolean)
117
+ .map((entry) => entry.replace(/^dingtalk:/i, "")),
118
+ },
119
+ outbound: {
120
+ deliveryMode: "direct",
121
+ chunker: (text, limit) => chunkMarkdownText(text, limit),
122
+ chunkerMode: "markdown",
123
+ textChunkLimit: 1800,
124
+ sendText: async ({ to, text, cfg, accountId }) => {
125
+ // DingTalk requires sessionWebhook for sending, which is only available
126
+ // during active conversations. For proactive messaging, we'd need a
127
+ // different API. For now, return not supported.
128
+ // In practice, replies are sent via the monitor's sendBlock dispatcher.
129
+ return {
130
+ channel: "dingtalk",
131
+ ok: false,
132
+ error: new Error("DingTalk requires active session webhook for sending"),
133
+ };
134
+ },
135
+ },
136
+ status: {
137
+ defaultRuntime: {
138
+ accountId: DEFAULT_ACCOUNT_ID,
139
+ running: false,
140
+ lastStartAt: null,
141
+ lastStopAt: null,
142
+ lastError: null,
143
+ },
144
+ probeAccount: async ({ account, timeoutMs }) => {
145
+ return probeDingTalk(account, timeoutMs);
146
+ },
147
+ buildAccountSnapshot: ({ account, runtime }) => ({
148
+ accountId: account.accountId,
149
+ name: account.name,
150
+ enabled: account.enabled,
151
+ configured: isDingTalkAccountConfigured(account),
152
+ credentialSource: account.credentialSource,
153
+ running: runtime?.running ?? false,
154
+ lastStartAt: runtime?.lastStartAt ?? null,
155
+ lastStopAt: runtime?.lastStopAt ?? null,
156
+ lastError: runtime?.lastError ?? null,
157
+ mode: "stream",
158
+ }),
159
+ buildChannelSummary: ({ snapshot }) => ({
160
+ configured: snapshot.configured ?? false,
161
+ credentialSource: snapshot.credentialSource ?? "none",
162
+ running: snapshot.running ?? false,
163
+ mode: snapshot.mode ?? "stream",
164
+ lastStartAt: snapshot.lastStartAt ?? null,
165
+ lastStopAt: snapshot.lastStopAt ?? null,
166
+ lastError: snapshot.lastError ?? null,
167
+ }),
168
+ },
169
+ gateway: {
170
+ startAccount: async (ctx) => {
171
+ const { account, cfg, abortSignal, log } = ctx;
172
+ if (!isDingTalkAccountConfigured(account)) {
173
+ throw new Error(`DingTalk credentials not configured for account "${account.accountId}". ` +
174
+ `Set channels.dingtalk.clientId and channels.dingtalk.clientSecret.`);
175
+ }
176
+ log?.info?.(`[${account.accountId}] starting DingTalk stream provider`);
177
+ return monitorDingTalkProvider({
178
+ account,
179
+ config: cfg,
180
+ abortSignal,
181
+ log: log,
182
+ });
183
+ },
184
+ },
185
+ };
186
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,EAEL,sBAAsB,EACtB,sBAAsB,EACtB,+BAA+B,EAC/B,2BAA2B,GAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;GAEG;AACH,MAAM,IAAI,GAAgB;IACxB,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,UAAU;IACjB,cAAc,EAAE,eAAe;IAC/B,KAAK,EAAE,0CAA0C;IACjD,QAAQ,EAAE,yBAAyB;IACnC,KAAK,EAAE,EAAE;IACT,OAAO,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC;IAC3B,WAAW,EAAE,UAAU;CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,YAAY,GAAwB;IACxC,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC9B,SAAS,EAAE,KAAK;IAChB,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,KAAK,EAAE,gCAAgC;IAC9C,cAAc,EAAE,KAAK;IACrB,cAAc,EAAE,IAAI,EAAE,yCAAyC;CAChE,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAA2C;IACpE,EAAE,EAAE,UAAU;IACd,IAAI;IACJ,YAAY;IACZ,MAAM,EAAE,EAAE,cAAc,EAAE,CAAC,mBAAmB,CAAC,EAAE;IAEjD,MAAM,EAAE;QACN,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,sBAAsB,CAAC,GAAG,CAAC;QACpD,cAAc,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,sBAAsB,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;QAC9E,gBAAgB,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,+BAA+B,CAAC,GAAG,CAAC;QAE/D,iBAAiB,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE;YACjD,MAAM,QAAQ,GAAI,GAAG,CAAC,QAAoC,EAAE,QAE/C,CAAC;YACd,IAAI,CAAC,QAAQ;gBAAE,OAAO,GAAG,CAAC;YAE1B,IAAI,SAAS,KAAK,kBAAkB,EAAE,CAAC;gBACrC,OAAO;oBACL,GAAG,GAAG;oBACN,QAAQ,EAAE;wBACR,GAAG,GAAG,CAAC,QAAQ;wBACf,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE;qBACnC;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAA4B,CAAC;YACtE,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAA4B,CAAC;YACvE,OAAO;gBACL,GAAG,GAAG;gBACN,QAAQ,EAAE;oBACR,GAAG,GAAG,CAAC,QAAQ;oBACf,QAAQ,EAAE;wBACR,GAAG,QAAQ;wBACX,QAAQ,EAAE;4BACR,GAAG,QAAQ;4BACX,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE;yBACrC;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,aAAa,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE;YACpC,MAAM,QAAQ,GAAI,GAAG,CAAC,QAAoC,EAAE,QAE/C,CAAC;YACd,IAAI,CAAC,QAAQ;gBAAE,OAAO,GAAG,CAAC;YAE1B,IAAI,SAAS,KAAK,kBAAkB,EAAE,CAAC;gBACrC,+BAA+B;gBAC/B,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;gBACvE,OAAO;oBACL,GAAG,GAAG;oBACN,QAAQ,EAAE;wBACR,GAAG,GAAG,CAAC,QAAQ;wBACf,QAAQ,EAAE,IAAI;qBACf;iBACF,CAAC;YACJ,CAAC;YAED,MAAM,QAAQ,GAAG,EAAE,GAAI,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAA6B,EAAE,CAAC;YAC/E,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC3B,OAAO;gBACL,GAAG,GAAG;gBACN,QAAQ,EAAE;oBACR,GAAG,GAAG,CAAC,QAAQ;oBACf,QAAQ,EAAE;wBACR,GAAG,QAAQ;wBACX,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;qBAClE;iBACF;aACF,CAAC;QACJ,CAAC;QAED,YAAY,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,2BAA2B,CAAC,OAAO,CAAC;QAE/D,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC7B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,2BAA2B,CAAC,OAAO,CAAC;YAChD,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;SAC3C,CAAC;QAEF,gBAAgB,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE;YACvC,MAAM,OAAO,GAAG,sBAAsB,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;YAC3D,OAAO,OAAO,CAAC,SAAS,CAAC;QAC3B,CAAC;QAED,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CACjC,SAAS;aACN,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;aACpC,MAAM,CAAC,OAAO,CAAC;aACf,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;KACtD;IAED,QAAQ,EAAE;QACR,YAAY,EAAE,QAAQ;QACtB,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAC;QACxD,WAAW,EAAE,UAAU;QACvB,cAAc,EAAE,IAAI;QAEpB,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE;YAC/C,wEAAwE;YACxE,oEAAoE;YACpE,gDAAgD;YAChD,wEAAwE;YACxE,OAAO;gBACL,OAAO,EAAE,UAAU;gBACnB,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,IAAI,KAAK,CAAC,sDAAsD,CAAC;aACzE,CAAC;QACJ,CAAC;KACF;IAED,MAAM,EAAE;QACN,cAAc,EAAE;YACd,SAAS,EAAE,kBAAkB;YAC7B,OAAO,EAAE,KAAK;YACd,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,IAAI;SAChB;QAED,YAAY,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE;YAC7C,OAAO,aAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC3C,CAAC;QAED,oBAAoB,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YAC/C,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,UAAU,EAAE,2BAA2B,CAAC,OAAO,CAAC;YAChD,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK;YAClC,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;YACzC,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,IAAI;YACvC,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;YACrC,IAAI,EAAE,QAAQ;SACf,CAAC;QAEF,mBAAmB,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,KAAK;YACxC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,IAAI,MAAM;YACrD,OAAO,EAAE,QAAQ,CAAC,OAAO,IAAI,KAAK;YAClC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,QAAQ;YAC/B,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,IAAI;YACzC,UAAU,EAAE,QAAQ,CAAC,UAAU,IAAI,IAAI;YACvC,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,IAAI;SACtC,CAAC;KACH;IAED,OAAO,EAAE;QACP,YAAY,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YAC1B,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;YAE/C,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1C,MAAM,IAAI,KAAK,CACb,oDAAoD,OAAO,CAAC,SAAS,KAAK;oBACxE,oEAAoE,CACvE,CAAC;YACJ,CAAC;YAED,GAAG,EAAE,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC,SAAS,qCAAqC,CAAC,CAAC;YAExE,OAAO,uBAAuB,CAAC;gBAC7B,OAAO;gBACP,MAAM,EAAE,GAAG;gBACX,WAAW;gBACX,GAAG,EAAE,GAA0D;aAChE,CAAC,CAAC;QACL,CAAC;KACF;CACF,CAAC"}