@co0ontty/wand 4.102.0 → 4.103.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.
- package/dist/ai-team-live.js +1 -1
- package/dist/apns-client.d.ts +45 -0
- package/dist/apns-client.js +156 -0
- package/dist/apns-service.d.ts +29 -0
- package/dist/apns-service.js +156 -0
- package/dist/build-info.json +3 -3
- package/dist/conversation-service.d.ts +2 -0
- package/dist/conversation-service.js +23 -3
- package/dist/conversation-types.d.ts +2 -0
- package/dist/dingtalk-auth.d.ts +41 -0
- package/dist/dingtalk-auth.js +127 -0
- package/dist/dingtalk-dws.d.ts +45 -0
- package/dist/dingtalk-dws.js +240 -0
- package/dist/dingtalk-service.d.ts +100 -0
- package/dist/dingtalk-service.js +865 -0
- package/dist/dingtalk-stream.d.ts +24 -0
- package/dist/dingtalk-stream.js +115 -0
- package/dist/dingtalk-types.d.ts +138 -0
- package/dist/dingtalk-types.js +1 -0
- package/dist/employee-knowledge.js +8 -0
- package/dist/live-activity-service.d.ts +26 -0
- package/dist/live-activity-service.js +158 -0
- package/dist/live-activity-state.d.ts +37 -0
- package/dist/live-activity-state.js +108 -0
- package/dist/middleware/api-scope.js +2 -0
- package/dist/pi-cli-checkpoint.d.ts +17 -0
- package/dist/pi-cli-checkpoint.js +10 -0
- package/dist/pi-event-projection.js +13 -0
- package/dist/pi-execution.js +2 -1
- package/dist/pi-protocol-reader.d.ts +6 -2
- package/dist/pi-protocol-reader.js +36 -12
- package/dist/pi-tmux-host.d.ts +1 -1
- package/dist/pi-tmux-host.js +28 -8
- package/dist/pi-tool-result-preview.d.ts +23 -0
- package/dist/pi-tool-result-preview.js +185 -0
- package/dist/render-daemon-client.js +1 -1
- package/dist/render-host.d.ts +3 -3
- package/dist/render-host.js +3 -3
- package/dist/server-apns-routes.d.ts +12 -0
- package/dist/server-apns-routes.js +111 -0
- package/dist/server-dingtalk-routes.d.ts +8 -0
- package/dist/server-dingtalk-routes.js +35 -0
- package/dist/server.js +49 -3
- package/dist/session-completion.d.ts +2 -1
- package/dist/session-completion.js +6 -2
- package/dist/session-registry.d.ts +3 -1
- package/dist/session-registry.js +3 -1
- package/dist/storage/apns-repository.d.ts +52 -0
- package/dist/storage/apns-repository.js +108 -0
- package/dist/storage/conversations-repository.d.ts +2 -0
- package/dist/storage/conversations-repository.js +10 -0
- package/dist/storage/dingtalk-repository.d.ts +20 -0
- package/dist/storage/dingtalk-repository.js +75 -0
- package/dist/storage/live-activity-repository.d.ts +68 -0
- package/dist/storage/live-activity-repository.js +117 -0
- package/dist/storage/migrations.js +22 -0
- package/dist/storage/sessions-repository.d.ts +5 -0
- package/dist/storage/sessions-repository.js +43 -1
- package/dist/storage-schema.js +2 -0
- package/dist/storage.d.ts +7 -1
- package/dist/storage.js +10 -0
- package/dist/structured-exec-host.d.ts +9 -1
- package/dist/structured-exec-pump.d.ts +11 -0
- package/dist/structured-exec-pump.js +27 -8
- package/dist/structured-pi-adapter.js +5 -0
- package/dist/structured-runner.d.ts +2 -0
- package/dist/structured-session-manager.d.ts +2 -0
- package/dist/structured-session-manager.js +51 -4
- package/dist/types.d.ts +7 -0
- package/dist/web-ui/content/module-manifest.json +1 -1
- package/dist/web-ui/content/modules/{4f30a913cc5b3f89 → 02fad74223254019}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{acb21c7e7fd6cb67 → 033e0a741edd2ba1}/page.js +1 -1
- package/dist/web-ui/content/modules/{e61136c22675ec7d → 0c04f94bbfd39a2f}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{119874145414688d → 12e91deb96ace24d}/shell-file-panel-drawer.js +1 -1
- package/dist/web-ui/content/modules/15279373f0e1461f/host.js +1 -0
- package/dist/web-ui/content/modules/{78a46adbf9807f89 → 17603a34d545c784}/chunk.js +1 -1
- package/dist/web-ui/content/modules/1f041aa8d3673d93/chunk.js +1 -0
- package/dist/web-ui/content/modules/{96dd661559b67ebf → 20483d6e57cfe9d7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{f55031a02775c89e → 217595f72a1c3fc5}/chunk.js +1 -1
- package/dist/web-ui/content/modules/2230c51655163cf3/runtime.js +279 -0
- package/dist/web-ui/content/modules/{82e40fdf0abfb8cd → 2460e872ab3a1f37}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{9e754b01fa4207fb → 2a47853ca7752c1f}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{e95b60ab18a79499 → 2afbc201474adacc}/login-visual.js +1 -1
- package/dist/web-ui/content/modules/{38917c19e2cf1702 → 30169d15cea782f0}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{5513bcbacdf44588 → 37abb74d1a0a0791}/notice-view.js +1 -1
- package/dist/web-ui/content/modules/{b62294e53dcb3147 → 38bb024e09cb5d5d}/host.js +1 -1
- package/dist/web-ui/content/modules/39faef0cffbad28e/home.js +6 -0
- package/dist/web-ui/content/modules/3a2fa12c8b537964/chunk.js +1 -0
- package/dist/web-ui/content/modules/{35a8fd2cfd31d7a0 → 3a72b79418f0f80a}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{321bd9c755bc30fc → 3bd3c84c4257ba0d}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{2981483671797b92 → 3d10e3f6f6f92b55}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{6f341fe3e8aee844 → 3d4451bc069c1498}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{4a9a3e1f87b2c32b → 3d5c498522b48225}/dialog-modal.js +1 -1
- package/dist/web-ui/content/modules/426b8133daebff78/host.js +1 -0
- package/dist/web-ui/content/modules/455436229dc57d7f/sidebar-peek.js +1 -0
- package/dist/web-ui/content/modules/46de3c2e2ca680c1/host.js +1 -0
- package/dist/web-ui/content/modules/47af6b35e1d01ea7/host.js +30 -0
- package/dist/web-ui/content/modules/4841e45cb7c5cc67/queue-view-adapter.js +3 -0
- package/dist/web-ui/content/modules/{47419445e0aaa3cc → 497789a07177ed7b}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{32c461164a1b364c → 5472191457a926d3}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{c152782274c04fad → 55a47b6e2c2016f2}/chunk.js +1 -1
- package/dist/web-ui/content/modules/5743d8116d15696b/employee-card.js +1 -0
- package/dist/web-ui/content/modules/{c81a3d95b14cdcd4 → 578703196f82222d}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{8ce71665ae55ccf1 → 57d68f0a47e8fd7c}/toast-region.js +1 -1
- package/dist/web-ui/content/modules/58866143a3365521/chunk.js +1 -0
- package/dist/web-ui/content/modules/{3601736ae2d678ef → 5bb5db89a343817f}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{a098c7b1aa4e2f6b → 5c9e8245d4a8a312}/sha256.js +1 -1
- package/dist/web-ui/content/modules/{8198bfd269c0caca → 5de35db482fb1a42}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{aab92f2990a7185f → 5e7104e569359449}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{4b9deeeb77570db3 → 601a2767ae24d1cb}/chunk.js +1 -1
- package/dist/web-ui/content/modules/6687ad7aa57f443b/task-board-host.js +22 -0
- package/dist/web-ui/content/modules/{c422f47fd13dc4bc → 684db83476dcba20}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{cf715621edb1d12e → 6b0bafa239dfe4e2}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{cd22aa55f6cc5276 → 6bd6ee3c9f05e2f5}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{09ef1bb1d195d727 → 79b0c18f2bf35740}/host.js +1 -1
- package/dist/web-ui/content/modules/{905f8bc3f8a3efb8 → 7ae83a3f06f2daa3}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{84b79a33c64e146c → 7f32261c1627c3cd}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{eece3c2d2374e8f7 → 805b859b1b76ce4d}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{eecaebc5482ee203 → 84358b5b729cbe48}/chunk.js +1 -1
- package/dist/web-ui/content/modules/85181d84d5ce62b3/employee-profile.js +1 -0
- package/dist/web-ui/content/modules/87edd7cc79811bb8/composer-surface-adapter.js +1 -0
- package/dist/web-ui/content/modules/{b0254a2d3652a925 → 8ea498cf092dba30}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{a4af270960a39ea6 → 8f0d4e22c18a58b0}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{c72c4f1d47c3726d → 907dcf0ea5b5f23f}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{9f33acc1c4284e03 → 916021ce252882ca}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{98c14fc0474455a5 → 91ee32135a3582b0}/chunk.js +1 -1
- package/dist/web-ui/content/modules/92df279c40bc4218/host.js +1 -0
- package/dist/web-ui/content/modules/{544dc812abdfbbb8 → 9661b076f08e64b4}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{5c94fb2b7abcd1a5 → 97ef63ff1f0784d9}/chunk.js +1 -1
- package/dist/web-ui/content/modules/99e48e07517d3f83/dropdown-surface.js +1 -0
- package/dist/web-ui/content/modules/9eb83751622e2b97/chunk.js +10 -0
- package/dist/web-ui/content/modules/{7375574a2ea42740 → a1715be0f97c2479}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{456634525d44777d → a2be1fd01cf06837}/chunk.js +1 -1
- package/dist/web-ui/content/modules/a33666b143331cd6/workspace-window.js +1 -0
- package/dist/web-ui/content/modules/{b38924f45bfa71d6 → a41351130003e6bb}/chunk.js +1 -1
- package/dist/web-ui/content/modules/a59c83b5b5b85da2/host.js +1 -0
- package/dist/web-ui/content/modules/{a4dca2ffaf656d3c → a63f0b3d73d97e0b}/chunk.js +1 -1
- package/dist/web-ui/content/modules/a685793c5d9b90d1/chunk.js +1 -0
- package/dist/web-ui/content/modules/a750f4868304b089/host.js +1 -0
- package/dist/web-ui/content/modules/abfe4b88dcd89d88/host.js +1 -0
- package/dist/web-ui/content/modules/{15bcc550ef9fd5b7 → acda148b7423bdab}/host.js +1 -1
- package/dist/web-ui/content/modules/{ad1136919a65fc6e → af6ff78aeb782cf2}/host.js +1 -1
- package/dist/web-ui/content/modules/b32c9addcd31f54b/panel-host.js +1 -0
- package/dist/web-ui/content/modules/{b937f1a939618be9 → b358eaf2e45849a6}/host.js +1 -1
- package/dist/web-ui/content/modules/{476ff7911bce1a38 → b7aeeb22bf604ec7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/bad2c42c7ddeab94/host.js +1 -0
- package/dist/web-ui/content/modules/{622a8d12c4c622bf → bb59e8cb4323bf06}/host.js +1 -1
- package/dist/web-ui/content/modules/{08c7b047195f138d → be497f1d39753979}/chunk.js +1 -1
- package/dist/web-ui/content/modules/bfa8e2c827201374/chunk.js +1 -0
- package/dist/web-ui/content/modules/{5395fa57a47e9b96 → bfe51130a84795fb}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{8e29056fb56439f7 → c03e0f84f798d33a}/chunk.js +1 -1
- package/dist/web-ui/content/modules/c118e0c96bc023ee/host-bridge.js +1 -0
- package/dist/web-ui/content/modules/c3512b18c4c0e4ac/brand-identity.js +1 -0
- package/dist/web-ui/content/modules/c3e0de0a61f0db34/chunk.js +1 -0
- package/dist/web-ui/content/modules/{9d48d1ea3c9228bd → c3e1f083e07d6840}/library-bridge.js +1 -1
- package/dist/web-ui/content/modules/cd5e90a37ccdf2dc/group-editor.js +1 -0
- package/dist/web-ui/content/modules/{2edc19639ac1bd4b → cdb8281bb89da303}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{f6f86d43c12b0864 → ce90d0b55bbe6430}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{72b13a7486b6d437 → d274491ffc8ee646}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{b1d43ed06a5d1a57 → d3cc94cf4a47a12a}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{b0c4eed46c1b6ad4 → d4b07cef43d36e79}/chat-render.js +5 -4
- package/dist/web-ui/content/modules/{8a4f0ef2c0812af6 → d7b540917fb90755}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{ef7f76b551fdc619 → d856bfc56bea5f20}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{42c439d3acfe22bd → d857ea8244b1026e}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{36ce8123a2079807 → d9019922118b2c37}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{58836e616e6d12ff → d90e77f9f8d4f1ec}/workspaces-panel.js +1 -1
- package/dist/web-ui/content/modules/{4d4870f20eb1c52d → da1aa5fa0186fea7}/chunk.js +1 -1
- package/dist/web-ui/content/modules/de977ff0b3ad3882/progress.js +1 -0
- package/dist/web-ui/content/modules/{222f48948517167e → e01769df89873feb}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{5df1b522f5d3c99d → e0ab9fa5a8882433}/host.js +1 -1
- package/dist/web-ui/content/modules/e25dea52e13504b6/markdown.js +1 -0
- package/dist/web-ui/content/modules/{36bd608366c56b72 → e43af4aa407885fd}/chunk.js +1 -1
- package/dist/web-ui/content/modules/ee893f06cdb2b4f7/panel.js +1 -0
- package/dist/web-ui/content/modules/{f90f80d7207dff1f → f2bdbdc4a1141826}/host.js +1 -1
- package/dist/web-ui/content/modules/{e33f6d66a02ec26c → f36b4d3d44491852}/chunk.js +1 -1
- package/dist/web-ui/content/modules/{665e81fe210f1b7a → fa79ed5d045c24dd}/chunk.js +1 -1
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +412 -406
- package/dist/web-ui/embedded-assets.js +4 -4
- package/package.json +1 -1
- package/scripts/install-render-binary.js +1 -1
- package/dist/web-ui/content/modules/1a7303b87763fd43/employee-profile.js +0 -1
- package/dist/web-ui/content/modules/1d35739f634745f6/task-board-host.js +0 -22
- package/dist/web-ui/content/modules/2099d37d57856cbd/brand-identity.js +0 -1
- package/dist/web-ui/content/modules/2d6339b2f6c2e2d0/host.js +0 -1
- package/dist/web-ui/content/modules/2f88fc37c6105f7e/sidebar-peek.js +0 -1
- package/dist/web-ui/content/modules/31124fb7ee6939df/host.js +0 -1
- package/dist/web-ui/content/modules/31b28c5d0019c363/host-bridge.js +0 -1
- package/dist/web-ui/content/modules/36e5c3a6d6705358/employee-card.js +0 -1
- package/dist/web-ui/content/modules/3700d99c54d3c400/host.js +0 -1
- package/dist/web-ui/content/modules/3ae29086b227f9d9/markdown.js +0 -1
- package/dist/web-ui/content/modules/42db858e4417c702/chunk.js +0 -10
- package/dist/web-ui/content/modules/443dc81eac29f233/host.js +0 -1
- package/dist/web-ui/content/modules/4af10e1f8a789204/runtime.js +0 -275
- package/dist/web-ui/content/modules/55b75ebcf6924001/host.js +0 -30
- package/dist/web-ui/content/modules/626c7ce0aa1714b0/host.js +0 -1
- package/dist/web-ui/content/modules/76adde4019731df1/chunk.js +0 -1
- package/dist/web-ui/content/modules/7925b65867b7aa4a/queue-view-adapter.js +0 -3
- package/dist/web-ui/content/modules/8a6844a4251a1271/chunk.js +0 -1
- package/dist/web-ui/content/modules/8bd214570df4a7a0/host.js +0 -1
- package/dist/web-ui/content/modules/8bff85e108320aab/panel.js +0 -1
- package/dist/web-ui/content/modules/988e01b67e6f1883/composer-surface-adapter.js +0 -1
- package/dist/web-ui/content/modules/a975ff38c3d43ba8/workspace-window.js +0 -1
- package/dist/web-ui/content/modules/b550260fc9c5363a/dropdown-surface.js +0 -1
- package/dist/web-ui/content/modules/bce467c603299460/chunk.js +0 -1
- package/dist/web-ui/content/modules/c138b442c1682189/panel-host.js +0 -1
- package/dist/web-ui/content/modules/c32d14632487364f/group-editor.js +0 -1
- package/dist/web-ui/content/modules/c6d0a1b2753a4883/host.js +0 -1
- package/dist/web-ui/content/modules/cdff6e7f72879c88/progress.js +0 -1
- package/dist/web-ui/content/modules/cfee7b0d79587d59/home.js +0 -6
- package/dist/web-ui/content/modules/e5e93fe5304838a1/chunk.js +0 -1
- package/dist/web-ui/content/modules/fbe35e7ddd7384fa/host.js +0 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { array, boundedFetch, DingTalkError, object, string } from "./dingtalk-dws.js";
|
|
3
|
+
/** Structured device OAuth, not scraping localized CLI stderr. Codes stay in memory and are exchanged over stdin. */
|
|
4
|
+
export class DingTalkAuth {
|
|
5
|
+
dws;
|
|
6
|
+
request;
|
|
7
|
+
attempts = new Map();
|
|
8
|
+
constructor(dws, request = boundedFetch) {
|
|
9
|
+
this.dws = dws;
|
|
10
|
+
this.request = request;
|
|
11
|
+
}
|
|
12
|
+
async accounts() {
|
|
13
|
+
const result = await this.dws.call(["profile", "list"]);
|
|
14
|
+
return array(result.profiles ?? result.items ?? result.data).flatMap(raw => {
|
|
15
|
+
const p = object(raw), id = string(p.profile ?? p.id), parts = id.split(":");
|
|
16
|
+
const corpId = string(p.corpId) || parts[0], userId = string(p.userId) || parts[1];
|
|
17
|
+
if (!corpId || !userId || p.authenticated === false)
|
|
18
|
+
return [];
|
|
19
|
+
return [{ id: `${corpId}:${userId}`, corpId, userId, name: string(p.userName ?? p.name) || userId, corpName: string(p.corpName) || corpId }];
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
async json(url, init) { return object(JSON.parse((await this.request(url, { ...init, redirect: "error" })).toString())); }
|
|
23
|
+
async begin() {
|
|
24
|
+
for (const a of this.attempts.values())
|
|
25
|
+
if (a.state === "waiting" || a.state === "exchanging")
|
|
26
|
+
return this.public(a);
|
|
27
|
+
this.attempts.clear();
|
|
28
|
+
const client = await this.json("https://mcp.dingtalk.com/cli/clientId", {});
|
|
29
|
+
const clientId = string(client.result);
|
|
30
|
+
if (client.success !== true || !clientId)
|
|
31
|
+
throw new DingTalkError("auth_unavailable", "无法取得钉钉授权应用信息。");
|
|
32
|
+
const raw = await this.json("https://login.dingtalk.com/oauth2/device/code.json", {
|
|
33
|
+
method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
34
|
+
body: new URLSearchParams({ client_id: clientId, scope: "openid corpid" }).toString(),
|
|
35
|
+
});
|
|
36
|
+
const data = object(raw.result);
|
|
37
|
+
const deviceCode = string(data.deviceCode), flowId = string(data.flowId);
|
|
38
|
+
const url = string(data.verificationUriComplete ?? data.verificationUri);
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = new URL(url);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new DingTalkError("auth_url", "钉钉授权链接无效。");
|
|
45
|
+
}
|
|
46
|
+
if (parsed.protocol !== "https:" || !["login.dingtalk.com", "open-dev.dingtalk.com"].includes(parsed.hostname) || parsed.username || parsed.password || parsed.port)
|
|
47
|
+
throw new DingTalkError("auth_url", "钉钉返回了未受信任的授权链接。");
|
|
48
|
+
if (raw.success !== true || !deviceCode || !string(data.userCode))
|
|
49
|
+
throw new DingTalkError("auth_invalid", "钉钉设备授权响应无效。");
|
|
50
|
+
const expires = Math.min(600, Math.max(30, Number(data.expiresIn) || 600));
|
|
51
|
+
const attempt = { id: randomUUID(), state: "waiting", url, userCode: data.userCode,
|
|
52
|
+
expiresAt: new Date(Date.now() + expires * 1000).toISOString(), abort: new AbortController() };
|
|
53
|
+
this.attempts.set(attempt.id, attempt);
|
|
54
|
+
void this.poll(attempt, clientId, deviceCode, flowId, Math.min(30, Math.max(2, Number(data.interval) || 2)));
|
|
55
|
+
return this.public(attempt);
|
|
56
|
+
}
|
|
57
|
+
get(id) { const value = this.attempts.get(id); if (!value)
|
|
58
|
+
throw new DingTalkError("not_found", "授权会话不存在或已失效,请重新授权。"); return this.public(value); }
|
|
59
|
+
cancel(id) {
|
|
60
|
+
const value = this.attempts.get(id);
|
|
61
|
+
if (!value)
|
|
62
|
+
throw new DingTalkError("not_found", "授权会话已失效。");
|
|
63
|
+
if (value.state === "waiting") {
|
|
64
|
+
value.state = "cancelled";
|
|
65
|
+
value.url = "";
|
|
66
|
+
value.userCode = "";
|
|
67
|
+
value.abort.abort();
|
|
68
|
+
}
|
|
69
|
+
// A one-time code already handed to DWS cannot be promised revoked. Report the real phase.
|
|
70
|
+
return this.public(value);
|
|
71
|
+
}
|
|
72
|
+
public(a) { return { id: a.id, state: a.state, url: a.state === "waiting" ? a.url : undefined, userCode: a.state === "waiting" ? a.userCode : undefined, expiresAt: a.expiresAt, error: a.error, account: a.account }; }
|
|
73
|
+
async poll(a, clientId, deviceCode, flowId, interval) {
|
|
74
|
+
try {
|
|
75
|
+
while (a.state === "waiting" && Date.now() < Date.parse(a.expiresAt)) {
|
|
76
|
+
await new Promise((resolve, reject) => {
|
|
77
|
+
const cancelled = () => { clearTimeout(timer); reject(new Error("cancelled")); };
|
|
78
|
+
const timer = setTimeout(() => { a.abort.signal.removeEventListener("abort", cancelled); resolve(); }, interval * 1000);
|
|
79
|
+
timer.unref?.();
|
|
80
|
+
a.abort.signal.addEventListener("abort", cancelled, { once: true });
|
|
81
|
+
});
|
|
82
|
+
if (a.abort.signal.aborted)
|
|
83
|
+
return;
|
|
84
|
+
const response = flowId
|
|
85
|
+
? await this.json(`https://mcp.dingtalk.com/cli/oauth/device/poll?flowId=${encodeURIComponent(flowId)}`, { signal: a.abort.signal })
|
|
86
|
+
: await this.json("https://login.dingtalk.com/oauth2/device/token.json", { method: "POST", signal: a.abort.signal,
|
|
87
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "urn:ietf:params:oauth:grant-type:device_code", device_code: deviceCode, client_id: clientId }).toString() });
|
|
88
|
+
const data = object(response.data ?? response.result);
|
|
89
|
+
if (["REJECTED", "EXPIRED", "CANCELLED"].includes(data.status))
|
|
90
|
+
throw new DingTalkError("auth_rejected", "授权被取消、拒绝或已过期,请重新授权。");
|
|
91
|
+
const code = string(data.authCode);
|
|
92
|
+
if (!code)
|
|
93
|
+
continue;
|
|
94
|
+
if (a.abort.signal.aborted || a.state !== "waiting")
|
|
95
|
+
return;
|
|
96
|
+
a.state = "exchanging";
|
|
97
|
+
a.url = "";
|
|
98
|
+
a.userCode = "";
|
|
99
|
+
const result = await this.dws.call(["auth", "exchange", "--code-stdin", "--client-id", clientId], { input: code });
|
|
100
|
+
const corpId = string(result.corpId), userId = string(result.userId);
|
|
101
|
+
if (!corpId || !userId)
|
|
102
|
+
throw new DingTalkError("identity", "钉钉未返回可验证的组织和用户身份。");
|
|
103
|
+
if (a.abort.signal.aborted || a.state !== "exchanging")
|
|
104
|
+
return;
|
|
105
|
+
a.account = { id: `${corpId}:${userId}`, corpId, userId, name: userId, corpName: corpId };
|
|
106
|
+
a.state = "connected";
|
|
107
|
+
a.url = "";
|
|
108
|
+
a.userCode = "";
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (a.state === "waiting")
|
|
112
|
+
throw new DingTalkError("expired", "授权已过期,请重新授权。");
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (a.state !== "waiting" && a.state !== "exchanging")
|
|
116
|
+
return;
|
|
117
|
+
a.state = "failed";
|
|
118
|
+
a.url = "";
|
|
119
|
+
a.userCode = "";
|
|
120
|
+
a.error = error instanceof DingTalkError ? error.message : "授权未完成,请重试;不会输出或保存授权码。";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
dispose() { for (const a of this.attempts.values()) {
|
|
124
|
+
a.state = "cancelled";
|
|
125
|
+
a.abort.abort();
|
|
126
|
+
} this.attempts.clear(); }
|
|
127
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare class DingTalkError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly unknownDelivery: boolean;
|
|
4
|
+
readonly httpStatus?: number | undefined;
|
|
5
|
+
constructor(code: string, message: string, unknownDelivery?: boolean, httpStatus?: number | undefined);
|
|
6
|
+
}
|
|
7
|
+
export declare const object: (v: unknown) => Record<string, any>;
|
|
8
|
+
export declare const string: (v: unknown) => string;
|
|
9
|
+
export declare const array: (v: unknown) => any[];
|
|
10
|
+
/** The CLI's composite helpers wrap JSON in MCP text content. Never return raw envelopes/errors to a client. */
|
|
11
|
+
export declare function dwsPayload(value: unknown): Record<string, any>;
|
|
12
|
+
export interface DwsTransport {
|
|
13
|
+
call(args: string[], options?: {
|
|
14
|
+
input?: string;
|
|
15
|
+
write?: boolean;
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}): Promise<Record<string, any>>;
|
|
18
|
+
stream(args: string[], onLine: (line: string) => void, onEnd: () => void, onReady?: () => void): {
|
|
19
|
+
close(): void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export declare class DwsClient implements DwsTransport {
|
|
23
|
+
private readonly directory;
|
|
24
|
+
private readonly configuredBinary;
|
|
25
|
+
private children;
|
|
26
|
+
private closed;
|
|
27
|
+
private installation;
|
|
28
|
+
readonly configDir: string;
|
|
29
|
+
constructor(directory: string, configuredBinary?: string | undefined);
|
|
30
|
+
private get binary();
|
|
31
|
+
private child;
|
|
32
|
+
call(args: string[], options?: {
|
|
33
|
+
input?: string;
|
|
34
|
+
write?: boolean;
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
}): Promise<Record<string, any>>;
|
|
37
|
+
stream(args: string[], onLine: (line: string) => void, onEnd: () => void, onReady?: () => void): {
|
|
38
|
+
close(): void;
|
|
39
|
+
};
|
|
40
|
+
dispose(): void;
|
|
41
|
+
/** Explicit admin action. Pinned release + checksum, private executable; never execute an install script. */
|
|
42
|
+
install(): Promise<void>;
|
|
43
|
+
private installPinned;
|
|
44
|
+
}
|
|
45
|
+
export declare function boundedFetch(url: string, init?: RequestInit, limit?: number): Promise<Buffer>;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { mkdirSync, existsSync, chmodSync, writeFileSync, renameSync } from "node:fs";
|
|
3
|
+
import { join, isAbsolute } from "node:path";
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
|
+
import { gunzipSync } from "node:zlib";
|
|
6
|
+
import { buildChildEnv } from "./env-utils.js";
|
|
7
|
+
export class DingTalkError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
unknownDelivery;
|
|
10
|
+
httpStatus;
|
|
11
|
+
constructor(code, message, unknownDelivery = false, httpStatus) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.unknownDelivery = unknownDelivery;
|
|
15
|
+
this.httpStatus = httpStatus;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export const object = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
19
|
+
export const string = (v) => typeof v === "string" ? v : "";
|
|
20
|
+
export const array = (v) => Array.isArray(v) ? v : [];
|
|
21
|
+
/** The CLI's composite helpers wrap JSON in MCP text content. Never return raw envelopes/errors to a client. */
|
|
22
|
+
export function dwsPayload(value) {
|
|
23
|
+
const envelope = (v) => Array.isArray(v) ? { items: v } : object(v);
|
|
24
|
+
let node = envelope(value);
|
|
25
|
+
for (let i = 0; i < 12; i++) {
|
|
26
|
+
if (node.ok === false || node.success === false || node.isError === true || node.error) {
|
|
27
|
+
throw new DingTalkError("provider_rejected", "钉钉拒绝了操作,请核对账号权限与当前资源状态。");
|
|
28
|
+
}
|
|
29
|
+
if (node.response) {
|
|
30
|
+
node = envelope(node.response);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const text = array(node.content).find(x => x?.type === "text")?.text;
|
|
34
|
+
if (typeof text === "string") {
|
|
35
|
+
try {
|
|
36
|
+
node = envelope(JSON.parse(text));
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof DingTalkError)
|
|
41
|
+
throw error;
|
|
42
|
+
throw new DingTalkError("invalid_response", "钉钉未返回可验证的结构化结果。");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const key = node.data && !Array.isArray(node.data) ? "data" : node.result && !Array.isArray(node.result) ? "result" : null;
|
|
46
|
+
if (key) {
|
|
47
|
+
const { [key]: inner, ...rest } = node;
|
|
48
|
+
node = { ...rest, ...object(inner) };
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
return node;
|
|
52
|
+
}
|
|
53
|
+
throw new DingTalkError("invalid_response", "钉钉响应层级异常。");
|
|
54
|
+
}
|
|
55
|
+
export class DwsClient {
|
|
56
|
+
directory;
|
|
57
|
+
configuredBinary;
|
|
58
|
+
children = new Set();
|
|
59
|
+
closed = false;
|
|
60
|
+
installation;
|
|
61
|
+
configDir;
|
|
62
|
+
constructor(directory, configuredBinary = process.env.WAND_DWS_BINARY) {
|
|
63
|
+
this.directory = directory;
|
|
64
|
+
this.configuredBinary = configuredBinary;
|
|
65
|
+
this.configDir = join(directory, "dingtalk", "dws");
|
|
66
|
+
}
|
|
67
|
+
get binary() {
|
|
68
|
+
if (this.configuredBinary) {
|
|
69
|
+
if (!isAbsolute(this.configuredBinary))
|
|
70
|
+
throw new DingTalkError("invalid_binary", "WAND_DWS_BINARY 必须是受信任的绝对路径。");
|
|
71
|
+
return this.configuredBinary;
|
|
72
|
+
}
|
|
73
|
+
const local = join(this.directory, "dingtalk", "bin", process.platform === "win32" ? "dws.exe" : "dws");
|
|
74
|
+
return existsSync(local) ? local : "dws";
|
|
75
|
+
}
|
|
76
|
+
child(args) {
|
|
77
|
+
// Atomic DWS leaves support @file expansion. Never grant that capability to external values.
|
|
78
|
+
// The unified chat shortcut instead has an explicit --body-stdin / --text - literal-body contract.
|
|
79
|
+
if (args.some(value => value.startsWith("@")))
|
|
80
|
+
throw new DingTalkError("literal_argument", "钉钉参数包含文件展开语法,已拒绝;消息正文应通过受限标准输入发送。");
|
|
81
|
+
if (this.closed)
|
|
82
|
+
throw new DingTalkError("closed", "钉钉连接器已关闭。");
|
|
83
|
+
mkdirSync(this.configDir, { recursive: true, mode: 0o700 });
|
|
84
|
+
// No shell; no HTTP-provided executable, env, path, token or command. Each business method owns its argv.
|
|
85
|
+
const child = spawn(this.binary, args, { env: buildChildEnv(false, { DWS_CONFIG_DIR: this.configDir }), stdio: "pipe" });
|
|
86
|
+
this.children.add(child);
|
|
87
|
+
child.once("close", () => this.children.delete(child));
|
|
88
|
+
return child;
|
|
89
|
+
}
|
|
90
|
+
async call(args, options = {}) {
|
|
91
|
+
const child = this.child([...args, "--format", "json"]);
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
let output = "", settled = false;
|
|
94
|
+
const fail = (code, message, unknownDelivery = options.write ?? false) => { if (!settled) {
|
|
95
|
+
settled = true;
|
|
96
|
+
reject(new DingTalkError(code, message, unknownDelivery));
|
|
97
|
+
} };
|
|
98
|
+
const timer = setTimeout(() => { fail("timeout", "钉钉操作超时,送达状态需核实;不会自动重做。"); child.kill("SIGTERM"); }, options.timeoutMs ?? 30_000);
|
|
99
|
+
timer.unref?.();
|
|
100
|
+
child.stdout.on("data", chunk => { output += chunk.toString(); if (Buffer.byteLength(output) > 2 * 1024 * 1024) {
|
|
101
|
+
fail("oversize", "钉钉响应超过安全大小。");
|
|
102
|
+
child.kill("SIGTERM");
|
|
103
|
+
} });
|
|
104
|
+
child.stderr.resume(); // May contain secrets: neither log, echo nor persist it.
|
|
105
|
+
child.once("error", () => { clearTimeout(timer); fail("unavailable", "DWS 不可用,请先安装连接器依赖。", false); });
|
|
106
|
+
child.once("close", code => {
|
|
107
|
+
clearTimeout(timer);
|
|
108
|
+
if (settled)
|
|
109
|
+
return;
|
|
110
|
+
try {
|
|
111
|
+
if (code !== 0)
|
|
112
|
+
throw new DingTalkError("cli_failed", "DWS 操作未确认,请检查授权、权限和资源状态。", options.write);
|
|
113
|
+
const result = dwsPayload(JSON.parse(output));
|
|
114
|
+
settled = true;
|
|
115
|
+
resolve(result);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
settled = true;
|
|
119
|
+
reject(error instanceof DingTalkError ? new DingTalkError(error.code, error.message, error.unknownDelivery || (!!options.write && error.code === "provider_rejected"), error.httpStatus) : new DingTalkError("invalid_response", "DWS 响应无效,操作状态需核实。", options.write));
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
child.stdin.end(options.input);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
stream(args, onLine, onEnd, onReady) {
|
|
126
|
+
const child = this.child(args);
|
|
127
|
+
let pending = "", diagnostic = "", ended = false;
|
|
128
|
+
const end = () => { if (!ended) {
|
|
129
|
+
ended = true;
|
|
130
|
+
onEnd();
|
|
131
|
+
} };
|
|
132
|
+
child.on("error", end);
|
|
133
|
+
child.on("close", end);
|
|
134
|
+
child.stderr.on("data", chunk => {
|
|
135
|
+
diagnostic = (diagnostic + chunk.toString()).slice(-16_384);
|
|
136
|
+
let newline;
|
|
137
|
+
while ((newline = diagnostic.indexOf("\n")) >= 0) {
|
|
138
|
+
const line = diagnostic.slice(0, newline);
|
|
139
|
+
diagnostic = diagnostic.slice(newline + 1);
|
|
140
|
+
// DWS documents this exact machine contract. Other diagnostic text is discarded, never logged.
|
|
141
|
+
if (line.startsWith("[event] ready "))
|
|
142
|
+
onReady?.();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
child.stdout.on("data", chunk => {
|
|
146
|
+
pending += chunk.toString();
|
|
147
|
+
if (Buffer.byteLength(pending) > 1024 * 1024) {
|
|
148
|
+
child.kill("SIGTERM");
|
|
149
|
+
end();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
let newline;
|
|
153
|
+
while ((newline = pending.indexOf("\n")) >= 0) {
|
|
154
|
+
const line = pending.slice(0, newline);
|
|
155
|
+
pending = pending.slice(newline + 1);
|
|
156
|
+
if (line.trim())
|
|
157
|
+
onLine(line);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
// Keep stdin open: DWS treats EOF as a graceful unsubscribe.
|
|
161
|
+
return { close() { child.stdin.end(); child.kill("SIGTERM"); } };
|
|
162
|
+
}
|
|
163
|
+
dispose() { this.closed = true; for (const child of this.children) {
|
|
164
|
+
child.stdin.end();
|
|
165
|
+
child.kill("SIGTERM");
|
|
166
|
+
} this.children.clear(); }
|
|
167
|
+
/** Explicit admin action. Pinned release + checksum, private executable; never execute an install script. */
|
|
168
|
+
install() {
|
|
169
|
+
if (this.installation)
|
|
170
|
+
return this.installation;
|
|
171
|
+
const work = this.installPinned();
|
|
172
|
+
this.installation = work;
|
|
173
|
+
void work.finally(() => { if (this.installation === work)
|
|
174
|
+
this.installation = undefined; }).catch(() => { });
|
|
175
|
+
return work;
|
|
176
|
+
}
|
|
177
|
+
async installPinned() {
|
|
178
|
+
if (!["darwin", "linux"].includes(process.platform) || !["arm64", "x64"].includes(process.arch))
|
|
179
|
+
throw new DingTalkError("unsupported_platform", "此系统暂不支持自动安装 DWS,请配置受信任的可执行文件。");
|
|
180
|
+
const name = `dws-${process.platform}-${process.arch === "x64" ? "amd64" : "arm64"}.tar.gz`;
|
|
181
|
+
const base = "https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/releases/download/v1.0.65/";
|
|
182
|
+
const checks = await boundedFetch(base + "checksums.txt", {}, 64 * 1024);
|
|
183
|
+
const archive = await boundedFetch(base + name, {}, 32 * 1024 * 1024);
|
|
184
|
+
const expected = checks.toString().split("\n").find(line => line.trim().split(/\s+/).at(-1) === name)?.split(/\s+/)[0];
|
|
185
|
+
if (!expected || createHash("sha256").update(archive).digest("hex") !== expected)
|
|
186
|
+
throw new DingTalkError("checksum", "DWS 下载校验失败,未安装。");
|
|
187
|
+
const tar = gunzipSync(archive, { maxOutputLength: 96 * 1024 * 1024 });
|
|
188
|
+
let executable;
|
|
189
|
+
for (let at = 0; at + 512 <= tar.length;) {
|
|
190
|
+
const header = tar.subarray(at, at + 512);
|
|
191
|
+
const filename = header.subarray(0, 100).toString().replace(/\0.*$/, "");
|
|
192
|
+
if (!filename)
|
|
193
|
+
break;
|
|
194
|
+
const size = Number.parseInt(header.subarray(124, 136).toString().replace(/\0.*$/, "").trim(), 8);
|
|
195
|
+
if (!Number.isSafeInteger(size) || size < 0 || at + 512 + size > tar.length)
|
|
196
|
+
throw new DingTalkError("archive", "DWS 安装包格式无效。");
|
|
197
|
+
if (filename.split("/").at(-1) === "dws" && (header[156] === 0 || header[156] === 48)) {
|
|
198
|
+
if (executable)
|
|
199
|
+
throw new DingTalkError("archive", "DWS 安装包包含重复程序。");
|
|
200
|
+
executable = tar.subarray(at + 512, at + 512 + size);
|
|
201
|
+
}
|
|
202
|
+
at += 512 + Math.ceil(size / 512) * 512;
|
|
203
|
+
}
|
|
204
|
+
if (!executable?.length)
|
|
205
|
+
throw new DingTalkError("archive", "安装包中缺少 DWS。");
|
|
206
|
+
const bin = join(this.directory, "dingtalk", "bin");
|
|
207
|
+
mkdirSync(bin, { recursive: true, mode: 0o700 });
|
|
208
|
+
const staged = join(bin, `.dws-${randomUUID()}`);
|
|
209
|
+
writeFileSync(staged, executable, { mode: 0o700 });
|
|
210
|
+
chmodSync(staged, 0o700);
|
|
211
|
+
renameSync(staged, join(bin, "dws"));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
export async function boundedFetch(url, init = {}, limit = 1024 * 1024) {
|
|
215
|
+
const timeout = AbortSignal.timeout(30_000);
|
|
216
|
+
const response = await fetch(url, { ...init, signal: init.signal ? AbortSignal.any([init.signal, timeout]) : timeout });
|
|
217
|
+
if (!response.ok || !response.body) {
|
|
218
|
+
await response.body?.cancel();
|
|
219
|
+
throw new DingTalkError("http_failed", "钉钉网络请求失败,请稍后核对状态。", false, response.status);
|
|
220
|
+
}
|
|
221
|
+
const chunks = [];
|
|
222
|
+
let size = 0;
|
|
223
|
+
const reader = response.body.getReader();
|
|
224
|
+
try {
|
|
225
|
+
while (true) {
|
|
226
|
+
const next = await reader.read();
|
|
227
|
+
if (next.done)
|
|
228
|
+
break;
|
|
229
|
+
size += next.value.length;
|
|
230
|
+
if (size > limit)
|
|
231
|
+
throw new DingTalkError("oversize", "远端响应超过安全大小。");
|
|
232
|
+
chunks.push(next.value);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
finally {
|
|
236
|
+
await reader.cancel().catch(() => { });
|
|
237
|
+
reader.releaseLock();
|
|
238
|
+
}
|
|
239
|
+
return Buffer.concat(chunks);
|
|
240
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { WandStorage } from "./storage.js";
|
|
2
|
+
import type { WandConfig, ProcessEvent, SessionSnapshot } from "./types.js";
|
|
3
|
+
import type { StructuredSessionManager } from "./structured-session-manager.js";
|
|
4
|
+
import { type ConversationReceipt } from "./conversation-types.js";
|
|
5
|
+
import { type DwsTransport } from "./dingtalk-dws.js";
|
|
6
|
+
import { DingTalkAuth } from "./dingtalk-auth.js";
|
|
7
|
+
import { DingTalkRobotStream } from "./dingtalk-stream.js";
|
|
8
|
+
import type { DingTalkBinding, DingTalkExternalConversation, DingTalkGroup, DingTalkJob, DingTalkPlan, DingTalkStatus } from "./dingtalk-types.js";
|
|
9
|
+
export declare const dingTalkId: (...parts: string[]) => string;
|
|
10
|
+
/** Only explicit final assistant text is exported. No transcript, thoughts, tool rows or diagnostics. */
|
|
11
|
+
export declare function dingTalkFinalText(session: SessionSnapshot): string | null;
|
|
12
|
+
export declare class DingTalkService {
|
|
13
|
+
private readonly deps;
|
|
14
|
+
readonly auth: DingTalkAuth;
|
|
15
|
+
private readonly discovered;
|
|
16
|
+
private readonly robotLocks;
|
|
17
|
+
private readonly robotStreams;
|
|
18
|
+
private readonly groupStreams;
|
|
19
|
+
private readonly busyRuns;
|
|
20
|
+
private deliveryActive;
|
|
21
|
+
private deliveryPumping;
|
|
22
|
+
private deliveryHalted;
|
|
23
|
+
private readonly reconnects;
|
|
24
|
+
private readonly reconnectTimers;
|
|
25
|
+
private disposed;
|
|
26
|
+
constructor(deps: {
|
|
27
|
+
storage: WandStorage;
|
|
28
|
+
dws: DwsTransport;
|
|
29
|
+
config: WandConfig;
|
|
30
|
+
structured: Pick<StructuredSessionManager, "createSession" | "sendMessage" | "get"> & {
|
|
31
|
+
stop?(id: string): unknown;
|
|
32
|
+
};
|
|
33
|
+
changed(): void;
|
|
34
|
+
robotStream?: (credentials: {
|
|
35
|
+
clientId: string;
|
|
36
|
+
clientSecret: string;
|
|
37
|
+
}, receive: (data: Record<string, any>) => Promise<void>, state: (connected: boolean) => void) => DingTalkRobotStream;
|
|
38
|
+
});
|
|
39
|
+
private get s();
|
|
40
|
+
private list;
|
|
41
|
+
private save;
|
|
42
|
+
private bindings;
|
|
43
|
+
private groups;
|
|
44
|
+
private robots;
|
|
45
|
+
private account;
|
|
46
|
+
private call;
|
|
47
|
+
status(): Promise<DingTalkStatus>;
|
|
48
|
+
discover(accountId: string, cursor?: string): Promise<{
|
|
49
|
+
groups: {
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
memberCount: any;
|
|
53
|
+
}[];
|
|
54
|
+
nextCursor: string;
|
|
55
|
+
complete: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
private assertConfigurationCapacity;
|
|
58
|
+
plan(input: {
|
|
59
|
+
accountId: unknown;
|
|
60
|
+
groupIds: unknown;
|
|
61
|
+
employeeIds: unknown;
|
|
62
|
+
excluded?: unknown;
|
|
63
|
+
robotNames?: unknown;
|
|
64
|
+
candidateIndices?: unknown;
|
|
65
|
+
}): Promise<DingTalkPlan>;
|
|
66
|
+
connect(planId: string, confirmed: boolean): Promise<DingTalkJob>;
|
|
67
|
+
private ensureMirror;
|
|
68
|
+
metadata(group: DingTalkGroup): DingTalkExternalConversation;
|
|
69
|
+
groupForConversation(id: string): DingTalkGroup | undefined;
|
|
70
|
+
private provision;
|
|
71
|
+
private ensureRobot;
|
|
72
|
+
private provisionRobot;
|
|
73
|
+
private startRobot;
|
|
74
|
+
private startGroup;
|
|
75
|
+
private history;
|
|
76
|
+
receiveGroup(groupId: string, data: Record<string, any>, live?: boolean): void;
|
|
77
|
+
receiveRobot(robotId: string, data: Record<string, any>): Promise<void>;
|
|
78
|
+
private execute;
|
|
79
|
+
ingest(event: ProcessEvent): void;
|
|
80
|
+
private settleSession;
|
|
81
|
+
private failRun;
|
|
82
|
+
private queueDelivery;
|
|
83
|
+
private pumpDeliveries;
|
|
84
|
+
private deliver;
|
|
85
|
+
send(id: string, requestId: string, input: string): Promise<ConversationReceipt>;
|
|
86
|
+
private linkEcho;
|
|
87
|
+
retryBinding(id: string): Promise<DingTalkJob>;
|
|
88
|
+
refreshGroup(id: string): Promise<DingTalkGroup>;
|
|
89
|
+
removeMirror(id: string): void;
|
|
90
|
+
removeBinding(id: string): {
|
|
91
|
+
removed: boolean;
|
|
92
|
+
};
|
|
93
|
+
updateBinding(id: string, input: {
|
|
94
|
+
paused?: unknown;
|
|
95
|
+
candidateIndex?: unknown;
|
|
96
|
+
allowGroupMembers?: unknown;
|
|
97
|
+
}): DingTalkBinding;
|
|
98
|
+
restore(): Promise<void>;
|
|
99
|
+
dispose(): void;
|
|
100
|
+
}
|