@xmanrui/dsh-im 0.3.0 → 0.4.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/README.md +34 -0
- package/assets/logo-icon.png +0 -0
- package/assets/logo.png +0 -0
- package/lib/client.js +57 -11
- package/lib/index.js +2 -2
- package/package.json +2 -1
- package/plugin-src/client/build.mjs +6 -1
- package/plugin-src/client/i18n.js +2 -1
- package/plugin-src/client/index.js +28 -1
- package/plugin-src/client/styles.js +19 -9
- package/src/channels/discord/discord-api.mjs +1 -1
- package/src/channels/weixin/weixin-api.mjs +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# dsh-im
|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="assets/logo.png" alt="dsh-im logo" width="160">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center"><strong>让聊天机器人轻松接入 DeepSeek Harness</strong></p>
|
|
8
|
+
<p align="center"><strong>Connect IM bots to DeepSeek Harness with ease</strong></p>
|
|
9
|
+
|
|
3
10
|
## 中文
|
|
4
11
|
|
|
5
12
|
通过扫码、App Manifest 或已有机器人凭据把 IM 机器人接入 DeepSeek Harness。一个插件、一个设置入口,统一管理飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord 和 WhatsApp 机器人。
|
|
@@ -171,3 +178,30 @@ IM management RPCs accept loopback browsers by default. When a Web profile is de
|
|
|
171
178
|
```
|
|
172
179
|
|
|
173
180
|
`trusted-host` reuses Harness's Host/Origin fence; it is not user authentication. Anyone who can reach that LAN authority can inspect bot status, scan or submit application credentials, reconnect bots, and remove bots. Enable it only on a trusted network.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 联系方式 / Contact
|
|
185
|
+
|
|
186
|
+
欢迎通过邮箱、微信或小红书联系我。
|
|
187
|
+
|
|
188
|
+
You can reach me by email, WeChat, or Xiaohongshu.
|
|
189
|
+
|
|
190
|
+
<table>
|
|
191
|
+
<tr>
|
|
192
|
+
<th align="center">邮箱 / Email</th>
|
|
193
|
+
<th align="center">微信 / WeChat</th>
|
|
194
|
+
<th align="center">小红书 / Xiaohongshu</th>
|
|
195
|
+
</tr>
|
|
196
|
+
<tr>
|
|
197
|
+
<td align="center" valign="middle">
|
|
198
|
+
<a href="mailto:longmanr307@gmail.com">longmanr307@gmail.com</a>
|
|
199
|
+
</td>
|
|
200
|
+
<td align="center" valign="top">
|
|
201
|
+
<a href="docs/images/weixin.jpg"><img src="docs/images/weixin.jpg" alt="微信二维码 / WeChat QR code" width="240"></a>
|
|
202
|
+
</td>
|
|
203
|
+
<td align="center" valign="top">
|
|
204
|
+
<a href="docs/images/xhs.jpg"><img src="docs/images/xhs.jpg" alt="小红书二维码 / Xiaohongshu QR code" width="240"></a>
|
|
205
|
+
</td>
|
|
206
|
+
</tr>
|
|
207
|
+
</table>
|
|
Binary file
|
package/assets/logo.png
ADDED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -366,7 +366,8 @@ var EN = Object.freeze({
|
|
|
366
366
|
"IM\u673A\u5668\u4EBA": "IM bots",
|
|
367
367
|
"IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings",
|
|
368
368
|
"IM \u6E20\u9053": "IM channels",
|
|
369
|
-
"\
|
|
369
|
+
"\u8BA9\u804A\u5929\u673A\u5668\u4EBA\u8F7B\u677E\u63A5\u5165 DeepSeek Harness": "Connect IM bots to DeepSeek Harness with ease",
|
|
370
|
+
"\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub": "Help & feedback \xB7 Open GitHub",
|
|
370
371
|
"\u5FAE\u4FE1": "WeChat",
|
|
371
372
|
"\u98DE\u4E66": "Feishu",
|
|
372
373
|
"\u9489\u9489": "DingTalk",
|
|
@@ -7232,8 +7233,17 @@ var CSS10 = String.raw`
|
|
|
7232
7233
|
box-sizing: border-box;
|
|
7233
7234
|
}
|
|
7234
7235
|
.dim-page *, .dim-page *::before, .dim-page *::after { box-sizing: border-box; }
|
|
7235
|
-
.dim-title { margin: 0 0
|
|
7236
|
-
.dim-
|
|
7236
|
+
.dim-title { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 18px; }
|
|
7237
|
+
.dim-brand { min-width: 0; display: flex; align-items: center; gap: 12px; }
|
|
7238
|
+
.dim-brandLogo { width: 48px; height: 48px; flex: 0 0 48px; display: block; object-fit: contain; filter: grayscale(1) contrast(1.08); }
|
|
7239
|
+
.dim-title p { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 20px; font-weight: 600; white-space: nowrap; }
|
|
7240
|
+
.dim-githubAction { position: relative; display: inline-flex; flex: none; }
|
|
7241
|
+
.dim-githubLink { min-height: 30px; display: inline-flex; align-items: center; gap: 5px; flex: none; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-1, #fff); font-size: 12px; line-height: normal; font-weight: 560; text-decoration: none; transition: border-color .15s ease, color .15s ease, background .15s ease; }
|
|
7242
|
+
.dim-githubLink:hover { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
7243
|
+
.dim-githubLink:focus-visible { outline: 2px solid color-mix(in srgb, var(--dim-blue) 70%, white); outline-offset: 2px; }
|
|
7244
|
+
.dim-githubArrow { font-size: 13px; line-height: 1; }
|
|
7245
|
+
.dim-githubTooltip { position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 20; width: max-content; max-width: min(220px, 80vw); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
|
|
7246
|
+
.dim-githubAction:hover .dim-githubTooltip, .dim-githubAction:focus-within .dim-githubTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
|
|
7237
7247
|
.dim-layout { display: grid; grid-template-columns: 174px 1px minmax(0, 1fr); gap: 24px; align-items: start; }
|
|
7238
7248
|
.dim-rail { max-height: 520px; display: grid; align-content: start; gap: 8px; overflow-y: auto; padding: 1px 4px 1px 1px; scrollbar-width: thin; scrollbar-color: var(--dsw-alias-border-l2, #dfe1e5) transparent; }
|
|
7239
7249
|
.dim-rail::-webkit-scrollbar { width: 4px; }
|
|
@@ -7278,7 +7288,7 @@ var CSS10 = String.raw`
|
|
|
7278
7288
|
.dim-panel .dim-credentialButton:hover:not(:disabled) { border-color: #4e5969; background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
7279
7289
|
.dim-panel .dim-credentialButton[aria-pressed="true"] { border-color: #4e5969; background: var(--dsw-alias-bg-module-platform, #f2f3f5); box-shadow: inset 0 0 0 1px rgb(78 89 105 / 8%); }
|
|
7280
7290
|
.dim-panel .bxf-headingTools .dim-onlineBadge, .dim-panel .dxw-tools .dim-onlineBadge, .dim-panel .ddt-tools .dim-onlineBadge { min-height: 30px; display: inline-flex; align-items: center; justify-self: end; gap: 0; padding: 0 11px; border: 0; border-radius: 999px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-module-platform, #f2f3f5); font: inherit; font-size: 12px; font-weight: 400; line-height: normal; white-space: nowrap; }
|
|
7281
|
-
.dim-panel .dim-channelPage { width: 100%; max-width: none; display: flex; flex-direction: column; gap:
|
|
7291
|
+
.dim-panel .dim-channelPage { width: 100%; max-width: none; display: flex; flex-direction: column; gap: 12px; padding: 0 0 24px; color: var(--dsw-alias-label-primary, #1f2329); box-sizing: border-box; }
|
|
7282
7292
|
.dim-panel .dim-surfaceCard { position: relative; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); border-radius: 14px; background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 1px 2px rgb(31 35 41 / 3%); }
|
|
7283
7293
|
.dim-panel .dim-surfaceCard::before { display: none; }
|
|
7284
7294
|
.dim-panel .dim-surfaceBody { padding: 24px; }
|
|
@@ -7294,9 +7304,9 @@ var CSS10 = String.raw`
|
|
|
7294
7304
|
.dim-panel .dim-credentialError { margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.5; }
|
|
7295
7305
|
.dim-panel .dim-credentialActions { margin-top: 0; }
|
|
7296
7306
|
.dim-panel .dim-listSection { display: flex; flex-direction: column; gap: 0; }
|
|
7297
|
-
.dim-panel .dim-listHeading { min-height: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin:
|
|
7307
|
+
.dim-panel .dim-listHeading { min-height: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 6px; padding: 0; }
|
|
7298
7308
|
.dim-panel .dim-listHeading h3 { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: normal; font-weight: 650; }
|
|
7299
|
-
.dim-panel .dim-botList { display: grid; gap:
|
|
7309
|
+
.dim-panel .dim-botList { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
|
|
7300
7310
|
.dim-panel .dim-loadingView { padding: 38px; color: var(--dsw-alias-label-secondary, #646a73); text-align: center; }
|
|
7301
7311
|
.dim-panel .dim-loadingView h3 { margin: 0 0 7px; color: var(--dsw-alias-label-primary, #1f2329); font-size: 17px; line-height: normal; font-weight: 650; }
|
|
7302
7312
|
.dim-panel .dim-loadingView p { margin: 0; line-height: 1.6; }
|
|
@@ -7344,7 +7354,7 @@ var CSS10 = String.raw`
|
|
|
7344
7354
|
.dim-panel .dim-confirm { padding: 18px 24px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
7345
7355
|
.dim-panel .dim-confirm strong, .dim-panel .dim-confirm h4 { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 1.4; font-weight: 650; }
|
|
7346
7356
|
.dim-panel .dim-confirm p { margin: 7px 0 0; color: var(--dsw-alias-label-secondary, #646a73); line-height: 1.6; }
|
|
7347
|
-
.dim-panel .dim-cardFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; padding-top:
|
|
7357
|
+
.dim-panel .dim-cardFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; padding-top: 8px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); }
|
|
7348
7358
|
.dim-panel .dim-cardSummary { min-width: 0; color: var(--dsw-alias-label-secondary, #646a73); font: inherit; font-size: 12px; font-weight: 400; line-height: normal; }
|
|
7349
7359
|
.dim-panel .dim-cardActions { flex: none; display: flex; align-items: center; flex-wrap: nowrap; gap: 8px; margin: 0 0 0 auto; }
|
|
7350
7360
|
.dim-panel .dim-cardActions .dim-cardAction { flex: none; min-height: 34px; padding: 0 13px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 13px; font-weight: 560; line-height: normal; white-space: nowrap; }
|
|
@@ -7352,7 +7362,7 @@ var CSS10 = String.raw`
|
|
|
7352
7362
|
.dim-panel .dim-cardActions .dim-cardAction[data-kind="danger"] { color: var(--dsw-alias-state-error-primary, #d54941); }
|
|
7353
7363
|
.dim-panel .dim-botCard { position: relative; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); border-radius: 14px; background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 1px 2px rgb(31 35 41 / 3%); }
|
|
7354
7364
|
.dim-panel .dim-botCard::before { display: none; }
|
|
7355
|
-
.dim-panel .dim-botCardBody { position: relative; padding:
|
|
7365
|
+
.dim-panel .dim-botCardBody { position: relative; padding: 14px; }
|
|
7356
7366
|
.dim-panel .dim-botCardTop { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
|
7357
7367
|
.dim-panel .dim-botIdentity { min-width: 0; display: flex; align-items: center; gap: 12px; }
|
|
7358
7368
|
.dim-panel .dim-botAvatar { flex: none; width: 42px; height: 42px; display: grid; place-items: center; overflow: hidden; border-radius: 12px; box-shadow: none; }
|
|
@@ -7365,8 +7375,8 @@ var CSS10 = String.raw`
|
|
|
7365
7375
|
.dim-panel .dim-botCard .dim-healthDot[data-tone="success"] { background: var(--dsw-alias-state-success-primary, #20a162); box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsw-alias-state-success-primary, #20a162) 14%, transparent); }
|
|
7366
7376
|
.dim-panel .dim-botCard .dim-healthDot[data-tone="warning"] { background: var(--dsw-alias-state-warn-primary, #d97706); }
|
|
7367
7377
|
.dim-panel .dim-botCard .dim-healthDot[data-tone="error"] { background: var(--dsw-alias-state-error-primary, #d54941); }
|
|
7368
|
-
.dim-panel .dim-botMetrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin:
|
|
7369
|
-
.dim-panel .dim-botMetric { min-width: 0; padding:
|
|
7378
|
+
.dim-panel .dim-botMetrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 8px 0; }
|
|
7379
|
+
.dim-panel .dim-botMetric { min-width: 0; padding: 8px; border: 0; border-radius: 9px; background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
7370
7380
|
.dim-panel .dim-botMetric dt { margin: 0; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; font-weight: 400; line-height: normal; }
|
|
7371
7381
|
.dim-panel .dim-botMetric dd { overflow: hidden; margin: 5px 0 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 13px; font-weight: 400; line-height: normal; text-overflow: ellipsis; white-space: nowrap; }
|
|
7372
7382
|
.dim-panel .dim-botCard .dim-cardFooter { margin-top: 0; }
|
|
@@ -7403,6 +7413,7 @@ var CSS10 = String.raw`
|
|
|
7403
7413
|
@media (max-width: 560px) {
|
|
7404
7414
|
.dim-title { flex-direction: column; gap: 10px; }
|
|
7405
7415
|
.dim-title p { white-space: normal; }
|
|
7416
|
+
.dim-githubTooltip { right: auto; left: 0; }
|
|
7406
7417
|
.dim-rail { grid-template-columns: minmax(0, 1fr); }
|
|
7407
7418
|
}
|
|
7408
7419
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -7426,6 +7437,7 @@ function installImStyles() {
|
|
|
7426
7437
|
// plugin-src/client/index.js
|
|
7427
7438
|
var name = "im-settings";
|
|
7428
7439
|
var inject = ["slots", "connection", "locale"];
|
|
7440
|
+
var IM_PLUGIN_LOGO_URL = "data:image/png;base64,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";
|
|
7429
7441
|
var CHANNELS = Object.freeze([
|
|
7430
7442
|
{ id: "weixin", label: "\u5FAE\u4FE1" },
|
|
7431
7443
|
{ id: "feishu", label: "\u98DE\u4E66" },
|
|
@@ -7515,6 +7527,7 @@ function IMSettingsTab({
|
|
|
7515
7527
|
whatsappRpcCall
|
|
7516
7528
|
}) {
|
|
7517
7529
|
const [selected, setSelected] = React13.useState("weixin");
|
|
7530
|
+
const githubTooltipId = React13.useId();
|
|
7518
7531
|
const active = CHANNELS.find((channel4) => channel4.id === selected) ?? CHANNELS[0];
|
|
7519
7532
|
return h2(
|
|
7520
7533
|
"section",
|
|
@@ -7522,7 +7535,40 @@ function IMSettingsTab({
|
|
|
7522
7535
|
h2(
|
|
7523
7536
|
"header",
|
|
7524
7537
|
{ className: "dim-title" },
|
|
7525
|
-
h2(
|
|
7538
|
+
h2(
|
|
7539
|
+
"div",
|
|
7540
|
+
{ className: "dim-brand" },
|
|
7541
|
+
h2("img", {
|
|
7542
|
+
className: "dim-brandLogo",
|
|
7543
|
+
src: IM_PLUGIN_LOGO_URL,
|
|
7544
|
+
alt: "dsh-im",
|
|
7545
|
+
width: 48,
|
|
7546
|
+
height: 48
|
|
7547
|
+
}),
|
|
7548
|
+
h2("p", null, "\u8BA9\u804A\u5929\u673A\u5668\u4EBA\u8F7B\u677E\u63A5\u5165 DeepSeek Harness")
|
|
7549
|
+
),
|
|
7550
|
+
h2(
|
|
7551
|
+
"span",
|
|
7552
|
+
{ className: "dim-githubAction" },
|
|
7553
|
+
h2(
|
|
7554
|
+
"a",
|
|
7555
|
+
{
|
|
7556
|
+
className: "dim-githubLink",
|
|
7557
|
+
href: "https://github.com/xmanrui/dsh-im",
|
|
7558
|
+
target: "_blank",
|
|
7559
|
+
rel: "noopener noreferrer",
|
|
7560
|
+
"aria-label": "dsh-im GitHub",
|
|
7561
|
+
"aria-describedby": githubTooltipId
|
|
7562
|
+
},
|
|
7563
|
+
h2("span", null, "GitHub"),
|
|
7564
|
+
h2("span", { className: "dim-githubArrow", "aria-hidden": "true" }, "\u2197")
|
|
7565
|
+
),
|
|
7566
|
+
h2("span", {
|
|
7567
|
+
id: githubTooltipId,
|
|
7568
|
+
className: "dim-githubTooltip",
|
|
7569
|
+
role: "tooltip"
|
|
7570
|
+
}, "\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub")
|
|
7571
|
+
)
|
|
7526
7572
|
),
|
|
7527
7573
|
h2(
|
|
7528
7574
|
"div",
|
package/lib/index.js
CHANGED
|
@@ -64,7 +64,7 @@ ${R}`),f.pop(),`{${H}}`}case"number":return isFinite(Q)?String(Q):a?a(Q):"null";
|
|
|
64
64
|
`).trim()}var jm=class{#A;#e;#t=null;#a=null;#n=new Map;#s="";#I=!1;#g=null;constructor({promptRpcId:a,afterSeq:o=-1}){this.#A=a,this.#e=o}get finished(){return this.#I}get answer(){return this.#s.trim()}get reason(){return this.#g}consume(a){let o=null,i=[...a].map(e=>e?.event??e).filter(Boolean).sort((e,r)=>(e.seq??-1)-(r.seq??-1));for(let e of i){let r=e.seq??-1;if(!(r<=this.#e)){if(this.#e=r,e.type==="turn/start"&&(this.#t=e.data?.turn??null),e.type==="user/message"&&e.data?.source?.rpcId===this.#A){this.#a=this.#t;continue}if(this.#a!==null){if(e.type==="turn/end"){if(e.data?.turn!==this.#a)continue;this.#I=!0,this.#g=e.data?.reason??null,this.#t=null;continue}if(e.data?.turn===this.#a){if(e.type==="assistant/chunk"&&e.data?.chunk?.type==="text-delta"){let A=e.data?.step??0,t=e.data.chunk.index??0,s=`${A}:${t}`;this.#n.set(s,(this.#n.get(s)??"")+e.data.chunk.text);let g=`${A}:`,c=[...this.#n.entries()].filter(([l])=>l.startsWith(g)).sort(([l],[C])=>Number(l.split(":")[1])-Number(C.split(":")[1])).map(([,l])=>l).join(`
|
|
65
65
|
`).trim();c&&c!==this.#s&&(this.#s=c,o={type:"text",text:c});continue}if(e.type==="assistant/message"){let A=i$(e);A&&A!==this.#s&&(this.#s=A,o={type:"text",text:A});continue}e.type==="tool/call"?o={type:"tool",name:e.data?.name??"\u5DE5\u5177"}:e.type==="tool/result"&&(o={type:"status",text:"\u6B63\u5728\u6574\u7406\u7ED3\u679C\u2026"})}}}}return o}},Bh=class extends Error{constructor(a,o){super(`${a}: ${o?.message??"unknown Harness RPC error"}`),this.name="HarnessRpcError",this.method=a,this.code=o?.code??"internal",this.details=o?.details??{}}},uh=class{#A;#e;#t;#a;#n;#s;#I=null;constructor({baseUrl:a,workspace:o,agentPreset:i="standard",autostart:e=!1,dshBin:r="dsh",fetchImpl:A=fetch}){this.#A=new URL(a),this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A}async rpc(a,o={},i=3e4,e={}){let r=e.rpcId??`dingtalk-${uv()}`,A=AbortSignal.timeout(i),t=e.signal?AbortSignal.any([e.signal,A]):A,s=await this.#s(new URL(`/api/${a}`,this.#A),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-request",rpcId:r,method:a,payload:o}),signal:t});if(!s.ok)throw new Error(`Harness transport ${a} failed: HTTP ${s.status}`);let g=await s.json();if(g?.type!=="server-response"||g?.rpcId!==r)throw new Error(`Harness returned an invalid response for ${a}`);if(!g.result?.ok)throw new Bh(a,g.result?.error);return g.result.value}async health(a={}){return await this.rpc("host.describe",{},5e3,a),!0}async ensureRunning(a={}){try{return await this.health(a)}catch(e){if(!this.#a)throw e}if(!this.#I||this.#I.exitCode!==null){let e=this.#A.port||(this.#A.protocol==="https:"?"443":"80");this.#I=r$(this.#n,["web","--host",this.#A.hostname,"--port",e],{cwd:this.#e,env:process.env,stdio:["ignore","inherit","inherit"]}),this.#I.on("error",r=>{console.error("[dsh-dingtalk] failed to start Harness:",r.message)})}let o=Date.now()+6e4,i;for(;Date.now()<o;){await Qv(1e3,a.signal);try{return await this.health(a)}catch(e){i=e}}throw new Error(`Harness did not become ready: ${i?.message??"timeout"}`)}async workspaceId(a={}){let{items:o}=await this.rpc("workspace.list",{},3e4,a),i=o.find(r=>r.path===this.#e);return i?i.workspaceId:(await this.rpc("workspace.create",{path:this.#e},3e4,a)).workspace.workspaceId}async createSession(a={}){await this.ensureRunning(a);let o=await this.workspaceId(a);return(await this.rpc("session.create",{workspaceId:o,agentPreset:this.#t},3e4,a)).sessionId}async sessionExists(a,o={}){try{return await this.rpc("session.history",{sessionId:a,maxMessages:1},3e4,o),!0}catch(i){if(i instanceof Bh&&i.code==="session-not-found")return!1;throw i}}async ask(a,o,i={}){typeof i=="number"&&(i={timeoutMs:i});let e=i.timeoutMs??6e5,r=i.signal,A=typeof i.onUpdate=="function"?i.onUpdate:null;await this.ensureRunning({signal:r});let t=await this.rpc("session.history",{sessionId:a,maxMessages:1},3e4,{signal:r}),s=Math.max(-1,...(t.events??[]).map(({event:C})=>C.seq??-1)),g=`dingtalk-${uv()}`,c=new jm({promptRpcId:g,afterSeq:s});await this.rpc("session.prompt",{sessionId:a,mode:"queue",content:[{type:"text",text:o}],clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,{rpcId:g,signal:r});let l=Date.now()+e;for(;Date.now()<l;){await Qv(300,r);let C=await this.rpc("session.history",{sessionId:a,maxMessages:50},3e4,{signal:r}),u=c.consume(C.events??[]);if(u&&A)try{await A(u)}catch(Q){console.warn("[dsh-dingtalk] ignored a progress update failure:",Q.message)}if(c.finished){if(c.answer)return c.answer;throw new Error(`Harness turn ended without a text reply${c.reason?` (${JSON.stringify(c.reason)})`:""}`)}}throw new Error(`Harness reply timed out after ${Math.round(e/1e3)} seconds`)}stopManagedProcess(){this.#I?.exitCode===null&&this.#I.kill("SIGTERM")}};import{randomUUID as o$}from"node:crypto";import{mkdir as n$,readFile as s$,rename as g$,unlink as c$,writeFile as I$}from"node:fs/promises";import{dirname as l$}from"node:path";var Qh=Object.freeze({version:1,sessions:{},seenMessageIds:[],pendingSenders:{}});function _t(n){return typeof n=="string"&&n.trim()?n.trim():null}function fv(n){return(_t(n)??"\u9489\u9489\u7528\u6237").slice(0,100)}function E$(n,a){if(!n||typeof n!="object")return null;let o=_t(n.requestId)??_t(a),i=_t(n.staffId),e=_t(n.requestedAt)??_t(n.lastSeenAt),r=_t(n.lastSeenAt)??e;return!o||!i||!e||!r?null:{requestId:o,staffId:i,displayName:fv(n.displayName??n.nick),requestedAt:e,lastSeenAt:r}}function C$(n){if(!n||typeof n!="object")return structuredClone(Qh);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[e,r]of Object.entries(n.sessions)){let A=_t(e),t=_t(r);A&&t&&(a[A]=t)}let o={},i=Array.isArray(n.pendingSenders)?n.pendingSenders.map(e=>[e?.requestId,e]):Object.entries(n.pendingSenders&&typeof n.pendingSenders=="object"?n.pendingSenders:{});for(let[e,r]of i){let A=E$(r,e);if(!A)continue;let t=Object.values(o).find(s=>s.staffId===A.staffId);(!t||t.lastSeenAt<A.lastSeenAt)&&(t&&delete o[t.requestId],o[A.requestId]=A)}return{version:1,sessions:a,seenMessageIds:Array.isArray(n.seenMessageIds)?[...new Set(n.seenMessageIds.map(_t).filter(Boolean))].slice(-1e3):[],pendingSenders:o}}var fh=class{#A;#e=structuredClone(Qh);#t=Promise.resolve();#a;#n;constructor(a,{idFactory:o=o$,now:i=()=>new Date().toISOString()}={}){if(!_t(a))throw new TypeError("state path is required");if(typeof o!="function"||typeof i!="function")throw new TypeError("idFactory and now must be functions");this.#A=a,this.#a=o,this.#n=i}async load(){try{this.#e=C$(JSON.parse(await s$(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(Qh),await this.#s()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){let i=_t(a),e=_t(o);if(!i||!e)throw new TypeError("key and sessionId are required");this.#e.sessions[i]=e,await this.#s()}async clearSession(a){let o=_t(a);!o||!(o in this.#e.sessions)||(delete this.#e.sessions[o],await this.#s())}hasSeen(a){let o=_t(a);return!!(o&&this.#e.seenMessageIds.includes(o))}async markSeen(a){let o=_t(a);if(!o)throw new TypeError("messageId is required");this.hasSeen(o)||(this.#e.seenMessageIds.push(o),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#s())}pendingSenders(){return Object.values(this.#e.pendingSenders).sort((a,o)=>a.requestedAt.localeCompare(o.requestedAt)).map(a=>structuredClone(a))}pendingSender(a){let o=_t(a),i=o?this.#e.pendingSenders[o]:null;return i?structuredClone(i):null}async recordPendingSender(a,o,i){let e=a&&typeof a=="object"?a:{staffId:a,displayName:o,lastSeenAt:i},r=_t(e.staffId);if(!r)throw new TypeError("staffId is required");let A=_t(e.lastSeenAt)??_t(e.requestedAt)??this.#n(),t=Object.values(this.#e.pendingSenders).find(g=>g.staffId===r),s={requestId:t?.requestId??`ding_sender_${this.#a()}`,staffId:r,displayName:fv(e.displayName??e.nick??o),requestedAt:t?.requestedAt??A,lastSeenAt:A};return this.#e.pendingSenders[s.requestId]=s,await this.#s(),structuredClone(s)}async removePendingSender(a){let o=_t(a);return!o||!this.#e.pendingSenders[o]?!1:(delete this.#e.pendingSenders[o],await this.#s(),!0)}async removePendingSenderByStaffId(a){let o=_t(a),i=o?Object.values(this.#e.pendingSenders).find(e=>e.staffId===o):null;return i?this.removePendingSender(i.requestId):!1}snapshot(){return structuredClone(this.#e)}async remove(){await this.#t;try{await c$(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(Qh)}async#s(){let a=`${JSON.stringify(this.#e,null,2)}
|
|
66
66
|
`,o=this.#t.then(async()=>{await n$(l$(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await I$(i,a,{encoding:"utf8",mode:384}),await g$(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};var yv=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function p$(n){if(!Array.isArray(n)||n.length===0)return[...yv];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...yv]}var yh=class{#A;#e;#t;#a;#n;#s;#I;#g=null;#o=null;#i=0;#r=!1;#c=!1;#l;#E;constructor({controller:a,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:r=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!a||typeof a.initialize!="function"||typeof a.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=p$(e),this.#n=Number.isFinite(r)&&r>=0?r:15e3,this.#s=A,this.#I=t,this.#l=new Promise(s=>{this.#E=s})}get ready(){return this.#l}start(){return this.#c||this.#r?this:(this.#c=!0,this.#C(0),this)}async close(){this.#r||(this.#r=!0,this.#g!==null&&this.#I(this.#g),this.#g=null,await this.#o?.catch(()=>{}),this.#E?.(null),this.#E=null)}#C(a){this.#r||(this.#g=this.#s(()=>{this.#g=null,this.#p()},a),this.#g?.unref?.())}async#p(){if(this.#r||this.#o)return;let a=this.#h();this.#o=a;try{await a}finally{this.#o===a&&(this.#o=null)}}async#h(){try{if(await this.#e.ensureRunning(),this.#r)return;let a=await this.#A.initialize();if(this.#r)return;this.#E?.(a),this.#E=null;let{configured:o,connected:i}=a.totals;if(i<o){let e=this.#a[Math.min(this.#i,this.#a.length-1)];this.#i+=1,this.#t.warn?.(`[dsh-dingtalk] ${i}/${o} bots connected; retrying in ${e}ms`),this.#C(e);return}this.#i=0,this.#C(this.#n)}catch(a){if(this.#r)return;let o=this.#a[Math.min(this.#i,this.#a.length-1)];this.#i+=1,this.#t.warn?.(`[dsh-dingtalk] connection reconciliation failed; retrying in ${o}ms`,a),this.#C(o)}}};function qm(n){return new yh(n)}function B$(n,a){if(a!==void 0)return new URL(a);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-dingtalk requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function u$(n){let a=Ac(n.dshHome??process.env.DSH_HOME??mh(d$(),".dsh")),o=Ac(n.dataDir??mh(a,"integrations","dsh-dingtalk"));return{root:o,config:Ac(n.configPath??mh(o,"config.json")),bots:Ac(n.botsDir??mh(o,"bots"))}}async function Vm(n,a={},o={}){if(!n?.credentials)throw new TypeError("dsh-dingtalk requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-dingtalk requires ctx.webServer");let i=o.ConfigStore??Ih,e=o.DeviceAuth??Eh,r=o.StateStore??fh,A=o.HarnessClient??uh,t=o.Controller??kl,s=o.Runtime??Fl,g=o.createConnectionSupervisor??qm,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,l=u$(a),C=await new i(l.config).load(),u=o.deviceAuth??new e({baseUrl:a.registrationBaseUrl}),Q=new Map,f=k=>Ac(l.bots,k,"state.json"),y=async k=>{let U=Q.get(k);return U||(U=await new r(f(k)).load(),Q.set(k,U)),U},m=new A({baseUrl:B$(n.webServer,a.harnessBaseUrl),workspace:Ac(a.workspace??process.cwd()),agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),R=new t({deviceAuth:u,credentials:n.credentials,configStore:C,logger:c,createRuntime:async({botId:k,config:U,clientSecret:H})=>{let F=await y(k);return new s({config:U,clientSecret:H,harness:m,state:F,replyTimeoutMs:a.replyTimeoutMs??6e5,maxMessageChars:a.maxMessageChars??4e3,connectTimeoutMs:a.connectTimeoutMs??15e3,logger:{error:(...q)=>c.error?.(`[${k}]`,...q),warn:(...q)=>c.warn?.(`[${k}]`,...q),info:(...q)=>c.info?.(`[${k}]`,...q),debug:(...q)=>c.debug?.(`[${k}]`,...q)}})},deleteState:async({botId:k})=>{let U=Q.get(k);if(Q.delete(k),U&&typeof U.remove=="function"){await U.remove();return}try{await h$(f(k))}catch(H){if(H?.code!=="ENOENT")throw H}}}),N=g({controller:R,harness:m,logger:c,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:R,ready:N.ready,async close(){await N.close(),await R.close(),m.stopManagedProcess()}}}import f$ from"qrcode";var Q$=new Set(["loopback","trusted-host"]);function Ra(n){if(n===void 0)return"loopback";if(Q$.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}var Sv="/dingtalk",Vt=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),Dv=Object.freeze(Object.values(Vt)),y$=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function Wm(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Bn(n,a){return Wm(n)&&Object.keys(n).every(o=>a.includes(o))}function Ms(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function mv(n,a){return typeof n=="string"&&n.trim().length>0&&n.length<=a}function m$(n,a){return Wm(a)?n===Vt.status?Bn(a,[])?null:"connection.status does not accept fields.":n===Vt.beginProvisioning?Bn(a,["locale"])&&(a.locale===void 0||a.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Vt.pollProvisioning,Vt.cancelProvisioning].includes(n)?Bn(a,["attemptId"])&&Ms(a.attemptId)?null:`${n} requires an attemptId.`:n===Vt.bindCredentials?Bn(a,["clientId","clientSecret"])&&mv(a.clientId,256)&&mv(a.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===Vt.reconnectBot?Bn(a,["botId"])&&Ms(a.botId)?null:"bot.reconnect requires a botId.":n===Vt.deleteBot?Bn(a,["botId","confirm"])&&Ms(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===Vt.approveSender?Bn(a,["botId","requestId","confirm"])&&Ms(a.botId)&&Ms(a.requestId)&&a.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===Vt.revokeSender?Bn(a,["botId","senderKey","confirm"])&&Ms(a.botId)&&Ms(a.senderKey)&&a.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function Sh(n){return{ok:!1,error:{code:"bad-request",message:n}}}function Dh(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function S$(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function ac(n){if(Array.isArray(n))return n.map(ac);if(!Wm(n))return n;let a={};for(let[o,i]of Object.entries(n))y$.has(o)||(a[o]=ac(i));return a}async function D$(n){return f$.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function zm(n,a){return!n||typeof n.verificationUrl!="string"?ac(n):ac({...n,qrCodeDataUrl:await a(n.verificationUrl)})}async function tc(n,a){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await zm(o.provisioning,a)),ac(o)}function w$(n){for(let a of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[a]!="function")throw new TypeError(`A complete DingTalk controller is required (${a})`)}function wv(n,{encodeQr:a=D$}={}){w$(n);let o=new Map,i=e=>{let r=o.get(e);return r||(o.size>=16&&o.delete(o.keys().next().value),r=Promise.resolve().then(()=>a(e)),o.set(e,r)),r};return async(e,r,A)=>{if(A?.aborted)return Dh();if(!Dv.includes(e))return Sh("Unknown DingTalk endpoint.");let t=m$(e,r);if(t)return Sh(t);try{let s;if(e===Vt.status)s=await tc(await n.status(),i);else if(e===Vt.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),Dh();s=await zm(g,i)}else if(e===Vt.pollProvisioning){let g=await n.registrationStatus(r.attemptId);if(!g)return Sh("The provisioning attempt no longer exists.");s=await zm(g,i)}else if(e===Vt.cancelProvisioning){if(s=await n.cancelProvisioning(r.attemptId),!s)return Sh("The provisioning attempt no longer exists.");s=ac(s)}else e===Vt.bindCredentials?s=await tc(await n.bindCredentials(r),i):e===Vt.reconnectBot?s=await tc(await n.reconnectBot(r.botId),i):e===Vt.deleteBot?s=await tc(await n.deleteBot(r.botId),i):e===Vt.approveSender?s=await tc(await n.approveSender(r.botId,r.requestId),i):s=await tc(await n.revokeSender(r.botId,r.senderKey),i);return A?.aborted?Dh():{ok:!0,value:s}}catch{return A?.aborted?Dh():S$()}}}function wh(n,a,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(Sv,wv(a,o),{authority:Ra(i)})}async function Ov(n,a={}){if(a?.controller)return wh(n,a.controller,a.rpcOptions,a.rpcAuthority);let o=await Vm(n,a,a.internals),i=wh(n,o.controller,a.rpcOptions,a.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as O$}from"node:crypto";import{mkdir as M$,readFile as b$,rename as _$,unlink as N$,writeFile as T$}from"node:fs/promises";import{dirname as R$}from"node:path";var Zm=Object.freeze({version:1,bots:Object.freeze([])});function Oo(n){return typeof n=="string"&&n.trim()?n.trim():null}function Mv(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Ll(n,{botPrefix:a,tokenRefPrefix:o}){let i=Oo(n);if(!i)throw new TypeError("platformId is required");let e=O$("sha256").update(i).digest("hex").slice(0,24);return{botId:`${a}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function Oh(n,a){let o=Oo(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:a:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var rc=class{#A;#e;#t;#a;#n;#s;#I=Zm;#g=Promise.resolve();constructor(a,{channel:o,botPrefix:i,tokenRefPrefix:e}){this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=new RegExp(`^${Mv(i)}_[a-f0-9]{24}$`),this.#s=new RegExp(`^${Mv(e)}_[A-F0-9]{24}$`)}async load(){try{let a=this.#i(JSON.parse(await b$(this.#A,"utf8")));if(!a)throw new Error(`dsh-im ${this.#e} config contains invalid bot data`);this.#I=a}catch(a){if(a?.code!=="ENOENT")throw a;this.#I=Zm}return this}list(){return structuredClone(this.#I.bots)}get(a){let o=this.#I.bots.find(i=>i.botId===a);return o?structuredClone(o):null}getByPlatformId(a){let o=this.#I.bots.find(i=>i.platformId===a);return o?structuredClone(o):null}async save(a){let o=this.#o(a);if(!o)throw new Error(`Refusing to persist incomplete ${this.#e} bot data`);return this.#r(i=>{let e=i.find(t=>t.platformId===o.platformId&&t.botId!==o.botId),r=i.find(t=>t.tokenRef===o.tokenRef&&t.botId!==o.botId);if(e||r)throw new Error(`Duplicate ${this.#e} bot identity`);let A=i.findIndex(t=>t.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(a){if(!this.#n.test(a))throw new TypeError(`Invalid ${this.#e} bot id`);return this.#r(o=>{let i=o.findIndex(r=>r.botId===a);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let a=this.#g.then(async()=>{try{await N$(this.#A)}catch(o){if(o?.code!=="ENOENT")throw o}this.#I=Zm});this.#g=a.then(()=>{},()=>{}),await a}#o(a){if(!a||typeof a!="object")return null;let o=Oo(a.platformId),i=Oo(a.botId),e=Oo(a.tokenRef),r=Oo(a.name);if(!o||!i||!e||!r||!this.#n.test(i)||!this.#s.test(e))return null;let A=Ll(o,{botPrefix:this.#t,tokenRefPrefix:this.#a});return A.botId!==i||A.tokenRef!==e?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:r,username:Oo(a.username),createdAt:Oo(a.createdAt)??new Date().toISOString(),connectedAt:Oo(a.connectedAt)})}#i(a){if(!a||a.version!==1||!Array.isArray(a.bots))return null;let o=a.bots.map(A=>this.#o(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,r=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||r.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),r.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#r(a){let o,i=this.#g.then(async()=>{let e=[...this.#I.bots];o=a(e);let r=Object.freeze({version:1,bots:Object.freeze(e)});await this.#c(r),this.#I=r});return this.#g=i.then(()=>{},()=>{}),await i,o}async#c(a){await M$(R$(this.#A),{recursive:!0,mode:448});let o=`${this.#A}.tmp`;await T$(o,`${JSON.stringify(a,null,2)}
|
|
67
|
-
`,{encoding:"utf8",mode:384}),await _$(o,this.#A)}};var bv=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function _v(n){return Ll(n,bv)}function Nv(n){return Oh(n,"Discord\u673A\u5668\u4EBA")}var Mh=class extends rc{constructor(a){super(a,{channel:"Discord",...bv})}};function Ul(n){return typeof n=="string"&&n.trim()?n.trim():null}function bh(n,a){return Object.freeze({code:n,message:a})}var ic=class{#A;#e;#t;#a;#n;#s;#I;#g;#o;#i=new Map;#r=new Map;#c=new Map;#l=0;#E=!1;constructor({descriptor:a,credentials:o,configStore:i,inspectToken:e,deriveIdentity:r,maskPlatformId:A,createRuntime:t,deleteState:s=async()=>{},logger:g=console}){if(!a?.key||!a?.label||!a?.connectionLabel)throw new TypeError("TokenBotController requires a channel descriptor");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError(`${a.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${a.label} requires a config store`);if(typeof e!="function"||typeof r!="function"||typeof A!="function"||typeof t!="function")throw new TypeError(`${a.label} controller dependencies are incomplete`);this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t,this.#g=s,this.#o=g}async initialize(){if(this.#E)return this.status();for(let a of this.#t.list())await this.#u(a.botId,async()=>{if(this.#E||this.#i.get(a.botId)?.status?.ready)return;let o=await this.#h(a.tokenRef);if(!o){this.#r.set(a.botId,bh("missing-token",`${this.#A.label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002`));return}try{await this.#C(a,o),this.#r.delete(a.botId)}catch(i){this.#r.set(a.botId,bh("connection-failed",`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002`)),this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${a.botId} failed to initialize:`,i)}finally{this.#B()}});return this.status()}async bindCredentials({token:a}={}){if(this.#E)throw new Error(`${this.#A.label} controller is closed`);let o=Ul(a);if(!o)throw new TypeError(`${this.#A.label} Bot Token is required`);let i=await this.#a(o),e=Ul(i?.platformId),r=Ul(i?.name);if(!e||!r)throw new Error(`${this.#A.label} returned an invalid bot identity`);let A=this.#n(e);return await this.#u(A.botId,async()=>{if(this.#E)throw new Error(`${this.#A.label} controller is closed`);let t=this.#t.getByPlatformId(e),s=await this.#e.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:r,username:Ul(i.username),createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#e.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#d(A.tokenRef,s),c}try{await this.#C(g,o),this.#r.delete(A.botId)}catch(c){this.#r.set(A.botId,bh("connection-failed",`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002`)),this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${A.botId} credential connection failed:`,c)}this.#B()}),this.status()}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#u(a,async()=>{let i=await this.#h(o.tokenRef);if(!i)throw new Error(`${this.#A.label} bot token is missing`);try{await this.#C(o,i),this.#r.delete(a)}catch(e){throw this.#r.set(a,bh("connection-failed",`${this.#A.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),e}finally{this.#B()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#u(a,async()=>{let i=await this.#e.resolve(o.tokenRef).catch(()=>{});await this.#p(a);try{await this.#e.unset(o.tokenRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.tokenRef,i.value).catch(()=>{}),await this.#C(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#A.label} bot safely.`,{cause:e})}await this.#g({botId:a,config:o}).catch(e=>{this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${a} state cleanup failed:`,e)}),this.#r.delete(a),this.#B()}),this.status()}status(){let a=this.#t.list().map(i=>{let e=this.#i.get(i.botId)?.status??null,r=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=r?"connected":e?.connectionState==="connecting"?"connecting":this.#r.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:r,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#s(i.platformId)},health:{status:r?"healthy":A==="error"?"error":"offline",summary:r?`${this.#A.label}${this.#A.connectionLabel}\u8FD0\u884C\u6B63\u5E38`:A==="error"?`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5`:`${this.#A.label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF`,lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},error:structuredClone(this.#r.get(i.botId)??null)}}),o=a.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#l,state:a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o}}}async close(){this.#E||(this.#E=!0,await Promise.allSettled([...this.#c.values()]),await Promise.allSettled([...this.#i.keys()].map(a=>this.#p(a))))}async#C(a,o){if(this.#E)throw new Error(`${this.#A.label} controller is closed`);if(await this.#p(a.botId),this.#E)throw new Error(`${this.#A.label} controller is closed`);let i=await this.#I({botId:a.botId,config:a,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#A.label} runtime`);this.#i.set(a.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#i.delete(a.botId),e}}async#p(a){let o=this.#i.get(a);this.#i.delete(a),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${a} failed to stop cleanly:`,i)})}async#h(a){let o=await this.#e.resolve(a).catch(()=>{});return Ul(o?.value)}async#d(a,o){o?.value?await this.#e.set(a,o.value).catch(()=>{}):await this.#e.unset(a).catch(()=>{})}#u(a,o){let r=(this.#c.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#c.get(a)===r&&this.#c.delete(a)});return this.#c.set(a,r),r}#B(){this.#l+=1}};var k$="https://discord.com/api/v10/";function Hl(n){return typeof n=="string"&&n.trim()?n.trim():null}function v$(n,a){let o=AbortSignal.timeout(a);return n?AbortSignal.any([n,o]):o}function P$(n,a){return new Promise((o,i)=>{if(a?.aborted){i(a.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),a?.addEventListener("abort",()=>{clearTimeout(e),i(a.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function oc(n,a){let o=Hl(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${a}`);return o}function G$(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var Kl=class{#A;#e;#t;constructor({token:a,fetchImpl:o=fetch,baseUrl:i=k$}){if(!G$(a))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#A=a.trim(),this.#e=o,this.#t=new URL(i)}getCurrentUser(a={}){return this.#a("users/@me",{...a,method:"GET"})}getGatewayBot(a={}){return this.#a("gateway/bot",{...a,method:"GET"})}createMessage({channelId:a,content:o,replyToMessageId:i,signal:e}){return this.#a(`channels/${oc(a,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:oc(i,"message id"),channel_id:oc(a,"channel id"),fail_if_not_exists:!1}}:{}}})}editMessage({channelId:a,messageId:o,content:i,signal:e}){return this.#a(`channels/${oc(a,"channel id")}/messages/${oc(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:a,signal:o}){return this.#a(`channels/${oc(a,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async#a(a,{method:o,body:i,signal:e,timeoutMs:r=15e3,expectBody:A=!0,retry:t=!0}){let s;try{s=await this.#e(new URL(a,this.#t),{method:o,headers:{authorization:`Bot ${this.#A}`,"content-type":"application/json","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.3.0)"},...i===void 0?{}:{body:JSON.stringify(i)},signal:v$(e,r),redirect:"error"})}catch(c){throw c?.name==="AbortError"||c?.name==="TimeoutError"?c:new Error(`Discord ${o} transport failed`)}let g=null;if(A||s.status===429||!s.ok)try{g=await s.json()}catch{if(A)throw new Error(`Discord ${o} returned invalid JSON`)}if(s.status===429&&t){let c=Math.min(1e4,Math.max(50,Number(g?.retry_after)*1e3||1e3));return await P$(c,e),this.#a(a,{method:o,body:i,signal:e,timeoutMs:r,expectBody:A,retry:!1})}if(!s.ok){let c=new Error(Hl(g?.message)??`Discord API failed with HTTP ${s.status}`);throw c.code=`discord-${s.status}`,c}return A?g:null}};async function Tv(n,a={}){let i=await new Kl({token:n,...a}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:Hl(i.global_name)??Hl(i.username)??"Discord\u673A\u5668\u4EBA",username:Hl(i.username)}}function _h(n){return typeof n=="string"?n.trim():""}function lr(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var Ri=class{#A;#e;#t;#a;#n;#s;#I;#g=new Map;constructor({descriptor:a,bot:o,harness:i,state:e,status:r=lr(),logger:A=console,replyTimeoutMs:t=6e5}){if(!a?.key||!a?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t}get status(){return structuredClone(this.#n)}accept(a){let o=_h(a?.conversationId),i=a?.kind==="group"?"group":"direct",e=`${i}:${o}`,A=(this.#g.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#o({...a,kind:i,conversationId:o})).finally(()=>{this.#g.get(e)===A&&this.#g.delete(e)});return this.#g.set(e,A),A}async waitForIdle(){await Promise.allSettled([...this.#g.values()])}async#o(a){let o=_h(a.messageId),i=_h(a.senderId);if(!o||!i||!a.conversationId||a.senderIsBot===!0||this.#a.hasSeen(o))return;if(this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString(),a.kind==="group"&&a.addressed!==!0){this.#n.messagesRejected+=1,this.#n.lastRejectedAt=new Date().toISOString();return}let e=a.replyTarget,r=_h(a.content);try{if(!r){await this.#e.sendText(e,"\u76EE\u524D\u4EC5\u652F\u6301\u6587\u5B57\u6D88\u606F\u3002"),await this.#a.markSeen(o);return}let A=r.toLowerCase();if(A==="/help"){await this.#e.sendText(e,[`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002`,"","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(`
|
|
67
|
+
`,{encoding:"utf8",mode:384}),await _$(o,this.#A)}};var bv=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function _v(n){return Ll(n,bv)}function Nv(n){return Oh(n,"Discord\u673A\u5668\u4EBA")}var Mh=class extends rc{constructor(a){super(a,{channel:"Discord",...bv})}};function Ul(n){return typeof n=="string"&&n.trim()?n.trim():null}function bh(n,a){return Object.freeze({code:n,message:a})}var ic=class{#A;#e;#t;#a;#n;#s;#I;#g;#o;#i=new Map;#r=new Map;#c=new Map;#l=0;#E=!1;constructor({descriptor:a,credentials:o,configStore:i,inspectToken:e,deriveIdentity:r,maskPlatformId:A,createRuntime:t,deleteState:s=async()=>{},logger:g=console}){if(!a?.key||!a?.label||!a?.connectionLabel)throw new TypeError("TokenBotController requires a channel descriptor");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError(`${a.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${a.label} requires a config store`);if(typeof e!="function"||typeof r!="function"||typeof A!="function"||typeof t!="function")throw new TypeError(`${a.label} controller dependencies are incomplete`);this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t,this.#g=s,this.#o=g}async initialize(){if(this.#E)return this.status();for(let a of this.#t.list())await this.#u(a.botId,async()=>{if(this.#E||this.#i.get(a.botId)?.status?.ready)return;let o=await this.#h(a.tokenRef);if(!o){this.#r.set(a.botId,bh("missing-token",`${this.#A.label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002`));return}try{await this.#C(a,o),this.#r.delete(a.botId)}catch(i){this.#r.set(a.botId,bh("connection-failed",`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002`)),this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${a.botId} failed to initialize:`,i)}finally{this.#B()}});return this.status()}async bindCredentials({token:a}={}){if(this.#E)throw new Error(`${this.#A.label} controller is closed`);let o=Ul(a);if(!o)throw new TypeError(`${this.#A.label} Bot Token is required`);let i=await this.#a(o),e=Ul(i?.platformId),r=Ul(i?.name);if(!e||!r)throw new Error(`${this.#A.label} returned an invalid bot identity`);let A=this.#n(e);return await this.#u(A.botId,async()=>{if(this.#E)throw new Error(`${this.#A.label} controller is closed`);let t=this.#t.getByPlatformId(e),s=await this.#e.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:r,username:Ul(i.username),createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#e.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#d(A.tokenRef,s),c}try{await this.#C(g,o),this.#r.delete(A.botId)}catch(c){this.#r.set(A.botId,bh("connection-failed",`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002`)),this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${A.botId} credential connection failed:`,c)}this.#B()}),this.status()}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#u(a,async()=>{let i=await this.#h(o.tokenRef);if(!i)throw new Error(`${this.#A.label} bot token is missing`);try{await this.#C(o,i),this.#r.delete(a)}catch(e){throw this.#r.set(a,bh("connection-failed",`${this.#A.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),e}finally{this.#B()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#u(a,async()=>{let i=await this.#e.resolve(o.tokenRef).catch(()=>{});await this.#p(a);try{await this.#e.unset(o.tokenRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.tokenRef,i.value).catch(()=>{}),await this.#C(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#A.label} bot safely.`,{cause:e})}await this.#g({botId:a,config:o}).catch(e=>{this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${a} state cleanup failed:`,e)}),this.#r.delete(a),this.#B()}),this.status()}status(){let a=this.#t.list().map(i=>{let e=this.#i.get(i.botId)?.status??null,r=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=r?"connected":e?.connectionState==="connecting"?"connecting":this.#r.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:r,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#s(i.platformId)},health:{status:r?"healthy":A==="error"?"error":"offline",summary:r?`${this.#A.label}${this.#A.connectionLabel}\u8FD0\u884C\u6B63\u5E38`:A==="error"?`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5`:`${this.#A.label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF`,lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},error:structuredClone(this.#r.get(i.botId)??null)}}),o=a.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#l,state:a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o}}}async close(){this.#E||(this.#E=!0,await Promise.allSettled([...this.#c.values()]),await Promise.allSettled([...this.#i.keys()].map(a=>this.#p(a))))}async#C(a,o){if(this.#E)throw new Error(`${this.#A.label} controller is closed`);if(await this.#p(a.botId),this.#E)throw new Error(`${this.#A.label} controller is closed`);let i=await this.#I({botId:a.botId,config:a,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#A.label} runtime`);this.#i.set(a.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#i.delete(a.botId),e}}async#p(a){let o=this.#i.get(a);this.#i.delete(a),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-im:${this.#A.key}] bot ${a} failed to stop cleanly:`,i)})}async#h(a){let o=await this.#e.resolve(a).catch(()=>{});return Ul(o?.value)}async#d(a,o){o?.value?await this.#e.set(a,o.value).catch(()=>{}):await this.#e.unset(a).catch(()=>{})}#u(a,o){let r=(this.#c.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#c.get(a)===r&&this.#c.delete(a)});return this.#c.set(a,r),r}#B(){this.#l+=1}};var k$="https://discord.com/api/v10/";function Hl(n){return typeof n=="string"&&n.trim()?n.trim():null}function v$(n,a){let o=AbortSignal.timeout(a);return n?AbortSignal.any([n,o]):o}function P$(n,a){return new Promise((o,i)=>{if(a?.aborted){i(a.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),a?.addEventListener("abort",()=>{clearTimeout(e),i(a.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function oc(n,a){let o=Hl(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${a}`);return o}function G$(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var Kl=class{#A;#e;#t;constructor({token:a,fetchImpl:o=fetch,baseUrl:i=k$}){if(!G$(a))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#A=a.trim(),this.#e=o,this.#t=new URL(i)}getCurrentUser(a={}){return this.#a("users/@me",{...a,method:"GET"})}getGatewayBot(a={}){return this.#a("gateway/bot",{...a,method:"GET"})}createMessage({channelId:a,content:o,replyToMessageId:i,signal:e}){return this.#a(`channels/${oc(a,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:oc(i,"message id"),channel_id:oc(a,"channel id"),fail_if_not_exists:!1}}:{}}})}editMessage({channelId:a,messageId:o,content:i,signal:e}){return this.#a(`channels/${oc(a,"channel id")}/messages/${oc(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:a,signal:o}){return this.#a(`channels/${oc(a,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async#a(a,{method:o,body:i,signal:e,timeoutMs:r=15e3,expectBody:A=!0,retry:t=!0}){let s;try{s=await this.#e(new URL(a,this.#t),{method:o,headers:{authorization:`Bot ${this.#A}`,"content-type":"application/json","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.4.0)"},...i===void 0?{}:{body:JSON.stringify(i)},signal:v$(e,r),redirect:"error"})}catch(c){throw c?.name==="AbortError"||c?.name==="TimeoutError"?c:new Error(`Discord ${o} transport failed`)}let g=null;if(A||s.status===429||!s.ok)try{g=await s.json()}catch{if(A)throw new Error(`Discord ${o} returned invalid JSON`)}if(s.status===429&&t){let c=Math.min(1e4,Math.max(50,Number(g?.retry_after)*1e3||1e3));return await P$(c,e),this.#a(a,{method:o,body:i,signal:e,timeoutMs:r,expectBody:A,retry:!1})}if(!s.ok){let c=new Error(Hl(g?.message)??`Discord API failed with HTTP ${s.status}`);throw c.code=`discord-${s.status}`,c}return A?g:null}};async function Tv(n,a={}){let i=await new Kl({token:n,...a}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:Hl(i.global_name)??Hl(i.username)??"Discord\u673A\u5668\u4EBA",username:Hl(i.username)}}function _h(n){return typeof n=="string"?n.trim():""}function lr(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var Ri=class{#A;#e;#t;#a;#n;#s;#I;#g=new Map;constructor({descriptor:a,bot:o,harness:i,state:e,status:r=lr(),logger:A=console,replyTimeoutMs:t=6e5}){if(!a?.key||!a?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t}get status(){return structuredClone(this.#n)}accept(a){let o=_h(a?.conversationId),i=a?.kind==="group"?"group":"direct",e=`${i}:${o}`,A=(this.#g.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#o({...a,kind:i,conversationId:o})).finally(()=>{this.#g.get(e)===A&&this.#g.delete(e)});return this.#g.set(e,A),A}async waitForIdle(){await Promise.allSettled([...this.#g.values()])}async#o(a){let o=_h(a.messageId),i=_h(a.senderId);if(!o||!i||!a.conversationId||a.senderIsBot===!0||this.#a.hasSeen(o))return;if(this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString(),a.kind==="group"&&a.addressed!==!0){this.#n.messagesRejected+=1,this.#n.lastRejectedAt=new Date().toISOString();return}let e=a.replyTarget,r=_h(a.content);try{if(!r){await this.#e.sendText(e,"\u76EE\u524D\u4EC5\u652F\u6301\u6587\u5B57\u6D88\u606F\u3002"),await this.#a.markSeen(o);return}let A=r.toLowerCase();if(A==="/help"){await this.#e.sendText(e,[`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002`,"","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(`
|
|
68
68
|
`)),await this.#a.markSeen(o);return}if(A==="/status"){await this.#t.ensureRunning(),await this.#e.sendText(e,`${this.#A.label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002`),await this.#a.markSeen(o);return}let t=`${a.kind}:${a.conversationId}`;if(A==="/new"){await this.#a.clearSession(t),await this.#e.sendText(e,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#a.markSeen(o);return}let s=this.#a.sessionFor(t);(!s||!await this.#t.sessionExists(s))&&(s=await this.#t.createSession(),await this.#a.setSession(t,s)),await this.#e.sendTyping?.(e).catch(C=>{this.#s.warn?.(`[dsh-im:${this.#A.key}] typing indicator failed:`,C)});let g=null,c=!1;if(typeof this.#e.openStream=="function")try{g=await this.#e.openStream(e)}catch(C){this.#s.warn?.(`[dsh-im:${this.#A.key}] unable to start a streamed reply; using text:`,C)}let l=await this.#t.ask(s,r,{timeoutMs:this.#I,onUpdate:g?async C=>{let u=C.type==="text"?C.text:C.type==="tool"?`\u6B63\u5728\u4F7F\u7528${C.name}\u2026`:C.text;u&&await g.update(u)}:void 0});if(g)try{await g.finish(l),c=!0}catch(C){g.cancel?.(),this.#s.warn?.(`[dsh-im:${this.#A.key}] streamed reply finalization failed; using text:`,C)}c||await this.#e.sendText(e,l),await this.#a.markSeen(o),this.#n.messagesReplied+=1,this.#n.lastReplyAt=new Date().toISOString(),this.#n.lastError=null}catch(A){this.#n.lastError=A?.message??String(A),this.#s.error?.(`[dsh-im:${this.#A.key}] failed to process a message:`,A);try{await this.#e.sendText(e,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),await this.#a.markSeen(o)}catch(t){this.#s.error?.(`[dsh-im:${this.#A.key}] failed to send the safe error reply:`,t)}}}};var Xm=Object.freeze({key:"discord",label:"Discord",connectionLabel:" Gateway \u957F\u8FDE\u63A5"}),Nh=class extends Ri{constructor(a){super({descriptor:Xm,...a})}};var Yl=class extends ic{constructor(a){super({...a,descriptor:Xm,inspectToken:a.inspectToken??Tv,deriveIdentity:_v,maskPlatformId:Nv})}};import{spawn as F$}from"node:child_process";import{randomUUID as Rv}from"node:crypto";var kv=n=>new Promise(a=>setTimeout(a,n));function L$(n){return(n?.data?.message?.content??[]).filter(a=>a.type==="text"&&typeof a.text=="string").map(a=>a.text).join(`
|
|
69
69
|
`).trim()}var $m=class{#A;#e;#t=null;#a=null;#n=new Map;#s="";#I=!1;#g=null;constructor({promptRpcId:a,afterSeq:o=-1}){this.#A=a,this.#e=o}get finished(){return this.#I}get answer(){return this.#s.trim()}get reason(){return this.#g}consume(a){let o=null,i=[...a].map(e=>e?.event??e).filter(Boolean).sort((e,r)=>(e.seq??-1)-(r.seq??-1));for(let e of i){let r=e.seq??-1;if(!(r<=this.#e)){if(this.#e=r,e.type==="turn/start"&&(this.#t=e.data?.turn??null),e.type==="user/message"&&e.data?.source?.rpcId===this.#A){this.#a=this.#t;continue}if(this.#a!==null){if(e.type==="turn/end"){if(e.data?.turn!==this.#a)continue;this.#I=!0,this.#g=e.data?.reason??null,this.#t=null;continue}if(e.data?.turn===this.#a){if(e.type==="assistant/chunk"&&e.data?.chunk?.type==="text-delta"){let A=e.data?.step??0,t=e.data.chunk.index??0,s=`${A}:${t}`;this.#n.set(s,(this.#n.get(s)??"")+e.data.chunk.text);let g=`${A}:`,c=[...this.#n.entries()].filter(([l])=>l.startsWith(g)).sort(([l],[C])=>Number(l.split(":")[1])-Number(C.split(":")[1])).map(([,l])=>l).join(`
|
|
70
70
|
`).trim();c&&c!==this.#s&&(this.#s=c,o={type:"text",text:c});continue}if(e.type==="assistant/message"){let A=L$(e);A&&A!==this.#s&&(this.#s=A,o={type:"text",text:A});continue}e.type==="tool/call"?o={type:"tool",name:e.data?.name??"\u5DE5\u5177"}:e.type==="tool/result"&&(o={type:"status",text:"\u6B63\u5728\u6574\u7406\u7ED3\u679C\u2026"})}}}}return o}},Th=class extends Error{constructor(a,o){super(`${a}: ${o?.message??"unknown Harness RPC error"}`),this.name="HarnessRpcError",this.method=a,this.code=o?.code??"internal",this.details=o?.details??{}}},ka=class{#A;#e;#t;#a;#n;#s=null;constructor({baseUrl:a,workspace:o,agentPreset:i="standard",autostart:e=!1,dshBin:r="dsh"}){this.#A=new URL(a),this.#e=o,this.#t=i,this.#a=e,this.#n=r}async rpc(a,o={},i=3e4,e={}){let r=e.rpcId??`weixin-${Rv()}`,A=await fetch(new URL(`/api/${a}`,this.#A),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-request",rpcId:r,method:a,payload:o}),signal:AbortSignal.timeout(i)});if(!A.ok)throw new Error(`Harness transport ${a} failed: HTTP ${A.status}`);let t=await A.json();if(t?.type!=="server-response"||t?.rpcId!==r)throw new Error(`Harness returned an invalid response for ${a}`);if(!t.result?.ok)throw new Th(a,t.result?.error);return t.result.value}async health(){return await this.rpc("host.describe",{},5e3),!0}async ensureRunning(){try{return await this.health()}catch(i){if(!this.#a)throw i}if(!this.#s||this.#s.exitCode!==null){let i=this.#A.port||(this.#A.protocol==="https:"?"443":"80");this.#s=F$(this.#n,["web","--host",this.#A.hostname,"--port",i],{cwd:this.#e,env:process.env,stdio:["ignore","inherit","inherit"]}),this.#s.on("error",e=>{console.error("[dsh-weixin] failed to start Harness:",e.message)})}let a=Date.now()+6e4,o;for(;Date.now()<a;){await kv(1e3);try{return await this.health()}catch(i){o=i}}throw new Error(`Harness did not become ready: ${o?.message??"timeout"}`)}async workspaceId(){let{items:a}=await this.rpc("workspace.list",{}),o=a.find(e=>e.path===this.#e);return o?o.workspaceId:(await this.rpc("workspace.create",{path:this.#e})).workspace.workspaceId}async createSession(){await this.ensureRunning();let a=await this.workspaceId();return(await this.rpc("session.create",{workspaceId:a,agentPreset:this.#t})).sessionId}async sessionExists(a){try{return await this.rpc("session.history",{sessionId:a,maxMessages:1}),!0}catch(o){if(o instanceof Th&&o.code==="session-not-found")return!1;throw o}}async ask(a,o,i={}){typeof i=="number"&&(i={timeoutMs:i});let e=i.timeoutMs??6e5,r=typeof i.onUpdate=="function"?i.onUpdate:null;await this.ensureRunning();let A=await this.rpc("session.history",{sessionId:a,maxMessages:1}),t=Math.max(-1,...(A.events??[]).map(({event:l})=>l.seq??-1)),s=`weixin-${Rv()}`,g=new $m({promptRpcId:s,afterSeq:t});await this.rpc("session.prompt",{sessionId:a,mode:"queue",content:[{type:"text",text:o}],clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,{rpcId:s});let c=Date.now()+e;for(;Date.now()<c;){await kv(300);let l=await this.rpc("session.history",{sessionId:a,maxMessages:50}),C=g.consume(l.events??[]);if(C&&r)try{await r(C)}catch(u){console.warn("[dsh-weixin] ignored a progress update failure:",u.message)}if(g.finished){if(g.answer)return g.answer;throw new Error(`Harness turn ended without a text reply${g.reason?` (${JSON.stringify(g.reason)})`:""}`)}}throw new Error(`Harness reply timed out after ${Math.round(e/1e3)} seconds`)}stopManagedProcess(){this.#s?.exitCode===null&&this.#s.kill("SIGTERM")}};var Rh=class extends ka{};function Or(n,a){let o=typeof n=="string"?n.trim():"";if(!o)return[];let i=[],e=o;for(;e.length>a;){let r=e.lastIndexOf(`
|
|
@@ -168,7 +168,7 @@ ${r.join(`
|
|
|
168
168
|
`,{encoding:"utf8",mode:384}),await sde(o,this.#A)}};var fu=class extends ka{};var Cde="https://work.weixin.qq.com/ai/qc/generate",pde="https://work.weixin.qq.com/ai/qc/query_result";function Ux(){return process.platform==="win32"?2:process.platform==="linux"?3:1}function eI(n){return typeof n=="string"&&n.trim()?n.trim():null}function hde(n){let a=eI(n);if(!a)return null;try{let o=new URL(a);return o.protocol==="https:"&&o.hostname==="work.weixin.qq.com"&&(!o.port||o.port==="443")?o.href:null}catch{return null}}function dde(n,a){return n?AbortSignal.any([n,AbortSignal.timeout(a)]):AbortSignal.timeout(a)}async function Hx(n,a,o){let i=await n(a,{method:"GET",redirect:"error",signal:dde(o,1e4),headers:{accept:"application/json"}});if(!i.ok)throw new Error(`Enterprise WeChat QR service returned HTTP ${i.status}`);return i.json()}var yu=class{#A;#e;#t;#a;constructor({fetch:a=globalThis.fetch,clock:o=()=>Date.now(),source:i="deepseek-harness",platform:e=Ux()}={}){if(typeof a!="function")throw new TypeError("A fetch implementation is required");this.#A=a,this.#e=o,this.#t=i,this.#a=[1,2,3].includes(e)?e:Ux()}async start({signal:a}={}){let o=new URL(Cde);o.searchParams.set("source",this.#t),o.searchParams.set("plat",String(this.#a));let i=await Hx(this.#A,o,a),e=eI(i?.data?.scode),r=hde(i?.data?.auth_url);if(!e||!r)throw new Error("Enterprise WeChat QR service returned invalid data");return{scode:e,verificationUrl:r,expiresAt:this.#e()+3e5,pollIntervalMs:3e3}}async poll({scode:a,signal:o}={}){let i=eI(a);if(!i)throw new TypeError("Enterprise WeChat QR poll code is required");let e=new URL(pde);e.searchParams.set("scode",i);let r=await Hx(this.#A,e,o),A=eI(r?.data?.status)?.toLowerCase();if(A==="success"){let t=eI(r?.data?.bot_info?.botid),s=eI(r?.data?.bot_info?.secret);if(!t||!s)throw new Error("Enterprise WeChat QR result omitted bot credentials");return{status:"success",remoteBotId:t,secret:s}}return["expired","timeout"].includes(A)?{status:"expired"}:["fail","failed","error"].includes(A)?{status:"failed"}:{status:"waiting"}}};import{mkdir as Bde,readFile as ude,rename as Qde,unlink as fde,writeFile as yde}from"node:fs/promises";import{dirname as mde}from"node:path";var mu=Object.freeze({version:1,sessions:{},seenMessageIds:[]});function Sde(n){if(!n||typeof n!="object")return structuredClone(mu);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[o,i]of Object.entries(n.sessions))typeof o=="string"&&typeof i=="string"&&i&&(a[o]=i);return{version:1,sessions:a,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[]}}var Su=class{#A;#e=structuredClone(mu);#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{this.#e=Sde(JSON.parse(await ude(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(mu),await this.#a()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){this.#e.sessions[a]=o,await this.#a()}async clearSession(a){delete this.#e.sessions[a],await this.#a()}hasSeen(a){return this.#e.seenMessageIds.includes(a)}async markSeen(a){this.hasSeen(a)||(this.#e.seenMessageIds.push(a),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#a())}async remove(){try{await fde(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(mu)}async#a(){let a=`${JSON.stringify(this.#e,null,2)}
|
|
169
169
|
`,o=this.#t.then(async()=>{await Bde(mde(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await yde(i,a,{encoding:"utf8",mode:384}),await Qde(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};import{randomUUID as Dde}from"node:crypto";var Kx=new Set(["pending","connecting"]),uC=new Set(["connected","failed","cancelled","expired"]);function Ig(n){return typeof n=="string"&&n.trim()?n.trim():null}function ar(n,a){return Object.freeze({code:n,message:a})}function lg(n){return n?{attemptId:n.id,status:n.state,pollIntervalMs:n.pollIntervalMs,qrRevision:n.qrRevision,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},...n.botId?{botId:n.botId}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}var QC=class{#A;#e;#t;#a;#n;#s;#I=new Map;#g=new Map;#o=new Map;#i=null;#r=new Map;#c=0;#l=!1;constructor({qrAuth:a,credentials:o,configStore:i,createRuntime:e,deleteState:r=async()=>{},logger:A=console}){if(!a||typeof a.start!="function"||typeof a.poll!="function")throw new TypeError("Enterprise WeChat QR auth is required");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("WecomController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("WecomController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A}async initialize(){if(this.#l)return this.status();for(let a of this.#t.list())await this.#Q(a.botId,async()=>{let o=this.#I.get(a.botId)?.status;if(this.#l||o?.ready||o?.wecomConnectionState==="connecting")return;let i=await this.#u(a.secretRef);if(!i){this.#g.set(a.botId,ar("missing-secret","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u626B\u7801\u3002"));return}try{await this.#h(a,i),this.#g.delete(a.botId)}catch{this.#g.set(a.botId,ar("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002")),this.#s.warn?.(`[dsh-im:wecom] bot ${a.botId} failed to initialize`)}finally{this.#f()}});return this.status()}async startProvisioning(){if(this.#l)throw new Error("Enterprise WeChat controller is closed");this.#i&&await this.cancelProvisioning(this.#i);let a={id:Dde(),state:"pending",createdAt:Date.now(),expiresAt:null,pollIntervalMs:3e3,qrRevision:1,verificationUrl:null,scode:null,botId:null,error:null,controller:new AbortController,polling:null,transition:null};this.#o.set(a.id,a),this.#i=a.id,this.#f();try{let o=await this.#A.start({signal:a.controller.signal});if(a.scode=Ig(o.scode),a.verificationUrl=Ig(o.verificationUrl),a.expiresAt=Number(o.expiresAt),a.pollIntervalMs=Math.min(1e4,Math.max(500,Number(o.pollIntervalMs)||3e3)),!a.scode||!a.verificationUrl||!Number.isFinite(a.expiresAt))throw new Error("Enterprise WeChat QR auth returned incomplete data");return this.#f(),lg(a)}catch(o){throw a.state=a.controller.signal.aborted?"cancelled":"failed",a.error=a.controller.signal.aborted?ar("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"):ar("qr-start-failed","\u65E0\u6CD5\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),this.#y(a),o}}async registrationStatus(a){let o=this.#o.get(a);if(!o||uC.has(o.state))return lg(o);if(o.state==="connecting")return await o.transition?.catch(()=>{}),lg(o);if(Date.now()>=o.expiresAt)return o.state="expired",o.error=ar("expired","\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"),o.controller.abort(),this.#y(o),lg(o);if(!o.polling){let i=this.#E(o).finally(()=>{o.polling===i&&(o.polling=null)});o.polling=i}return await o.polling.catch(()=>{}),lg(o)}async bindCredentials({botId:a,secret:o}={}){if(this.#l)throw new Error("Enterprise WeChat controller is closed");let i=Ig(a),e=Ig(o);if(!i||!e)throw new TypeError("Enterprise WeChat Bot ID and Secret are required");if(this.#i&&await this.cancelProvisioning(this.#i),this.#l)throw new Error("Enterprise WeChat controller is closed");let r=Qu(i);return await this.#Q(r.botId,async()=>{if(this.#l)throw new Error("Enterprise WeChat controller is closed");let A=this.#t.getByRemoteBotId(i),t=await this.#e.resolve(r.secretRef).catch(()=>{});if(this.#l)throw new Error("Enterprise WeChat controller is closed");let s={botId:r.botId,remoteBotId:i,secretRef:r.secretRef,createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#e.set(r.secretRef,e);try{await this.#t.save(s)}catch(g){throw await this.#B(r.secretRef,t),g}try{await this.#h(s,e),this.#g.delete(r.botId)}catch{this.#g.set(r.botId,ar("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002")),this.#s.warn?.(`[dsh-im:wecom] bot ${r.botId} credential connection failed`)}this.#f()}),this.status()}async cancelProvisioning(a){let o=this.#o.get(a);return o?(uC.has(o.state)||(o.controller.abort(),await Promise.allSettled([o.polling,o.transition].filter(Boolean)),uC.has(o.state)||(o.state="cancelled"),o.error??=ar("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"),this.#y(o)),lg(o)):null}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(a,async()=>{let i=await this.#u(o.secretRef);if(!i)throw new Error("Enterprise WeChat bot secret is missing");try{await this.#h(o,i),this.#g.delete(a)}catch(e){throw this.#g.set(a,ar("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),e}finally{this.#f()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(a,async()=>{let i=await this.#e.resolve(o.secretRef).catch(()=>{});await this.#d(a);try{await this.#e.unset(o.secretRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.secretRef,i.value).catch(()=>{}),await this.#h(o,i.value).catch(()=>{})),new Error("Unable to remove the Enterprise WeChat bot safely.",{cause:e})}await this.#n({botId:a,config:o}).catch(e=>{this.#s.warn?.(`[dsh-im:wecom] bot ${a} state cleanup failed:`,e)}),this.#g.delete(a),this.#f()}),this.status()}status(){let a=this.#t.list().map(e=>{let r=this.#I.get(e.botId)?.status??null,A=r?.ready===!0&&r.wecomConnectionState==="connected"&&r.harnessReachable===!0,t=A?"connected":r?.wecomConnectionState==="connecting"?"connecting":this.#g.has(e.botId)||r?.wecomConnectionState==="failed"?"error":"offline";return{botId:e.botId,state:t,connected:A,configured:!0,bot:{name:"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA",appIdMasked:Fx(e.remoteBotId)},health:{status:A?"healthy":t==="error"?"error":"offline",summary:A?"\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":t==="error"?"\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",lastCheckedAt:r?.lastCheckedAt??null,lastConnectedAt:r?.lastConnectedAt??null},stats:{messagesReceived:r?.messagesReceived??0,messagesReplied:r?.messagesReplied??0},error:structuredClone(this.#g.get(e.botId)??null)}}),o=a.filter(e=>e.connected).length,i=this.#i?this.#o.get(this.#i):null;return{schemaVersion:1,revision:this.#c,state:i&&Kx.has(i.state)?"provisioning":a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o},...i&&Kx.has(i.state)?{provisioning:lg(i)}:{}}}async close(){this.#l||(this.#l=!0,this.#i&&await this.cancelProvisioning(this.#i),await Promise.allSettled([...this.#r.values()]),await Promise.allSettled([...this.#I.keys()].map(a=>this.#d(a))))}async#E(a){try{let o=await this.#A.poll({scode:a.scode,signal:a.controller.signal});if(a.controller.signal.aborted||uC.has(a.state)||o.status==="waiting")return;if(o.status==="expired"){a.state="expired",a.error=ar("expired","\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"),this.#y(a);return}if(o.status!=="success"){a.state="failed",a.error=ar("qr-connect-failed","\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u6CA1\u6709\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002"),this.#y(a);return}a.state="connecting",a.verificationUrl=null,a.expiresAt=null,a.scode=null,this.#f();let i=this.#C(a,o);a.transition=i,await i}catch{if(a.controller.signal.aborted)return;a.state="failed",a.error=ar("qr-connect-failed","\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002"),this.#s.warn?.("[dsh-im:wecom] QR polling failed"),this.#y(a)}}async#C(a,o){try{let i=Ig(o.remoteBotId),e=Ig(o.secret);if(!i||!e)throw new Error("Enterprise WeChat authorization returned incomplete credentials");a.botId=await this.#p(a,{remoteBotId:i,secret:e}),a.state="connected",a.error=null}catch{a.controller.signal.aborted?(a.state="cancelled",a.error=ar("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(a.state="failed",a.error=ar("activation-failed","\u4F01\u4E1A\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002"),this.#s.error?.("[dsh-im:wecom] provisioning failed"))}finally{this.#y(a)}}async#p(a,{remoteBotId:o,secret:i}){let e=Qu(o),r=this.#t.getByRemoteBotId(o),A=await this.#e.resolve(e.secretRef).catch(()=>{}),t={botId:e.botId,remoteBotId:o,secretRef:e.secretRef,createdAt:r?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};return this.#Q(e.botId,async()=>{await this.#e.set(e.secretRef,i);try{if(a.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#t.save(t)}catch(s){throw await this.#B(e.secretRef,A),s}try{if(a.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#h(t,i),this.#g.delete(e.botId)}catch(s){if(a.controller.signal.aborted)throw await this.#d(e.botId),r?await this.#t.save(r).catch(()=>{}):await this.#t.remove(e.botId).catch(()=>{}),await this.#B(e.secretRef,A),s;this.#g.set(e.botId,ar("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002")),this.#s.warn?.(`[dsh-im:wecom] bot ${e.botId} activation connection failed`)}return this.#f(),e.botId})}async#h(a,o){if(this.#l)throw new Error("Enterprise WeChat controller is closed");if(await this.#d(a.botId),this.#l)throw new Error("Enterprise WeChat controller is closed");let i=await this.#a({botId:a.botId,config:a,secret:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid Enterprise WeChat runtime");this.#I.set(a.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#I.delete(a.botId),e}}async#d(a){let o=this.#I.get(a);this.#I.delete(a),await o?.stop().catch(i=>{this.#s.warn?.(`[dsh-im:wecom] bot ${a} failed to stop cleanly:`,i)})}async#u(a){let o=await this.#e.resolve(a).catch(()=>{});return Ig(o?.value)}async#B(a,o){o?.value?await this.#e.set(a,o.value).catch(()=>{}):await this.#e.unset(a).catch(()=>{})}#Q(a,o){let r=(this.#r.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#r.get(a)===r&&this.#r.delete(a)});return this.#r.set(a,r),r}#y(a){a.scode=null,a.verificationUrl=null,a.expiresAt=null,this.#i===a.id&&(this.#i=null),this.#f();let o=[...this.#o.values()].filter(i=>uC.has(i.state));for(;o.length>16;)this.#o.delete(o.shift().id)}#f(){this.#c+=1}};import{WSAuthFailureError as Nde,WSClient as Tde,WSReconnectExhaustedError as Rde}from"@wecom/aibot-node-sdk";import{generateReqId as wde}from"@wecom/aibot-node-sdk";var Ode=["\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(`
|
|
170
170
|
`),Mde=18e3;function F_(n){return n?.body&&typeof n.body=="object"?n.body:{}}function Yx(n){let a=F_(n);return a.chattype==="group"?`group:${a.chatid}`:`direct:${a.from?.userid}`}function bde(n){let a=F_(n);return a.msgtype==="text"?typeof a.text?.content=="string"?a.text.content.trim():"":a.msgtype==="voice"?typeof a.voice?.content=="string"?a.voice.content.trim():"":a.msgtype==="mixed"&&Array.isArray(a.mixed?.msg_item)?a.mixed.msg_item.filter(o=>o?.msgtype==="text"&&typeof o.text?.content=="string").map(o=>o.text.content).join(`
|
|
171
|
-
`).trim():""}function Du(n,a=Mde){let o=String(n??"").trim();if(!o)return[];let i=[],e="",r=0;for(let A of o){let t=Buffer.byteLength(A);e&&r+t>a?(i.push(e),e=A,r=t):(e+=A,r+=t)}return e&&i.push(e),i}function _de(n){return n?.type==="text"?n.text:n?.type==="tool"?`\u6B63\u5728\u4F7F\u7528${n.name}\u2026`:n?.text}function L_(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var wu=class{#A;#e;#t;#a;#n;#s;#I;#g=new Map;constructor({client:a,harness:o,state:i,status:e=L_(),logger:r=console,replyTimeoutMs:A=6e5,generateStreamId:t=wde}){if(!a||typeof a.replyStream!="function"||typeof a.sendMessage!="function")throw new TypeError("Enterprise WeChat client is required");if(!o||!i)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t}get status(){return structuredClone(this.#a)}accept(a){let o=Yx(a),e=(this.#g.get(o)??Promise.resolve()).catch(()=>{}).then(()=>this.#r(a)).finally(()=>{this.#g.get(o)===e&&this.#g.delete(o)});return this.#g.set(o,e),e}async waitForIdle(){await Promise.allSettled([...this.#g.values()])}async#o(a,o){for(let i of Du(o))await this.#A.sendMessage(a,{msgtype:"markdown",markdown:{content:i}})}async#i(a,o,i){let e=Du(i);if(e.length!==0)try{await this.#A.replyStream(a,this.#I("stream"),e[0],!0);for(let r of e.slice(1))await this.#A.sendMessage(o,{msgtype:"markdown",markdown:{content:r}})}catch{await this.#o(o,i)}}async#r(a){let o=F_(a),i=typeof o.msgid=="string"?o.msgid:"",e=typeof o.from?.userid=="string"?o.from.userid:"",r=o.chattype==="group"?o.chatid:e;if(!i||!e||!r||!["single","group"].includes(o.chattype)||this.#t.hasSeen(i))return;this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString();let A=bde(a),t=null,s=!1;try{if(!A){await this.#i(a,r,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u8BED\u97F3\u8F6C\u5199\u548C\u56FE\u6587\u6DF7\u6392\u4E2D\u7684\u6587\u5B57\u6D88\u606F\u3002"),await this.#t.markSeen(i);return}let g=A.toLowerCase();if(g==="/help"){await this.#i(a,r,Ode),await this.#t.markSeen(i);return}if(g==="/status"){await this.#e.ensureRunning(),await this.#i(a,r,"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),await this.#t.markSeen(i);return}let c=Yx(a);if(g==="/new"){await this.#t.clearSession(c),await this.#i(a,r,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#t.markSeen(i);return}let l=this.#t.sessionFor(c);(!l||!await this.#e.sessionExists(l))&&(l=await this.#e.createSession(),await this.#t.setSession(c,l)),t=this.#I("stream");try{await this.#A.replyStream(a,t,"\u6B63\u5728\u601D\u8003\u4E2D\u2026",!1),s=!0}catch(f){this.#n.warn?.("[dsh-im:wecom] unable to start a stream; using an active reply:",f)}let C=await this.#e.ask(l,A,{timeoutMs:this.#s,onUpdate:s&&typeof this.#A.replyStreamNonBlocking=="function"?async f=>{let y=Du(_de(f))[0];y&&await this.#A.replyStreamNonBlocking(a,t,y,!1)}:void 0}),u=Du(C||"\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u4F46\u6CA1\u6709\u751F\u6210\u53EF\u663E\u793A\u7684\u6587\u672C\u3002"),Q=!1;if(s&&u.length>0)try{await this.#A.replyStream(a,t,u[0],!0);for(let f of u.slice(1))await this.#A.sendMessage(r,{msgtype:"markdown",markdown:{content:f}});Q=!0}catch(f){this.#n.warn?.("[dsh-im:wecom] stream finalization failed; using an active reply:",f)}Q||await this.#o(r,C),await this.#t.markSeen(i),this.#a.messagesReplied+=1,this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null}catch(g){this.#a.lastError=g?.message??String(g),this.#n.error?.("[dsh-im:wecom] failed to process an inbound message");try{s&&t?await this.#A.replyStream(a,t,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",!0):await this.#i(a,r,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),await this.#t.markSeen(i)}catch{this.#n.error?.("[dsh-im:wecom] failed to send the safe error reply")}}}};function kde(){let n=new Error("Enterprise WeChat WebSocket authentication timed out");return n.code="connect-timeout",n}function vde(){return{startedAt:null,ready:!1,wecomConnectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...L_()}}var fC=class{#A;#e;#t;#a;#n;#s;#I;#g;#o;#i=vde();#r=null;#c=null;#l=null;#E=null;constructor({config:a,secret:o,harness:i,state:e,logger:r=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,maxReconnectAttempts:s=10,createClient:g=c=>new Tde(c)}){if(!a||!o||!i||!e)throw new TypeError("WecomRuntime requires config, secret, Harness, and state");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t,this.#g=s,this.#o=g}get status(){return structuredClone(this.#i)}async start(){if(this.#i.ready&&this.#r)return this.status;if(this.#l)return this.#l;let a=new AbortController;return this.#E=a,this.#l=this.#C(a.signal).finally(()=>{this.#E===a&&(this.#E=null),this.#l=null}),this.#l}async#C(a){await this.#p(),a.throwIfAborted(),this.#i.startedAt=new Date().toISOString(),this.#i.wecomConnectionState="connecting",this.#i.lastError=null,await this.#t.ensureRunning(),this.#i.harnessReachable=!0;let o={debug(){},info(){},warn(){},error(){}},i=this.#o({botId:this.#A.remoteBotId,secret:this.#e,logger:o,maxReconnectAttempts:this.#g});if(!i||typeof i.connect!="function"||typeof i.disconnect!="function")throw new TypeError("Enterprise WeChat client factory returned an invalid client");this.#r=i,this.#c=new wu({client:i,harness:this.#t,state:this.#a,status:this.#i,logger:this.#n,replyTimeoutMs:this.#s});let e,r,A=!1,t=new Promise((Q,f)=>{e=Q,r=f}),s=()=>{if(this.#r!==i||a.aborted)return;A=!0;let Q=Date.now();this.#i.ready=!0,this.#i.wecomConnectionState="connected",this.#i.lastCheckedAt=Q,this.#i.lastConnectedAt=Q,this.#i.lastError=null,e()},g=()=>{this.#r===i&&(this.#i.ready=!1,this.#i.wecomConnectionState="connecting",this.#i.lastCheckedAt=Date.now())},c=()=>{this.#r===i&&(this.#i.ready=!1,this.#i.wecomConnectionState="connecting",this.#i.lastCheckedAt=Date.now())},l=Q=>{if(this.#r!==i)return;let f=Q instanceof Nde||Q instanceof Rde;!A&&f&&r(Q),f&&(this.#i.ready=!1,this.#i.wecomConnectionState="failed"),this.#i.lastError=f?Q.name:"connection-error",this.#n.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} connection error`)},C=Q=>this.#c?.accept(Q);i.on("authenticated",s),i.on("disconnected",g),i.on("reconnecting",c),i.on("error",l),i.on("message",C);let u;try{return i.connect(),await Promise.race([t,new Promise((Q,f)=>{a.addEventListener("abort",()=>f(a.reason),{once:!0})}),new Promise((Q,f)=>{u=setTimeout(()=>f(kde()),this.#I)})]),this.status}catch(Q){throw a.aborted?(await this.#p(),Q):(this.#i.ready=!1,this.#i.wecomConnectionState="failed",this.#i.lastError=Q?.message??String(Q),await this.#p(),Q)}finally{clearTimeout(u)}}async stop(){let a=this.#l;return this.#E?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),await this.#p(),await a?.catch(()=>{}),this.status}async#p(){let a=this.#r,o=this.#c;this.#r=null,this.#c=null;try{a?.disconnect(),a?.removeAllListeners?.()}catch{this.#n.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} failed to stop cleanly`)}await o?.waitForIdle(),this.#i.ready=!1,this.#i.wecomConnectionState="idle"}};var xx=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function Pde(n){if(!Array.isArray(n)||n.length===0)return[...xx];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...xx]}var Ou=class{#A;#e;#t;#a;#n;#s;#I;#g=null;#o=null;#i=0;#r=!1;#c=!1;#l;#E;constructor({controller:a,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:r=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!a||typeof a.initialize!="function"||typeof a.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=Pde(e),this.#n=Number.isFinite(r)&&r>=0?r:15e3,this.#s=A,this.#I=t,this.#l=new Promise(s=>{this.#E=s})}get ready(){return this.#l}start(){return this.#c||this.#r?this:(this.#c=!0,this.#C(0),this)}async close(){this.#r||(this.#r=!0,this.#g!==null&&this.#I(this.#g),this.#g=null,await this.#o?.catch(()=>{}),this.#E?.(null),this.#E=null)}#C(a){this.#r||(this.#g=this.#s(()=>{this.#g=null,this.#p()},a),this.#g?.unref?.())}async#p(){if(this.#r||this.#o)return;let a=this.#h();this.#o=a;try{await a}finally{this.#o===a&&(this.#o=null)}}async#h(){try{if(await this.#e.ensureRunning(),this.#r)return;let a=await this.#A.initialize();if(this.#r)return;this.#E?.(a),this.#E=null;let{configured:o,connected:i}=a.totals;if(i<o){let e=this.#a[Math.min(this.#i,this.#a.length-1)];this.#i+=1,this.#t.warn?.(`[dsh-im:wecom] ${i}/${o} bots connected; retrying in ${e}ms`),this.#C(e);return}this.#i=0,this.#C(this.#n)}catch(a){if(this.#r)return;let o=this.#a[Math.min(this.#i,this.#a.length-1)];this.#i+=1,this.#t.warn?.(`[dsh-im:wecom] connection reconciliation failed; retrying in ${o}ms`,a),this.#C(o)}}};function U_(n){return new Ou(n)}function Lde(n,a){if(a!==void 0)return new URL(a);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-im Enterprise WeChat requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function Ude(n){let a=AI(n.dshHome??process.env.DSH_HOME??Mu(Fde(),".dsh")),o=AI(n.dataDir??Mu(a,"integrations","dsh-wecom"));return{config:AI(n.configPath??Mu(o,"config.json")),bots:AI(n.botsDir??Mu(o,"bots"))}}async function H_(n,a={},o={}){if(!n?.credentials)throw new TypeError("dsh-im Enterprise WeChat requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-im Enterprise WeChat requires ctx.webServer");let i=o.ConfigStore??uu,e=o.StateStore??Su,r=o.HarnessClient??fu,A=o.Controller??QC,t=o.Runtime??fC,s=o.QrAuth??yu,g=o.createConnectionSupervisor??U_,c=typeof n.logger=="function"?n.logger("dsh-im:wecom"):n.logger??console,l=Ude(a),C=await new i(l.config).load(),u=o.qrAuth??new s({source:a.qrSource??"deepseek-harness",platform:a.qrPlatform}),Q=new Map,f=k=>AI(l.bots,k,"state.json"),y=async k=>{let U=Q.get(k);return U||(U=await new e(f(k)).load(),Q.set(k,U)),U},m=new r({baseUrl:Lde(n.webServer,a.harnessBaseUrl),workspace:AI(a.workspace??process.cwd()),agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),R=new A({qrAuth:u,credentials:n.credentials,configStore:C,logger:c,createRuntime:async({botId:k,config:U,secret:H})=>new t({config:U,secret:H,harness:m,state:await y(k),replyTimeoutMs:a.replyTimeoutMs??6e5,connectTimeoutMs:a.connectTimeoutMs??2e4,maxReconnectAttempts:a.maxReconnectAttempts??10,logger:{error:(...F)=>c.error?.(`[${k}]`,...F),warn:(...F)=>c.warn?.(`[${k}]`,...F),info:(...F)=>c.info?.(`[${k}]`,...F),debug:(...F)=>c.debug?.(`[${k}]`,...F)}}),deleteState:async({botId:k})=>{let U=Q.get(k);if(Q.delete(k),U&&typeof U.remove=="function")return U.remove();try{await Gde(f(k))}catch(H){if(H?.code!=="ENOENT")throw H}}}),N=g({controller:R,harness:m,logger:c,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:R,ready:N.ready,async close(){await N.close(),await R.close(),m.stopManagedProcess()}}}import Hde from"qrcode";var jx="/wecom",Ha=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete"}),qx=Object.freeze(Object.values(Ha)),Kde=new Set(["secret","secretRef","scode","remoteBotId","verificationUrl","bot_info","botid"]);function x_(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function tI(n,a){return x_(n)&&Object.keys(n).every(o=>a.includes(o))}function K_(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function Jx(n,a){return typeof n=="string"&&n.trim().length>0&&n.length<=a}function Yde(n,a){return x_(a)?n===Ha.status?tI(a,[])?null:"connection.status does not accept fields.":n===Ha.beginProvisioning?tI(a,["locale"])&&(a.locale===void 0||a.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Ha.pollProvisioning,Ha.cancelProvisioning].includes(n)?tI(a,["attemptId"])&&K_(a.attemptId)?null:`${n} requires an attemptId.`:n===Ha.bindCredentials?tI(a,["botId","secret"])&&Jx(a.botId,512)&&Jx(a.secret,1024)?null:"bot.bind-credentials requires Bot ID and Secret.":n===Ha.reconnectBot?tI(a,["botId"])&&K_(a.botId)?null:"bot.reconnect requires a botId.":n===Ha.deleteBot?tI(a,["botId","confirm"])&&K_(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":"Unknown Enterprise WeChat endpoint.":"Payload must be an object."}function aI(n){if(Array.isArray(n))return n.map(aI);if(!x_(n))return n;let a={};for(let[o,i]of Object.entries(n))Kde.has(o)||(a[o]=aI(i));return a}async function xde(n){return Hde.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function Y_(n,a){return!n||typeof n.verificationUrl!="string"?aI(n):aI({...n,qrCodeDataUrl:await a(n.verificationUrl)})}async function bu(n,a){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await Y_(o.provisioning,a)),aI(o)}function Vx(n,{encodeQr:a=xde}={}){for(let e of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[e]!="function")throw new TypeError(`A complete Enterprise WeChat controller is required (${e})`);let o=new Map,i=e=>{let r=o.get(e);return r||(o.size>=16&&o.delete(o.keys().next().value),r=Promise.resolve().then(()=>a(e)),o.set(e,r)),r};return async(e,r,A)=>{if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!qx.includes(e))return{ok:!1,error:{code:"bad-request",message:"Unknown Enterprise WeChat endpoint."}};let t=Yde(e,r);if(t)return{ok:!1,error:{code:"bad-request",message:t}};try{let s;if(e===Ha.status)s=await bu(await n.status(),i);else if(e===Ha.beginProvisioning)s=await Y_(await n.startProvisioning(),i);else if(e===Ha.pollProvisioning){let g=await n.registrationStatus(r.attemptId);if(!g)return{ok:!1,error:{code:"bad-request",message:"The provisioning attempt no longer exists."}};s=await Y_(g,i)}else e===Ha.cancelProvisioning?s=aI(await n.cancelProvisioning(r.attemptId)):e===Ha.bindCredentials?s=await bu(await n.bindCredentials(r),i):e===Ha.reconnectBot?s=await bu(await n.reconnectBot(r.botId),i):s=await bu(await n.deleteBot(r.botId),i);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:s}}catch{return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:{code:"wecom-operation-failed",message:"\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}}}function _u(n,a,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(jx,Vx(a,o),{authority:Ra(i)})}async function zx(n,a={}){if(a?.controller)return _u(n,a.controller,a.rpcOptions,a.rpcAuthority);let o=await H_(n,a,a.internals),i=_u(n,o.controller,a.rpcOptions,a.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Enterprise WeChat bot connections"),i}import{unlink as SBe}from"node:fs/promises";import{homedir as DBe}from"node:os";import{join as Lu,resolve as nI}from"node:path";import{createHash as tBe}from"node:crypto";import{mkdir as aBe,readFile as rBe,rename as iBe,unlink as oBe,writeFile as nBe}from"node:fs/promises";import{dirname as sBe}from"node:path";import{randomBytes as Jde,randomUUID as jde}from"node:crypto";var Tu="https://ilinkai.weixin.qq.com/",qde="2.4.6",Vde="3",zde="bot",Wde=2<<16|1024|6,Zde=15e3,Wx=35e3,Xde=new Set(["wait","scaned","confirmed","expired","scaned_but_redirect","need_verifycode","verify_code_blocked","binded_redirect"]),ct=class extends Error{constructor(a,o,i={}){super(o,i),this.name="WeixinApiError",this.code=a,this.status=i.status}};function Ei(n){return typeof n=="string"&&n.trim()?n.trim():null}function J_(n){let a=n.toLowerCase().replace(/\.$/,"");return a==="weixin.qq.com"||a.endsWith(".weixin.qq.com")}function iI(n){let a;try{a=new URL(n)}catch{throw new ct("invalid-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002")}if(a.protocol!=="https:"||!J_(a.hostname)||a.port!==""&&a.port!=="443")throw new ct("untrusted-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002");return a.username="",a.password="",a.search="",a.hash="",a.pathname.endsWith("/")||(a.pathname+="/"),a.toString()}function $de(n){let a=Ei(n);if(!a)throw new ct("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u5730\u5740\u3002");let o;try{o=new URL(a)}catch{throw new ct("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u626B\u7801\u5730\u5740\u3002")}if(o.protocol!=="https:"||!J_(o.hostname))throw new ct("untrusted-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002");return o.toString()}function Xx(){return{"iLink-App-Id":zde,"iLink-App-ClientVersion":String(Wde)}}function eBe(n){let a={...Xx(),"content-type":"application/json",AuthorizationType:"ilink_bot_token","X-WECHAT-UIN":Buffer.from(String(Jde(4).readUInt32BE(0)),"utf8").toString("base64")};return Ei(n)&&(a.Authorization=`Bearer ${n.trim()}`),a}function Nu(){return{channel_version:qde,bot_agent:"DeepSeekHarness/0.3.0"}}function Zx(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}async function rI(n,{method:a,baseUrl:o,endpoint:i,body:e,token:r,timeoutMs:A=Zde,signal:t,authenticated:s=!0}){let g=iI(o),c=new URL(i,g);if(!J_(c.hostname))throw new ct("untrusted-endpoint","\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002");let l=new AbortController,C=!1,u=()=>l.abort(t?.reason);if(t?.aborted)throw Zx(t);t?.addEventListener("abort",u,{once:!0});let Q=A>0?setTimeout(()=>{C=!0,l.abort()},A):null;try{let f=await n(c,{method:a,headers:s?eBe(r):Xx(),...e===void 0?{}:{body:JSON.stringify(e)},signal:l.signal});if(!f.ok)throw new ct("http-error",`\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${f.status}\uFF09\u3002`,{status:f.status});try{return await f.json()}catch(y){throw new ct("invalid-response","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002",{cause:y})}}catch(f){throw t?.aborted?Zx(t):C?new ct("timeout","\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002",{cause:f}):f instanceof ct?f:new ct("network-error","\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002",{cause:f})}finally{Q&&clearTimeout(Q),t?.removeEventListener("abort",u)}}function ABe(n){if(!n||typeof n!="object"||!Xde.has(n.status))throw new ct("invalid-login-status","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002");return n}function $x({fetchImpl:n=fetch}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");return Object.freeze({async beginLogin({localTokens:a=[],botType:o=Vde,signal:i}={}){let e=[...new Set(a.map(Ei).filter(Boolean))].slice(-10),r=await rI(n,{method:"POST",baseUrl:Tu,endpoint:`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(o)}`,body:{local_token_list:e},timeoutMs:1e4,signal:i}),A=Ei(r?.qrcode);if(!A)throw new ct("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4EE4\u724C\u3002");return{qrcode:A,qrcodeUrl:$de(r.qrcode_img_content)}},async pollLogin({qrcode:a,baseUrl:o=Tu,verifyCode:i,signal:e}){let r=Ei(a);if(!r)throw new TypeError("qrcode is required");let A=`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(r)}`;Ei(i)&&(A+=`&verify_code=${encodeURIComponent(i.trim())}`);let t=await rI(n,{method:"GET",baseUrl:o,endpoint:A,timeoutMs:Wx,signal:e,authenticated:!1});return ABe(t)},async getUpdates({baseUrl:a,token:o,getUpdatesBuf:i="",timeoutMs:e,signal:r}){try{return await rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/getupdates",body:{get_updates_buf:i,base_info:Nu()},token:o,timeoutMs:e??Wx,signal:r})}catch(A){if(A instanceof ct&&A.code==="timeout")return{ret:0,msgs:[],get_updates_buf:i};throw A}},async sendText({baseUrl:a,token:o,toUserId:i,text:e,contextToken:r,runId:A,signal:t}){let s=Ei(i),g=Ei(e);if(!s||!g)throw new TypeError("toUserId and text are required");let c=await rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/sendmessage",token:o,signal:t,body:{msg:{from_user_id:"",to_user_id:s,client_id:`dsh-weixin-${jde()}`,message_type:2,message_state:2,item_list:[{type:1,text_item:{text:g}}],...Ei(r)?{context_token:r.trim()}:{},...Ei(A)?{run_id:A.trim()}:{}},base_info:Nu()}});if(c?.ret!==void 0&&c.ret!==0)throw new ct("send-rejected","\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async notifyStart({baseUrl:a,token:o,signal:i}){let e=await rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystart",token:o,signal:i,timeoutMs:1e4,body:{base_info:Nu()}});if(e?.ret!==void 0&&e.ret!==0)throw new ct("start-rejected","\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002");return e},async notifyStop({baseUrl:a,token:o,signal:i}){return rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystop",token:o,signal:i,timeoutMs:1e4,body:{base_info:Nu()}})}})}function e1(n){for(let a of n?.item_list??[]){if(a?.type===1&&typeof a.text_item?.text=="string"){let o=a.text_item.text.trim();if(o)return o}if(a?.type===3&&typeof a.voice_item?.text=="string"){let o=a.voice_item.text.trim();if(o)return o}}return null}function A1(n){return n?.message_id!==void 0&&n.message_id!==null?String(n.message_id):Ei(n?.client_id)}function t1(n,a=4e3){if(n.length<=a)return[n];let o=[],i=n;for(;i.length>a;){let e=i.lastIndexOf(`
|
|
171
|
+
`).trim():""}function Du(n,a=Mde){let o=String(n??"").trim();if(!o)return[];let i=[],e="",r=0;for(let A of o){let t=Buffer.byteLength(A);e&&r+t>a?(i.push(e),e=A,r=t):(e+=A,r+=t)}return e&&i.push(e),i}function _de(n){return n?.type==="text"?n.text:n?.type==="tool"?`\u6B63\u5728\u4F7F\u7528${n.name}\u2026`:n?.text}function L_(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var wu=class{#A;#e;#t;#a;#n;#s;#I;#g=new Map;constructor({client:a,harness:o,state:i,status:e=L_(),logger:r=console,replyTimeoutMs:A=6e5,generateStreamId:t=wde}){if(!a||typeof a.replyStream!="function"||typeof a.sendMessage!="function")throw new TypeError("Enterprise WeChat client is required");if(!o||!i)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t}get status(){return structuredClone(this.#a)}accept(a){let o=Yx(a),e=(this.#g.get(o)??Promise.resolve()).catch(()=>{}).then(()=>this.#r(a)).finally(()=>{this.#g.get(o)===e&&this.#g.delete(o)});return this.#g.set(o,e),e}async waitForIdle(){await Promise.allSettled([...this.#g.values()])}async#o(a,o){for(let i of Du(o))await this.#A.sendMessage(a,{msgtype:"markdown",markdown:{content:i}})}async#i(a,o,i){let e=Du(i);if(e.length!==0)try{await this.#A.replyStream(a,this.#I("stream"),e[0],!0);for(let r of e.slice(1))await this.#A.sendMessage(o,{msgtype:"markdown",markdown:{content:r}})}catch{await this.#o(o,i)}}async#r(a){let o=F_(a),i=typeof o.msgid=="string"?o.msgid:"",e=typeof o.from?.userid=="string"?o.from.userid:"",r=o.chattype==="group"?o.chatid:e;if(!i||!e||!r||!["single","group"].includes(o.chattype)||this.#t.hasSeen(i))return;this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString();let A=bde(a),t=null,s=!1;try{if(!A){await this.#i(a,r,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u8BED\u97F3\u8F6C\u5199\u548C\u56FE\u6587\u6DF7\u6392\u4E2D\u7684\u6587\u5B57\u6D88\u606F\u3002"),await this.#t.markSeen(i);return}let g=A.toLowerCase();if(g==="/help"){await this.#i(a,r,Ode),await this.#t.markSeen(i);return}if(g==="/status"){await this.#e.ensureRunning(),await this.#i(a,r,"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),await this.#t.markSeen(i);return}let c=Yx(a);if(g==="/new"){await this.#t.clearSession(c),await this.#i(a,r,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#t.markSeen(i);return}let l=this.#t.sessionFor(c);(!l||!await this.#e.sessionExists(l))&&(l=await this.#e.createSession(),await this.#t.setSession(c,l)),t=this.#I("stream");try{await this.#A.replyStream(a,t,"\u6B63\u5728\u601D\u8003\u4E2D\u2026",!1),s=!0}catch(f){this.#n.warn?.("[dsh-im:wecom] unable to start a stream; using an active reply:",f)}let C=await this.#e.ask(l,A,{timeoutMs:this.#s,onUpdate:s&&typeof this.#A.replyStreamNonBlocking=="function"?async f=>{let y=Du(_de(f))[0];y&&await this.#A.replyStreamNonBlocking(a,t,y,!1)}:void 0}),u=Du(C||"\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u4F46\u6CA1\u6709\u751F\u6210\u53EF\u663E\u793A\u7684\u6587\u672C\u3002"),Q=!1;if(s&&u.length>0)try{await this.#A.replyStream(a,t,u[0],!0);for(let f of u.slice(1))await this.#A.sendMessage(r,{msgtype:"markdown",markdown:{content:f}});Q=!0}catch(f){this.#n.warn?.("[dsh-im:wecom] stream finalization failed; using an active reply:",f)}Q||await this.#o(r,C),await this.#t.markSeen(i),this.#a.messagesReplied+=1,this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null}catch(g){this.#a.lastError=g?.message??String(g),this.#n.error?.("[dsh-im:wecom] failed to process an inbound message");try{s&&t?await this.#A.replyStream(a,t,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",!0):await this.#i(a,r,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),await this.#t.markSeen(i)}catch{this.#n.error?.("[dsh-im:wecom] failed to send the safe error reply")}}}};function kde(){let n=new Error("Enterprise WeChat WebSocket authentication timed out");return n.code="connect-timeout",n}function vde(){return{startedAt:null,ready:!1,wecomConnectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...L_()}}var fC=class{#A;#e;#t;#a;#n;#s;#I;#g;#o;#i=vde();#r=null;#c=null;#l=null;#E=null;constructor({config:a,secret:o,harness:i,state:e,logger:r=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,maxReconnectAttempts:s=10,createClient:g=c=>new Tde(c)}){if(!a||!o||!i||!e)throw new TypeError("WecomRuntime requires config, secret, Harness, and state");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A,this.#I=t,this.#g=s,this.#o=g}get status(){return structuredClone(this.#i)}async start(){if(this.#i.ready&&this.#r)return this.status;if(this.#l)return this.#l;let a=new AbortController;return this.#E=a,this.#l=this.#C(a.signal).finally(()=>{this.#E===a&&(this.#E=null),this.#l=null}),this.#l}async#C(a){await this.#p(),a.throwIfAborted(),this.#i.startedAt=new Date().toISOString(),this.#i.wecomConnectionState="connecting",this.#i.lastError=null,await this.#t.ensureRunning(),this.#i.harnessReachable=!0;let o={debug(){},info(){},warn(){},error(){}},i=this.#o({botId:this.#A.remoteBotId,secret:this.#e,logger:o,maxReconnectAttempts:this.#g});if(!i||typeof i.connect!="function"||typeof i.disconnect!="function")throw new TypeError("Enterprise WeChat client factory returned an invalid client");this.#r=i,this.#c=new wu({client:i,harness:this.#t,state:this.#a,status:this.#i,logger:this.#n,replyTimeoutMs:this.#s});let e,r,A=!1,t=new Promise((Q,f)=>{e=Q,r=f}),s=()=>{if(this.#r!==i||a.aborted)return;A=!0;let Q=Date.now();this.#i.ready=!0,this.#i.wecomConnectionState="connected",this.#i.lastCheckedAt=Q,this.#i.lastConnectedAt=Q,this.#i.lastError=null,e()},g=()=>{this.#r===i&&(this.#i.ready=!1,this.#i.wecomConnectionState="connecting",this.#i.lastCheckedAt=Date.now())},c=()=>{this.#r===i&&(this.#i.ready=!1,this.#i.wecomConnectionState="connecting",this.#i.lastCheckedAt=Date.now())},l=Q=>{if(this.#r!==i)return;let f=Q instanceof Nde||Q instanceof Rde;!A&&f&&r(Q),f&&(this.#i.ready=!1,this.#i.wecomConnectionState="failed"),this.#i.lastError=f?Q.name:"connection-error",this.#n.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} connection error`)},C=Q=>this.#c?.accept(Q);i.on("authenticated",s),i.on("disconnected",g),i.on("reconnecting",c),i.on("error",l),i.on("message",C);let u;try{return i.connect(),await Promise.race([t,new Promise((Q,f)=>{a.addEventListener("abort",()=>f(a.reason),{once:!0})}),new Promise((Q,f)=>{u=setTimeout(()=>f(kde()),this.#I)})]),this.status}catch(Q){throw a.aborted?(await this.#p(),Q):(this.#i.ready=!1,this.#i.wecomConnectionState="failed",this.#i.lastError=Q?.message??String(Q),await this.#p(),Q)}finally{clearTimeout(u)}}async stop(){let a=this.#l;return this.#E?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),await this.#p(),await a?.catch(()=>{}),this.status}async#p(){let a=this.#r,o=this.#c;this.#r=null,this.#c=null;try{a?.disconnect(),a?.removeAllListeners?.()}catch{this.#n.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} failed to stop cleanly`)}await o?.waitForIdle(),this.#i.ready=!1,this.#i.wecomConnectionState="idle"}};var xx=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function Pde(n){if(!Array.isArray(n)||n.length===0)return[...xx];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...xx]}var Ou=class{#A;#e;#t;#a;#n;#s;#I;#g=null;#o=null;#i=0;#r=!1;#c=!1;#l;#E;constructor({controller:a,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:r=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!a||typeof a.initialize!="function"||typeof a.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=Pde(e),this.#n=Number.isFinite(r)&&r>=0?r:15e3,this.#s=A,this.#I=t,this.#l=new Promise(s=>{this.#E=s})}get ready(){return this.#l}start(){return this.#c||this.#r?this:(this.#c=!0,this.#C(0),this)}async close(){this.#r||(this.#r=!0,this.#g!==null&&this.#I(this.#g),this.#g=null,await this.#o?.catch(()=>{}),this.#E?.(null),this.#E=null)}#C(a){this.#r||(this.#g=this.#s(()=>{this.#g=null,this.#p()},a),this.#g?.unref?.())}async#p(){if(this.#r||this.#o)return;let a=this.#h();this.#o=a;try{await a}finally{this.#o===a&&(this.#o=null)}}async#h(){try{if(await this.#e.ensureRunning(),this.#r)return;let a=await this.#A.initialize();if(this.#r)return;this.#E?.(a),this.#E=null;let{configured:o,connected:i}=a.totals;if(i<o){let e=this.#a[Math.min(this.#i,this.#a.length-1)];this.#i+=1,this.#t.warn?.(`[dsh-im:wecom] ${i}/${o} bots connected; retrying in ${e}ms`),this.#C(e);return}this.#i=0,this.#C(this.#n)}catch(a){if(this.#r)return;let o=this.#a[Math.min(this.#i,this.#a.length-1)];this.#i+=1,this.#t.warn?.(`[dsh-im:wecom] connection reconciliation failed; retrying in ${o}ms`,a),this.#C(o)}}};function U_(n){return new Ou(n)}function Lde(n,a){if(a!==void 0)return new URL(a);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-im Enterprise WeChat requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function Ude(n){let a=AI(n.dshHome??process.env.DSH_HOME??Mu(Fde(),".dsh")),o=AI(n.dataDir??Mu(a,"integrations","dsh-wecom"));return{config:AI(n.configPath??Mu(o,"config.json")),bots:AI(n.botsDir??Mu(o,"bots"))}}async function H_(n,a={},o={}){if(!n?.credentials)throw new TypeError("dsh-im Enterprise WeChat requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-im Enterprise WeChat requires ctx.webServer");let i=o.ConfigStore??uu,e=o.StateStore??Su,r=o.HarnessClient??fu,A=o.Controller??QC,t=o.Runtime??fC,s=o.QrAuth??yu,g=o.createConnectionSupervisor??U_,c=typeof n.logger=="function"?n.logger("dsh-im:wecom"):n.logger??console,l=Ude(a),C=await new i(l.config).load(),u=o.qrAuth??new s({source:a.qrSource??"deepseek-harness",platform:a.qrPlatform}),Q=new Map,f=k=>AI(l.bots,k,"state.json"),y=async k=>{let U=Q.get(k);return U||(U=await new e(f(k)).load(),Q.set(k,U)),U},m=new r({baseUrl:Lde(n.webServer,a.harnessBaseUrl),workspace:AI(a.workspace??process.cwd()),agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),R=new A({qrAuth:u,credentials:n.credentials,configStore:C,logger:c,createRuntime:async({botId:k,config:U,secret:H})=>new t({config:U,secret:H,harness:m,state:await y(k),replyTimeoutMs:a.replyTimeoutMs??6e5,connectTimeoutMs:a.connectTimeoutMs??2e4,maxReconnectAttempts:a.maxReconnectAttempts??10,logger:{error:(...F)=>c.error?.(`[${k}]`,...F),warn:(...F)=>c.warn?.(`[${k}]`,...F),info:(...F)=>c.info?.(`[${k}]`,...F),debug:(...F)=>c.debug?.(`[${k}]`,...F)}}),deleteState:async({botId:k})=>{let U=Q.get(k);if(Q.delete(k),U&&typeof U.remove=="function")return U.remove();try{await Gde(f(k))}catch(H){if(H?.code!=="ENOENT")throw H}}}),N=g({controller:R,harness:m,logger:c,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:R,ready:N.ready,async close(){await N.close(),await R.close(),m.stopManagedProcess()}}}import Hde from"qrcode";var jx="/wecom",Ha=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete"}),qx=Object.freeze(Object.values(Ha)),Kde=new Set(["secret","secretRef","scode","remoteBotId","verificationUrl","bot_info","botid"]);function x_(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function tI(n,a){return x_(n)&&Object.keys(n).every(o=>a.includes(o))}function K_(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function Jx(n,a){return typeof n=="string"&&n.trim().length>0&&n.length<=a}function Yde(n,a){return x_(a)?n===Ha.status?tI(a,[])?null:"connection.status does not accept fields.":n===Ha.beginProvisioning?tI(a,["locale"])&&(a.locale===void 0||a.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Ha.pollProvisioning,Ha.cancelProvisioning].includes(n)?tI(a,["attemptId"])&&K_(a.attemptId)?null:`${n} requires an attemptId.`:n===Ha.bindCredentials?tI(a,["botId","secret"])&&Jx(a.botId,512)&&Jx(a.secret,1024)?null:"bot.bind-credentials requires Bot ID and Secret.":n===Ha.reconnectBot?tI(a,["botId"])&&K_(a.botId)?null:"bot.reconnect requires a botId.":n===Ha.deleteBot?tI(a,["botId","confirm"])&&K_(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":"Unknown Enterprise WeChat endpoint.":"Payload must be an object."}function aI(n){if(Array.isArray(n))return n.map(aI);if(!x_(n))return n;let a={};for(let[o,i]of Object.entries(n))Kde.has(o)||(a[o]=aI(i));return a}async function xde(n){return Hde.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function Y_(n,a){return!n||typeof n.verificationUrl!="string"?aI(n):aI({...n,qrCodeDataUrl:await a(n.verificationUrl)})}async function bu(n,a){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await Y_(o.provisioning,a)),aI(o)}function Vx(n,{encodeQr:a=xde}={}){for(let e of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[e]!="function")throw new TypeError(`A complete Enterprise WeChat controller is required (${e})`);let o=new Map,i=e=>{let r=o.get(e);return r||(o.size>=16&&o.delete(o.keys().next().value),r=Promise.resolve().then(()=>a(e)),o.set(e,r)),r};return async(e,r,A)=>{if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!qx.includes(e))return{ok:!1,error:{code:"bad-request",message:"Unknown Enterprise WeChat endpoint."}};let t=Yde(e,r);if(t)return{ok:!1,error:{code:"bad-request",message:t}};try{let s;if(e===Ha.status)s=await bu(await n.status(),i);else if(e===Ha.beginProvisioning)s=await Y_(await n.startProvisioning(),i);else if(e===Ha.pollProvisioning){let g=await n.registrationStatus(r.attemptId);if(!g)return{ok:!1,error:{code:"bad-request",message:"The provisioning attempt no longer exists."}};s=await Y_(g,i)}else e===Ha.cancelProvisioning?s=aI(await n.cancelProvisioning(r.attemptId)):e===Ha.bindCredentials?s=await bu(await n.bindCredentials(r),i):e===Ha.reconnectBot?s=await bu(await n.reconnectBot(r.botId),i):s=await bu(await n.deleteBot(r.botId),i);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:s}}catch{return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:{code:"wecom-operation-failed",message:"\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}}}function _u(n,a,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(jx,Vx(a,o),{authority:Ra(i)})}async function zx(n,a={}){if(a?.controller)return _u(n,a.controller,a.rpcOptions,a.rpcAuthority);let o=await H_(n,a,a.internals),i=_u(n,o.controller,a.rpcOptions,a.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Enterprise WeChat bot connections"),i}import{unlink as SBe}from"node:fs/promises";import{homedir as DBe}from"node:os";import{join as Lu,resolve as nI}from"node:path";import{createHash as tBe}from"node:crypto";import{mkdir as aBe,readFile as rBe,rename as iBe,unlink as oBe,writeFile as nBe}from"node:fs/promises";import{dirname as sBe}from"node:path";import{randomBytes as Jde,randomUUID as jde}from"node:crypto";var Tu="https://ilinkai.weixin.qq.com/",qde="2.4.6",Vde="3",zde="bot",Wde=2<<16|1024|6,Zde=15e3,Wx=35e3,Xde=new Set(["wait","scaned","confirmed","expired","scaned_but_redirect","need_verifycode","verify_code_blocked","binded_redirect"]),ct=class extends Error{constructor(a,o,i={}){super(o,i),this.name="WeixinApiError",this.code=a,this.status=i.status}};function Ei(n){return typeof n=="string"&&n.trim()?n.trim():null}function J_(n){let a=n.toLowerCase().replace(/\.$/,"");return a==="weixin.qq.com"||a.endsWith(".weixin.qq.com")}function iI(n){let a;try{a=new URL(n)}catch{throw new ct("invalid-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002")}if(a.protocol!=="https:"||!J_(a.hostname)||a.port!==""&&a.port!=="443")throw new ct("untrusted-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002");return a.username="",a.password="",a.search="",a.hash="",a.pathname.endsWith("/")||(a.pathname+="/"),a.toString()}function $de(n){let a=Ei(n);if(!a)throw new ct("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u5730\u5740\u3002");let o;try{o=new URL(a)}catch{throw new ct("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u626B\u7801\u5730\u5740\u3002")}if(o.protocol!=="https:"||!J_(o.hostname))throw new ct("untrusted-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002");return o.toString()}function Xx(){return{"iLink-App-Id":zde,"iLink-App-ClientVersion":String(Wde)}}function eBe(n){let a={...Xx(),"content-type":"application/json",AuthorizationType:"ilink_bot_token","X-WECHAT-UIN":Buffer.from(String(Jde(4).readUInt32BE(0)),"utf8").toString("base64")};return Ei(n)&&(a.Authorization=`Bearer ${n.trim()}`),a}function Nu(){return{channel_version:qde,bot_agent:"DeepSeekHarness/0.4.0"}}function Zx(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}async function rI(n,{method:a,baseUrl:o,endpoint:i,body:e,token:r,timeoutMs:A=Zde,signal:t,authenticated:s=!0}){let g=iI(o),c=new URL(i,g);if(!J_(c.hostname))throw new ct("untrusted-endpoint","\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002");let l=new AbortController,C=!1,u=()=>l.abort(t?.reason);if(t?.aborted)throw Zx(t);t?.addEventListener("abort",u,{once:!0});let Q=A>0?setTimeout(()=>{C=!0,l.abort()},A):null;try{let f=await n(c,{method:a,headers:s?eBe(r):Xx(),...e===void 0?{}:{body:JSON.stringify(e)},signal:l.signal});if(!f.ok)throw new ct("http-error",`\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${f.status}\uFF09\u3002`,{status:f.status});try{return await f.json()}catch(y){throw new ct("invalid-response","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002",{cause:y})}}catch(f){throw t?.aborted?Zx(t):C?new ct("timeout","\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002",{cause:f}):f instanceof ct?f:new ct("network-error","\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002",{cause:f})}finally{Q&&clearTimeout(Q),t?.removeEventListener("abort",u)}}function ABe(n){if(!n||typeof n!="object"||!Xde.has(n.status))throw new ct("invalid-login-status","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002");return n}function $x({fetchImpl:n=fetch}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");return Object.freeze({async beginLogin({localTokens:a=[],botType:o=Vde,signal:i}={}){let e=[...new Set(a.map(Ei).filter(Boolean))].slice(-10),r=await rI(n,{method:"POST",baseUrl:Tu,endpoint:`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(o)}`,body:{local_token_list:e},timeoutMs:1e4,signal:i}),A=Ei(r?.qrcode);if(!A)throw new ct("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4EE4\u724C\u3002");return{qrcode:A,qrcodeUrl:$de(r.qrcode_img_content)}},async pollLogin({qrcode:a,baseUrl:o=Tu,verifyCode:i,signal:e}){let r=Ei(a);if(!r)throw new TypeError("qrcode is required");let A=`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(r)}`;Ei(i)&&(A+=`&verify_code=${encodeURIComponent(i.trim())}`);let t=await rI(n,{method:"GET",baseUrl:o,endpoint:A,timeoutMs:Wx,signal:e,authenticated:!1});return ABe(t)},async getUpdates({baseUrl:a,token:o,getUpdatesBuf:i="",timeoutMs:e,signal:r}){try{return await rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/getupdates",body:{get_updates_buf:i,base_info:Nu()},token:o,timeoutMs:e??Wx,signal:r})}catch(A){if(A instanceof ct&&A.code==="timeout")return{ret:0,msgs:[],get_updates_buf:i};throw A}},async sendText({baseUrl:a,token:o,toUserId:i,text:e,contextToken:r,runId:A,signal:t}){let s=Ei(i),g=Ei(e);if(!s||!g)throw new TypeError("toUserId and text are required");let c=await rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/sendmessage",token:o,signal:t,body:{msg:{from_user_id:"",to_user_id:s,client_id:`dsh-weixin-${jde()}`,message_type:2,message_state:2,item_list:[{type:1,text_item:{text:g}}],...Ei(r)?{context_token:r.trim()}:{},...Ei(A)?{run_id:A.trim()}:{}},base_info:Nu()}});if(c?.ret!==void 0&&c.ret!==0)throw new ct("send-rejected","\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async notifyStart({baseUrl:a,token:o,signal:i}){let e=await rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystart",token:o,signal:i,timeoutMs:1e4,body:{base_info:Nu()}});if(e?.ret!==void 0&&e.ret!==0)throw new ct("start-rejected","\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002");return e},async notifyStop({baseUrl:a,token:o,signal:i}){return rI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystop",token:o,signal:i,timeoutMs:1e4,body:{base_info:Nu()}})}})}function e1(n){for(let a of n?.item_list??[]){if(a?.type===1&&typeof a.text_item?.text=="string"){let o=a.text_item.text.trim();if(o)return o}if(a?.type===3&&typeof a.voice_item?.text=="string"){let o=a.voice_item.text.trim();if(o)return o}}return null}function A1(n){return n?.message_id!==void 0&&n.message_id!==null?String(n.message_id):Ei(n?.client_id)}function t1(n,a=4e3){if(n.length<=a)return[n];let o=[],i=n;for(;i.length>a;){let e=i.lastIndexOf(`
|
|
172
172
|
`,a);e<Math.floor(a*.6)&&(e=a),o.push(i.slice(0,e)),i=i.slice(e).replace(/^\n+/,"")}return i&&o.push(i),o}var j_=Object.freeze({version:1,accounts:Object.freeze([])});function Gn(n){return typeof n=="string"&&n.trim()?n.trim():null}function a1(n){let a=Gn(n);return a&&/^wx_[a-f0-9]{24}$/.test(a)?a:null}function gBe(n){let a=Gn(n);return a&&/^DSH_WEIXIN_BOT_TOKEN_[A-F0-9]{24}$/.test(a)?a:null}function q_(n){let a=Gn(n);if(!a)throw new TypeError("accountId is required");let o=tBe("sha256").update(a).digest("hex").slice(0,24);return{botId:`wx_${o}`,tokenRef:`DSH_WEIXIN_BOT_TOKEN_${o.toUpperCase()}`}}function r1(n){let a=Gn(n)??"";return a.length<=10?a?`${a.slice(0,3)}\u2022\u2022\u2022`:"\u5FAE\u4FE1\u673A\u5668\u4EBA":`${a.slice(0,6)}\u2022\u2022\u2022\u2022${a.slice(-4)}`}function i1(n){if(!n||typeof n!="object")return null;let a=Gn(n.accountId),o=Gn(n.ownerUserId),i=a1(n.botId),e=gBe(n.tokenRef);if(!a||!o||!i||!e)return null;let r=q_(a);if(r.botId!==i||r.tokenRef!==e)return null;let A;try{A=iI(n.baseUrl)}catch{return null}return Object.freeze({botId:i,accountId:a,tokenRef:e,ownerUserId:o,baseUrl:A,createdAt:Gn(n.createdAt)??new Date().toISOString(),connectedAt:Gn(n.connectedAt)})}function cBe(n){if(!n||n.version!==1||!Array.isArray(n.accounts))return null;let a=n.accounts.map(i1);if(a.some(r=>r===null))return null;let o=new Set,i=new Set,e=new Set;for(let r of a){if(o.has(r.botId)||i.has(r.accountId)||e.has(r.tokenRef))return null;o.add(r.botId),i.add(r.accountId),e.add(r.tokenRef)}return Object.freeze({version:1,accounts:Object.freeze(a)})}var Ru=class{#A;#e=j_;#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{let a=cBe(JSON.parse(await rBe(this.#A,"utf8")));if(!a)throw new Error("dsh-weixin config contains invalid account data");this.#e=a}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=j_}return this}list(){return structuredClone(this.#e.accounts)}get(a){let o=this.#e.accounts.find(i=>i.botId===a);return o?structuredClone(o):null}getByAccountId(a){let o=this.#e.accounts.find(i=>i.accountId===a);return o?structuredClone(o):null}async save(a){let o=i1(a);if(!o)throw new Error("Refusing to persist incomplete dsh-weixin account data");return this.#a(i=>{let e=i.find(t=>t.accountId===o.accountId&&t.botId!==o.botId),r=i.find(t=>t.tokenRef===o.tokenRef&&t.botId!==o.botId);if(e||r)throw new Error("Duplicate Weixin account identity");let A=i.findIndex(t=>t.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(a){if(!a1(a))throw new TypeError("Invalid Weixin bot id");return this.#a(o=>{let i=o.findIndex(r=>r.botId===a);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let a=this.#t.then(async()=>{try{await oBe(this.#A)}catch(o){if(o?.code!=="ENOENT")throw o}this.#e=j_});this.#t=a.then(()=>{},()=>{}),await a}async#a(a){let o,i=this.#t.then(async()=>{let e=[...this.#e.accounts];o=a(e);let r=Object.freeze({version:1,accounts:Object.freeze(e)});await this.#n(r),this.#e=r});return this.#t=i.then(()=>{},()=>{}),await i,o}async#n(a){await aBe(sBe(this.#A),{recursive:!0,mode:448});let o=`${this.#A}.tmp`;await nBe(o,`${JSON.stringify(a,null,2)}
|
|
173
173
|
`,{encoding:"utf8",mode:384}),await iBe(o,this.#A)}};import{mkdir as IBe,readFile as lBe,rename as EBe,unlink as CBe,writeFile as pBe}from"node:fs/promises";import{dirname as hBe}from"node:path";var ku=Object.freeze({version:1,sessions:{},seenMessageIds:[],getUpdatesBuf:""});function dBe(n){if(!n||typeof n!="object")return structuredClone(ku);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[o,i]of Object.entries(n.sessions))typeof o=="string"&&typeof i=="string"&&i&&(a[o]=i);return{version:1,sessions:a,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[],getUpdatesBuf:typeof n.getUpdatesBuf=="string"?n.getUpdatesBuf:""}}var vu=class{#A;#e=structuredClone(ku);#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{this.#e=dBe(JSON.parse(await lBe(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(ku),await this.#a()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){this.#e.sessions[a]=o,await this.#a()}async clearSession(a){delete this.#e.sessions[a],await this.#a()}hasSeen(a){return this.#e.seenMessageIds.includes(a)}async markSeen(a){this.hasSeen(a)||(this.#e.seenMessageIds.push(a),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#a())}getUpdatesBuf(){return this.#e.getUpdatesBuf}async setGetUpdatesBuf(a){typeof a!="string"||a===this.#e.getUpdatesBuf||(this.#e.getUpdatesBuf=a,await this.#a())}snapshot(){return structuredClone(this.#e)}async remove(){try{await CBe(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(ku)}async#a(){let a=`${JSON.stringify(this.#e,null,2)}
|
|
174
174
|
`,o=this.#t.then(async()=>{await IBe(hBe(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await pBe(i,a,{encoding:"utf8",mode:384}),await EBe(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};import{randomUUID as BBe}from"node:crypto";var o1=new Set(["starting","pending","scanned","needs_verification","connecting"]),Pu=new Set(["connected","expired","failed","cancelled"]),n1=5*6e4;function oI(n){return typeof n=="string"&&n.trim()?n.trim():null}function uBe(){return new DOMException("Provisioning was cancelled","AbortError")}function s1(n,a){let o=oI(n);return o?iI(o.includes("://")?o:`https://${o}`):iI(a)}function yC(n){return n?{attemptId:n.id,status:n.state,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},pollIntervalMs:1e3,...n.state==="needs_verification"?{verificationRequired:!0}:{},...n.botId?{botId:n.botId}:{},...n.alreadyConnected?{alreadyConnected:!0}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}function Br(n,a){return Object.freeze({code:n,message:a})}var mC=class{#A;#e;#t;#a;#n;#s;#I=new Map;#g=new Map;#o=new Map;#i=null;#r=new Map;#c=0;#l=!1;constructor({api:a,credentials:o,configStore:i,createRuntime:e,deleteState:r=async()=>{},logger:A=console}){if(!a||typeof a.beginLogin!="function"||typeof a.pollLogin!="function")throw new TypeError("WeixinController requires a Weixin API client");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("WeixinController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("WeixinController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#n=r,this.#s=A}async initialize(){if(this.#l)return this.status();for(let a of this.#t.list())this.#I.get(a.botId)?.status?.ready!==!0&&await this.#Q(a.botId,async()=>{let i=this.#t.get(a.botId);if(!(!i||this.#l))try{let e=await this.#d(i.tokenRef);if(!e){this.#g.set(i.botId,Br("missing-token","\u767B\u5F55\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u8D26\u53F7\u540E\u91CD\u65B0\u626B\u7801\u3002"));return}await this.#p(i,e),this.#g.delete(i.botId)}catch(e){this.#g.set(i.botId,Br("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002")),this.#s.warn?.(`[dsh-weixin] account ${i.botId} failed to initialize:`,e)}finally{this.#f()}});return this.status()}async startProvisioning(){if(this.#l)throw new Error("dsh-weixin controller is closed");this.#i&&await this.cancelProvisioning(this.#i);let a={id:BBe(),state:"starting",createdAt:Date.now(),expiresAt:Date.now()+n1,controller:new AbortController,pendingVerifyCode:null,verifyResolve:null,currentBaseUrl:Tu,error:null,botId:null,task:null};this.#o.set(a.id,a),this.#i=a.id,this.#f();try{let o=(await Promise.all(this.#t.list().slice(-10).map(async e=>this.#d(e.tokenRef)))).filter(Boolean),i=await this.#A.beginLogin({localTokens:o,signal:a.controller.signal});return this.#B(a),a.qrcode=i.qrcode,a.verificationUrl=i.qrcodeUrl,a.state="pending",a.expiresAt=Date.now()+n1,this.#f(),a.task=this.#E(a),yC(a)}catch(o){throw a.controller.signal.aborted?(a.state="cancelled",a.error=Br("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(a.state="failed",a.error=Br(o instanceof ct?o.code:"qr-start-failed",o instanceof ct?o.message:"\u65E0\u6CD5\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),this.#i===a.id&&(this.#i=null),this.#f(),o}}registrationStatus(a){return yC(this.#o.get(a))}async submitVerification(a,o){let i=this.#o.get(a);if(!i||i.state!=="needs_verification")throw new Error("The provisioning attempt is not waiting for a verification code");let e=oI(o);if(!e||!/^\d{4,8}$/.test(e))throw new TypeError("Verification code must contain 4 to 8 digits");return i.pendingVerifyCode=e,i.state="scanned",i.verifyResolve?.(),i.verifyResolve=null,this.#f(),yC(i)}async cancelProvisioning(a){let o=this.#o.get(a);return o?(Pu.has(o.state)||(o.controller.abort(),o.verifyResolve?.(),o.verifyResolve=null,await o.task?.catch(()=>{}),Pu.has(o.state)||(o.state="cancelled"),o.error??=Br("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")),this.#i===o.id&&(this.#i=null),this.#f(),yC(o)):null}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Weixin account");return await this.#Q(a,async()=>{let i=await this.#d(o.tokenRef);if(!i)throw new Error("The Weixin token is missing");try{await this.#p(o,i),this.#g.delete(a)}catch(e){throw this.#g.set(a,Br("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),e}finally{this.#f()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Weixin account");return await this.#Q(a,async()=>{let i=await this.#e.resolve(o.tokenRef).catch(()=>{});await this.#h(a);try{await this.#e.unset(o.tokenRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.tokenRef,i.value).catch(()=>{}),await this.#p(o,i.value).catch(()=>{})),new Error("Unable to remove the Weixin account safely.",{cause:e})}try{await this.#n({botId:a,config:o})}catch(e){this.#s.warn?.(`[dsh-weixin] account ${a} state cleanup failed:`,e)}this.#g.delete(a),this.#f()}),this.status()}status(){let a=this.#t.list().map(e=>{let r=this.#I.get(e.botId)?.status??null,A=r?.ready===!0&&r.weixinConnectionState==="connected"&&r.harnessReachable===!0,t=A?"connected":r?.weixinConnectionState==="connecting"?"connecting":this.#g.has(e.botId)||r?.weixinConnectionState==="failed"?"error":"offline",s=this.#g.get(e.botId)??(t==="error"?Br("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"):null);return{botId:e.botId,state:t,connected:A,configured:!0,bot:{name:"\u5FAE\u4FE1\u673A\u5668\u4EBA",accountIdMasked:r1(e.accountId)},health:{status:A?"healthy":t==="error"?"error":"offline",summary:A?"\u5FAE\u4FE1\u6D88\u606F\u957F\u8F6E\u8BE2\u8FD0\u884C\u6B63\u5E38":t==="error"?"\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"\u5FAE\u4FE1\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",lastCheckedAt:r?.lastCheckedAt??null},stats:{messagesReceived:r?.messagesReceived??0,messagesReplied:r?.messagesReplied??0},error:s?structuredClone(s):null}}),o=a.filter(e=>e.connected).length,i=this.#i?this.#o.get(this.#i):null;return{schemaVersion:1,revision:this.#c,state:i&&o1.has(i.state)?"provisioning":a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o},...i&&o1.has(i.state)?{provisioning:yC(i)}:{}}}async close(){this.#l||(this.#l=!0,this.#i&&await this.cancelProvisioning(this.#i),await Promise.allSettled([...this.#I.keys()].map(a=>this.#h(a))))}async#E(a){try{for(;!a.controller.signal.aborted&&Date.now()<a.expiresAt;){a.state==="needs_verification"&&!a.pendingVerifyCode&&(await new Promise(i=>{a.verifyResolve=i,a.controller.signal.aborted&&i()}),a.verifyResolve=null,this.#B(a));let o=await this.#A.pollLogin({qrcode:a.qrcode,baseUrl:a.currentBaseUrl,verifyCode:a.pendingVerifyCode,signal:a.controller.signal});if(this.#B(a),o.status==="wait")a.state="pending";else if(o.status==="scaned")a.pendingVerifyCode=null,a.state="scanned";else if(o.status==="need_verifycode")a.pendingVerifyCode=null,a.state="needs_verification";else if(o.status==="verify_code_blocked"){a.state="failed",a.error=Br("verification-blocked","\u914D\u5BF9\u7801\u591A\u6B21\u9519\u8BEF\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002");break}else if(o.status==="expired"){a.state="expired",a.error=Br("expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002");break}else if(o.status==="scaned_but_redirect")a.currentBaseUrl=s1(o.redirect_host,a.currentBaseUrl),a.state="scanned";else if(o.status==="binded_redirect"){let i=this.#t.list().find(e=>this.#I.get(e.botId)?.status?.ready===!0)??this.#t.list()[0];i?(a.state="connected",a.botId=i.botId,a.alreadyConnected=!0):(a.state="failed",a.error=Br("already-bound","\u8BE5\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u7ED1\u5B9A\uFF0C\u4F46\u672C\u673A\u6CA1\u6709\u53EF\u6062\u590D\u7684\u51ED\u636E\u3002"));break}else if(o.status==="confirmed"){let i=oI(o.bot_token),e=oI(o.ilink_bot_id),r=oI(o.ilink_user_id);if(!i||!e||!r)throw new ct("incomplete-login","\u5FAE\u4FE1\u6388\u6743\u6210\u529F\uFF0C\u4F46\u8FD4\u56DE\u7684\u8D26\u53F7\u51ED\u636E\u4E0D\u5B8C\u6574\u3002");a.state="connecting",this.#f();let A=s1(o.baseurl,a.currentBaseUrl);a.botId=await this.#C(a,{token:i,accountId:e,ownerUserId:r,baseUrl:A}),a.state="connected",a.error=null;break}this.#f()}!a.controller.signal.aborted&&Date.now()>=a.expiresAt&&!Pu.has(a.state)&&(a.state="expired",a.error=Br("expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"))}catch(o){a.controller.signal.aborted||o?.name==="AbortError"?(a.state="cancelled",a.error=Br("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(a.state="failed",a.error=Br(o instanceof ct?o.code:"activation-failed",o instanceof ct?o.message:"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u4FDD\u5B58\u51ED\u636E\u6216\u542F\u52A8\u6D88\u606F\u8FDE\u63A5\u3002"),this.#s.error?.("[dsh-weixin] provisioning failed:",o))}finally{a.pendingVerifyCode=null,a.verifyResolve?.(),a.verifyResolve=null,this.#i===a.id&&(this.#i=null),this.#f(),this.#y()}}async#C(a,{token:o,accountId:i,ownerUserId:e,baseUrl:r}){let A=q_(i),t=this.#t.getByAccountId(i),s={botId:A.botId,accountId:i,tokenRef:A.tokenRef,ownerUserId:e,baseUrl:r,createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()},g=await this.#e.resolve(A.tokenRef).catch(()=>{});return this.#Q(A.botId,async()=>{await this.#e.set(A.tokenRef,o);try{return this.#B(a),await this.#t.save(s),this.#B(a),await this.#p(s,o),this.#B(a),this.#g.delete(A.botId),this.#f(),A.botId}catch(c){throw await this.#h(A.botId),t?await this.#t.save(t).catch(()=>{}):this.#t.get(A.botId)&&await this.#t.remove(A.botId).catch(()=>{}),await this.#u(A.tokenRef,g),t&&g?.value&&await this.#p(t,g.value).catch(()=>{}),c}})}async#p(a,o){await this.#h(a.botId);let i=await this.#a({botId:a.botId,config:a,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid Weixin runtime");try{await i.start(),this.#I.set(a.botId,i)}catch(e){throw await i.stop().catch(()=>{}),e}}async#h(a){let o=this.#I.get(a);this.#I.delete(a),await o?.stop().catch(i=>{this.#s.warn?.(`[dsh-weixin] account ${a} failed to stop cleanly:`,i)})}async#d(a){let o=await this.#e.resolve(a).catch(()=>{});return oI(o?.value)}async#u(a,o){try{o?.value?await this.#e.set(a,o.value):await this.#e.unset(a)}catch(i){this.#s.error?.(`[dsh-weixin] failed to restore credential ${a}:`,i)}}#B(a){if(a.controller.signal.aborted||this.#i!==a.id)throw uBe()}#Q(a,o){let r=(this.#r.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#r.get(a)===r&&this.#r.delete(a)});return this.#r.set(a,r),r}#y(){for(let[a,o]of this.#o)a!==this.#i&&Pu.has(o.state)&&this.#o.size>16&&this.#o.delete(a)}#f(){this.#c+=1}};var QBe=["\u5FAE\u4FE1\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u6216\u5E26\u6587\u5B57\u8BC6\u522B\u7ED3\u679C\u7684\u8BED\u97F3\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmanrui/dsh-im",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "通过扫码、App Manifest或机器人凭据把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord和WhatsApp)。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"./package.json": "./package.json"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
|
+
"assets",
|
|
26
27
|
"bin",
|
|
27
28
|
"cordis.patch.yml",
|
|
28
29
|
"lib",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdir, writeFile } from 'node:fs/promises';
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { dirname, resolve } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
|
|
@@ -8,6 +8,8 @@ const sourceDirectory = dirname(fileURLToPath(import.meta.url));
|
|
|
8
8
|
const packageRoot = resolve(sourceDirectory, '../..');
|
|
9
9
|
const outputPath = resolve(packageRoot, 'lib/client.js');
|
|
10
10
|
const loaderId = process.env.DSH_IM_CLIENT_ID ?? '@xmanrui/dsh-im';
|
|
11
|
+
const logoPath = resolve(packageRoot, 'assets/logo-icon.png');
|
|
12
|
+
const logoDataUrl = `data:image/png;base64,${(await readFile(logoPath)).toString('base64')}`;
|
|
11
13
|
|
|
12
14
|
const result = await build({
|
|
13
15
|
entryPoints: [resolve(sourceDirectory, 'index.js')],
|
|
@@ -16,6 +18,9 @@ const result = await build({
|
|
|
16
18
|
platform: 'browser',
|
|
17
19
|
target: ['chrome100'],
|
|
18
20
|
external: ['react'],
|
|
21
|
+
define: {
|
|
22
|
+
'globalThis.__DSH_IM_LOGO_DATA_URL__': JSON.stringify(logoDataUrl),
|
|
23
|
+
},
|
|
19
24
|
write: false,
|
|
20
25
|
minify: process.env.NODE_ENV === 'production',
|
|
21
26
|
legalComments: 'none',
|
|
@@ -7,7 +7,8 @@ const EN = Object.freeze({
|
|
|
7
7
|
'IM机器人': 'IM bots',
|
|
8
8
|
'IM机器人设置': 'IM bot settings',
|
|
9
9
|
'IM 渠道': 'IM channels',
|
|
10
|
-
'
|
|
10
|
+
'让聊天机器人轻松接入 DeepSeek Harness': 'Connect IM bots to DeepSeek Harness with ease',
|
|
11
|
+
'帮助与反馈 · 前往 GitHub': 'Help & feedback · Open GitHub',
|
|
11
12
|
'微信': 'WeChat',
|
|
12
13
|
'飞书': 'Feishu',
|
|
13
14
|
'钉钉': 'DingTalk',
|
|
@@ -43,6 +43,8 @@ import { installImStyles } from './styles.js';
|
|
|
43
43
|
export const name = 'im-settings';
|
|
44
44
|
export const inject = ['slots', 'connection', 'locale'];
|
|
45
45
|
|
|
46
|
+
const IM_PLUGIN_LOGO_URL = globalThis.__DSH_IM_LOGO_DATA_URL__ ?? 'assets/logo-icon.png';
|
|
47
|
+
|
|
46
48
|
const CHANNELS = Object.freeze([
|
|
47
49
|
{ id: 'weixin', label: '微信' },
|
|
48
50
|
{ id: 'feishu', label: '飞书' },
|
|
@@ -122,10 +124,35 @@ export function IMSettingsTab({
|
|
|
122
124
|
whatsappRpcCall,
|
|
123
125
|
}) {
|
|
124
126
|
const [selected, setSelected] = React.useState('weixin');
|
|
127
|
+
const githubTooltipId = React.useId();
|
|
125
128
|
const active = CHANNELS.find((channel) => channel.id === selected) ?? CHANNELS[0];
|
|
126
129
|
return h('section', { className: 'dim-page', 'aria-label': 'IM机器人设置' },
|
|
127
130
|
h('header', { className: 'dim-title' },
|
|
128
|
-
h('
|
|
131
|
+
h('div', { className: 'dim-brand' },
|
|
132
|
+
h('img', {
|
|
133
|
+
className: 'dim-brandLogo',
|
|
134
|
+
src: IM_PLUGIN_LOGO_URL,
|
|
135
|
+
alt: 'dsh-im',
|
|
136
|
+
width: 48,
|
|
137
|
+
height: 48,
|
|
138
|
+
}),
|
|
139
|
+
h('p', null, '让聊天机器人轻松接入 DeepSeek Harness')),
|
|
140
|
+
h('span', { className: 'dim-githubAction' },
|
|
141
|
+
h('a', {
|
|
142
|
+
className: 'dim-githubLink',
|
|
143
|
+
href: 'https://github.com/xmanrui/dsh-im',
|
|
144
|
+
target: '_blank',
|
|
145
|
+
rel: 'noopener noreferrer',
|
|
146
|
+
'aria-label': 'dsh-im GitHub',
|
|
147
|
+
'aria-describedby': githubTooltipId,
|
|
148
|
+
},
|
|
149
|
+
h('span', null, 'GitHub'),
|
|
150
|
+
h('span', { className: 'dim-githubArrow', 'aria-hidden': 'true' }, '↗')),
|
|
151
|
+
h('span', {
|
|
152
|
+
id: githubTooltipId,
|
|
153
|
+
className: 'dim-githubTooltip',
|
|
154
|
+
role: 'tooltip',
|
|
155
|
+
}, '帮助与反馈 · 前往 GitHub')),
|
|
129
156
|
),
|
|
130
157
|
h('div', { className: 'dim-layout' },
|
|
131
158
|
h('nav', { className: 'dim-rail', role: 'tablist', 'aria-label': 'IM 渠道' },
|
|
@@ -11,8 +11,17 @@ const CSS = String.raw`
|
|
|
11
11
|
box-sizing: border-box;
|
|
12
12
|
}
|
|
13
13
|
.dim-page *, .dim-page *::before, .dim-page *::after { box-sizing: border-box; }
|
|
14
|
-
.dim-title { margin: 0 0
|
|
15
|
-
.dim-
|
|
14
|
+
.dim-title { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 18px; }
|
|
15
|
+
.dim-brand { min-width: 0; display: flex; align-items: center; gap: 12px; }
|
|
16
|
+
.dim-brandLogo { width: 48px; height: 48px; flex: 0 0 48px; display: block; object-fit: contain; filter: grayscale(1) contrast(1.08); }
|
|
17
|
+
.dim-title p { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 20px; font-weight: 600; white-space: nowrap; }
|
|
18
|
+
.dim-githubAction { position: relative; display: inline-flex; flex: none; }
|
|
19
|
+
.dim-githubLink { min-height: 30px; display: inline-flex; align-items: center; gap: 5px; flex: none; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-layer-1, #fff); font-size: 12px; line-height: normal; font-weight: 560; text-decoration: none; transition: border-color .15s ease, color .15s ease, background .15s ease; }
|
|
20
|
+
.dim-githubLink:hover { border-color: #aeb3bb; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
21
|
+
.dim-githubLink:focus-visible { outline: 2px solid color-mix(in srgb, var(--dim-blue) 70%, white); outline-offset: 2px; }
|
|
22
|
+
.dim-githubArrow { font-size: 13px; line-height: 1; }
|
|
23
|
+
.dim-githubTooltip { position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 20; width: max-content; max-width: min(220px, 80vw); padding: 6px 9px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 7px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-3, #fff); box-shadow: 0 8px 24px rgb(31 35 41 / 14%); font-size: 11px; line-height: 16px; font-weight: 500; white-space: nowrap; opacity: 0; visibility: hidden; transform: translateY(3px); pointer-events: none; transition: opacity .15s ease, transform .15s ease, visibility .15s ease; }
|
|
24
|
+
.dim-githubAction:hover .dim-githubTooltip, .dim-githubAction:focus-within .dim-githubTooltip { opacity: 1; visibility: visible; transform: translateY(0); }
|
|
16
25
|
.dim-layout { display: grid; grid-template-columns: 174px 1px minmax(0, 1fr); gap: 24px; align-items: start; }
|
|
17
26
|
.dim-rail { max-height: 520px; display: grid; align-content: start; gap: 8px; overflow-y: auto; padding: 1px 4px 1px 1px; scrollbar-width: thin; scrollbar-color: var(--dsw-alias-border-l2, #dfe1e5) transparent; }
|
|
18
27
|
.dim-rail::-webkit-scrollbar { width: 4px; }
|
|
@@ -57,7 +66,7 @@ const CSS = String.raw`
|
|
|
57
66
|
.dim-panel .dim-credentialButton:hover:not(:disabled) { border-color: #4e5969; background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
58
67
|
.dim-panel .dim-credentialButton[aria-pressed="true"] { border-color: #4e5969; background: var(--dsw-alias-bg-module-platform, #f2f3f5); box-shadow: inset 0 0 0 1px rgb(78 89 105 / 8%); }
|
|
59
68
|
.dim-panel .bxf-headingTools .dim-onlineBadge, .dim-panel .dxw-tools .dim-onlineBadge, .dim-panel .ddt-tools .dim-onlineBadge { min-height: 30px; display: inline-flex; align-items: center; justify-self: end; gap: 0; padding: 0 11px; border: 0; border-radius: 999px; color: var(--dsw-alias-label-secondary, #646a73); background: var(--dsw-alias-bg-module-platform, #f2f3f5); font: inherit; font-size: 12px; font-weight: 400; line-height: normal; white-space: nowrap; }
|
|
60
|
-
.dim-panel .dim-channelPage { width: 100%; max-width: none; display: flex; flex-direction: column; gap:
|
|
69
|
+
.dim-panel .dim-channelPage { width: 100%; max-width: none; display: flex; flex-direction: column; gap: 12px; padding: 0 0 24px; color: var(--dsw-alias-label-primary, #1f2329); box-sizing: border-box; }
|
|
61
70
|
.dim-panel .dim-surfaceCard { position: relative; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); border-radius: 14px; background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 1px 2px rgb(31 35 41 / 3%); }
|
|
62
71
|
.dim-panel .dim-surfaceCard::before { display: none; }
|
|
63
72
|
.dim-panel .dim-surfaceBody { padding: 24px; }
|
|
@@ -73,9 +82,9 @@ const CSS = String.raw`
|
|
|
73
82
|
.dim-panel .dim-credentialError { margin: 0; color: var(--dsw-alias-state-error-primary, #d54941); font-size: 12px; line-height: 1.5; }
|
|
74
83
|
.dim-panel .dim-credentialActions { margin-top: 0; }
|
|
75
84
|
.dim-panel .dim-listSection { display: flex; flex-direction: column; gap: 0; }
|
|
76
|
-
.dim-panel .dim-listHeading { min-height: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin:
|
|
85
|
+
.dim-panel .dim-listHeading { min-height: 0; display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 6px; padding: 0; }
|
|
77
86
|
.dim-panel .dim-listHeading h3 { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: normal; font-weight: 650; }
|
|
78
|
-
.dim-panel .dim-botList { display: grid; gap:
|
|
87
|
+
.dim-panel .dim-botList { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
|
|
79
88
|
.dim-panel .dim-loadingView { padding: 38px; color: var(--dsw-alias-label-secondary, #646a73); text-align: center; }
|
|
80
89
|
.dim-panel .dim-loadingView h3 { margin: 0 0 7px; color: var(--dsw-alias-label-primary, #1f2329); font-size: 17px; line-height: normal; font-weight: 650; }
|
|
81
90
|
.dim-panel .dim-loadingView p { margin: 0; line-height: 1.6; }
|
|
@@ -123,7 +132,7 @@ const CSS = String.raw`
|
|
|
123
132
|
.dim-panel .dim-confirm { padding: 18px 24px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
124
133
|
.dim-panel .dim-confirm strong, .dim-panel .dim-confirm h4 { margin: 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 14px; line-height: 1.4; font-weight: 650; }
|
|
125
134
|
.dim-panel .dim-confirm p { margin: 7px 0 0; color: var(--dsw-alias-label-secondary, #646a73); line-height: 1.6; }
|
|
126
|
-
.dim-panel .dim-cardFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; padding-top:
|
|
135
|
+
.dim-panel .dim-cardFooter { display: flex; align-items: center; justify-content: space-between; gap: 15px; padding-top: 8px; border-top: 1px solid var(--dsw-alias-border-l1, #eef0f3); }
|
|
127
136
|
.dim-panel .dim-cardSummary { min-width: 0; color: var(--dsw-alias-label-secondary, #646a73); font: inherit; font-size: 12px; font-weight: 400; line-height: normal; }
|
|
128
137
|
.dim-panel .dim-cardActions { flex: none; display: flex; align-items: center; flex-wrap: nowrap; gap: 8px; margin: 0 0 0 auto; }
|
|
129
138
|
.dim-panel .dim-cardActions .dim-cardAction { flex: none; min-height: 34px; padding: 0 13px; border: 1px solid var(--dsw-alias-border-l2, #dfe1e5); border-radius: 8px; color: var(--dsw-alias-label-primary, #1f2329); background: var(--dsw-alias-bg-layer-1, #fff); font: inherit; font-size: 13px; font-weight: 560; line-height: normal; white-space: nowrap; }
|
|
@@ -131,7 +140,7 @@ const CSS = String.raw`
|
|
|
131
140
|
.dim-panel .dim-cardActions .dim-cardAction[data-kind="danger"] { color: var(--dsw-alias-state-error-primary, #d54941); }
|
|
132
141
|
.dim-panel .dim-botCard { position: relative; overflow: hidden; border: 1px solid var(--dsw-alias-border-l2, #e5e6eb); border-radius: 14px; background: var(--dsw-alias-bg-layer-1, #fff); box-shadow: 0 1px 2px rgb(31 35 41 / 3%); }
|
|
133
142
|
.dim-panel .dim-botCard::before { display: none; }
|
|
134
|
-
.dim-panel .dim-botCardBody { position: relative; padding:
|
|
143
|
+
.dim-panel .dim-botCardBody { position: relative; padding: 14px; }
|
|
135
144
|
.dim-panel .dim-botCardTop { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
|
|
136
145
|
.dim-panel .dim-botIdentity { min-width: 0; display: flex; align-items: center; gap: 12px; }
|
|
137
146
|
.dim-panel .dim-botAvatar { flex: none; width: 42px; height: 42px; display: grid; place-items: center; overflow: hidden; border-radius: 12px; box-shadow: none; }
|
|
@@ -144,8 +153,8 @@ const CSS = String.raw`
|
|
|
144
153
|
.dim-panel .dim-botCard .dim-healthDot[data-tone="success"] { background: var(--dsw-alias-state-success-primary, #20a162); box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsw-alias-state-success-primary, #20a162) 14%, transparent); }
|
|
145
154
|
.dim-panel .dim-botCard .dim-healthDot[data-tone="warning"] { background: var(--dsw-alias-state-warn-primary, #d97706); }
|
|
146
155
|
.dim-panel .dim-botCard .dim-healthDot[data-tone="error"] { background: var(--dsw-alias-state-error-primary, #d54941); }
|
|
147
|
-
.dim-panel .dim-botMetrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin:
|
|
148
|
-
.dim-panel .dim-botMetric { min-width: 0; padding:
|
|
156
|
+
.dim-panel .dim-botMetrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 8px 0; }
|
|
157
|
+
.dim-panel .dim-botMetric { min-width: 0; padding: 8px; border: 0; border-radius: 9px; background: var(--dsw-alias-interactive-bg-hover, #f7f8fa); }
|
|
149
158
|
.dim-panel .dim-botMetric dt { margin: 0; color: var(--dsw-alias-label-tertiary, #8f959e); font-size: 11px; font-weight: 400; line-height: normal; }
|
|
150
159
|
.dim-panel .dim-botMetric dd { overflow: hidden; margin: 5px 0 0; color: var(--dsw-alias-label-primary, #1f2329); font-size: 13px; font-weight: 400; line-height: normal; text-overflow: ellipsis; white-space: nowrap; }
|
|
151
160
|
.dim-panel .dim-botCard .dim-cardFooter { margin-top: 0; }
|
|
@@ -182,6 +191,7 @@ const CSS = String.raw`
|
|
|
182
191
|
@media (max-width: 560px) {
|
|
183
192
|
.dim-title { flex-direction: column; gap: 10px; }
|
|
184
193
|
.dim-title p { white-space: normal; }
|
|
194
|
+
.dim-githubTooltip { right: auto; left: 0; }
|
|
185
195
|
.dim-rail { grid-template-columns: minmax(0, 1fr); }
|
|
186
196
|
}
|
|
187
197
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -108,7 +108,7 @@ export class DiscordApi {
|
|
|
108
108
|
headers: {
|
|
109
109
|
authorization: `Bot ${this.#token}`,
|
|
110
110
|
'content-type': 'application/json',
|
|
111
|
-
'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.
|
|
111
|
+
'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.4.0)',
|
|
112
112
|
},
|
|
113
113
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
114
114
|
signal: requestSignal(signal, timeoutMs),
|