@xmanrui/dsh-im 3.0.6 → 3.0.7

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.en.md CHANGED
@@ -257,13 +257,14 @@ Without a setting, Chinese is used. Chinese is always the fallback language —
257
257
 
258
258
  ## Contact
259
259
 
260
- You can reach me by email, WeChat, or Xiaohongshu.
260
+ You can reach me by email, WeChat, Xiaohongshu, or WhatsApp.
261
261
 
262
262
  <table>
263
263
  <tr>
264
264
  <th align="center">Email</th>
265
265
  <th align="center">WeChat</th>
266
266
  <th align="center">Xiaohongshu</th>
267
+ <th align="center">WhatsApp</th>
267
268
  </tr>
268
269
  <tr>
269
270
  <td align="center" valign="middle">
@@ -275,5 +276,8 @@ You can reach me by email, WeChat, or Xiaohongshu.
275
276
  <td align="center" valign="top">
276
277
  <a href="docs/images/xhs.jpg"><img src="docs/images/xhs.jpg" alt="Xiaohongshu QR code" width="240"></a>
277
278
  </td>
279
+ <td align="center" valign="top">
280
+ <a href="docs/images/WhatsApp.jpg"><img src="docs/images/WhatsApp.jpg" alt="WhatsApp QR code" width="240"></a>
281
+ </td>
278
282
  </tr>
279
283
  </table>
package/README.md CHANGED
@@ -260,13 +260,14 @@ IM 管理 RPC 默认仅接受回环浏览器。如果 Web profile 在受信任
260
260
 
261
261
  ## 联系方式
262
262
 
263
- 欢迎通过邮箱、微信或小红书联系我。
263
+ 欢迎通过邮箱、微信、小红书或 WhatsApp 联系我。
264
264
 
265
265
  <table>
266
266
  <tr>
267
267
  <th align="center">邮箱</th>
268
268
  <th align="center">微信</th>
269
269
  <th align="center">小红书</th>
270
+ <th align="center">WhatsApp</th>
270
271
  </tr>
271
272
  <tr>
272
273
  <td align="center" valign="middle">
@@ -278,5 +279,8 @@ IM 管理 RPC 默认仅接受回环浏览器。如果 Web profile 在受信任
278
279
  <td align="center" valign="top">
279
280
  <a href="docs/images/xhs.jpg"><img src="docs/images/xhs.jpg" alt="小红书二维码" width="240"></a>
280
281
  </td>
282
+ <td align="center" valign="top">
283
+ <a href="docs/images/WhatsApp.jpg"><img src="docs/images/WhatsApp.jpg" alt="WhatsApp 二维码" width="240"></a>
284
+ </td>
281
285
  </tr>
282
286
  </table>
package/lib/client.js CHANGED
@@ -47,7 +47,7 @@ var React20 = __toESM(require("react"), 1);
47
47
  // package.json
48
48
  var package_default = {
49
49
  name: "@xmanrui/dsh-im",
50
- version: "3.0.6",
50
+ version: "3.0.7",
51
51
  description: "\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
52
52
  keywords: [
53
53
  "deepseek-harness",
package/lib/index.js CHANGED
@@ -143,7 +143,7 @@ ${D("\u9519\u8BEF\u7801\uFF1A{code}\uFF1B\u53C2\u8003\u53F7\uFF1A{referenceId}",
143
143
  `:/^\s{0,3}(?:[-*+] |\d+[.)] |#{1,6} |\||> )/.test(o[a+1])?`${e}
144
144
  `:`${e}<br>`}).join("")}function Nb(n,t){if(!n||typeof n!="object"||n.errcode!==0)throw new gt("registration-rejected",`\u9489\u9489\u626B\u7801${t}\u5931\u8D25\u3002`);return n}function Rb(n,t){let o=Number(n);return Number.isFinite(o)&&o>0?o:t}function GH({fetchImpl:n=fetch,registrationBaseUrl:t=process.env.DINGTALK_REGISTRATION_BASE_URL||TH,registrationSource:o=process.env.DINGTALK_REGISTRATION_SOURCE||Wge,now:i=()=>Date.now(),cardMinIntervalMs:e=50,cardBackoffMs:a=1e3,delay:A=oce}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");if(typeof i!="function")throw new TypeError("now must be a function");if(!Number.isFinite(e)||e<0)throw new TypeError("cardMinIntervalMs must be a non-negative number");if(!Number.isFinite(a)||a<0)throw new TypeError("cardBackoffMs must be a non-negative number");if(typeof A!="function")throw new TypeError("delay must be a function");let r=kb(t,{label:"\u9489\u9489\u6CE8\u518C\u670D\u52A1",requireSubdomain:!1}),s=new URL(Vge),g=WA(o);if(!g)throw new TypeError("registrationSource is required");let c=new Map,I=new Map,d=new Map,B=Promise.resolve(),f=0,Q=(H,j)=>new URL(j.replace(/^\//,""),H);async function y({clientId:H,clientSecret:j,signal:q,requestKind:U="normal"}){let R=WA(H),V=WA(j);if(!R||!V)throw new TypeError("clientId and clientSecret are required");let L=c.get(R);if(L&&L.expiresAt>i())return L.token;let T=U==="reaction"?d:I;if(T.has(R))return T.get(R);let W=(async()=>{let ae=await bn(n,Q(s,"v1.0/oauth2/accessToken"),{body:{appKey:R,appSecret:V},signal:q,action:"\u9274\u6743"}),ge=WA(ae?.accessToken);if(!ge)throw new gt("invalid-access-token","\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u8BBF\u95EE\u4EE4\u724C\u3002");let Se=Rb(ae?.expireIn??ae?.expiresIn,7200),de=Math.max(1e3,(Se-60)*1e3);return c.set(R,{token:ge,expiresAt:i()+de}),ge})().finally(()=>T.delete(R));return T.set(R,W),W}async function m({clientId:H,clientSecret:j,robotCode:q,messageId:U,conversationId:R,reactionName:V=zc,signal:L},T){let P=WA(H),W=WA(j),ae=WA(q)??P,ge=WA(U),Se=WA(R),de=WA(V);if(!P||!W)throw new TypeError("clientId and clientSecret are required");if(!ae)throw new TypeError("robotCode is required");if(!ge||!Se)throw new TypeError("messageId and conversationId are required");if(!de)throw new TypeError("reactionName is required");let De=await y({clientId:P,clientSecret:W,signal:L,requestKind:"reaction"}),Be=await bn(n,Q(s,`v1.0/robot/emotion/${T}`),{body:{robotCode:ae,openMsgId:ge,openConversationId:Se,emotionType:2,emotionName:de,textEmotion:{emotionId:ece,emotionName:de,text:de,backgroundId:Ace}},headers:{"x-acs-dingtalk-access-token":De},signal:L,timeoutMs:$ge,action:T==="reply"?"\u6D88\u606F\u72B6\u6001\u6DFB\u52A0":"\u6D88\u606F\u72B6\u6001\u64A4\u56DE"}),ve=Be?.success===!1?qh(Be?.code??Be?.errcode)??"rejected":_b(Be);if(ve)throw new gt("reaction-rejected","\u9489\u9489\u670D\u52A1\u62D2\u7EDD\u4E86\u6D88\u606F\u72B6\u6001\u8BF7\u6C42\u3002",{providerCode:ve});return!0}async function _({clientId:H,clientSecret:j,robotCode:q,downloadCode:U,signal:R,kind:V}){let L=WA(q),T=WA(U);if(!L||!T)throw new TypeError("robotCode and downloadCode are required");let P=await y({clientId:H,clientSecret:j,signal:R}),W;try{W=await bn(n,Q(s,"v1.0/robot/messageFiles/download"),{body:{downloadCode:T,robotCode:L},headers:{"x-acs-dingtalk-access-token":P},signal:R,action:`${V==="image"?"\u56FE\u7247":"\u6587\u4EF6"}\u4E0B\u8F7D\u5730\u5740`})}catch(ge){throw R?.aborted?ge:new gt(`${V}-download-address-failed`,`\u9489\u9489${V==="image"?"\u56FE\u7247":"\u6587\u4EF6"}\u4E0B\u8F7D\u5730\u5740\u83B7\u53D6\u5931\u8D25\u3002`,{cause:ge,status:ge?.status,providerCode:ge?.providerCode})}let ae=WA(W?.downloadUrl??W?.download_url);if(!ae)throw new gt(`invalid-${V}-download`,`\u9489\u9489\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE${V==="image"?"\u56FE\u7247":"\u6587\u4EF6"}\u4E0B\u8F7D\u5730\u5740\u3002`);return ice(ae)}function N(H){let j=async()=>{let U=Math.max(0,f-i());U>0&&await A(U,H),f=Math.max(f,i())+e},q=B.then(j,j);return B=q.catch(()=>{}),q}async function G(H,j){await N(j.signal);try{return await bn(n,Q(s,H),j)}catch(q){if(!(q instanceof gt)||q.status!==403)throw q;return await A(a,j.signal),await N(j.signal),bn(n,Q(s,H),j)}}async function Y({clientId:H,clientSecret:j,cardInstanceId:q,text:U,signal:R}){let V=WA(q),L=WA(U);if(!V)throw new TypeError("cardInstanceId is required");if(!L)throw new TypeError("text is required");let P={"x-acs-dingtalk-access-token":await y({clientId:H,clientSecret:j,signal:R})},W=[G("v1.0/card/streaming",{method:"PUT",body:{outTrackId:V,guid:Yh(),key:"msgContent",content:Jh(L),isFull:!0,isFinalize:!1,isError:!0},headers:P,signal:R,action:"AI Card \u5931\u8D25\u6536\u53E3"}),G("v1.0/card/instances",{method:"PUT",body:{outTrackId:V,cardData:Tb(L,"5"),cardUpdateOptions:{updateCardDataByKey:!0}},headers:P,signal:R,action:"AI Card \u5931\u8D25\u72B6\u6001"})],ae=await Promise.allSettled(W);if(ae.every(({status:ge})=>ge==="rejected"))throw ae[0].reason;return!0}async function J({clientId:H,clientSecret:j,target:q,file:U,signal:R},{uploadType:V,messageKey:L,createMessageParams:T}){if(!U||typeof U!="object"||typeof U.fileName!="string"||!U.fileName||!Buffer.isBuffer(U.bytes))throw new TypeError("A DingTalk file is required");let P=sce(q),W;try{W=await y({clientId:H,clientSecret:j,signal:R})}catch(Re){if(R?.aborted)throw Mn(R);let AA=Number(Re?.status),ue=Re?.code==="http-error"&&AA>=400&&AA<500?"artifact-provider-rejected":"artifact-provider-failed";throw jh(Re,{fallback:ue})}let ae=new URL("media/upload",TH);ae.searchParams.set("access_token",W),ae.searchParams.set("type",V);let ge=new FormData;ge.append("media",new Blob([U.bytes],{type:U.mediaType??"application/octet-stream"}),U.fileName);let Se;try{Se=await nce(n,ae,{body:ge,signal:R})}catch(Re){if(R?.aborted)throw Mn(R);let AA=Number(Re?.status),ue=Re?.code==="http-error"&&AA>=400&&AA<500?"artifact-provider-rejected":"artifact-provider-failed";throw jh(Re,{fallback:ue})}let de=_b(Se),De=WA(Se?.media_id);if(de||!De)throw jh(new gt("upload-rejected","\u9489\u9489\u670D\u52A1\u62D2\u7EDD\u4E86\u6587\u4EF6\u4E0A\u4F20\u3002",{providerCode:de??"missing-media-id"}));R?.throwIfAborted();let Be={robotCode:P.robotCode,msgKey:L,msgParam:JSON.stringify(T(De,U)),...P.type==="group"?{openConversationId:P.openConversationId}:{userIds:[P.userId]}},ve=P.type==="group"?"v1.0/robot/groupMessages/send":"v1.0/robot/oToMessages/batchSend",eA;try{eA=await bn(n,Q(s,ve),{body:Be,headers:{"x-acs-dingtalk-access-token":W},signal:R,action:"\u6587\u4EF6\u6D88\u606F\u53D1\u9001"})}catch(Re){throw ace(Re,R)}let iA=_b(eA);if(iA)throw jh(new gt("send-rejected","\u9489\u9489\u670D\u52A1\u62D2\u7EDD\u4E86\u6587\u4EF6\u6D88\u606F\u3002",{providerCode:iA}));return eA}return Object.freeze({async beginRegistration({signal:H}={}){let j=Nb(await bn(n,Q(r,"app/registration/init"),{body:{source:g},signal:H,action:"\u521D\u59CB\u5316"}),"\u521D\u59CB\u5316"),q=WA(j.nonce);if(!q)throw new gt("invalid-registration","\u9489\u9489\u626B\u7801\u521D\u59CB\u5316\u7F3A\u5C11 nonce\u3002");let U=Nb(await bn(n,Q(r,"app/registration/begin"),{body:{nonce:q},signal:H,action:"\u521B\u5EFA"}),"\u521B\u5EFA"),R=WA(U.device_code),V=WA(U.verification_uri_complete);if(!R||!V)throw new gt("invalid-registration","\u9489\u9489\u626B\u7801\u670D\u52A1\u8FD4\u56DE\u7684\u4FE1\u606F\u4E0D\u5B8C\u6574\u3002");let L=kb(V,{label:"\u9489\u9489\u626B\u7801",requireSubdomain:!1}).toString();return{deviceCode:R,userCode:WA(U.user_code)??void 0,verificationUri:WA(U.verification_uri)??void 0,verificationUriComplete:L,expiresInSeconds:Rb(U.expires_in,7200),intervalSeconds:Rb(U.interval,5)}},async pollRegistration({deviceCode:H,signal:j}={}){let q=WA(H);if(!q)throw new TypeError("deviceCode is required");let U=Nb(await bn(n,Q(r,"app/registration/poll"),{body:{device_code:q},signal:j,action:"\u72B6\u6001\u67E5\u8BE2"}),"\u72B6\u6001\u67E5\u8BE2"),R=WA(U.status)?.toUpperCase();if(!R||!tce.has(R))throw new gt("invalid-registration-status","\u9489\u9489\u626B\u7801\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u72B6\u6001\u3002");let V={status:R,failReason:WA(U.fail_reason)??void 0};if(R==="SUCCESS"&&(V.clientId=WA(U.client_id)??void 0,V.clientSecret=WA(U.client_secret)??void 0,!V.clientId||!V.clientSecret))throw new gt("missing-credentials","\u9489\u9489\u626B\u7801\u5DF2\u786E\u8BA4\uFF0C\u4F46\u6CA1\u6709\u8FD4\u56DE\u673A\u5668\u4EBA\u51ED\u636E\u3002");return V},accessToken:y,async addReaction(H){return m(H,"reply")},async recallReaction(H){return m(H,"recall")},async addThinkingReaction(H){return m({...H,reactionName:zc},"reply")},async recallThinkingReaction(H){return m({...H,reactionName:zc},"recall")},async downloadImage({clientId:H,clientSecret:j,robotCode:q,downloadCode:U,signal:R,maxBytes:V}){let L=await _({clientId:H,clientSecret:j,robotCode:q,downloadCode:U,signal:R,kind:"image"});try{return await no(L,{fetchImpl:n,signal:R,maxBytes:V})}catch(T){throw R?.aborted||T instanceof ut?T:new gt("image-content-download-failed","\u9489\u9489\u56FE\u7247\u5185\u5BB9\u4E0B\u8F7D\u5931\u8D25\u3002",{cause:T})}},async downloadFile({clientId:H,clientSecret:j,robotCode:q,downloadCode:U,signal:R}){let V=await _({clientId:H,clientSecret:j,robotCode:q,downloadCode:U,signal:R,kind:"file"});if(V.protocol!=="https:")throw new gt("invalid-file-download","\u9489\u9489\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u6587\u4EF6\u4E0B\u8F7D\u5730\u5740\u3002");try{let L=await n(V,{method:"GET",redirect:"follow",signal:R});if(!L?.ok)throw await L?.body?.cancel?.().catch?.(()=>{}),new gt("file-content-download-failed",`\u9489\u9489\u6587\u4EF6\u5185\u5BB9\u4E0B\u8F7D\u5931\u8D25\uFF08HTTP ${L?.status??"unknown"}\uFF09\u3002`,{status:L?.status});return Buffer.from(await L.arrayBuffer())}catch(L){throw R?.aborted?Mn(R):L instanceof gt?L:new gt("file-content-download-failed","\u9489\u9489\u6587\u4EF6\u5185\u5BB9\u4E0B\u8F7D\u5931\u8D25\u3002",{cause:L})}},async createAiCard({clientId:H,clientSecret:j,target:q,initialText:U,signal:R}){let V=WA(H),L=WA(j),T=WA(U);if(!V||!L)throw new TypeError("clientId and clientSecret are required");if(!T)throw new TypeError("initialText is required");let P=cce(q),W=await y({clientId:V,clientSecret:L,signal:R}),ae=`dsh_${Yh()}`,ge={"x-acs-dingtalk-access-token":W},Se=!1;try{await G("v1.0/card/instances",{body:{cardTemplateId:Zge,outTrackId:ae,cardData:{cardParamMap:{config:JSON.stringify({autoLayout:!0})}},callbackType:"STREAM",imGroupOpenSpaceModel:{supportForward:!0},imRobotOpenSpaceModel:{supportForward:!0}},headers:ge,signal:R,action:"AI Card \u521B\u5EFA"}),await G("v1.0/card/instances/deliver",{body:Ice(ae,P,V),headers:ge,signal:R,action:"AI Card \u6295\u653E"}),Se=!0,await G("v1.0/card/instances",{method:"PUT",body:{outTrackId:ae,cardData:Tb(T,"2")},headers:ge,signal:R,action:"AI Card \u542F\u52A8"}),await G("v1.0/card/streaming",{method:"PUT",body:{outTrackId:ae,guid:Yh(),key:"msgContent",content:Jh(T).replace(/\n+$/,""),isFull:!0,isFinalize:!1,isError:!1},headers:ge,signal:R,action:"AI Card \u542F\u52A8"})}catch(de){if(Se){let De=AbortSignal.timeout(5e3);await Y({clientId:V,clientSecret:L,cardInstanceId:ae,text:D("\u5361\u7247\u5DF2\u7ED3\u675F\uFF0C\u8BF7\u67E5\u770B\u540E\u7EED\u6D88\u606F\u3002"),signal:De}).catch(()=>{})}throw de}return{cardInstanceId:ae}},async updateAiCard({clientId:H,clientSecret:j,cardInstanceId:q,text:U,signal:R}){let V=WA(q),L=WA(U);if(!V)throw new TypeError("cardInstanceId is required");if(!L)throw new TypeError("text is required");let T=await y({clientId:H,clientSecret:j,signal:R});return await G("v1.0/card/streaming",{method:"PUT",body:{outTrackId:V,guid:Yh(),key:"msgContent",content:Jh(L).replace(/\n+$/,""),isFull:!0,isFinalize:!1,isError:!1},headers:{"x-acs-dingtalk-access-token":T},signal:R,action:"AI Card \u66F4\u65B0"}),!0},async finishAiCard({clientId:H,clientSecret:j,cardInstanceId:q,text:U,signal:R}){let V=WA(q),L=WA(U);if(!V)throw new TypeError("cardInstanceId is required");if(!L)throw new TypeError("text is required");let P={"x-acs-dingtalk-access-token":await y({clientId:H,clientSecret:j,signal:R})},W=Jh(L);await G("v1.0/card/streaming",{method:"PUT",body:{outTrackId:V,guid:Yh(),key:"msgContent",content:W,isFull:!0,isFinalize:!0,isError:!1},headers:P,signal:R,action:"AI Card \u5B8C\u6210"});let ae=!0,ge={method:"PUT",body:{outTrackId:V,cardData:Tb(L,"3"),cardUpdateOptions:{updateCardDataByKey:!0}},headers:P,signal:R,action:"AI Card \u6536\u53E3"};try{await G("v1.0/card/instances",ge)}catch{try{await G("v1.0/card/instances",ge)}catch{ae=!1}}return{delivered:!0,completed:ae}},failAiCard:Y,async sendText({clientId:H,clientSecret:j,sessionWebhook:q,text:U,signal:R}){let V=WA(U);if(!V)throw new TypeError("text is required");let L=Rg(q),T=await y({clientId:H,clientSecret:j,signal:R}),P=await bn(n,L,{body:{msgtype:"text",text:{content:V}},headers:{"x-acs-dingtalk-access-token":T},signal:R,action:"\u6D88\u606F\u56DE\u590D"});if(P?.errcode!==void 0&&P.errcode!==0||P?.code!==void 0&&P.code!==0)throw new gt("send-rejected","\u9489\u9489\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async sendFile(H){return J(H,{uploadType:"file",messageKey:"sampleFile",createMessageParams:(j,q)=>({mediaId:j,fileName:q.fileName,fileType:gce(q.fileName)})})},async sendImage(H){return J(H,{uploadType:"image",messageKey:"sampleImageMsg",createMessageParams:j=>({photoURL:j})})},clearAccessToken(H){let j=WA(H);j&&c.delete(j)}})}var lce=500,pce="\u5361\u7247\u5DF2\u7ED3\u675F\uFF0C\u8BF7\u67E5\u770B\u540E\u7EED\u6D88\u606F\u3002";function vb(n,t){if(typeof n!="string")throw new TypeError(`${t} must be a string`);return n}function FH(n,t){if(typeof n!="string"||!n.trim())throw new TypeError(`${t} is required`);return n.trim()}function LH({api:n,clientId:t,clientSecret:o,target:i,signal:e,logger:a=console,updateIntervalMs:A=lce,clock:r=()=>Date.now(),timer:s={setTimeout:(g,c)=>globalThis.setTimeout(g,c),clearTimeout:g=>globalThis.clearTimeout(g)}}={}){if(!n||typeof n.createAiCard!="function"||typeof n.updateAiCard!="function"||typeof n.finishAiCard!="function")throw new TypeError("DingTalk AI Card API is required");let g=FH(t,"clientId"),c=FH(o,"clientSecret");if(i==null)throw new TypeError("target is required");if(!Number.isFinite(A)||A<0)throw new TypeError("updateIntervalMs must be a non-negative number");if(typeof r!="function")throw new TypeError("clock must be a function");if(typeof s?.setTimeout!="function"||typeof s?.clearTimeout!="function")throw new TypeError("timer must provide setTimeout and clearTimeout");let I=()=>{let T=r();if(!Number.isFinite(T))throw new TypeError("clock must return a finite timestamp");return T};I();let d=e?.aborted?"aborted":"idle",B=null,f=null,Q=null,y=null,m=null,_=null,N=0,G=()=>{Q!==null&&(s.clearTimeout(Q),Q=null)},Y=()=>e?.removeEventListener("abort",q),J=T=>{d=T,f=null,G(),Y()},H=()=>!B||typeof n.failAiCard!="function"?Promise.resolve(!1):(_||(_=n.failAiCard({...B,text:D(pce),signal:AbortSignal.timeout(5e3)}).then(()=>!0,()=>!1)),_),j=T=>{d==="failed"||d==="finished"||d==="aborted"||(H(),J("failed"),a?.error?.(`[dsh-dingtalk] AI Card ${T} failed`))};function q(){d==="finished"||d==="failed"||d==="aborted"||(H(),J("aborted"))}d!=="aborted"&&e?.addEventListener("abort",q,{once:!0});let U=()=>{if(d!=="active"||y||f===null)return;let T=Math.max(0,N+A-I());if(T>0){Q=s.setTimeout(()=>{Q=null,U()},T);return}let P=f;f=null,y=(async()=>{try{await n.updateAiCard({...B,text:P,finished:!1}),N=I()}catch{if(e?.aborted||d==="aborted")return;j("update")}})().finally(()=>{y=null,d==="active"&&f!==null&&U()})};return Object.freeze({start:async T=>{if(vb(T,"initialText"),d!=="idle")return!1;d="starting";try{let P=await n.createAiCard({clientId:g,clientSecret:c,target:i,initialText:T,signal:e}),W=typeof P?.cardInstanceId=="string"?P.cardInstanceId.trim():"";if(!W)throw new TypeError("DingTalk did not return a card instance id");return B=Object.freeze({clientId:g,clientSecret:c,target:i,cardInstanceId:W,signal:e}),d!=="starting"?(H(),!1):(N=I(),d="active",!0)}catch{return e?.aborted||d==="aborted"?(J("aborted"),!1):(j("creation"),!1)}},push:T=>{vb(T,"progressText"),d==="active"&&(f=T,!Q&&!y&&U())},finish:T=>{if(vb(T,"finalText"),d==="finished")return Promise.resolve(!0);if(d==="finishing")return m;if(d!=="active")return Promise.resolve(!1);d="finishing",f=null,G();let P=y;return m=(async()=>{if(P&&await P,d!=="finishing")return!1;try{return await n.finishAiCard({...B,text:T}),d!=="finishing"?!1:(J("finished"),!0)}catch{return e?.aborted||d==="aborted"?(J("aborted"),!1):(j("finish"),!1)}})(),m}})}function df(n){return typeof n=="string"&&n.trim()?n.trim():null}function ti(n){return n&&typeof n.id=="string"&&typeof n.question=="string"&&(n.header===void 0||typeof n.header=="string")&&(n.detail===void 0||typeof n.detail=="string")&&(n.multiSelect===void 0||typeof n.multiSelect=="boolean")&&(n.options===void 0||Array.isArray(n.options)&&n.options.every(t=>t&&typeof t.label=="string"&&(t.description===void 0||typeof t.description=="string")))}function ri(n,t,o,{requiresMention:i=!1}={}){let e=[],a=o>1?`\uFF08${t+1}/${o}\uFF09`:"";e.push(D("DeepSeek Harness \u9700\u8981\u4F60\u8865\u5145\u4FE1\u606F{progress}\uFF1A",{progress:a})),df(n.header)&&e.push("",n.header.trim()),e.push("",df(n.question)??D("\u8BF7\u8F93\u5165\u4F60\u7684\u56DE\u7B54\u3002")),df(n.detail)&&e.push("",n.detail.trim());let A=Array.isArray(n.options)?n.options:[];return A.length>0?(e.push(""),A.forEach((r,s)=>{let g=typeof r?.label=="string"?r.label:"",c=df(r?.description);e.push(`${s+1}. ${g}${c?` \u2014 ${c}`:""}`)}),e.push("",n.multiSelect===!0?D("\u8BF7\u56DE\u590D\u9009\u9879\u5E8F\u53F7\u6216\u6587\u5B57\uFF1B\u591A\u9009\u7528\u9017\u53F7\u5206\u9694\uFF0C\u4E5F\u53EF\u8865\u5145\u5176\u4ED6\u5185\u5BB9\u3002"):D("\u8BF7\u56DE\u590D\u4E00\u4E2A\u9009\u9879\u5E8F\u53F7\u6216\u6587\u5B57\uFF0C\u4E5F\u53EF\u76F4\u63A5\u8F93\u5165\u5176\u4ED6\u7B54\u6848\u3002"))):e.push("",D("\u8BF7\u76F4\u63A5\u56DE\u590D\u4F60\u7684\u7B54\u6848\u3002")),i&&e.push("",D("\u7FA4\u804A\u4E2D\u8BF7 @\u673A\u5668\u4EBA \u540E\u53D1\u9001\u7B54\u6848\u3002")),e.join(`
145
145
  `)}function UH(n,t){let o=n.trim();if(!o)return null;if(/^\d+$/.test(o)){let e=t[Number(o)-1];return typeof e?.label=="string"?e.label:null}let i=t.find(e=>e?.label===o);return typeof i?.label=="string"?i.label:null}function ai(n,t){let o=Array.isArray(n.options)?n.options:[];if(o.length===0)return{id:n.id,selected:[],custom:t};let i=UH(t,o);if(n.multiSelect!==!0)return i?{id:n.id,selected:[i]}:{id:n.id,selected:[],custom:t};if(i)return{id:n.id,selected:[i]};let e=[],a=[];for(let A of t.split(/[,,、;;\n]+/)){let r=A.trim();if(!r)continue;let s=UH(r,o);s?e.includes(s)||e.push(s):a.push(r)}return{id:n.id,selected:e,...a.length>0?{custom:a.join("\u3001")}:{}}}var dce=new Map([["\u6279\u51C6","allowed-once"],["\u540C\u610F","allowed-once"],["yes","allowed-once"],["\u62D2\u7EDD","rejected"],["\u4E0D\u540C\u610F","rejected"],["no","rejected"]]),Pb="\u8BF7\u7CBE\u51C6\u56DE\u590D\u300C\u6279\u51C6\u300D\u6216\u300C\u62D2\u7EDD\u300D\uFF08\u4E5F\u652F\u6301\uFF1A\u540C\u610F / \u4E0D\u540C\u610F / yes / no\uFF09\u3002",hce="\u8BF7\u5148\u5B8C\u6210\u5F53\u524D\u95EE\u9898\uFF0C\u518D\u7CBE\u51C6\u56DE\u590D\u300C\u6279\u51C6\u300D\u6216\u300C\u62D2\u7EDD\u300D\u3002",Gl="\u8BE5\u5BA1\u6279\u5DF2\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u590D\u3002",Ece=5*6e4,Cce=2048;function wa(n){return typeof n=="string"?n.trim():""}function Gb(n){return wa(n).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g,"")}function uce(n){return dce.get(wa(n).toLowerCase())??null}function KH(n){return n?.type==="approval/requested"&&!!wa(n.sessionId)&&!!wa(n.approvalId)&&!!wa(n.toolName)&&(n.callId===void 0||!!wa(n.callId))&&(n.reason===void 0||typeof n.reason=="string")}function Bce(n){let t=n?.arguments;if(t!==null&&typeof t=="object")try{return JSON.stringify(t,null,2)}catch{return null}if(typeof t!="string")return null;let o=Gb(t);if(!o)return t===""?"{}":null;try{return JSON.stringify(JSON.parse(o),null,2)}catch{return o}}function Fb(n,{toolCall:t,requiresMention:o=!1,maxArgumentsLength:i=6e3}={}){if(!KH(n))return null;let e=wa(n.callId);if(!e||wa(t?.callId)!==e||wa(t?.name)!==wa(n.toolName))return null;let a=Bce(t);if(!a||a.length>i)return null;let A=[D("DeepSeek Harness \u9700\u8981\u4F60\u7684\u5BA1\u6279\uFF1A"),"",D("\u5DE5\u5177\uFF1A{tool}",{tool:Gb(n.toolName)}),D("\u64CD\u4F5C\u53C2\u6570\uFF1A"),a],r=Gb(n.reason);return r&&A.push(D("\u539F\u56E0\uFF1A{reason}",{reason:r})),A.push("",D(Pb)),o&&A.push("",D("\u7FA4\u804A\u4E2D\u8BF7 @\u673A\u5668\u4EBA \u540E\u53D1\u9001\u5BA1\u6279\u51B3\u5B9A\u3002")),A.join(`
146
- `)}function HH(n,t){return{ok:!0,value:{sessionId:n.sessionId,approvalId:n.approvalId,outcome:t}}}function hf(n){return n==="allowed-once"?D("\u5DF2\u6279\u51C6\uFF0C\u4EC5\u5BF9\u672C\u6B21\u64CD\u4F5C\u6709\u6548\u3002"):n==="rejected"?D("\u5DF2\u62D2\u7EDD\u6B64\u6B21\u64CD\u4F5C\u3002"):D(Gl)}var ii=class{#e;#A;#t=new Map;#r=new Map;#a=new Map;constructor({label:t="IM",logger:o=console}={}){this.#e=t,this.#A=o}hasPending(t){return this.#r.get(t)?.items.some(o=>!o.inactive)===!0}claimReply({key:t,actor:o,text:i,addressed:e=!0,hasPendingQuestion:a=!1,questionCompletion:A,isQuestionPending:r,send:s}){let c=this.#r.get(t)?.items[0],I=uce(i),d=(f,Q=!1)=>({...Q?{resolved:!0}:{},process:async y=>{typeof y=="function"&&await y()===!1||await s(f)}}),B=a&&c&&A&&typeof A.then=="function";return a&&!B?null:!c||c.inactive?(this.#a.get(t)??0)<=Date.now()?(this.#a.delete(t),null):I?d(D(Gl),!0):null:c.actor!==o||c.requiresMention&&e!==!0?I?d(D("\u53EA\u6709\u53D1\u8D77\u5F53\u524D\u4EFB\u52A1\u7684\u7528\u6237\u53EF\u4EE5\u5904\u7406\u8FD9\u6761\u5BA1\u6279\u3002")):null:{process:async f=>{let Q=c.presented,m=(c.replyTail??Promise.resolve()).catch(()=>{}).then(async()=>{if(!(typeof f=="function"&&await f()===!1)){if(B){if(await A.catch(()=>{}),c.inactive||c.resolving)return;if(typeof r=="function"&&r()){await s(D(hce));return}}if(await c.activationTask?.catch(()=>{}),await c.presentationTask?.catch(()=>{}),c.inactive||c.resolving){await s(D(Gl));return}if(c.send=s,!Q||!c.presented){if(c.presented||await this.#i(c),c.inactive||c.resolving)return;await s(D(Pb));return}if(c.submitting){await s(D("\u5BA1\u6279\u51B3\u5B9A\u6B63\u5728\u63D0\u4EA4\uFF0C\u8BF7\u7A0D\u5019\u3002"));return}if(!I){await s(D(Pb));return}await this.#c(c,I)}});c.replyTail=m;try{await m}finally{c.replyTail===m&&(c.replyTail=null)}}}}async handleRequested(t,o){if(t?.kind!=="approval")return!1;let i=t.payload,e=wa(i?.approvalId);if(!wa(t.rpcId)||!wa(t.sessionId)||!e||!KH(i)||i.sessionId!==t.sessionId||typeof t.respond!="function")return this.#A.warn?.(`[dsh-im:${this.#e}] ignored an invalid Harness approval`),!0;if(t.recovered===!0)return await this.#g(t,i),!0;let a=this.#t.get(e);if(a)return a.interaction=t,a.toolCall=t.toolCall,a.presented||await this.#i(a),!0;let A=o?.send,r=wa(o?.key),s=wa(o?.actor);if(!r||!s||typeof A!="function")return this.#A.warn?.(`[dsh-im:${this.#e}] ignored an approval without a reply route`),await this.#g(t,i),!0;let g=Fb(i,{toolCall:t.toolCall,requiresMention:o.requiresMention===!0});if(!g){let d=await this.#g(t,i);return await A(d?D("\u65E0\u6CD5\u5B8C\u6574\u5C55\u793A\u8FD9\u6B21\u64CD\u4F5C\uFF0C\u5DF2\u5B89\u5168\u62D2\u7EDD\u6B64\u6B21\u5BA1\u6279\u3002"):D(Gl)),!0}let c={approvalId:e,sessionId:t.sessionId,interaction:t,toolCall:t.toolCall,key:r,actor:s,requiresMention:o.requiresMention===!0,send:A,text:g,presented:!1,presentationTask:null,deliveryCompleted:!1,replyTail:null,submitting:!1,inactive:!1,resolving:!1,closedOutcome:null,resolutionNotified:!1,activationTask:null};this.#t.set(e,c);let I=this.#r.get(r)??{items:[]};return I.items.push(c),this.#r.set(r,I),I.items[0]===c&&await this.#i(c),!0}async handleResolved(t){if(t?.kind!=="approval")return!1;let o=this.#t.get(wa(t.interactionId));if(!o||(o.resolving=!0,o.activationTask&&await o.activationTask.catch(()=>{}),o.inactive||this.#t.get(o.approvalId)!==o))return!0;let i=o.presentationTask,e=o.presented||i,a=o.send,A=this.#o(o);return await this.#s(A,async()=>{let r=o.presented;i&&(r=await i.then(()=>!0,()=>!1)),e&&r&&(o.resolutionNotified=!0,await a(hf(t.outcome)).catch(()=>{}))}),!0}async closeRoute(t){let o=this.#r.get(t);if(!o)return;let i=[...o.items];for(let e of i)this.#o(e);await Promise.all(i.map(async e=>{try{await e.interaction.respond(HH(e,"rejected"),{signal:AbortSignal.timeout(5e3)}),e.closedOutcome="rejected",(e.presented||e.deliveryCompleted)&&!e.resolutionNotified&&(e.resolutionNotified=!0,await e.send(hf("rejected")).catch(()=>{}))}catch(a){a?.code==="interaction-not-pending"?(e.closedOutcome="resolved",(e.presented||e.deliveryCompleted)&&!e.resolutionNotified&&(e.resolutionNotified=!0,await e.send(D(Gl)).catch(()=>{}))):this.#A.warn?.(`[dsh-im:${this.#e}] failed to reject a closing approval:`,a)}}))}async#i(t){if(this.#r.get(t.key)?.items[0]!==t||t.inactive||t.resolving||t.presented||(await t.activationTask?.catch(()=>{}),this.#r.get(t.key)?.items[0]!==t||t.inactive||t.resolving||t.presented))return;if(t.presentationTask)return t.presentationTask;let o=Promise.resolve().then(()=>t.send(t.text));t.presentationTask=o;try{await o,t.deliveryCompleted=!0,t.inactive?t.closedOutcome&&!t.resolutionNotified&&(t.resolutionNotified=!0,await t.send(hf(t.closedOutcome)).catch(()=>{})):t.presented=!0}finally{t.presentationTask===o&&(t.presentationTask=null)}}async#c(t,o){t.submitting=!0;try{await t.interaction.respond(HH(t,o))}catch(a){if(a?.code==="interaction-not-pending"){let A=t.send,r=this.#o(t);await this.#s(r,async()=>{t.resolutionNotified||await A(D(Gl)).catch(()=>{})});return}if(t.inactive)return;t.submitting=!1,this.#A.error?.(`[dsh-im:${this.#e}] failed to submit an approval:`,a),await t.send(D("\u5BA1\u6279\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u56DE\u590D\u300C\u6279\u51C6\u300D\u6216\u300C\u62D2\u7EDD\u300D\u3002")).catch(()=>{});return}let i=t.send,e=this.#o(t);await this.#s(e,async()=>{t.resolutionNotified||await i(hf(o)).catch(()=>{})})}async#s(t,o){let i,e=new Promise(a=>{i=a});t&&(t.activationTask=e);try{await o()}finally{i(),t?.activationTask===e&&(t.activationTask=null)}await this.#I(t)}async#I(t){if(t)try{await this.#i(t)}catch(o){this.#A.error?.(`[dsh-im:${this.#e}] failed to present the next approval:`,o);try{t.interaction.reconnect?.()}catch{}}}#o(t){if(t.inactive)return null;t.inactive=!0,this.#n(t.key),this.#t.delete(t.approvalId);let o=this.#r.get(t.key);if(!o)return null;let i=o.items[0]===t,e=o.items.indexOf(t);return e!==-1&&o.items.splice(e,1),o.items.length===0?(this.#r.delete(t.key),null):i?o.items[0]:null}#n(t){let o=Date.now();for(let[i,e]of this.#a)e<=o&&this.#a.delete(i);for(this.#a.delete(t),this.#a.set(t,o+Ece);this.#a.size>Cce;)this.#a.delete(this.#a.keys().next().value)}async#g(t,o){try{return await t.respond({ok:!0,value:{sessionId:t.sessionId,approvalId:o.approvalId,outcome:"rejected"}},{signal:AbortSignal.timeout(5e3)}),!0}catch(i){if(i?.code==="interaction-not-pending")return!1;throw i}}};var Lb=new WeakMap;function fce(n){let t=Lb.get(n);return t||(t=new Map,Lb.set(n,t)),t}async function Vc(n,t,o){let i=typeof n;if(i!=="object"&&i!=="function"||n===null)throw new TypeError("state is required");if(typeof t!="string"||!t)throw new TypeError("conversation key is required");if(typeof o!="function")throw new TypeError("operation is required");let e=fce(n),a=e.get(t)??Promise.resolve(),A,r=new Promise(s=>{A=s});e.set(t,r),await a;try{return await o()}finally{A(),e.get(t)===r&&(e.delete(t),e.size===0&&Lb.delete(n))}}var oi="workspace-session-stale";function xH(n,t){return typeof n.workspaceSession=="function"?n.workspaceSession(t):Object.freeze({sessionId:t,sessionExists:(...o)=>n.sessionExists(t,...o),models:(...o)=>n.getSessionModels(t,...o),selectModel:(...o)=>n.selectSessionModel(t,...o),isRunning:(...o)=>n.isSessionRunning(t,...o),hasActiveTurn:(...o)=>n.hasActiveTurn(t,...o),stopActiveTurn:(...o)=>n.stopActiveTurn(t,...o),steerActiveTurn:(...o)=>n.steerActiveTurn(t,...o),ask:(...o)=>n.ask(t,...o)})}async function Qce(n,t){return t===void 0?n.sessionExists():n.sessionExists(t)}async function yce(n,t){return t===void 0?n.createSession():n.createSession(t)}async function ni({harness:n,state:t,key:o,text:i,content:e,createOptions:a,existsOptions:A,askOptions:r}){for(;;)try{let s=await Vc(t,o,async()=>{let B=t.sessionFor(o),f=B?xH(n,B):null;if(!f||!await Qce(f,A)){if(B=await yce(n,a),await t.setSession(o,B)===!1)return null;f=xH(n,B)}return{sessionId:B,session:f}});if(!s)continue;let g=[],c=typeof r=="object"&&typeof r?.onArtifact=="function"?r.onArtifact:null,I=typeof r=="number"?{timeoutMs:r}:{...r};I.onArtifact=async B=>{g.push(B),await c?.(B)};let d=await s.session.ask(e??i,I);return{sessionId:s.sessionId,answer:d,...g.length>0?{artifacts:g}:{}}}catch(s){if(s?.code!==oi)throw s}}var mce=/^\/compact(?=$|\s)([\s\S]*)$/i,Sce="\u7528\u6CD5\uFF1A/compact\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",YH=new Map([["No compactable history yet.","\u6682\u65E0\u53EF\u538B\u7F29\u7684\u5386\u53F2\u8BB0\u5F55\u3002"],["Compaction is unavailable because this process has an active compaction, or the agent is not idle.","\u5F53\u524D\u4F1A\u8BDD\u6B63\u5728\u751F\u6210\u56DE\u590D\u6216\u6267\u884C\u538B\u7F29\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"],["Compaction cancelled.","\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88\u3002"],["The history selected for compaction changed before it could be replaced. The conversation is unchanged; the attempt is recorded in the session log.","\u538B\u7F29\u671F\u95F4\u4F1A\u8BDD\u5386\u53F2\u53D1\u751F\u53D8\u5316\uFF0C\u672C\u6B21\u672A\u4FEE\u6539\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u8BD5\u3002"],["Compaction could not produce a useful summary. The conversation is unchanged; the attempt is recorded in the session log.","\u672A\u80FD\u751F\u6210\u6709\u6548\u7684\u538B\u7F29\u6458\u8981\uFF0C\u672C\u6B21\u672A\u4FEE\u6539\u4F1A\u8BDD\u3002"],["Compaction did not finish cleanly; some session history may have changed. Inspect the current session state before retrying.","\u4E0A\u4E0B\u6587\u538B\u7F29\u672A\u6B63\u5E38\u5B8C\u6210\uFF0C\u90E8\u5206\u4F1A\u8BDD\u5386\u53F2\u53EF\u80FD\u5DF2\u53D8\u5316\uFF0C\u8BF7\u68C0\u67E5\u4F1A\u8BDD\u540E\u518D\u91CD\u8BD5\u3002"],["Compaction finished, but the session could not be saved.","\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29\uFF0C\u4F46\u4F1A\u8BDD\u4FDD\u5B58\u5931\u8D25\u3002"]]);function Wc(n){return{handled:!0,message:n,messages:[n]}}function Dce(n){if(!n||typeof n!="object"||!["success","error"].includes(n.kind)||n.text!==void 0&&typeof n.text!="string")throw new TypeError("Harness returned an invalid /compact result");let t=n.text?.trim()??"",o=/^Compacted (\d+) history items \(~(\d+) tokens\)\.$/u.exec(t);return o?D("\u5DF2\u538B\u7F29 {count} \u6761\u5386\u53F2\u8BB0\u5F55\uFF08\u7EA6 {tokens} \u4E2A token\uFF09\u3002",{count:o[1],tokens:o[2]}):YH.has(t)?D(YH.get(t)):t||(n.kind==="success"?D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5B8C\u6210\u3002"):D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25\u3002"))}function wce(n){let t=n?.code??n?.failure?.code;return t==="session-not-found"?D("\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u7684\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u53D1\u9001\u65B0\u6D88\u606F\u5F00\u542F\u4F1A\u8BDD\u3002"):t==="agent-busy"?D("\u5F53\u524D\u4F1A\u8BDD\u6B63\u5728\u751F\u6210\u56DE\u590D\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"):t==="cancelled"||n?.name==="AbortError"?D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88\u3002"):t===oi||t==="workspace-bot-not-found"?D("\u5DE5\u4F5C\u533A\u6216\u673A\u5668\u4EBA\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u8BD5\u3002"):t==="commands-unavailable"?D("\u5F53\u524D Harness \u6682\u4E0D\u652F\u6301\u4ECE\u673A\u5668\u4EBA\u6267\u884C\u4E0A\u4E0B\u6587\u538B\u7F29\u3002"):D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}async function si(n,t,o,i,e={}){if(typeof n!="string")return null;let a=mce.exec(n.trim());if(!a)return null;if(a[1].trim())return Wc(D(Sce));if(typeof o?.sessionFor!="function")return Wc(D("\u5F53\u524D\u673A\u5668\u4EBA\u6CA1\u6709\u53EF\u7528\u7684\u4F1A\u8BDD\u72B6\u6001\u3002"));let A=o.sessionFor(i);if(typeof A!="string"||!A)return Wc(D("\u5F53\u524D\u804A\u5929\u8FD8\u6CA1\u6709\u53EF\u538B\u7F29\u7684\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u53D1\u9001\u4E00\u6761\u6D88\u606F\u3002"));if(typeof t?.executeCommand!="function")return Wc(D("\u5F53\u524D\u673A\u5668\u4EBA\u6682\u4E0D\u652F\u6301\u4E0A\u4E0B\u6587\u538B\u7F29\u3002"));try{let r=await t.executeCommand(A,"/compact",e);return Wc(r===void 0?D("\u5F53\u524D Harness \u672A\u6CE8\u518C /compact \u547D\u4EE4\uFF0C\u8BF7\u786E\u8BA4\u4E0A\u4E0B\u6587\u538B\u7F29\u7EC4\u4EF6\u5DF2\u542F\u7528\u3002"):Dce(r?.result))}catch(r){return Wc(wce(r))}}var jH={name:"@xmanrui/dsh-im",version:"3.0.6",description:"\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",keywords:["deepseek-harness","dsh","dsh-plugin","ai-agent","im","instant-messaging","chatbot","feishu","lark","wechat","wecom","dingtalk","qq","slack","telegram","discord","whatsapp","ai-office"],author:{name:"xmanrui",url:"https://github.com/xmanrui"},contributors:[{name:"C3H3-AI",url:"https://github.com/C3H3-AI"}],license:"MIT",type:"module",repository:{type:"git",url:"git+https://github.com/xmanrui/dsh-im.git"},homepage:"https://github.com/xmanrui/dsh-im#readme",bugs:"https://github.com/xmanrui/dsh-im/issues",publishConfig:{access:"public"},bin:{"dsh-im":"bin/dsh-im.mjs"},main:"./lib/index.js",exports:{".":"./lib/index.js","./client":"./lib/client.js","./package.json":"./package.json"},files:["assets","bin","cordis.patch.yml","lib","plugin-src","scripts","src","LICENSE","README.md","README.en.md","THIRD_PARTY_NOTICES.md"],dsh:{bundle:{patch:"./cordis.patch.yml"},client:{inject:["@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-runtime","@deepseek-ai/dsh-client-ui-settings","@deepseek-ai/dsh-client-ui-slots","@deepseek-ai/dsh-client-locale"],platform:"web"}},scripts:{build:"node plugin-src/client/build.mjs && node plugin-src/host/build.mjs",test:"node --test test/*.test.mjs test/channels/*/*.test.mjs",check:"npm run build && npm test && node scripts/verify-package.mjs"},engines:{node:">=22.19"},dependencies:{"@tencent-connect/qqbot-connector":"1.2.0","@tencent-connect/qqbot-nodejs":"1.0.4","@wecom/aibot-node-sdk":"1.0.7","dingtalk-stream":"2.1.4",qrcode:"1.5.4"},devDependencies:{"@larksuiteoapi/node-sdk":"1.73.0","@whiskeysockets/baileys":"7.0.0-rc14",esbuild:"0.25.9","https-proxy-agent":"5.0.1",react:"18.3.1","react-dom":"18.3.1","react-test-renderer":"18.3.1"}};var bce=/^\/(?:stop|steer|version)(?=$|\s)/iu,Mce=/^\/stop(?=$|\s)/iu,_ce=/^\/version(?=$|\s)/iu,Tce="\u7528\u6CD5\uFF1A/stop\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",Nce="\u7528\u6CD5\uFF1A/version\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",Rce="\u7528\u6CD5\uFF1A/steer <\u8865\u5145\u6307\u4EE4>",kce="\u63A7\u5236\u547D\u4EE4\u4EC5\u652F\u6301\u7EAF\u6587\u5B57\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u540E\u91CD\u8BD5\u3002";function co(n,t={}){return{message:n,...t}}function JH(n){return n?{signal:n}:{}}function qH(n,t,o){if(typeof t?.sessionFor!="function")return null;let i=t.sessionFor(o);if(typeof i!="string"||!i)return null;if(typeof n?.workspaceSession!="function")throw new TypeError("Harness does not support workspace sessions");let e=n.workspaceSession(i);if(!e||typeof e!="object")throw new TypeError("Harness returned an invalid workspace session");return e}function Pi(n){return typeof n=="string"&&bce.test(n.trim())}async function gi(n,t,o,i,{signal:e,hasImages:a=!1,pendingInteraction:A=!1,control:r}={}){if(!Pi(n))return null;let s=n.trim(),g=Mce.test(s),c=_ce.test(s);if(a)return co(D(kce));if(c)return/^\/version$/iu.test(s)?co(`dsh-im v${jH.version}`):co(D(Nce));if(g){if(!/^\/stop$/iu.test(s))return co(D(Tce));let Q=qH(t,o,i);if(!Q)return co(D("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"));if(typeof Q.stopActiveTurn!="function")throw new TypeError("Harness session does not support stopping active turns");return await Q.stopActiveTurn(r,JH(e))?co(D("\u5DF2\u8BF7\u6C42\u505C\u6B62\u5F53\u524D\u4EFB\u52A1\u3002"),{stopped:!0}):co(D("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"))}let d=/^\/steer(?:\s+([\s\S]*))?$/iu.exec(s)?.[1]?.trim()??"";if(!d)return co(D(Rce));if(A)return co([D("\u5F53\u524D\u4EFB\u52A1\u6B63\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54\u6216\u5BA1\u6279\u3002"),"",D("\u8BF7\u5148\u5904\u7406\u5F53\u524D\u8BF7\u6C42\uFF0C\u6216\u8005\u53D1\u9001 /stop \u505C\u6B62\u4EFB\u52A1\u3002")].join(`
146
+ `)}function HH(n,t){return{ok:!0,value:{sessionId:n.sessionId,approvalId:n.approvalId,outcome:t}}}function hf(n){return n==="allowed-once"?D("\u5DF2\u6279\u51C6\uFF0C\u4EC5\u5BF9\u672C\u6B21\u64CD\u4F5C\u6709\u6548\u3002"):n==="rejected"?D("\u5DF2\u62D2\u7EDD\u6B64\u6B21\u64CD\u4F5C\u3002"):D(Gl)}var ii=class{#e;#A;#t=new Map;#r=new Map;#a=new Map;constructor({label:t="IM",logger:o=console}={}){this.#e=t,this.#A=o}hasPending(t){return this.#r.get(t)?.items.some(o=>!o.inactive)===!0}claimReply({key:t,actor:o,text:i,addressed:e=!0,hasPendingQuestion:a=!1,questionCompletion:A,isQuestionPending:r,send:s}){let c=this.#r.get(t)?.items[0],I=uce(i),d=(f,Q=!1)=>({...Q?{resolved:!0}:{},process:async y=>{typeof y=="function"&&await y()===!1||await s(f)}}),B=a&&c&&A&&typeof A.then=="function";return a&&!B?null:!c||c.inactive?(this.#a.get(t)??0)<=Date.now()?(this.#a.delete(t),null):I?d(D(Gl),!0):null:c.actor!==o||c.requiresMention&&e!==!0?I?d(D("\u53EA\u6709\u53D1\u8D77\u5F53\u524D\u4EFB\u52A1\u7684\u7528\u6237\u53EF\u4EE5\u5904\u7406\u8FD9\u6761\u5BA1\u6279\u3002")):null:{process:async f=>{let Q=c.presented,m=(c.replyTail??Promise.resolve()).catch(()=>{}).then(async()=>{if(!(typeof f=="function"&&await f()===!1)){if(B){if(await A.catch(()=>{}),c.inactive||c.resolving)return;if(typeof r=="function"&&r()){await s(D(hce));return}}if(await c.activationTask?.catch(()=>{}),await c.presentationTask?.catch(()=>{}),c.inactive||c.resolving){await s(D(Gl));return}if(c.send=s,!Q||!c.presented){if(c.presented||await this.#i(c),c.inactive||c.resolving)return;await s(D(Pb));return}if(c.submitting){await s(D("\u5BA1\u6279\u51B3\u5B9A\u6B63\u5728\u63D0\u4EA4\uFF0C\u8BF7\u7A0D\u5019\u3002"));return}if(!I){await s(D(Pb));return}await this.#c(c,I)}});c.replyTail=m;try{await m}finally{c.replyTail===m&&(c.replyTail=null)}}}}async handleRequested(t,o){if(t?.kind!=="approval")return!1;let i=t.payload,e=wa(i?.approvalId);if(!wa(t.rpcId)||!wa(t.sessionId)||!e||!KH(i)||i.sessionId!==t.sessionId||typeof t.respond!="function")return this.#A.warn?.(`[dsh-im:${this.#e}] ignored an invalid Harness approval`),!0;if(t.recovered===!0)return await this.#g(t,i),!0;let a=this.#t.get(e);if(a)return a.interaction=t,a.toolCall=t.toolCall,a.presented||await this.#i(a),!0;let A=o?.send,r=wa(o?.key),s=wa(o?.actor);if(!r||!s||typeof A!="function")return this.#A.warn?.(`[dsh-im:${this.#e}] ignored an approval without a reply route`),await this.#g(t,i),!0;let g=Fb(i,{toolCall:t.toolCall,requiresMention:o.requiresMention===!0});if(!g){let d=await this.#g(t,i);return await A(d?D("\u65E0\u6CD5\u5B8C\u6574\u5C55\u793A\u8FD9\u6B21\u64CD\u4F5C\uFF0C\u5DF2\u5B89\u5168\u62D2\u7EDD\u6B64\u6B21\u5BA1\u6279\u3002"):D(Gl)),!0}let c={approvalId:e,sessionId:t.sessionId,interaction:t,toolCall:t.toolCall,key:r,actor:s,requiresMention:o.requiresMention===!0,send:A,text:g,presented:!1,presentationTask:null,deliveryCompleted:!1,replyTail:null,submitting:!1,inactive:!1,resolving:!1,closedOutcome:null,resolutionNotified:!1,activationTask:null};this.#t.set(e,c);let I=this.#r.get(r)??{items:[]};return I.items.push(c),this.#r.set(r,I),I.items[0]===c&&await this.#i(c),!0}async handleResolved(t){if(t?.kind!=="approval")return!1;let o=this.#t.get(wa(t.interactionId));if(!o||(o.resolving=!0,o.activationTask&&await o.activationTask.catch(()=>{}),o.inactive||this.#t.get(o.approvalId)!==o))return!0;let i=o.presentationTask,e=o.presented||i,a=o.send,A=this.#o(o);return await this.#s(A,async()=>{let r=o.presented;i&&(r=await i.then(()=>!0,()=>!1)),e&&r&&(o.resolutionNotified=!0,await a(hf(t.outcome)).catch(()=>{}))}),!0}async closeRoute(t){let o=this.#r.get(t);if(!o)return;let i=[...o.items];for(let e of i)this.#o(e);await Promise.all(i.map(async e=>{try{await e.interaction.respond(HH(e,"rejected"),{signal:AbortSignal.timeout(5e3)}),e.closedOutcome="rejected",(e.presented||e.deliveryCompleted)&&!e.resolutionNotified&&(e.resolutionNotified=!0,await e.send(hf("rejected")).catch(()=>{}))}catch(a){a?.code==="interaction-not-pending"?(e.closedOutcome="resolved",(e.presented||e.deliveryCompleted)&&!e.resolutionNotified&&(e.resolutionNotified=!0,await e.send(D(Gl)).catch(()=>{}))):this.#A.warn?.(`[dsh-im:${this.#e}] failed to reject a closing approval:`,a)}}))}async#i(t){if(this.#r.get(t.key)?.items[0]!==t||t.inactive||t.resolving||t.presented||(await t.activationTask?.catch(()=>{}),this.#r.get(t.key)?.items[0]!==t||t.inactive||t.resolving||t.presented))return;if(t.presentationTask)return t.presentationTask;let o=Promise.resolve().then(()=>t.send(t.text));t.presentationTask=o;try{await o,t.deliveryCompleted=!0,t.inactive?t.closedOutcome&&!t.resolutionNotified&&(t.resolutionNotified=!0,await t.send(hf(t.closedOutcome)).catch(()=>{})):t.presented=!0}finally{t.presentationTask===o&&(t.presentationTask=null)}}async#c(t,o){t.submitting=!0;try{await t.interaction.respond(HH(t,o))}catch(a){if(a?.code==="interaction-not-pending"){let A=t.send,r=this.#o(t);await this.#s(r,async()=>{t.resolutionNotified||await A(D(Gl)).catch(()=>{})});return}if(t.inactive)return;t.submitting=!1,this.#A.error?.(`[dsh-im:${this.#e}] failed to submit an approval:`,a),await t.send(D("\u5BA1\u6279\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u56DE\u590D\u300C\u6279\u51C6\u300D\u6216\u300C\u62D2\u7EDD\u300D\u3002")).catch(()=>{});return}let i=t.send,e=this.#o(t);await this.#s(e,async()=>{t.resolutionNotified||await i(hf(o)).catch(()=>{})})}async#s(t,o){let i,e=new Promise(a=>{i=a});t&&(t.activationTask=e);try{await o()}finally{i(),t?.activationTask===e&&(t.activationTask=null)}await this.#I(t)}async#I(t){if(t)try{await this.#i(t)}catch(o){this.#A.error?.(`[dsh-im:${this.#e}] failed to present the next approval:`,o);try{t.interaction.reconnect?.()}catch{}}}#o(t){if(t.inactive)return null;t.inactive=!0,this.#n(t.key),this.#t.delete(t.approvalId);let o=this.#r.get(t.key);if(!o)return null;let i=o.items[0]===t,e=o.items.indexOf(t);return e!==-1&&o.items.splice(e,1),o.items.length===0?(this.#r.delete(t.key),null):i?o.items[0]:null}#n(t){let o=Date.now();for(let[i,e]of this.#a)e<=o&&this.#a.delete(i);for(this.#a.delete(t),this.#a.set(t,o+Ece);this.#a.size>Cce;)this.#a.delete(this.#a.keys().next().value)}async#g(t,o){try{return await t.respond({ok:!0,value:{sessionId:t.sessionId,approvalId:o.approvalId,outcome:"rejected"}},{signal:AbortSignal.timeout(5e3)}),!0}catch(i){if(i?.code==="interaction-not-pending")return!1;throw i}}};var Lb=new WeakMap;function fce(n){let t=Lb.get(n);return t||(t=new Map,Lb.set(n,t)),t}async function Vc(n,t,o){let i=typeof n;if(i!=="object"&&i!=="function"||n===null)throw new TypeError("state is required");if(typeof t!="string"||!t)throw new TypeError("conversation key is required");if(typeof o!="function")throw new TypeError("operation is required");let e=fce(n),a=e.get(t)??Promise.resolve(),A,r=new Promise(s=>{A=s});e.set(t,r),await a;try{return await o()}finally{A(),e.get(t)===r&&(e.delete(t),e.size===0&&Lb.delete(n))}}var oi="workspace-session-stale";function xH(n,t){return typeof n.workspaceSession=="function"?n.workspaceSession(t):Object.freeze({sessionId:t,sessionExists:(...o)=>n.sessionExists(t,...o),models:(...o)=>n.getSessionModels(t,...o),selectModel:(...o)=>n.selectSessionModel(t,...o),isRunning:(...o)=>n.isSessionRunning(t,...o),hasActiveTurn:(...o)=>n.hasActiveTurn(t,...o),stopActiveTurn:(...o)=>n.stopActiveTurn(t,...o),steerActiveTurn:(...o)=>n.steerActiveTurn(t,...o),ask:(...o)=>n.ask(t,...o)})}async function Qce(n,t){return t===void 0?n.sessionExists():n.sessionExists(t)}async function yce(n,t){return t===void 0?n.createSession():n.createSession(t)}async function ni({harness:n,state:t,key:o,text:i,content:e,createOptions:a,existsOptions:A,askOptions:r}){for(;;)try{let s=await Vc(t,o,async()=>{let B=t.sessionFor(o),f=B?xH(n,B):null;if(!f||!await Qce(f,A)){if(B=await yce(n,a),await t.setSession(o,B)===!1)return null;f=xH(n,B)}return{sessionId:B,session:f}});if(!s)continue;let g=[],c=typeof r=="object"&&typeof r?.onArtifact=="function"?r.onArtifact:null,I=typeof r=="number"?{timeoutMs:r}:{...r};I.onArtifact=async B=>{g.push(B),await c?.(B)};let d=await s.session.ask(e??i,I);return{sessionId:s.sessionId,answer:d,...g.length>0?{artifacts:g}:{}}}catch(s){if(s?.code!==oi)throw s}}var mce=/^\/compact(?=$|\s)([\s\S]*)$/i,Sce="\u7528\u6CD5\uFF1A/compact\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",YH=new Map([["No compactable history yet.","\u6682\u65E0\u53EF\u538B\u7F29\u7684\u5386\u53F2\u8BB0\u5F55\u3002"],["Compaction is unavailable because this process has an active compaction, or the agent is not idle.","\u5F53\u524D\u4F1A\u8BDD\u6B63\u5728\u751F\u6210\u56DE\u590D\u6216\u6267\u884C\u538B\u7F29\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"],["Compaction cancelled.","\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88\u3002"],["The history selected for compaction changed before it could be replaced. The conversation is unchanged; the attempt is recorded in the session log.","\u538B\u7F29\u671F\u95F4\u4F1A\u8BDD\u5386\u53F2\u53D1\u751F\u53D8\u5316\uFF0C\u672C\u6B21\u672A\u4FEE\u6539\u4F1A\u8BDD\uFF0C\u8BF7\u91CD\u8BD5\u3002"],["Compaction could not produce a useful summary. The conversation is unchanged; the attempt is recorded in the session log.","\u672A\u80FD\u751F\u6210\u6709\u6548\u7684\u538B\u7F29\u6458\u8981\uFF0C\u672C\u6B21\u672A\u4FEE\u6539\u4F1A\u8BDD\u3002"],["Compaction did not finish cleanly; some session history may have changed. Inspect the current session state before retrying.","\u4E0A\u4E0B\u6587\u538B\u7F29\u672A\u6B63\u5E38\u5B8C\u6210\uFF0C\u90E8\u5206\u4F1A\u8BDD\u5386\u53F2\u53EF\u80FD\u5DF2\u53D8\u5316\uFF0C\u8BF7\u68C0\u67E5\u4F1A\u8BDD\u540E\u518D\u91CD\u8BD5\u3002"],["Compaction finished, but the session could not be saved.","\u4E0A\u4E0B\u6587\u5DF2\u538B\u7F29\uFF0C\u4F46\u4F1A\u8BDD\u4FDD\u5B58\u5931\u8D25\u3002"]]);function Wc(n){return{handled:!0,message:n,messages:[n]}}function Dce(n){if(!n||typeof n!="object"||!["success","error"].includes(n.kind)||n.text!==void 0&&typeof n.text!="string")throw new TypeError("Harness returned an invalid /compact result");let t=n.text?.trim()??"",o=/^Compacted (\d+) history items \(~(\d+) tokens\)\.$/u.exec(t);return o?D("\u5DF2\u538B\u7F29 {count} \u6761\u5386\u53F2\u8BB0\u5F55\uFF08\u7EA6 {tokens} \u4E2A token\uFF09\u3002",{count:o[1],tokens:o[2]}):YH.has(t)?D(YH.get(t)):t||(n.kind==="success"?D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5B8C\u6210\u3002"):D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25\u3002"))}function wce(n){let t=n?.code??n?.failure?.code;return t==="session-not-found"?D("\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u7684\u4F1A\u8BDD\u5DF2\u4E0D\u5B58\u5728\uFF0C\u8BF7\u53D1\u9001\u65B0\u6D88\u606F\u5F00\u542F\u4F1A\u8BDD\u3002"):t==="agent-busy"?D("\u5F53\u524D\u4F1A\u8BDD\u6B63\u5728\u751F\u6210\u56DE\u590D\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"):t==="cancelled"||n?.name==="AbortError"?D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5DF2\u53D6\u6D88\u3002"):t===oi||t==="workspace-bot-not-found"?D("\u5DE5\u4F5C\u533A\u6216\u673A\u5668\u4EBA\u72B6\u6001\u5DF2\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u8BD5\u3002"):t==="commands-unavailable"?D("\u5F53\u524D Harness \u6682\u4E0D\u652F\u6301\u4ECE\u673A\u5668\u4EBA\u6267\u884C\u4E0A\u4E0B\u6587\u538B\u7F29\u3002"):D("\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}async function si(n,t,o,i,e={}){if(typeof n!="string")return null;let a=mce.exec(n.trim());if(!a)return null;if(a[1].trim())return Wc(D(Sce));if(typeof o?.sessionFor!="function")return Wc(D("\u5F53\u524D\u673A\u5668\u4EBA\u6CA1\u6709\u53EF\u7528\u7684\u4F1A\u8BDD\u72B6\u6001\u3002"));let A=o.sessionFor(i);if(typeof A!="string"||!A)return Wc(D("\u5F53\u524D\u804A\u5929\u8FD8\u6CA1\u6709\u53EF\u538B\u7F29\u7684\u4F1A\u8BDD\uFF0C\u8BF7\u5148\u53D1\u9001\u4E00\u6761\u6D88\u606F\u3002"));if(typeof t?.executeCommand!="function")return Wc(D("\u5F53\u524D\u673A\u5668\u4EBA\u6682\u4E0D\u652F\u6301\u4E0A\u4E0B\u6587\u538B\u7F29\u3002"));try{let r=await t.executeCommand(A,"/compact",e);return Wc(r===void 0?D("\u5F53\u524D Harness \u672A\u6CE8\u518C /compact \u547D\u4EE4\uFF0C\u8BF7\u786E\u8BA4\u4E0A\u4E0B\u6587\u538B\u7F29\u7EC4\u4EF6\u5DF2\u542F\u7528\u3002"):Dce(r?.result))}catch(r){return Wc(wce(r))}}var jH={name:"@xmanrui/dsh-im",version:"3.0.7",description:"\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",keywords:["deepseek-harness","dsh","dsh-plugin","ai-agent","im","instant-messaging","chatbot","feishu","lark","wechat","wecom","dingtalk","qq","slack","telegram","discord","whatsapp","ai-office"],author:{name:"xmanrui",url:"https://github.com/xmanrui"},contributors:[{name:"C3H3-AI",url:"https://github.com/C3H3-AI"}],license:"MIT",type:"module",repository:{type:"git",url:"git+https://github.com/xmanrui/dsh-im.git"},homepage:"https://github.com/xmanrui/dsh-im#readme",bugs:"https://github.com/xmanrui/dsh-im/issues",publishConfig:{access:"public"},bin:{"dsh-im":"bin/dsh-im.mjs"},main:"./lib/index.js",exports:{".":"./lib/index.js","./client":"./lib/client.js","./package.json":"./package.json"},files:["assets","bin","cordis.patch.yml","lib","plugin-src","scripts","src","LICENSE","README.md","README.en.md","THIRD_PARTY_NOTICES.md"],dsh:{bundle:{patch:"./cordis.patch.yml"},client:{inject:["@deepseek-ai/dsh-client-connection","@deepseek-ai/dsh-client-runtime","@deepseek-ai/dsh-client-ui-settings","@deepseek-ai/dsh-client-ui-slots","@deepseek-ai/dsh-client-locale"],platform:"web"}},scripts:{build:"node plugin-src/client/build.mjs && node plugin-src/host/build.mjs",test:"node --test test/*.test.mjs test/channels/*/*.test.mjs",check:"npm run build && npm test && node scripts/verify-package.mjs"},engines:{node:">=22.19"},dependencies:{"@tencent-connect/qqbot-connector":"1.2.0","@tencent-connect/qqbot-nodejs":"1.0.4","@wecom/aibot-node-sdk":"1.0.7","dingtalk-stream":"2.1.4",qrcode:"1.5.4"},devDependencies:{"@larksuiteoapi/node-sdk":"1.73.0","@whiskeysockets/baileys":"7.0.0-rc14",esbuild:"0.25.9","https-proxy-agent":"5.0.1",react:"18.3.1","react-dom":"18.3.1","react-test-renderer":"18.3.1"}};var bce=/^\/(?:stop|steer|version)(?=$|\s)/iu,Mce=/^\/stop(?=$|\s)/iu,_ce=/^\/version(?=$|\s)/iu,Tce="\u7528\u6CD5\uFF1A/stop\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",Nce="\u7528\u6CD5\uFF1A/version\uFF08\u4E0D\u5E26\u53C2\u6570\uFF09",Rce="\u7528\u6CD5\uFF1A/steer <\u8865\u5145\u6307\u4EE4>",kce="\u63A7\u5236\u547D\u4EE4\u4EC5\u652F\u6301\u7EAF\u6587\u5B57\uFF0C\u8BF7\u79FB\u9664\u56FE\u7247\u540E\u91CD\u8BD5\u3002";function co(n,t={}){return{message:n,...t}}function JH(n){return n?{signal:n}:{}}function qH(n,t,o){if(typeof t?.sessionFor!="function")return null;let i=t.sessionFor(o);if(typeof i!="string"||!i)return null;if(typeof n?.workspaceSession!="function")throw new TypeError("Harness does not support workspace sessions");let e=n.workspaceSession(i);if(!e||typeof e!="object")throw new TypeError("Harness returned an invalid workspace session");return e}function Pi(n){return typeof n=="string"&&bce.test(n.trim())}async function gi(n,t,o,i,{signal:e,hasImages:a=!1,pendingInteraction:A=!1,control:r}={}){if(!Pi(n))return null;let s=n.trim(),g=Mce.test(s),c=_ce.test(s);if(a)return co(D(kce));if(c)return/^\/version$/iu.test(s)?co(`dsh-im v${jH.version}`):co(D(Nce));if(g){if(!/^\/stop$/iu.test(s))return co(D(Tce));let Q=qH(t,o,i);if(!Q)return co(D("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"));if(typeof Q.stopActiveTurn!="function")throw new TypeError("Harness session does not support stopping active turns");return await Q.stopActiveTurn(r,JH(e))?co(D("\u5DF2\u8BF7\u6C42\u505C\u6B62\u5F53\u524D\u4EFB\u52A1\u3002"),{stopped:!0}):co(D("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002"))}let d=/^\/steer(?:\s+([\s\S]*))?$/iu.exec(s)?.[1]?.trim()??"";if(!d)return co(D(Rce));if(A)return co([D("\u5F53\u524D\u4EFB\u52A1\u6B63\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54\u6216\u5BA1\u6279\u3002"),"",D("\u8BF7\u5148\u5904\u7406\u5F53\u524D\u8BF7\u6C42\uFF0C\u6216\u8005\u53D1\u9001 /stop \u505C\u6B62\u4EFB\u52A1\u3002")].join(`
147
147
  `));let B=qH(t,o,i);if(!B)return co(D("\u5F53\u524D\u804A\u5929\u6CA1\u6709\u7ED1\u5B9A\u4F1A\u8BDD\uFF0C\u65E0\u6CD5\u8865\u5145\u6307\u4EE4\u3002\u8BF7\u5148\u7ED1\u5B9A\u4F1A\u8BDD\u3002"));if(typeof B.steerActiveTurn!="function")throw new TypeError("Harness session does not support steering active turns");let f=await B.steerActiveTurn(d,r,JH(e));return co(f?D("\u5DF2\u63D0\u4EA4\u8865\u5145\u6307\u4EE4\uFF0CAgent \u4F1A\u5728\u4E0B\u4E00\u6B65\u8BFB\u53D6\u3002"):D("\u4EFB\u52A1\u5DF2\u7ED3\u675F\uFF0C\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\uFF0C\u65E0\u6CD5\u8865\u5145\u6307\u4EE4\u3002\u8BF7\u76F4\u63A5\u53D1\u9001\u6D88\u606F\u5F00\u59CB\u65B0\u4EFB\u52A1\u3002"))}import{realpath as WH,stat as ZH}from"node:fs/promises";import{isAbsolute as XH,resolve as vce}from"node:path";var Pce=/^\/workspace(?:\s+([\s\S]+))?$/i,Gce=/^\/workspacelist(?:\s+([\s\S]+))?$/i,Fce=/^\/sessionlist(?:\s+([\s\S]+))?$/i,Lce=/^\/session(?=$|\s)/i,Uce=/^\/session[ \t]+([^\s]+)$/i,Hce=4096,Kce=1800,xce=256,$H=/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u,Yce=/[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]+/gu,eK="\u7528\u6CD5\uFF1A/session Session ID \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7\uFF08/session N\uFF09",Fl=["\u7528\u6CD5\uFF1A","/sessionlist \u5217\u51FA\u5F53\u524D\u5DE5\u4F5C\u533A\u4F1A\u8BDD","/sessionlist \u5DE5\u4F5C\u533A\u5E8F\u53F7 \u6309 /workspacelist \u5E8F\u53F7\u5217\u51FA\u4F1A\u8BDD","/sessionlist \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5217\u51FA\u6307\u5B9A\u5DE5\u4F5C\u533A\u4F1A\u8BDD"].join(`
148
148
  `);function Pt(n,t=[n]){return{handled:!0,message:n,messages:t}}function Ll(n){return typeof n!="string"||n.length>Hce||!XH(n)||$H.test(n)?null:vce(n)}function Ef(n){return typeof n!="string"?"":n.replace(Yce," ").replace(/\s+/gu," ").trim()}function zH(n){return typeof n=="string"&&n.length>0&&n.length<=xce&&!new RegExp("\\p{White_Space}","u").test(n)&&!$H.test(n)}async function Ub(n){let t=await Promise.all(n.map(async o=>{let i=Ll(o);if(!i)return null;try{return(await ZH(i)).isDirectory()?Ll(await WH(i)):null}catch{return null}}));return[...new Set(t.filter(Boolean))]}async function Hb(n){if(typeof n!="string"||!XH(n.trim()))return{error:D(`\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002
149
149
  {usage}`,{usage:D(Fl)})};let t=Ll(n.trim());if(!t)return{error:D(`\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5305\u542B\u4E0D\u652F\u6301\u7684\u5B57\u7B26\u6216\u957F\u5EA6\u8D85\u8FC7\u9650\u5236\u3002
@@ -211,7 +211,7 @@ ${N}`:J;y&&await Q.finish(H)||await this.#O(g,H)}catch{this.#c.error?.("[dsh-din
211
211
  `).trim()}function pi(n){return typeof n=="string"&&n.trim()?n.trim():null}function lpe(n){if(!n||typeof n!="object")return null;let t=pi(n.message);if(t)return t;let o=pi(n.name),i=pi(n.code);return o||i?[o??"Error",i].filter(Boolean).join(": "):null}function ppe(n,t){let o=[...t].map(i=>i?.event??i).filter(Boolean).sort((i,e)=>(i.seq??-1)-(e.seq??-1));for(let i of o){let e=i.seq??-1;if(e<=n.lastSeq)continue;if(n.lastSeq=e,i.type==="turn/start"){let A=i.data?.turn??null;n.active&&A!==n.turn&&(n.active=!1),n.turn!==null&&A!==n.turn&&(n.completed=!0),n.openTurn=A;continue}if(i.type==="user/message"&&i.data?.source?.rpcId===n.promptRpcId){n.active=!0,n.started=!0,n.completed=!1,n.turn=i.data?.turn??n.openTurn;continue}if(i.type==="turn/end"&&i.data?.turn===n.turn){n.active=!1,n.completed=!0;continue}let a=null;if(i.type==="tool/call"&&n.active&&i.data?.turn===n.turn&&typeof i.data?.callId=="string"&&i.data.callId)a={callId:i.data.callId,name:i.data?.name,arguments:i.data?.arguments};else if(i.type==="tool/code-dispatch-start"&&n.active&&typeof i.data?.subCallId=="string"&&i.data.subCallId){let A;try{A=JSON.stringify(i.data?.arguments)}catch{A=void 0}a={callId:i.data.subCallId,name:i.data?.name,arguments:A}}a&&n.toolCalls.set(a.callId,Object.freeze(a))}}var jl=class{#e;#A;#t=null;#r=null;#a=new Map;#i="";#c=!1;#s=null;#I=new Map;#o=null;constructor({promptRpcId:t,afterSeq:o=-1}){this.#e=t,this.#A=o}get finished(){return this.#c}get answer(){return this.#i.trim()}get reason(){return this.#s}get tracking(){return this.#r!==null&&!this.#c}get turn(){return this.#r}consumeAll(t){let o=[],i=a=>{if(a.type==="text"&&o.length>0&&o[o.length-1].type==="text"){o[o.length-1]=a;return}o.push(a)},e=[...t].map(a=>a?.event??a).filter(Boolean).sort((a,A)=>(a.seq??-1)-(A.seq??-1));for(let a of e){let A=a.seq??-1;if(!(A<=this.#A)){if(this.#A=A,a.type==="turn/start"&&(this.#t=a.data?.turn??null),a.type==="user/message"&&a.data?.source?.rpcId===this.#e){this.#r=this.#t;continue}if(this.#r!==null){if(a.type==="turn/end"){if(a.data?.turn!==this.#r)continue;this.#c=!0,this.#s=a.data?.reason??null,this.#t=null;continue}if(a.data?.turn===this.#r){if(a.type==="assistant/chunk"&&a.data?.chunk?.type==="text-delta"){let r=a.data?.step??0,s=a.data.chunk.index??0,g=`${r}:${s}`;this.#a.set(g,(this.#a.get(g)??"")+a.data.chunk.text);let c=`${r}:`,I=[...this.#a.entries()].filter(([d])=>d.startsWith(c)).sort(([d],[B])=>Number(d.split(":")[1])-Number(B.split(":")[1])).map(([,d])=>d).join(`
212
212
  `).trim();I&&I!==this.#i&&(this.#i=I,i({type:"text",text:I}));continue}if(a.type==="assistant/message"){let r=Ipe(a);r&&r!==this.#i&&(this.#i=r,i({type:"text",text:r}));continue}if(a.type==="tool/call"){let r=pi(a.data?.name)??D("\u5DE5\u5177"),s=pi(a.data?.callId)??pi(a.data?.subCallId);s&&this.#I.set(s,r),this.#o=r,i({type:"tool",name:r,...s?{callId:s}:{}})}else if(a.type==="tool/result"){let r=pi(a.data?.message?.source?.callId)??pi(a.data?.callId)??pi(a.data?.subCallId),s=(r?this.#I.get(r):null)??this.#o,g=lpe(a.data?.error);i({type:"status",text:D("\u6B63\u5728\u6574\u7406\u7ED3\u679C\u2026"),...s?{toolName:s}:{},...g?{error:g}:{}})}}}}}return o}consume(t){return this.consumeAll(t).at(-1)??null}},Xo=class extends Error{constructor(t,o){super(`${t}: ${o?.message??"unknown Harness RPC error"}`),this.name="HarnessRpcError",this.method=t,this.code=o?.code??"internal",this.details=o?.details??{}}},kg=class extends Error{constructor(t,o,{cause:i,status:e}={}){let a=Number.isInteger(e)?`, HTTP ${e}`:"";super(`Harness ${o} transport failed (${t}${a})`,{cause:i}),this.name="HarnessTransportError",this.code=t,this.method=o,Number.isInteger(e)&&(this.status=e)}},IM=class extends Error{constructor(t){super("Harness health RPC was rejected",{cause:t}),this.name="HarnessHealthError",this.code="harness-rpc-rejected",this.method="host.describe"}},Jl=class extends Error{constructor(t,o){super(o),this.name="HarnessInteractionError",this.code=t}},kn=class extends Error{constructor(t,{reason:o,providerCode:i}={}){super(`Harness turn failed (${t})`),this.name="HarnessTurnError",this.code=t,this.promptAccepted=!0,o&&typeof o=="object"&&(this.reason=o),typeof i=="string"&&i&&(this.providerCode=i)}};function Ax(n){let t=pi(n?.kind)??pi(n);if(t==="error"){let o=n?.error??n?.failure;return new kn("harness-turn-failed",{reason:n,providerCode:pi(o?.code)??void 0})}return t==="max-tokens"?new kn("model-max-tokens",{reason:n}):t==="blocked"?new kn("turn-blocked",{reason:n}):["interrupted","stopped","cancelled","canceled"].includes(t)?new kn("turn-interrupted",{reason:n}):t==="aborted"?new kn("turn-aborted",{reason:n}):t==="completed"?new kn("model-empty-response",{reason:n}):new kn("harness-turn-failed",{reason:n})}function dpe(n){return n==null?!0:(pi(n?.kind)??pi(n))==="completed"}var lr=class{#e;#A;#t;#r;#a;#i;#c;#s;#I;#o;#n;#g;#l;#p;#d=null;#h;#E;#u;#B;constructor({baseUrl:t,workspace:o,agentPreset:i,autostart:e=!1,dshBin:a="dsh",fetchImpl:A=fetch,createWebSocket:r=Q=>new WebSocket(Q),interactionReconnectDelayMs:s=500,rpcIdPrefix:g="im",logPrefix:c="dsh-im",commandExecutor:I,controlExecutor:d,sessionMaintenanceExecutor:B,fileIngressExecutor:f}){if(typeof r!="function")throw new TypeError("createWebSocket must be a function");if(!Number.isFinite(s)||s<0)throw new TypeError("interactionReconnectDelayMs must be a non-negative number");if(typeof g!="string"||!g.trim())throw new TypeError("rpcIdPrefix must be a non-empty string");if(typeof c!="string"||!c.trim())throw new TypeError("logPrefix must be a non-empty string");if(I!==void 0&&typeof I!="function")throw new TypeError("commandExecutor must be a function");if(d!==void 0&&typeof d!="function")throw new TypeError("controlExecutor must be a function");if(B!==void 0&&typeof B!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(f!==void 0&&typeof f!="function")throw new TypeError("fileIngressExecutor must be a function");this.#e=new URL(t),this.#A=o,this.#t=i??void 0,this.#r=e,this.#a=a,this.#i=A,this.#c=r,this.#s=s,this.#I=g.trim(),this.#o=c.trim(),this.#n=I,this.#g=d,this.#l=B,this.#p=f,this.#h=ape(this.#e.origin),this.#E=this.#h.ownerships,this.#u=this.#h.claims,this.#B=this.#h.controls}async rpc(t,o={},i=3e4,e={}){let a=e.rpcId??`${this.#I}-${WK()}`,A=AbortSignal.timeout(i),r=e.signal?AbortSignal.any([e.signal,A]):A,s;try{s=await this.#i(new URL(`/api/${t}`,this.#e),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-request",rpcId:a,method:t,payload:o}),signal:r})}catch(c){throw e.signal?.aborted?c:new kg(A.aborted?"harness-timeout":"harness-connect-failed",t,{cause:c})}if(!s.ok){let c=await rpe(s,this.#e.hostname);throw new kg(c,t,{status:s.status})}let g;try{g=await s.json()}catch(c){throw new kg("harness-response-invalid",t,{cause:c})}if(g?.type!=="server-response"||g?.rpcId!==a)throw new kg("harness-response-invalid",t,{cause:new Error(`Harness returned an invalid response for ${t}`)});if(!g.result||typeof g.result!="object"||typeof g.result.ok!="boolean")throw new kg("harness-response-invalid",t,{cause:new Error(`Harness returned an invalid result for ${t}`)});if(!g.result?.ok)throw new Xo(t,g.result?.error);return g.result.value}async health(t={}){try{return await this.rpc("host.describe",{},5e3,t),!0}catch(o){throw o instanceof Xo?new IM(o):o}}async ensureRunning(t={}){try{return await this.health(t)}catch(e){if(!this.#r)throw e}if(!this.#d||this.#d.exitCode!==null){let e=this.#e.port||(this.#e.protocol==="https:"?"443":"80");this.#d=Xle(this.#a,["web","--host",this.#e.hostname,"--port",e],{cwd:this.#A,env:process.env,stdio:["ignore","inherit","inherit"]}),this.#d.on("error",a=>{console.error(`[${this.#o}] failed to start Harness:`,a.message)})}let o=Date.now()+6e4,i;for(;Date.now()<o;){await eE(1e3,t.signal);try{return await this.health(t)}catch(e){i=e}}throw i||new kg("harness-timeout","host.describe")}async listWorkspaces(t={}){return await this.ensureRunning(t),ope(await this.rpc("workspace.list",{},3e4,t))}async listWorkspaceSessions(t,o={}){await this.ensureRunning(o);let i=await this.rpc("workspace.list",{},3e4,o),e=npe(t,i);if(!e)return{workspace:t,sessions:[]};let a=await this.rpc("session.list",{},3e4,o);return cpe(e,i.archivedSessionIds,a)}async listModels(t={}){await this.ensureRunning(t);let o=await this.rpc("llm.models",{},3e4,t);return $K(o,"llm.models")}async getSessionModels(t,o={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");await this.ensureRunning(o);let i=await this.rpc("session.models",{sessionId:t},3e4,o);return $K(i,"session.models",{session:!0})}async selectSessionModel(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(!cM(o))throw new TypeError("A provider and model are required");await this.ensureRunning(i);let e=A=>{let r=A&&i.signal?AbortSignal.any([A,i.signal]):A??i.signal;return this.rpc("session.selectModel",{sessionId:t,provider:o.provider,model:o.model,...o.reasoningEffort===void 0?{}:{reasoningEffort:o.reasoningEffort}},3e4,r?{...i,signal:r}:i)},a=this.#l?await this.#l({sessionId:t,operation:e}):await e();if(!a||typeof a!="object"||!cM(a.selected))throw new Error("Harness returned an invalid response for session.selectModel");return a}async isSessionRunning(t,o={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");await this.ensureRunning(o);let i=await this.rpc("session.list",{},3e4,o);if(!i||typeof i!="object"||!Array.isArray(i.items))throw new Error("Harness returned an invalid response for session.list");for(let e of i.items)if(!e||typeof e!="object"||typeof e.sessionId!="string"||!e.sessionId||typeof e.running!="boolean")throw new Error("Harness returned an invalid response for session.list");return i.items.find(e=>e.sessionId===t)?.running??!1}async adoptWorkspaceSession(t,o={}){return VK(this,t,o)}async workspaceId(t={}){let{workspace:o=this.#A,...i}=t,{items:e}=await this.rpc("workspace.list",{},3e4,i),a=e.find(r=>r.path===o);return a?a.workspaceId:(await this.rpc("workspace.create",{path:o},3e4,i)).workspace.workspaceId}async createSession(t={}){let{agentPreset:o,...i}=t;await this.ensureRunning(i);let a={workspaceId:await this.workspaceId(i)},A=o!==void 0?o:this.#t;return A!=null&&(a.agentPreset=A),(await this.rpc("session.create",a,3e4,i)).sessionId}async executeCommand(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(typeof o!="string"||!o)throw new TypeError("command line is required");if(!this.#n){let e=new Error("Harness command execution is unavailable");throw e.code="commands-unavailable",e}try{return await this.#n(t,o,i)}catch(e){throw e?.failure&&typeof e.failure=="object"?new Xo("commands.execute",e.failure):e}}async sessionExists(t,o={}){try{return await this.rpc("session.history",{sessionId:t,maxMessages:1},3e4,o),!0}catch(i){if(i instanceof Xo&&i.code==="session-not-found")return!1;throw i}}async respondInteraction(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("rpcId is required");if(!o||typeof o!="object"||typeof o.ok!="boolean")throw new TypeError("A Harness RPC result is required");let e=AbortSignal.timeout(i.timeoutMs??3e4),a=i.signal?AbortSignal.any([i.signal,e]):e,A=await this.#i(new URL("/api/respond",this.#e),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-response",rpcId:t,result:o}),signal:a});if(!A.ok)throw new Error(`Harness transport respond failed: HTTP ${A.status}`);let r=await A.json();if(r?.accepted===!0)return r;if(r?.accepted!==!1||r.reason!=="bad-response"&&r.reason!=="not-pending")throw new Error("Harness returned an invalid interaction response receipt");let s=r.reason;throw new Jl(`interaction-${s}`,`Harness interaction response was rejected (${s})`)}async watchInteractions(t,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A}={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(!o||typeof o.addEventListener!="function")throw new TypeError("watchInteractions requires an AbortSignal");if(i!==void 0&&typeof i!="function")throw new TypeError("onInteraction must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("onResolved must be a function");if(a!==void 0&&typeof a!="function")throw new TypeError("onOpen must be a function");for(;!o.aborted;){try{await this.#R(t,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A})}catch(r){if(o.aborted)return;console.warn(`[${this.#o}] Harness interaction stream disconnected:`,r.message)}if(o.aborted)return;try{await eE(this.#s,o)}catch{if(o.aborted)return;throw new Error("Harness interaction reconnect wait failed")}}}#f(t,o){let i=this.#E.get(t)??new Set;o.order=this.#h.nextOrder,this.#h.nextOrder+=1,i.add(o),this.#E.set(t,i)}#m(t,o){let i=this.#E.get(t);i?.delete(o),i?.size===0&&this.#E.delete(t);for(let[e,a]of this.#u)a.ownership===o&&this.#u.delete(e)}#y(t){if(!t.control)return;let o=this.#B.get(t.control.owner);o||(o=new Map,this.#B.set(t.control.owner,o));let i=o.get(t.control.key)??new Set;i.add(t),o.set(t.control.key,i)}#Q(t){if(!t.control)return;let o=this.#B.get(t.control.owner),i=o?.get(t.control.key);i?.delete(t),i?.size===0&&o.delete(t.control.key),o?.size===0&&this.#B.delete(t.control.owner)}#C(t,o){let i=XK(o);return i?[...this.#B.get(i.owner)?.get(i.key)??[]].filter(a=>a.sessionId===t).sort((a,A)=>a.order-A.order):[]}#b(t,o){return this.#C(t,o).find(i=>i.started&&i.active&&!i.completed&&i.turn!==null)??null}async#M(t,o,i){let e=this.#C(t,o);if(e.length===0)return null;try{let a=await this.rpc("session.history",{sessionId:t,maxMessages:50},3e4,i);this.#w(t,a.events??[])}catch(a){if(!(a instanceof Xo)||a.code!=="session-not-found")throw a;for(let A of e)A.active=!1,A.completed=!0;return null}return this.#b(t,o)}async hasActiveTurn(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");return!!await this.#M(t,o,i)}async stopActiveTurn(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");let e=await this.#M(t,o,i);if(!e)return!1;if(e.stopRequested)return!0;if(this.#b(t,o)!==e)return!1;e.stopRequested=!0;try{if(this.#g){let a=this.#g({sessionId:t,expectedTurn:e.turn,promptRpcId:e.promptRpcId,action:"stop"});if(a&&typeof a.then=="function")throw new TypeError("controlExecutor must return synchronously");if(a!==void 0){if(typeof a!="boolean")throw new TypeError("controlExecutor must return a boolean or undefined");return a||(e.stopRequested=!1),a}}return await this.rpc("session.cancel",{sessionId:t,keepInbox:!0},3e4,i),!0}catch(a){if(this.#b(t,o)===e&&(e.stopRequested=!1),a instanceof Xo&&a.code==="session-not-found")return!1;throw a}}async steerActiveTurn(t,o,i,e={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(typeof o!="string"||!o.trim())throw new TypeError("Steering text is required");let a=await this.#M(t,i,e);if(!a||a.stopRequested||this.#b(t,i)!==a)return!1;if(this.#g){let A=this.#g({sessionId:t,expectedTurn:a.turn,promptRpcId:a.promptRpcId,action:"steer",text:o});if(A&&typeof A.then=="function")throw new TypeError("controlExecutor must return synchronously");if(A!==void 0){if(typeof A!="boolean")throw new TypeError("controlExecutor must return a boolean or undefined");return A}}return await this.rpc("session.prompt",{sessionId:t,mode:"steer",content:[{type:"text",text:o}],clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,e),!0}#w(t,o){for(let i of this.#E.get(t)??[])ppe(i,o)}async#S(t,o){let i=await this.rpc("session.history",{sessionId:t,maxMessages:50},3e4,{signal:o});this.#w(t,i.events??[])}#_(t,o,i){let e=this.#u.get(o);if(e&&this.#E.get(t)?.has(e.ownership))return e;let a=[...this.#E.get(t)??[]],A=a.filter(s=>s.active).sort((s,g)=>s.order-g.order);if(A.length>0)return{ownership:A[0],recovered:!1};let r=a.filter(s=>!s.started&&!s.completed).sort((s,g)=>s.order-g.order)[0]??null;return r?{ownership:r,recovered:!0}:null}async ask(t,o,i={}){typeof i=="number"&&(i={timeoutMs:i});let e=i.timeoutMs??6e5,a=i.signal,A=typeof i.onUpdate=="function"?i.onUpdate:null,r=i.progressMode==="all"?"all":"latest",s=typeof i.onArtifact=="function"?i.onArtifact:null,g=typeof i.onInteraction=="function"?i.onInteraction:void 0,c=typeof i.onInteractionResolved=="function"?i.onInteractionResolved:void 0,I=XK(i.control),d=Array.isArray(i.files)?i.files.filter(Boolean):[];await this.ensureRunning({signal:a});let B=await this.rpc("session.history",{sessionId:t,maxMessages:1},3e4,{signal:a}),f=Math.max(-1,...(B.events??[]).map(({event:V})=>V.seq??-1)),Q=`${this.#I}-${WK()}`,y=new jl({promptRpcId:Q,afterSeq:f}),m=g||c?new AbortController:null,_=m?a?AbortSignal.any([a,m.signal]):m.signal:null,N=m||I?{sessionId:t,promptRpcId:Q,active:!1,started:!1,completed:!1,stopRequested:!1,turn:null,openTurn:null,lastSeq:f,reconnect:null,order:-1,toolCalls:new Map,control:I}:null,G=null,Y=!1,J=0,H=null,j=!1,q=!1,U=async()=>{if(!s||Y||y.turn===null)return J;Y=!0;let V=$c.take(t,y.turn,{signal:a});for(let L of V)try{await s(L),J+=1}catch(T){$c.release(L),console.warn(`[${this.#o}] ignored an artifact handoff failure:`,T.message)}return J};N&&(this.#f(t,N),this.#y(N));let R=$c.openConsumer(t,Q);try{if(d.length>0){if(!this.#p)throw new ho("inbound-file-ingress-unavailable","Harness file ingress is unavailable in this Host process.");let T=(await this.rpc("session.list",{},3e4,{signal:a}))?.items?.find(P=>P?.sessionId===t)?.cwd;H=await this.#p({sessionId:t,workspace:T,files:d,signal:a}),o=_K(o,H)}if(_){let L,T=new Promise(P=>{L=P});G=this.watchInteractions(t,{signal:_,onInteraction:g,onResolved:c,onOpen:L,ownership:N}),G.catch(()=>{}),await Promise.race([T,eE(3e4,_).then(()=>{throw new Error("Harness interaction stream did not open within 30 seconds")})])}let V=typeof o=="string"?[{type:"text",text:o}]:o;if(!Array.isArray(V)||V.length===0)throw new TypeError("Harness prompt content is required");await this.rpc("session.prompt",{sessionId:t,mode:"queue",content:V,clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,{rpcId:Q,signal:a}),j=!0;try{let L=Date.now()+e;for(;Date.now()<L;){await eE(300,a);let T=await this.rpc("session.history",{sessionId:t,maxMessages:50},3e4,{signal:a}),P=N?.active===!0;N&&(this.#w(t,T.events??[]),!P&&N.active&&N.reconnect?.());let W=y.consumeAll(T.events??[]);if(A){let ge=r==="all"?W:W.slice(-1);for(let Se of ge)try{await A(Se)}catch(de){console.warn(`[${this.#o}] ignored a progress update failure:`,de.message)}}if(!y.finished)continue;if(q=!0,!N?.stopRequested&&!dpe(y.reason))throw Ax(y.reason);let ae=N?.stopRequested?0:await U();if(y.answer)return y.answer;if(ae>0)return"";throw N?.stopRequested?ex():Ax(y.reason)}throw new kn("harness-reply-timeout")}catch(L){if(!N?.stopRequested)throw L;if(y.answer)return y.answer;throw L?.code==="turn-stopped"?L:ex()}}finally{H&&(!j||q)&&await H.cleanup().catch(V=>{console.warn(`[${this.#o}] unable to clean inbound files:`,V.message)}),R(),N&&(this.#Q(N),this.#m(t,N)),y.turn!==null&&$c.discard(t,y.turn),m?.abort(new DOMException("Harness turn finished","AbortError")),G&&await G.catch(()=>{})}}#R(t,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A}){let r=new URL("/api/events.mux",this.#e);return r.protocol=r.protocol==="https:"?"wss:":"ws:",new Promise((s,g)=>{let c;try{c=this.#c(r.toString())}catch(U){g(U);return}let I=!1,d=!1,B=null,f=Promise.resolve(),Q=A==null,y=[],m=U=>{if(!d){if(d=!0,c.removeEventListener("open",N),c.removeEventListener("message",J),c.removeEventListener("close",H),c.removeEventListener("error",j),o.removeEventListener("abort",q),A?.reconnect===_&&(A.reconnect=null),o.aborted){s();return}f.then(()=>{let R=U??B;R?g(R):s()},g)}},_=()=>{try{(c.readyState===0||c.readyState===1)&&c.close()}catch{}},N=()=>{I=!0,A&&(A.reconnect=_);try{a?.()}catch(U){console.warn(`[${this.#o}] ignored an interaction open callback failure:`,U.message)}A&&this.#S(t,o).then(()=>{if(!d){Q=!0;for(let U of y.splice(0))Y(U)}}).catch(U=>{B??=U,_(),m(U)})},G=(U,R)=>{U&&(f=f.then(()=>U(R)).catch(V=>{B??=V,_(),m(B)}))},Y=U=>{let R=U.payload;if(A&&R.type==="session/event"){this.#w(t,[R.event]);return}if(R.type==="question/requested"||R.type==="approval/requested"){let V=R.type==="question/requested"?"question":"approval",L=V==="question"?U.rpcId:R.approvalId,T=`${V}:${L}`;if(A){let W=this.#_(t,T,V);if(W?.ownership!==A)return;this.#u.set(T,W)}let P=V==="approval"&&A&&typeof R.callId=="string"?this.#u.get(T)?.ownership.toolCalls.get(R.callId):void 0;G(i,Object.freeze({kind:V,interactionId:L,rpcId:U.rpcId,sessionId:t,payload:R,recovered:A?this.#u.get(T)?.recovered===!0:!1,...P?{toolCall:P}:{},reconnect:_,respond:(W,ae={})=>this.respondInteraction(U.rpcId,W,{...ae,signal:ae.signal??o})}));return}if(R.type==="question/resolved"||R.type==="approval/resolved"){let V=R.type==="question/resolved"?"question":"approval",L=V==="question"?R.questionRpcId:R.approvalId,T=`${V}:${L}`;if(A){if(this.#u.get(T)?.ownership!==A)return;this.#u.delete(T)}G(e,Object.freeze({kind:V,interactionId:L,sessionId:t,outcome:R.outcome,payload:R}))}},J=U=>{try{if(typeof U.data!="string")throw new Error("binary WebSocket frame");let R=JSON.parse(U.data),V=R?.payload;if(R?.type!=="server-request"||typeof R.rpcId!="string"||!V||typeof V!="object"||R.method!==V.type)throw new Error("invalid server-request envelope");if(V.sessionId!==t)return;Q?Y(R):y.push(R)}catch(R){console.warn(`[${this.#o}] ignored a malformed Harness interaction frame:`,R.message)}},H=()=>m(I?null:new Error("Harness interaction WebSocket closed before opening")),j=()=>{m(new Error(I?"Harness interaction WebSocket failed":"Harness interaction WebSocket failed before opening")),_()},q=()=>{_(),m()};c.addEventListener("open",N),c.addEventListener("message",J),c.addEventListener("close",H,{once:!0}),c.addEventListener("error",j,{once:!0}),o.addEventListener("abort",q,{once:!0}),o.aborted&&q()})}async watchHarnessEvents({signal:t,onSessionEvent:o,onReconnect:i}={}){if(typeof o!="function")throw new TypeError("watchHarnessEvents requires onSessionEvent");if(!t||typeof t.addEventListener!="function")throw new TypeError("watchHarnessEvents requires an AbortSignal");if(i!==void 0&&typeof i!="function")throw new TypeError("onReconnect must be a function");let e=new URL("/api/events.mux",this.#e);for(e.protocol=e.protocol==="https:"?"wss:":"ws:";!t.aborted;){try{await this.#k(e.toString(),{signal:t,onSessionEvent:o,onReconnect:i})}catch(a){if(t.aborted)return;console.warn(`[${this.#o}] Harness event mux disconnected:`,a.message)}if(t.aborted)return;try{await eE(this.#s,t)}catch{if(t.aborted)return;throw new Error("Harness event mux reconnect wait failed")}}}#k(t,{signal:o,onSessionEvent:i,onReconnect:e}){return new Promise((a,A)=>{let r;try{r=this.#c(t)}catch(m){A(m);return}let s=!1,g=!1,c=()=>{try{r.close()}catch{}},I=m=>{g||(g=!0,r.removeEventListener("open",d),r.removeEventListener("message",B),r.removeEventListener("close",f),r.removeEventListener("error",Q),o.removeEventListener("abort",y),m?A(m):a())},d=()=>{s=!0;try{e?.()}catch(m){console.warn(`[${this.#o}] mux reconnect hook failed:`,m.message)}},B=m=>{try{if(typeof m.data!="string")return;let _=JSON.parse(m.data),N=_?.payload;if(_?.type!=="server-request"||!N||typeof N!="object"||_.method!==N.type||N.type!=="session/event"||typeof N.sessionId!="string"||!N.event||typeof N.event!="object")return;i({sessionId:N.sessionId,event:N.event})}catch(_){console.warn(`[${this.#o}] ignored a malformed global mux frame:`,_.message)}},f=()=>I(s?null:new Error("Harness event mux WebSocket closed before opening")),Q=()=>{I(new Error(s?"Harness event mux WebSocket failed":"Harness event mux WebSocket failed before opening")),c()},y=()=>{c(),I()};r.addEventListener("open",d),r.addEventListener("message",B),r.addEventListener("close",f,{once:!0}),r.addEventListener("error",Q,{once:!0}),o.addEventListener("abort",y,{once:!0}),o.aborted&&y()})}stopManagedProcess(){this.#d?.exitCode===null&&this.#d.kill("SIGTERM")}};var wf=class extends lr{constructor(t){super({...t,rpcIdPrefix:"dingtalk",logPrefix:"dsh-dingtalk"})}};import{randomUUID as hpe}from"node:crypto";import{mkdir as Epe,readFile as Cpe,rename as upe,unlink as Bpe,writeFile as fpe}from"node:fs/promises";import{dirname as Qpe}from"node:path";var Of=Object.freeze({version:1,sessions:{},seenMessageIds:[],pendingSenders:{}});function pr(n){return typeof n=="string"&&n.trim()?n.trim():null}function tx(n){return(pr(n)??D("\u9489\u9489\u7528\u6237")).slice(0,100)}function ype(n,t){if(!n||typeof n!="object")return null;let o=pr(n.requestId)??pr(t),i=pr(n.staffId),e=pr(n.requestedAt)??pr(n.lastSeenAt),a=pr(n.lastSeenAt)??e;return!o||!i||!e||!a?null:{requestId:o,staffId:i,displayName:tx(n.displayName??n.nick),requestedAt:e,lastSeenAt:a}}function mpe(n){if(!n||typeof n!="object")return structuredClone(Of);let t={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[e,a]of Object.entries(n.sessions)){let A=pr(e),r=pr(a);A&&r&&(t[A]=r)}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,a]of i){let A=ype(a,e);if(!A)continue;let r=Object.values(o).find(s=>s.staffId===A.staffId);(!r||r.lastSeenAt<A.lastSeenAt)&&(r&&delete o[r.requestId],o[A.requestId]=A)}return{version:1,sessions:t,seenMessageIds:Array.isArray(n.seenMessageIds)?[...new Set(n.seenMessageIds.map(pr).filter(Boolean))].slice(-1e3):[],pendingSenders:o}}var bf=class{#e;#A=structuredClone(Of);#t=Promise.resolve();#r;#a;constructor(t,{idFactory:o=hpe,now:i=()=>new Date().toISOString()}={}){if(!pr(t))throw new TypeError("state path is required");if(typeof o!="function"||typeof i!="function")throw new TypeError("idFactory and now must be functions");this.#e=t,this.#r=o,this.#a=i}async load(){try{this.#A=mpe(JSON.parse(await Cpe(this.#e,"utf8")))}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=structuredClone(Of),await this.#i()}return this}sessionFor(t){return this.#A.sessions[t]??null}async setSession(t,o){let i=pr(t),e=pr(o);if(!i||!e)throw new TypeError("key and sessionId are required");this.#A.sessions[i]=e,await this.#i()}async clearSession(t){let o=pr(t);!o||!(o in this.#A.sessions)||(delete this.#A.sessions[o],await this.#i())}async clearSessions(){this.#A.sessions={},await this.#i()}hasSeen(t){let o=pr(t);return!!(o&&this.#A.seenMessageIds.includes(o))}async markSeen(t){let o=pr(t);if(!o)throw new TypeError("messageId is required");this.hasSeen(o)||(this.#A.seenMessageIds.push(o),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#i())}pendingSenders(){return Object.values(this.#A.pendingSenders).sort((t,o)=>t.requestedAt.localeCompare(o.requestedAt)).map(t=>structuredClone(t))}pendingSender(t){let o=pr(t),i=o?this.#A.pendingSenders[o]:null;return i?structuredClone(i):null}async recordPendingSender(t,o,i){let e=t&&typeof t=="object"?t:{staffId:t,displayName:o,lastSeenAt:i},a=pr(e.staffId);if(!a)throw new TypeError("staffId is required");let A=pr(e.lastSeenAt)??pr(e.requestedAt)??this.#a(),r=Object.values(this.#A.pendingSenders).find(g=>g.staffId===a),s={requestId:r?.requestId??`ding_sender_${this.#r()}`,staffId:a,displayName:tx(e.displayName??e.nick??o),requestedAt:r?.requestedAt??A,lastSeenAt:A};return this.#A.pendingSenders[s.requestId]=s,await this.#i(),structuredClone(s)}async removePendingSender(t){let o=pr(t);return!o||!this.#A.pendingSenders[o]?!1:(delete this.#A.pendingSenders[o],await this.#i(),!0)}async removePendingSenderByStaffId(t){let o=pr(t),i=o?Object.values(this.#A.pendingSenders).find(e=>e.staffId===o):null;return i?this.removePendingSender(i.requestId):!1}snapshot(){return structuredClone(this.#A)}async remove(){await this.#t;try{await Bpe(this.#e)}catch(t){if(t?.code!=="ENOENT")throw t}this.#A=structuredClone(Of)}async#i(){let t=`${JSON.stringify(this.#A,null,2)}
213
213
  `,o=this.#t.then(async()=>{await Epe(Qpe(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await fpe(i,t,{encoding:"utf8",mode:384}),await upe(i,this.#e)});this.#t=o.then(()=>{},()=>{}),await o}};import{mkdir as Spe,readFile as Dpe,realpath as wpe,rename as Ope,stat as bpe,unlink as Mpe,writeFile as _pe}from"node:fs/promises";import{dirname as Tpe,isAbsolute as ix,resolve as AE}from"node:path";var b5e=Object.freeze({version:1,workspaces:Object.freeze({})});function eI(n){let t=new Error(n);return t.code=oi,t}async function lM(n){return AE(await wpe(n))}async function Npe(n,t){if(n===t)return!0;try{return await lM(n)===await lM(t)}catch{return!1}}function di(n){if(typeof n!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n))throw new TypeError("Invalid bot id");return n}function Rpe(n){if(!n||n.version!==1||!n.workspaces||typeof n.workspaces!="object"||Array.isArray(n.workspaces))return null;let t={};for(let[i,e]of Object.entries(n.workspaces)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(i)||typeof e!="string"||!ix(e))return null;t[i]=AE(e)}let o={};if(n.agentPresets!==void 0){if(!n.agentPresets||typeof n.agentPresets!="object"||Array.isArray(n.agentPresets))return null;for(let[i,e]of Object.entries(n.agentPresets)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(i))return null;try{let a=Kl(e);if(!a)return null;o[i]=a}catch{return null}}}return{version:1,workspaces:t,agentPresets:o}}async function rx(n){if(typeof n!="string"||!n.trim()||!ix(n.trim())){let i=new Error("\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");throw i.code="workspace-not-absolute",i}let t=AE(n.trim()),o;try{o=await bpe(t)}catch(i){let e=new Error("\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002",{cause:i});throw e.code="workspace-not-found",e}if(!o.isDirectory()){let i=new Error("\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002");throw i.code="workspace-not-directory",i}return t}var Zr=class{#e;#A;#t={};#r={};#a=new Map;#i=1;#c=new Map;#s=1;#I=new Map;#o=new WeakMap;#n=new Set;#g=Promise.resolve();#l=new Map;constructor(t,{defaultWorkspace:o=process.cwd()}={}){if(typeof t!="string"||!t)throw new TypeError("workspace store path is required");this.#e=t,this.#A=AE(o)}async load(){try{let t=Rpe(JSON.parse(await Dpe(this.#e,"utf8")));if(!t)throw new Error("dsh-im workspace config is invalid");this.#t=t.workspaces,this.#r=t.agentPresets}catch(t){if(t?.code!=="ENOENT")throw t;this.#t={},this.#r={}}this.#a.clear(),this.#i=1,this.#c.clear(),this.#s=1,this.#I.clear(),this.#n.clear();for(let t of Object.keys(this.#t))this.#a.set(t,this.#p()),this.#c.set(t,this.#d());return this}has(t){let o=di(t);return Object.hasOwn(this.#t,o)&&!this.#I.has(o)}incarnationFor(t){return this.#c.get(di(t))??null}workspaceFor(t){return this.#t[di(t)]??this.#A}agentPresetFor(t){return this.#r[di(t)]??null}generationFor(t){return this.#a.get(di(t))??null}async whenIdle(){await this.#g}async whenBotIdle(t){let o=di(t);for(;;){let i=this.#l.get(o);if(!i||(await i,this.#l.get(o)===i))return}}async ensure(t,{workspace:o=this.#A,defaultAgentPreset:i}={}){let e=di(t),a=AE(o);return this.#u(e,async()=>{if(this.#t[e])this.#a.has(e)||this.#a.set(e,this.#p());else{let A=Kl(i),r=Object.hasOwn(this.#r,e),s=this.#r[e];this.#t[e]=a,A&&(this.#r[e]=A),this.#a.set(e,this.#p()),this.#c.set(e,this.#d());try{await this.#B()}catch(g){throw delete this.#t[e],r?this.#r[e]=s:delete this.#r[e],this.#a.delete(e),this.#c.delete(e),g}}return this.#t[e]})}async setWorkspace(t,o,{clearSessions:i,incarnation:e}={}){let a=di(t);if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}let A=await rx(o);return this.#u(a,async()=>{if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let s=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw s.code="workspace-bot-not-found",s}if(A===this.workspaceFor(a))return A;let r=this.#t[a];this.#a.set(a,this.#p()),await i?.(),this.#t[a]=A;try{await this.#B()}catch(s){throw this.#t[a]=r,s}return A})}async setAgentPreset(t,o,{incarnation:i}={}){let e=di(t);if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let A=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw A.code="workspace-bot-not-found",A}let a=Kl(o);return this.#u(e,async()=>{if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}let A=this.#r[e]??null;if(A===a)return a;a?this.#r[e]=a:delete this.#r[e];try{await this.#B()}catch(r){throw A?this.#r[e]=A:delete this.#r[e],r}return a})}async bindWorkspaceSession(t,o,{conversationKey:i,sessionId:e,clearSessions:a,setSession:A,incarnation:r,expectedGeneration:s}={}){let g=di(t);if(typeof i!="string"||!i||typeof e!="string"||!e)throw new TypeError("conversationKey and sessionId are required");if(typeof a!="function"||typeof A!="function")throw new TypeError("session state callbacks are required");if(!this.has(g)||r!==void 0&&r!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}let c=await lM(await rx(o));return this.#u(g,async()=>{if(!this.has(g)||r!==void 0&&r!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}if(s!==void 0&&s!==this.generationFor(g))throw eI("The bot workspace changed before the session binding could be committed.");if(!await Npe(c,this.workspaceFor(g))){let I=this.#t[g];this.#a.set(g,this.#p()),await a(),this.#t[g]=c;try{await this.#B()}catch(d){throw this.#t[g]=I,d}}return await A(i,e),{workspace:c,sessionId:e,generation:this.#a.get(g)}})}async invalidateSessions(t,{clearSessions:o}={}){let i=di(t);return this.#u(i,async()=>{this.#a.set(i,this.#p()),await o?.()})}async beginRemoval(t,{clearSessions:o}={}){let i=di(t);return this.#u(i,async()=>{let e=this.#I.get(i);if(e)return e;let a=Object.freeze({});this.#I.set(i,a),this.#o.set(a,{botId:i,incarnation:this.incarnationFor(i)}),this.#a.set(i,this.#p());try{await o?.()}catch(A){throw this.#I.get(i)===a&&this.#I.delete(i),A}return a})}async abortRemoval(t){let{botId:o}=this.#h(t);return this.#u(o,async()=>this.#I.get(o)!==t?!1:(this.#I.delete(o),Object.hasOwn(this.#t,o)&&(this.#a.set(o,this.#p()),this.#c.has(o)||this.#c.set(o,this.#d())),!0))}async finishRemoval(t){let{botId:o,incarnation:i}=this.#h(t);return this.#u(o,async()=>this.#I.get(o)!==t?{removed:!1,persisted:!0,error:null,stale:!0}:this.incarnationFor(o)!==i?(this.#I.delete(o),{removed:!1,persisted:!0,error:null,stale:!0}):(this.#I.delete(o),this.#E(o)))}async retireAfterConfigCommit(t){let o=di(t);return this.#u(o,async()=>(this.#I.delete(o),this.#E(o)))}async remove(t){let o=await this.retireAfterConfigCommit(t);if(o.error)throw o.error;return o.removed}async reconcile(t){let o=new Set([...t].map(di)),i=new Set([...Object.keys(this.#t),...Object.keys(this.#r),...this.#n]);for(let e of i)o.has(e)||await this.remove(e)}decorateStatus(t){return!t||typeof t!="object"||!Array.isArray(t.bots)?t:{...t,bots:t.bots.map(o=>o?.botId?{...o,workspace:this.workspaceFor(o.botId),agentPreset:this.agentPresetFor(o.botId)}:o)}}#p(){let t=this.#i;return this.#i+=1,t}#d(){let t=this.#s;return this.#s+=1,t}#h(t){if(!t||typeof t!="object")throw new TypeError("Invalid workspace removal transaction");let o=this.#o.get(t);if(!o)throw new TypeError("Invalid workspace removal transaction");return o}async#E(t){let o=Object.hasOwn(this.#t,t),i=Object.hasOwn(this.#r,t),e=o||i||this.#n.has(t);if(delete this.#t[t],delete this.#r[t],this.#a.delete(t),this.#c.delete(t),!e)return{removed:!1,persisted:!0,error:null,stale:!1};try{return await this.#f(),{removed:o,persisted:!0,error:null,stale:!1}}catch(a){return this.#n.add(t),{removed:o,persisted:!1,error:a,stale:!1}}}async#u(t,o){let i=this.#g.then(o,o),e=i.then(()=>{},()=>{});return this.#g=e,this.#l.set(t,e),e.finally(()=>{this.#l.get(t)===e&&this.#l.delete(t)}),i}async#B(){let t={version:1,workspaces:this.#t};Object.keys(this.#r).length>0&&(t.agentPresets=this.#r),await Spe(Tpe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await _pe(o,`${JSON.stringify(t,null,2)}
214
- `,{encoding:"utf8",mode:384}),await Ope(o,this.#e),this.#n.clear()}async#f(){if(Object.keys(this.#t).length>0||Object.keys(this.#r).length>0){await this.#B();return}try{await Mpe(this.#e),this.#n.clear()}catch(t){if(t?.code!=="ENOENT")throw t;this.#n.clear()}}};function pM(n){if(!n)return null;let t=typeof n=="function"?n():n;return t&&typeof t.then=="function"?t.then(_n):_n(t)}function ox(){let n=new Error("Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002");return n.code="agent-preset-unavailable",n}function ql(n){if(n())return;let t=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw t.code="workspace-bot-not-found",t}function ax(n,t,o){let i=e=>{let a=n.decorateStatus(e);if(!o||!a||typeof a!="object")return a;let A=s=>s?{...a,agentPresetCatalog:s}:a,r=pM(o);return r&&typeof r.then=="function"?r.then(A):A(r)};return t&&typeof t.then=="function"?t.then(i):i(t)}function kpe(n){return Promise.resolve(n.status())}function Ma(n,{workspaces:t,method:o="remove",botIdFromRemoved:i=e=>e?.botId}){if(!n||!t||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(e,a){let A=Reflect.get(e,a,e);return a===o?async(...r)=>{let s=await A.apply(e,r),g=s?i(s,r):null;return g&&await t.retireAfterConfigCommit(g),s}:typeof A=="function"?A.bind(e):A}})}function _a(n,{botId:t,workspaces:o,state:i,agentPresetCatalog:e}={}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let a=o.incarnationFor(t),A=()=>o.has(t)&&o.incarnationFor(t)===a,r=async(I=e)=>{let d;try{d=await pM(I)??_n(null)}catch(B){throw ql(A),B}return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:d}},s=new Map,g=new Proxy(n,{get(I,d){if(d==="agentPresetSettings")return async(f={})=>{f?.signal?.throwIfAborted(),ql(A);let Q=await r();return f?.signal?.throwIfAborted(),Q};if(d==="updateAgentPreset")return async(f,Q={})=>{Q?.signal?.throwIfAborted(),ql(A);let y=f==="--default"?null:Kl(f),m=null;if(y&&({agentPresetCatalog:m}=await r(),Q?.signal?.throwIfAborted(),!m.items.some(_=>_.id===y)))throw ox();if(await o.setAgentPreset(t,y,{incarnation:a}),ql(A),m)return{agentPreset:o.agentPresetFor(t),agentPresetCatalog:m};try{return await r()}catch(_){if(_?.code==="workspace-bot-not-found")throw _;return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:_n(null)}}};if(d==="currentWorkspace")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}return o.workspaceFor(t)};if(d==="assertWorkspaceScope")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}};if((d==="listWorkspaces"||d==="listWorkspaceSessions"||d==="listModels")&&typeof I[d]=="function")return async(...f)=>{if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=await I[d](...f);if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}return Q};if(d==="switchWorkspace")return f=>{if(!A()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return Q.code="workspace-bot-not-found",Promise.reject(Q)}return o.setWorkspace(t,f,{clearSessions:()=>i.clearSessions(),incarnation:a})};if(d==="bindWorkspaceSession")return async(f,Q)=>{if(typeof f!="string"||!f||typeof Q!="string"||!Q)throw new TypeError("conversationKey and sessionId are required");if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(typeof I.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let y=o.generationFor(t),m=await I.adoptWorkspaceSession(Q);if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(y!==o.generationFor(t))throw eI("The bot workspace changed while the session was being adopted.");if(!m||typeof m!="object"||m.sessionId!==Q||typeof m.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let _=await o.bindWorkspaceSession(t,m.workspace,{conversationKey:f,sessionId:Q,clearSessions:()=>i.clearSessions(),setSession:(N,G)=>i.setSession(N,G),incarnation:a,expectedGeneration:y});if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(_.generation!==o.generationFor(t))throw eI("The bot workspace changed before the session binding completed.");return s.set(Q,_.generation),{...m,workspace:_.workspace,sessionId:_.sessionId}};if(d==="createSession")return async(f={})=>{if(await o.whenBotIdle(t),!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}let Q=o.generationFor(t),y=o.agentPresetFor(t),m=await I.createSession({...f,workspace:o.workspaceFor(t),...y==null?{}:{agentPreset:y}});return s.set(m,Q),m};if(d==="workspaceSession")return f=>{if(typeof f!="string"||!f)throw new TypeError("sessionId is required");let Q=s.get(f)??o.generationFor(t);s.delete(f);let y=()=>A()&&Q===o.generationFor(t),m=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);let J=await I[N](f,...G);if(!y())throw eI(`The bot workspace changed while this ${Y} was running.`);return J},_=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);return I[N](f,...G)};return Object.freeze({sessionId:f,async sessionExists(...N){if(!y())return!1;let G=await I.sessionExists(f,...N);return y()&&G},models(...N){return m("getSessionModels",N,"model listing")},selectModel(...N){return m("selectSessionModel",N,"model selection")},isRunning(...N){return m("isSessionRunning",N,"run-state check")},hasActiveTurn(...N){return m("hasActiveTurn",N,"turn ownership check")},stopActiveTurn(...N){return _("stopActiveTurn",N,"turn stop")},steerActiveTurn(...N){return _("steerActiveTurn",N,"turn steering")},ask(...N){if(!y())throw eI("The bot workspace changed before this prompt started.");return I.ask(f,...N)}})};if(d==="sessionExists")return(f,...Q)=>{if(!A())return!1;let y=s.get(f);return y!==void 0&&y!==o.generationFor(t)?(s.delete(f),!1):I.sessionExists(f,...Q)};if(d==="ask")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this prompt started.");throw m.code=oi,m}return I.ask(f,...Q)};if(d==="executeCommand"&&typeof I.executeCommand=="function")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this command started.");throw m.code=oi,m}return I.executeCommand(f,...Q)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}}),c=new Proxy(i,{get(I,d){if(d===Ob)return I;if(d==="sessionFor")return(f,...Q)=>{if(!A())return null;let y=I.sessionFor(f,...Q);return y&&!s.has(y)&&s.set(y,o.generationFor(t)),y};if(d==="setSession")return(f,Q,...y)=>{let m=s.get(Q);return!A()||m!==void 0&&m!==o.generationFor(t)?(s.delete(Q),!1):I.setSession(f,Q,...y)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}});return Object.freeze({harness:g,state:c})}function Ta(n,{workspaces:t,stateFor:o,agentPresetCatalog:i}={}){if(!n||!t||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let e=new Map,a=(c,I)=>{let B=(e.get(c)??Promise.resolve()).catch(()=>{}).then(I);return e.set(c,B),B.finally(()=>{e.get(c)===B&&e.delete(c)})},A=c=>ax(t,c,i),r=(c,I)=>{let d=t.incarnationFor(c);return a(c,async()=>{if(!(await n.status())?.bots?.some(Q=>Q?.botId===c)){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}let f=await o(c);return await t.setWorkspace(c,I,{clearSessions:()=>f.clearSessions(),incarnation:d}),A(await n.status())})},s=(c,I)=>{let d=t.incarnationFor(c),B=Kl(I);return a(c,async()=>{if(!(await n.status())?.bots?.some(y=>y?.botId===c)){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=B&&i?await pM(i):null;if(B&&i&&!Q?.items.some(y=>y.id===B))throw ox();return await t.setAgentPreset(c,B,{incarnation:d}),ax(t,await n.status(),Q??i)})},g=(c,I)=>a(c,async()=>{let d=await t.beginRemoval(c,{clearSessions:async()=>{try{let B=await o(c);if(!B||typeof B.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await B.clearSessions()}catch(B){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${c}:`,B?.message??B)}}});try{let B=await I();return await t.finishRemoval(d),A(B)}catch(B){let f=await kpe(n).catch(()=>null);throw Array.isArray(f?.bots)&&!f.bots.some(y=>y?.botId===c)?await t.finishRemoval(d):await t.abortRemoval(d),B}});return new Proxy(n,{get(c,I){if(I==="updateWorkspace")return r;if(I==="updateAgentPreset")return s;let d=Reflect.get(c,I,c);return typeof d!="function"?d:I==="deleteBot"?(B,...f)=>g(B,()=>d.call(c,B,...f)):I==="disconnect"?async(...B)=>{let Q=(await c.status())?.bots?.[0]?.botId;return Q?g(Q,()=>d.apply(c,B)):A(d.apply(c,B))}:(...B)=>A(d.apply(c,B))}})}var nx=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function vpe(n){if(!Array.isArray(n)||n.length===0)return[...nx];let t=n.filter(o=>Number.isFinite(o)&&o>=0);return t.length>0?t:[...nx]}var Mf=class{#e;#A;#t;#r;#a;#i;#c;#s=null;#I=null;#o=0;#n=!1;#g=!1;#l;#p;constructor({controller:t,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:r=clearTimeout}){if(!t||typeof t.initialize!="function"||typeof t.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=t,this.#A=o,this.#t=i,this.#r=vpe(e),this.#a=Number.isFinite(a)&&a>=0?a:15e3,this.#i=A,this.#c=r,this.#l=new Promise(s=>{this.#p=s})}get ready(){return this.#l}start(){return this.#g||this.#n?this:(this.#g=!0,this.#d(0),this)}async close(){this.#n||(this.#n=!0,this.#s!==null&&this.#c(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#d(t){this.#n||(this.#s=this.#i(()=>{this.#s=null,this.#h()},t),this.#s?.unref?.())}async#h(){if(this.#n||this.#I)return;let t=this.#E();this.#I=t;try{await t}finally{this.#I===t&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#n)return;let t=await this.#e.initialize();if(this.#n)return;this.#p?.(t),this.#p=null;let{configured:o,connected:i}=t.totals;if(i<o){let e=this.#r[Math.min(this.#o,this.#r.length-1)];this.#o+=1,this.#t.warn?.(`[dsh-dingtalk] ${i}/${o} bots connected; retrying in ${e}ms`),this.#d(e);return}this.#o=0,this.#d(this.#a)}catch(t){if(this.#n)return;let o=this.#r[Math.min(this.#o,this.#r.length-1)];this.#o+=1,this.#t.warn?.(`[dsh-dingtalk] connection reconciliation failed; retrying in ${o}ms`,t),this.#d(o)}}};function dM(n){return new Mf(n)}function Na(n,t){if(t!==void 0){if(typeof t!="function")throw new TypeError("commandExecutor must be a function");return t}let o=n?.typertGateway;if(o){if(typeof o.invoke!="function")throw new TypeError("dsh-im requires a callable ctx.typertGateway");return(i,e,a={})=>o.invoke({namespace:"commands",method:"execute",args:{agentId:i,line:e},signal:a.signal})}}import{randomUUID as Ppe}from"node:crypto";function Gpe(n){if(typeof n?.get!="function")return;let t;try{t=n.get("agents")}catch{return}if(t!=null){if(typeof t.get!="function")throw new TypeError('dsh-im requires a callable AgentRegistry when ctx.get("agents") is present');return t}}function Fpe(n,t,o){if(n?.status!=="running")return!1;let i=n?.session?.events;if(!Array.isArray(i))return!1;let e=null,a=!1;for(let A of i){if(A?.type==="turn/start"){e=A.data?.turn??null,a=!1;continue}if(A?.type==="turn/end"&&A.data?.turn===e){e=null,a=!1;continue}e===t&&A?.type==="user/message"&&A.data?.source?.rpcId===o&&(a=!0)}return e===t&&a}function sx(n){if(!n||typeof n!="object"||Object.isFrozen(n))return n;for(let t of Object.values(n))sx(t);return Object.freeze(n)}function Lpe(n){return sx({id:Ppe(),role:"user",content:[{type:"text",text:n}],source:{kind:"user"}})}function Upe(n){let t=new Error("Session is busy with an active turn or maintenance task",{cause:n});return t.code="agent-busy",t}function Hpe(n){return({sessionId:t,expectedTurn:o,promptRpcId:i,action:e,text:a})=>{let A=n.get(t);if(A){if(!Fpe(A,o,i))return!1;if(e==="stop")return A.cancel({kind:"user"},{keepInbox:!0}),!0;if(e==="steer")return typeof a!="string"||!a.trim()?!1:(A.inject(Lpe(a)),!0);throw new TypeError(`Unsupported Harness control action: ${String(e)}`)}}}function Kpe(n){return({sessionId:t,operation:o})=>{if(typeof o!="function")throw new TypeError("maintenance operation is required");let i=n.get(t);if(!i)return o();try{return i.runMaintenance(e=>{if(n.get(t)!==i){let a=new Error("Session agent changed before maintenance started");throw a.code="agent-unavailable",a}return o(e)})}catch(e){throw Upe(e)}}}function xpe(n){return({sessionId:t,workspace:o,files:i,signal:e})=>{let A=n.get(t)?.session?.header?.cwd,r=typeof A=="string"&&A?A:o;if(typeof r!="string"||!r)throw new ho("inbound-file-workspace-unavailable","The Harness Session workspace is unavailable for inbound files.");return MK({files:i},{workspace:r,signal:e})}}function Ra(n,t={}){let{controlExecutor:o,sessionMaintenanceExecutor:i,fileIngressExecutor:e}=t;if(o!==void 0&&typeof o!="function")throw new TypeError("controlExecutor must be a function");if(i!==void 0&&typeof i!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("fileIngressExecutor must be a function");let a=o&&i&&e?void 0:Gpe(n);return{controlExecutor:o??(a?Hpe(a):void 0),sessionMaintenanceExecutor:i??(a?Kpe(a):void 0),fileIngressExecutor:e??xpe(a??{get:()=>{}})}}function Jpe(n,t){if(t!==void 0)return new URL(t);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 qpe(n){let t=AI(n.dshHome??process.env.DSH_HOME??tE(jpe(),".dsh")),o=AI(n.dataDir??tE(t,"integrations","dsh-dingtalk"));return{root:o,config:AI(n.configPath??tE(o,"config.json")),bots:AI(n.botsDir??tE(o,"bots")),workspaces:AI(n.workspacesPath??tE(o,"workspaces.json"))}}async function hM(n,t={},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??cf,e=o.DeviceAuth??lf,a=o.StateStore??bf,A=o.HarnessClient??wf,r=o.Controller??xh,s=o.Runtime??Xh,g=o.createConnectionSupervisor??dM,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,I=()=>Oa(n),d=qpe(t),B=await new i(d.config).load(),f=AI(t.workspace??process.cwd()),Q=o.WorkspaceStore??Zr,y=o.workspaces??await new Q(d.workspaces,{defaultWorkspace:f}).load(),m=typeof B.list=="function",_=m?B.list():[];m&&await y.reconcile(_.map(W=>W.botId)),await Promise.all(_.map(W=>y.ensure(W.botId,{defaultAgentPreset:t.agentPreset})));let N=typeof B.remove=="function"?Ma(B,{workspaces:y}):B,G=o.deviceAuth??new e({baseUrl:t.registrationBaseUrl}),Y=new Map,J=W=>AI(d.bots,W,"state.json"),H=async W=>{let ae=Y.get(W);return ae||(ae=await new a(J(W)).load(),Y.set(W,ae)),ae},j=Na(n,o.commandExecutor),{controlExecutor:q,sessionMaintenanceExecutor:U,fileIngressExecutor:R}=Ra(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),V=new A({baseUrl:Jpe(n.webServer,t.harnessBaseUrl),workspace:f,autostart:!1,dshBin:t.dshBin??"dsh",...j?{commandExecutor:j}:{},...q?{controlExecutor:q}:{},...U?{sessionMaintenanceExecutor:U}:{},...R?{fileIngressExecutor:R}:{}}),L=new r({deviceAuth:G,credentials:n.credentials,configStore:N,logger:c,createRuntime:async({botId:W,config:ae,clientSecret:ge})=>{let Se=await H(W);await y.ensure(W,{defaultAgentPreset:t.agentPreset});let de=_a(V,{botId:W,workspaces:y,state:Se,agentPresetCatalog:I});return new s({config:ae,clientSecret:ge,harness:de.harness,state:de.state,replyTimeoutMs:t.replyTimeoutMs??6e5,maxMessageChars:t.maxMessageChars??4e3,connectTimeoutMs:t.connectTimeoutMs??15e3,logger:{error:(...De)=>c.error?.(`[${W}]`,...De),warn:(...De)=>c.warn?.(`[${W}]`,...De),info:(...De)=>c.info?.(`[${W}]`,...De),debug:(...De)=>c.debug?.(`[${W}]`,...De)}})},deleteState:async({botId:W})=>{let ae=Y.get(W);if(Y.delete(W),ae&&typeof ae.remove=="function")await ae.remove();else try{await Ype(J(W))}catch(ge){if(ge?.code!=="ENOENT")throw ge}}}),T=Ta(L,{workspaces:y,stateFor:H,agentPresetCatalog:I}),P=g({controller:T,harness:V,logger:c,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:T,ready:P.ready,async close(){await P.close(),await T.close(),V.stopManagedProcess()}}}import Zpe from"qrcode";var zpe=new Set(["loopback","trusted-host"]);function yr(n){if(n===void 0)return"loopback";if(zpe.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as Vpe}from"node:path";var hi="bot.workspace.set";function ka(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(t=>["botId","workspace"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&Vpe(n.workspace.trim())}function va(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found","agent-preset-invalid","agent-preset-unavailable"].includes(n?.code)?{code:n.code,message:n.message}:null}var Ei="bot.preset.set";function Wpe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Pa(n){return Wpe(n)&&Object.keys(n).every(t=>["botId","agentPreset"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&(n.agentPreset===null||typeof n.agentPreset=="string"&&zb.test(n.agentPreset))}var cx="/dingtalk",ar=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:hi,setAgentPreset:Ei,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),Ix=Object.freeze(Object.values(ar)),Xpe=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function CM(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function vg(n,t){return CM(n)&&Object.keys(n).every(o=>t.includes(o))}function tI(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function gx(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function $pe(n,t){return CM(t)?n===ar.status?vg(t,[])?null:"connection.status does not accept fields.":n===ar.beginProvisioning?vg(t,["locale"])&&(t.locale===void 0||t.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[ar.pollProvisioning,ar.cancelProvisioning].includes(n)?vg(t,["attemptId"])&&tI(t.attemptId)?null:`${n} requires an attemptId.`:n===ar.bindCredentials?vg(t,["clientId","clientSecret"])&&gx(t.clientId,256)&&gx(t.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===ar.reconnectBot?vg(t,["botId","sendTest"])&&tI(t.botId)&&(t.sendTest===void 0||t.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===ar.deleteBot?vg(t,["botId","confirm"])&&tI(t.botId)&&t.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===ar.setWorkspace?ka(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===ar.setAgentPreset?Pa(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===ar.approveSender?vg(t,["botId","requestId","confirm"])&&tI(t.botId)&&tI(t.requestId)&&t.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===ar.revokeSender?vg(t,["botId","senderKey","confirm"])&&tI(t.botId)&&tI(t.senderKey)&&t.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function _f(n){return{ok:!1,error:{code:"bad-request",message:n}}}function rE(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function ede(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function zl(n){if(Array.isArray(n))return n.map(zl);if(!CM(n))return n;let t={};for(let[o,i]of Object.entries(n))Xpe.has(o)||(t[o]=zl(i));return t}async function Ade(n){return Zpe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function EM(n,t){return!n||typeof n.verificationUrl!="string"?zl(n):zl({...n,qrCodeDataUrl:await t(n.verificationUrl)})}async function Pg(n,t){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await EM(o.provisioning,t)),zl(o)}function tde(n){for(let t of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[t]!="function")throw new TypeError(`A complete DingTalk controller is required (${t})`)}function lx(n,{encodeQr:t=Ade}={}){tde(n);let o=new Map,i=e=>{let a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>t(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return rE();if(!Ix.includes(e))return _f("Unknown DingTalk endpoint.");let r=$pe(e,a);if(r)return _f(r);try{let s;if(e===ar.status)s=await Pg(await n.status(),i);else if(e===ar.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),rE();s=await EM(g,i)}else if(e===ar.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return _f("The provisioning attempt no longer exists.");s=await EM(g,i)}else if(e===ar.cancelProvisioning){if(s=await n.cancelProvisioning(a.attemptId),!s)return _f("The provisioning attempt no longer exists.");s=zl(s)}else if(e===ar.bindCredentials)s=await Pg(await n.bindCredentials(a),i);else if(e===ar.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return rE();let c;if(a.sendTest===!0)if(!g?.bots?.some(d=>d?.botId===a.botId&&d?.connected===!0)||typeof n.sendConnectionTest!="function")c=rr(Ir("\u9489\u9489\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=rr()}catch(d){c=rr(d)}s=await Pg({...g,...c?{testMessage:c}:{}},i)}else if(e===ar.deleteBot)s=await Pg(await n.deleteBot(a.botId),i);else if(e===ar.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await Pg(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===ar.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await Pg(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else e===ar.approveSender?s=await Pg(await n.approveSender(a.botId,a.requestId),i):s=await Pg(await n.revokeSender(a.botId,a.senderKey),i);return A?.aborted?rE():{ok:!0,value:s}}catch(s){let g=va(s);return A?.aborted?rE():g?{ok:!1,error:g}:ede()}}}function Tf(n,t,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(cx,lx(t,o),{authority:yr(i)})}async function px(n,t={}){if(t?.controller)return Tf(n,t.controller,t.rpcOptions,t.rpcAuthority);let o=await hM(n,t,t.internals),i=Tf(n,o.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as rde}from"node:crypto";import{mkdir as ade,readFile as ide,rename as ode,unlink as nde,writeFile as sde}from"node:fs/promises";import{dirname as gde}from"node:path";var uM=Object.freeze({version:1,bots:Object.freeze([])});function Gs(n){return typeof n=="string"&&n.trim()?n.trim():null}function dx(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function aE(n,{botPrefix:t,tokenRefPrefix:o}){let i=Gs(n);if(!i)throw new TypeError("platformId is required");let e=rde("sha256").update(i).digest("hex").slice(0,24);return{botId:`${t}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function Nf(n,t){let o=Gs(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:t:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var Vl=class{#e;#A;#t;#r;#a;#i;#c;#s=uM;#I=Promise.resolve();constructor(t,{channel:o,botPrefix:i,tokenRefPrefix:e,normalizeBotExtension:a=()=>({})}){if(typeof a!="function")throw new TypeError("normalizeBotExtension must be a function");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=new RegExp(`^${dx(i)}_[a-f0-9]{24}$`),this.#c=new RegExp(`^${dx(e)}_[A-F0-9]{24}$`)}async load(){try{let t=this.#n(JSON.parse(await ide(this.#e,"utf8")));if(!t)throw new Error(`dsh-im ${this.#A} config contains invalid bot data`);this.#s=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#s=uM}return this}list(){return structuredClone(this.#s.bots)}get(t){let o=this.#s.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByPlatformId(t){let o=this.#s.bots.find(i=>i.platformId===t);return o?structuredClone(o):null}async save(t){let o=this.#o(t);if(!o)throw new Error(`Refusing to persist incomplete ${this.#A} bot data`);return this.#g(i=>{let e=i.find(r=>r.platformId===o.platformId&&r.botId!==o.botId),a=i.find(r=>r.tokenRef===o.tokenRef&&r.botId!==o.botId);if(e||a)throw new Error(`Duplicate ${this.#A} bot identity`);let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!this.#i.test(t))throw new TypeError(`Invalid ${this.#A} bot id`);return this.#g(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#I.then(async()=>{try{await nde(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#s=uM});this.#I=t.then(()=>{},()=>{}),await t}#o(t){if(!t||typeof t!="object")return null;let o=Gs(t.platformId),i=Gs(t.botId),e=Gs(t.tokenRef),a=Gs(t.name);if(!o||!i||!e||!a||!this.#i.test(i)||!this.#c.test(e))return null;let A=aE(o,{botPrefix:this.#t,tokenRefPrefix:this.#r});if(A.botId!==i||A.tokenRef!==e)return null;let r=this.#a(t);return!r||typeof r!="object"||Array.isArray(r)?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:a,username:Gs(t.username),createdAt:Gs(t.createdAt)??new Date().toISOString(),connectedAt:Gs(t.connectedAt),...r})}#n(t){if(!t||t.version!==1||!Array.isArray(t.bots))return null;let o=t.bots.map(A=>this.#o(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||a.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),a.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#g(t){let o,i=this.#I.then(async()=>{let e=[...this.#s.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#s=a});return this.#I=i.then(()=>{},()=>{}),await i,o}async#l(t){await ade(gde(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await sde(o,`${JSON.stringify(t,null,2)}
214
+ `,{encoding:"utf8",mode:384}),await Ope(o,this.#e),this.#n.clear()}async#f(){if(Object.keys(this.#t).length>0||Object.keys(this.#r).length>0){await this.#B();return}try{await Mpe(this.#e),this.#n.clear()}catch(t){if(t?.code!=="ENOENT")throw t;this.#n.clear()}}};function pM(n){if(!n)return null;let t=typeof n=="function"?n():n;return t&&typeof t.then=="function"?t.then(_n):_n(t)}function ox(){let n=new Error("Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002");return n.code="agent-preset-unavailable",n}function ql(n){if(n())return;let t=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw t.code="workspace-bot-not-found",t}function ax(n,t,o){let i=e=>{let a=n.decorateStatus(e);if(!o||!a||typeof a!="object")return a;let A=s=>s?{...a,agentPresetCatalog:s}:a,r=pM(o);return r&&typeof r.then=="function"?r.then(A):A(r)};return t&&typeof t.then=="function"?t.then(i):i(t)}function kpe(n){return Promise.resolve(n.status())}function Ma(n,{workspaces:t,method:o="remove",botIdFromRemoved:i=e=>e?.botId}){if(!n||!t||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(e,a){let A=Reflect.get(e,a,e);return a===o?async(...r)=>{let s=await A.apply(e,r),g=s?i(s,r):null;return g&&await t.retireAfterConfigCommit(g),s}:typeof A=="function"?A.bind(e):A}})}function _a(n,{botId:t,workspaces:o,state:i,agentPresetCatalog:e}={}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let a=o.incarnationFor(t),A=()=>o.has(t)&&o.incarnationFor(t)===a,r=async(I=e)=>{let d;try{d=await pM(I)??_n(null)}catch(B){throw ql(A),B}return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:d}},s=new Map,g=new Proxy(n,{get(I,d){if(d==="agentPresetSettings")return async(f={})=>{f?.signal?.throwIfAborted(),ql(A);let Q=await r();return f?.signal?.throwIfAborted(),Q};if(d==="updateAgentPreset")return async(f,Q={})=>{Q?.signal?.throwIfAborted(),ql(A);let y=f==="--default"?null:Kl(f),m=null;if(y&&({agentPresetCatalog:m}=await r(),Q?.signal?.throwIfAborted(),!m.items.some(_=>_.id===y)))throw ox();if(await o.setAgentPreset(t,y,{incarnation:a}),ql(A),m)return{agentPreset:o.agentPresetFor(t),agentPresetCatalog:m};try{return await r()}catch(_){if(_?.code==="workspace-bot-not-found")throw _;return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:_n(null)}}};if(d==="currentWorkspace")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}return o.workspaceFor(t)};if(d==="assertWorkspaceScope")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}};if((d==="listWorkspaces"||d==="listWorkspaceSessions"||d==="listModels")&&typeof I[d]=="function")return async(...f)=>{if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=await I[d](...f);if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}return Q};if(d==="switchWorkspace")return f=>{if(!A()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return Q.code="workspace-bot-not-found",Promise.reject(Q)}return o.setWorkspace(t,f,{clearSessions:()=>i.clearSessions(),incarnation:a})};if(d==="bindWorkspaceSession")return async(f,Q)=>{if(typeof f!="string"||!f||typeof Q!="string"||!Q)throw new TypeError("conversationKey and sessionId are required");if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(typeof I.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let y=o.generationFor(t),m=await I.adoptWorkspaceSession(Q);if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(y!==o.generationFor(t))throw eI("The bot workspace changed while the session was being adopted.");if(!m||typeof m!="object"||m.sessionId!==Q||typeof m.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let _=await o.bindWorkspaceSession(t,m.workspace,{conversationKey:f,sessionId:Q,clearSessions:()=>i.clearSessions(),setSession:(N,G)=>i.setSession(N,G),incarnation:a,expectedGeneration:y});if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(_.generation!==o.generationFor(t))throw eI("The bot workspace changed before the session binding completed.");return s.set(Q,_.generation),{...m,workspace:_.workspace,sessionId:_.sessionId}};if(d==="createSession")return async(f={})=>{if(await o.whenBotIdle(t),!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}let Q=o.generationFor(t),y=o.agentPresetFor(t),m=await I.createSession({...f,workspace:o.workspaceFor(t),...y==null?{}:{agentPreset:y}});return s.set(m,Q),m};if(d==="workspaceSession")return f=>{if(typeof f!="string"||!f)throw new TypeError("sessionId is required");let Q=s.get(f)??o.generationFor(t);s.delete(f);let y=()=>A()&&Q===o.generationFor(t),m=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);let J=await I[N](f,...G);if(!y())throw eI(`The bot workspace changed while this ${Y} was running.`);return J},_=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);return I[N](f,...G)};return Object.freeze({sessionId:f,async sessionExists(...N){if(!y())return!1;let G=await I.sessionExists(f,...N);return y()&&G},models(...N){return m("getSessionModels",N,"model listing")},selectModel(...N){return m("selectSessionModel",N,"model selection")},isRunning(...N){return m("isSessionRunning",N,"run-state check")},hasActiveTurn(...N){return m("hasActiveTurn",N,"turn ownership check")},stopActiveTurn(...N){return _("stopActiveTurn",N,"turn stop")},steerActiveTurn(...N){return _("steerActiveTurn",N,"turn steering")},ask(...N){if(!y())throw eI("The bot workspace changed before this prompt started.");return I.ask(f,...N)}})};if(d==="sessionExists")return(f,...Q)=>{if(!A())return!1;let y=s.get(f);return y!==void 0&&y!==o.generationFor(t)?(s.delete(f),!1):I.sessionExists(f,...Q)};if(d==="ask")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this prompt started.");throw m.code=oi,m}return I.ask(f,...Q)};if(d==="executeCommand"&&typeof I.executeCommand=="function")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this command started.");throw m.code=oi,m}return I.executeCommand(f,...Q)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}}),c=new Proxy(i,{get(I,d){if(d===Ob)return I;if(d==="sessionFor")return(f,...Q)=>{if(!A())return null;let y=I.sessionFor(f,...Q);return y&&!s.has(y)&&s.set(y,o.generationFor(t)),y};if(d==="setSession")return(f,Q,...y)=>{let m=s.get(Q);return!A()||m!==void 0&&m!==o.generationFor(t)?(s.delete(Q),!1):I.setSession(f,Q,...y)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}});return Object.freeze({harness:g,state:c})}function Ta(n,{workspaces:t,stateFor:o,agentPresetCatalog:i}={}){if(!n||!t||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let e=new Map,a=(c,I)=>{let B=(e.get(c)??Promise.resolve()).catch(()=>{}).then(I);return e.set(c,B),B.finally(()=>{e.get(c)===B&&e.delete(c)})},A=c=>ax(t,c,i),r=(c,I)=>{let d=t.incarnationFor(c);return a(c,async()=>{if(!(await n.status())?.bots?.some(Q=>Q?.botId===c)){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}let f=await o(c);return await t.setWorkspace(c,I,{clearSessions:()=>f.clearSessions(),incarnation:d}),A(await n.status())})},s=(c,I)=>{let d=t.incarnationFor(c),B=Kl(I);return a(c,async()=>{if(!(await n.status())?.bots?.some(y=>y?.botId===c)){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=B&&i?await pM(i):null;if(B&&i&&!Q?.items.some(y=>y.id===B))throw ox();return await t.setAgentPreset(c,B,{incarnation:d}),ax(t,await n.status(),Q??i)})},g=(c,I)=>a(c,async()=>{let d=await t.beginRemoval(c,{clearSessions:async()=>{try{let B=await o(c);if(!B||typeof B.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await B.clearSessions()}catch(B){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${c}:`,B?.message??B)}}});try{let B=await I();return await t.finishRemoval(d),A(B)}catch(B){let f=await kpe(n).catch(()=>null);throw Array.isArray(f?.bots)&&!f.bots.some(y=>y?.botId===c)?await t.finishRemoval(d):await t.abortRemoval(d),B}});return new Proxy(n,{get(c,I){if(I==="updateWorkspace")return r;if(I==="updateAgentPreset")return s;let d=Reflect.get(c,I,c);return typeof d!="function"?d:I==="deleteBot"?(B,...f)=>g(B,()=>d.call(c,B,...f)):I==="disconnect"?async(...B)=>{let Q=(await c.status())?.bots?.[0]?.botId;return Q?g(Q,()=>d.apply(c,B)):A(d.apply(c,B))}:(...B)=>A(d.apply(c,B))}})}var nx=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function vpe(n){if(!Array.isArray(n)||n.length===0)return[...nx];let t=n.filter(o=>Number.isFinite(o)&&o>=0);return t.length>0?t:[...nx]}var Mf=class{#e;#A;#t;#r;#a;#i;#c;#s=null;#I=null;#o=0;#n=!1;#g=!1;#l;#p;constructor({controller:t,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:r=clearTimeout}){if(!t||typeof t.initialize!="function"||typeof t.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=t,this.#A=o,this.#t=i,this.#r=vpe(e),this.#a=Number.isFinite(a)&&a>=0?a:15e3,this.#i=A,this.#c=r,this.#l=new Promise(s=>{this.#p=s})}get ready(){return this.#l}start(){return this.#g||this.#n?this:(this.#g=!0,this.#d(0),this)}async close(){this.#n||(this.#n=!0,this.#s!==null&&this.#c(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#d(t){this.#n||(this.#s=this.#i(()=>{this.#s=null,this.#h()},t),this.#s?.unref?.())}async#h(){if(this.#n||this.#I)return;let t=this.#E();this.#I=t;try{await t}finally{this.#I===t&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#n)return;let t=await this.#e.initialize();if(this.#n)return;this.#p?.(t),this.#p=null;let{configured:o,connected:i}=t.totals;if(i<o){let e=this.#r[Math.min(this.#o,this.#r.length-1)];this.#o+=1,this.#t.warn?.(`[dsh-dingtalk] ${i}/${o} bots connected; retrying in ${e}ms`),this.#d(e);return}this.#o=0,this.#d(this.#a)}catch(t){if(this.#n)return;let o=this.#r[Math.min(this.#o,this.#r.length-1)];this.#o+=1,this.#t.warn?.(`[dsh-dingtalk] connection reconciliation failed; retrying in ${o}ms`,t),this.#d(o)}}};function dM(n){return new Mf(n)}function Na(n,t){if(t!==void 0){if(typeof t!="function")throw new TypeError("commandExecutor must be a function");return t}let o=n?.typertGateway;if(o){if(typeof o.invoke!="function")throw new TypeError("dsh-im requires a callable ctx.typertGateway");return async(i,e,a={})=>{let A={namespace:"commands",method:"execute",args:{agentId:i,line:e,images:[]},signal:a.signal};try{return await o.invoke(A)}catch(r){if(r?.name!=="TypertGatewayError"||r.code!=="arguments-invalid"||r.endpoint!=="commands/execute"||r.message!=='typert gateway: commands/execute: args fields do not match the descriptor: unexpected "images"')throw r;return a.signal?.throwIfAborted(),o.invoke({...A,args:{agentId:i,line:e}})}}}}import{randomUUID as Ppe}from"node:crypto";function Gpe(n){if(typeof n?.get!="function")return;let t;try{t=n.get("agents")}catch{return}if(t!=null){if(typeof t.get!="function")throw new TypeError('dsh-im requires a callable AgentRegistry when ctx.get("agents") is present');return t}}function Fpe(n,t,o){if(n?.status!=="running")return!1;let i=n?.session?.events;if(!Array.isArray(i))return!1;let e=null,a=!1;for(let A of i){if(A?.type==="turn/start"){e=A.data?.turn??null,a=!1;continue}if(A?.type==="turn/end"&&A.data?.turn===e){e=null,a=!1;continue}e===t&&A?.type==="user/message"&&A.data?.source?.rpcId===o&&(a=!0)}return e===t&&a}function sx(n){if(!n||typeof n!="object"||Object.isFrozen(n))return n;for(let t of Object.values(n))sx(t);return Object.freeze(n)}function Lpe(n){return sx({id:Ppe(),role:"user",content:[{type:"text",text:n}],source:{kind:"user"}})}function Upe(n){let t=new Error("Session is busy with an active turn or maintenance task",{cause:n});return t.code="agent-busy",t}function Hpe(n){return({sessionId:t,expectedTurn:o,promptRpcId:i,action:e,text:a})=>{let A=n.get(t);if(A){if(!Fpe(A,o,i))return!1;if(e==="stop")return A.cancel({kind:"user"},{keepInbox:!0}),!0;if(e==="steer")return typeof a!="string"||!a.trim()?!1:(A.inject(Lpe(a)),!0);throw new TypeError(`Unsupported Harness control action: ${String(e)}`)}}}function Kpe(n){return({sessionId:t,operation:o})=>{if(typeof o!="function")throw new TypeError("maintenance operation is required");let i=n.get(t);if(!i)return o();try{return i.runMaintenance(e=>{if(n.get(t)!==i){let a=new Error("Session agent changed before maintenance started");throw a.code="agent-unavailable",a}return o(e)})}catch(e){throw Upe(e)}}}function xpe(n){return({sessionId:t,workspace:o,files:i,signal:e})=>{let A=n.get(t)?.session?.header?.cwd,r=typeof A=="string"&&A?A:o;if(typeof r!="string"||!r)throw new ho("inbound-file-workspace-unavailable","The Harness Session workspace is unavailable for inbound files.");return MK({files:i},{workspace:r,signal:e})}}function Ra(n,t={}){let{controlExecutor:o,sessionMaintenanceExecutor:i,fileIngressExecutor:e}=t;if(o!==void 0&&typeof o!="function")throw new TypeError("controlExecutor must be a function");if(i!==void 0&&typeof i!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("fileIngressExecutor must be a function");let a=o&&i&&e?void 0:Gpe(n);return{controlExecutor:o??(a?Hpe(a):void 0),sessionMaintenanceExecutor:i??(a?Kpe(a):void 0),fileIngressExecutor:e??xpe(a??{get:()=>{}})}}function Jpe(n,t){if(t!==void 0)return new URL(t);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 qpe(n){let t=AI(n.dshHome??process.env.DSH_HOME??tE(jpe(),".dsh")),o=AI(n.dataDir??tE(t,"integrations","dsh-dingtalk"));return{root:o,config:AI(n.configPath??tE(o,"config.json")),bots:AI(n.botsDir??tE(o,"bots")),workspaces:AI(n.workspacesPath??tE(o,"workspaces.json"))}}async function hM(n,t={},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??cf,e=o.DeviceAuth??lf,a=o.StateStore??bf,A=o.HarnessClient??wf,r=o.Controller??xh,s=o.Runtime??Xh,g=o.createConnectionSupervisor??dM,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,I=()=>Oa(n),d=qpe(t),B=await new i(d.config).load(),f=AI(t.workspace??process.cwd()),Q=o.WorkspaceStore??Zr,y=o.workspaces??await new Q(d.workspaces,{defaultWorkspace:f}).load(),m=typeof B.list=="function",_=m?B.list():[];m&&await y.reconcile(_.map(W=>W.botId)),await Promise.all(_.map(W=>y.ensure(W.botId,{defaultAgentPreset:t.agentPreset})));let N=typeof B.remove=="function"?Ma(B,{workspaces:y}):B,G=o.deviceAuth??new e({baseUrl:t.registrationBaseUrl}),Y=new Map,J=W=>AI(d.bots,W,"state.json"),H=async W=>{let ae=Y.get(W);return ae||(ae=await new a(J(W)).load(),Y.set(W,ae)),ae},j=Na(n,o.commandExecutor),{controlExecutor:q,sessionMaintenanceExecutor:U,fileIngressExecutor:R}=Ra(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),V=new A({baseUrl:Jpe(n.webServer,t.harnessBaseUrl),workspace:f,autostart:!1,dshBin:t.dshBin??"dsh",...j?{commandExecutor:j}:{},...q?{controlExecutor:q}:{},...U?{sessionMaintenanceExecutor:U}:{},...R?{fileIngressExecutor:R}:{}}),L=new r({deviceAuth:G,credentials:n.credentials,configStore:N,logger:c,createRuntime:async({botId:W,config:ae,clientSecret:ge})=>{let Se=await H(W);await y.ensure(W,{defaultAgentPreset:t.agentPreset});let de=_a(V,{botId:W,workspaces:y,state:Se,agentPresetCatalog:I});return new s({config:ae,clientSecret:ge,harness:de.harness,state:de.state,replyTimeoutMs:t.replyTimeoutMs??6e5,maxMessageChars:t.maxMessageChars??4e3,connectTimeoutMs:t.connectTimeoutMs??15e3,logger:{error:(...De)=>c.error?.(`[${W}]`,...De),warn:(...De)=>c.warn?.(`[${W}]`,...De),info:(...De)=>c.info?.(`[${W}]`,...De),debug:(...De)=>c.debug?.(`[${W}]`,...De)}})},deleteState:async({botId:W})=>{let ae=Y.get(W);if(Y.delete(W),ae&&typeof ae.remove=="function")await ae.remove();else try{await Ype(J(W))}catch(ge){if(ge?.code!=="ENOENT")throw ge}}}),T=Ta(L,{workspaces:y,stateFor:H,agentPresetCatalog:I}),P=g({controller:T,harness:V,logger:c,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:T,ready:P.ready,async close(){await P.close(),await T.close(),V.stopManagedProcess()}}}import Zpe from"qrcode";var zpe=new Set(["loopback","trusted-host"]);function yr(n){if(n===void 0)return"loopback";if(zpe.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as Vpe}from"node:path";var hi="bot.workspace.set";function ka(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(t=>["botId","workspace"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&Vpe(n.workspace.trim())}function va(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found","agent-preset-invalid","agent-preset-unavailable"].includes(n?.code)?{code:n.code,message:n.message}:null}var Ei="bot.preset.set";function Wpe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Pa(n){return Wpe(n)&&Object.keys(n).every(t=>["botId","agentPreset"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&(n.agentPreset===null||typeof n.agentPreset=="string"&&zb.test(n.agentPreset))}var cx="/dingtalk",ar=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:hi,setAgentPreset:Ei,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),Ix=Object.freeze(Object.values(ar)),Xpe=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function CM(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function vg(n,t){return CM(n)&&Object.keys(n).every(o=>t.includes(o))}function tI(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function gx(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function $pe(n,t){return CM(t)?n===ar.status?vg(t,[])?null:"connection.status does not accept fields.":n===ar.beginProvisioning?vg(t,["locale"])&&(t.locale===void 0||t.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[ar.pollProvisioning,ar.cancelProvisioning].includes(n)?vg(t,["attemptId"])&&tI(t.attemptId)?null:`${n} requires an attemptId.`:n===ar.bindCredentials?vg(t,["clientId","clientSecret"])&&gx(t.clientId,256)&&gx(t.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===ar.reconnectBot?vg(t,["botId","sendTest"])&&tI(t.botId)&&(t.sendTest===void 0||t.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===ar.deleteBot?vg(t,["botId","confirm"])&&tI(t.botId)&&t.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===ar.setWorkspace?ka(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===ar.setAgentPreset?Pa(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===ar.approveSender?vg(t,["botId","requestId","confirm"])&&tI(t.botId)&&tI(t.requestId)&&t.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===ar.revokeSender?vg(t,["botId","senderKey","confirm"])&&tI(t.botId)&&tI(t.senderKey)&&t.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function _f(n){return{ok:!1,error:{code:"bad-request",message:n}}}function rE(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function ede(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function zl(n){if(Array.isArray(n))return n.map(zl);if(!CM(n))return n;let t={};for(let[o,i]of Object.entries(n))Xpe.has(o)||(t[o]=zl(i));return t}async function Ade(n){return Zpe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function EM(n,t){return!n||typeof n.verificationUrl!="string"?zl(n):zl({...n,qrCodeDataUrl:await t(n.verificationUrl)})}async function Pg(n,t){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await EM(o.provisioning,t)),zl(o)}function tde(n){for(let t of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[t]!="function")throw new TypeError(`A complete DingTalk controller is required (${t})`)}function lx(n,{encodeQr:t=Ade}={}){tde(n);let o=new Map,i=e=>{let a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>t(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return rE();if(!Ix.includes(e))return _f("Unknown DingTalk endpoint.");let r=$pe(e,a);if(r)return _f(r);try{let s;if(e===ar.status)s=await Pg(await n.status(),i);else if(e===ar.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),rE();s=await EM(g,i)}else if(e===ar.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return _f("The provisioning attempt no longer exists.");s=await EM(g,i)}else if(e===ar.cancelProvisioning){if(s=await n.cancelProvisioning(a.attemptId),!s)return _f("The provisioning attempt no longer exists.");s=zl(s)}else if(e===ar.bindCredentials)s=await Pg(await n.bindCredentials(a),i);else if(e===ar.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return rE();let c;if(a.sendTest===!0)if(!g?.bots?.some(d=>d?.botId===a.botId&&d?.connected===!0)||typeof n.sendConnectionTest!="function")c=rr(Ir("\u9489\u9489\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=rr()}catch(d){c=rr(d)}s=await Pg({...g,...c?{testMessage:c}:{}},i)}else if(e===ar.deleteBot)s=await Pg(await n.deleteBot(a.botId),i);else if(e===ar.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await Pg(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===ar.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await Pg(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else e===ar.approveSender?s=await Pg(await n.approveSender(a.botId,a.requestId),i):s=await Pg(await n.revokeSender(a.botId,a.senderKey),i);return A?.aborted?rE():{ok:!0,value:s}}catch(s){let g=va(s);return A?.aborted?rE():g?{ok:!1,error:g}:ede()}}}function Tf(n,t,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(cx,lx(t,o),{authority:yr(i)})}async function px(n,t={}){if(t?.controller)return Tf(n,t.controller,t.rpcOptions,t.rpcAuthority);let o=await hM(n,t,t.internals),i=Tf(n,o.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as rde}from"node:crypto";import{mkdir as ade,readFile as ide,rename as ode,unlink as nde,writeFile as sde}from"node:fs/promises";import{dirname as gde}from"node:path";var uM=Object.freeze({version:1,bots:Object.freeze([])});function Gs(n){return typeof n=="string"&&n.trim()?n.trim():null}function dx(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function aE(n,{botPrefix:t,tokenRefPrefix:o}){let i=Gs(n);if(!i)throw new TypeError("platformId is required");let e=rde("sha256").update(i).digest("hex").slice(0,24);return{botId:`${t}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function Nf(n,t){let o=Gs(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:t:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var Vl=class{#e;#A;#t;#r;#a;#i;#c;#s=uM;#I=Promise.resolve();constructor(t,{channel:o,botPrefix:i,tokenRefPrefix:e,normalizeBotExtension:a=()=>({})}){if(typeof a!="function")throw new TypeError("normalizeBotExtension must be a function");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=new RegExp(`^${dx(i)}_[a-f0-9]{24}$`),this.#c=new RegExp(`^${dx(e)}_[A-F0-9]{24}$`)}async load(){try{let t=this.#n(JSON.parse(await ide(this.#e,"utf8")));if(!t)throw new Error(`dsh-im ${this.#A} config contains invalid bot data`);this.#s=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#s=uM}return this}list(){return structuredClone(this.#s.bots)}get(t){let o=this.#s.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByPlatformId(t){let o=this.#s.bots.find(i=>i.platformId===t);return o?structuredClone(o):null}async save(t){let o=this.#o(t);if(!o)throw new Error(`Refusing to persist incomplete ${this.#A} bot data`);return this.#g(i=>{let e=i.find(r=>r.platformId===o.platformId&&r.botId!==o.botId),a=i.find(r=>r.tokenRef===o.tokenRef&&r.botId!==o.botId);if(e||a)throw new Error(`Duplicate ${this.#A} bot identity`);let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!this.#i.test(t))throw new TypeError(`Invalid ${this.#A} bot id`);return this.#g(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#I.then(async()=>{try{await nde(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#s=uM});this.#I=t.then(()=>{},()=>{}),await t}#o(t){if(!t||typeof t!="object")return null;let o=Gs(t.platformId),i=Gs(t.botId),e=Gs(t.tokenRef),a=Gs(t.name);if(!o||!i||!e||!a||!this.#i.test(i)||!this.#c.test(e))return null;let A=aE(o,{botPrefix:this.#t,tokenRefPrefix:this.#r});if(A.botId!==i||A.tokenRef!==e)return null;let r=this.#a(t);return!r||typeof r!="object"||Array.isArray(r)?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:a,username:Gs(t.username),createdAt:Gs(t.createdAt)??new Date().toISOString(),connectedAt:Gs(t.connectedAt),...r})}#n(t){if(!t||t.version!==1||!Array.isArray(t.bots))return null;let o=t.bots.map(A=>this.#o(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||a.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),a.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#g(t){let o,i=this.#I.then(async()=>{let e=[...this.#s.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#s=a});return this.#I=i.then(()=>{},()=>{}),await i,o}async#l(t){await ade(gde(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await sde(o,`${JSON.stringify(t,null,2)}
215
215
  `,{encoding:"utf8",mode:384}),await ode(o,this.#e)}};var hx=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function Ex(n){return aE(n,hx)}function Cx(n){return Nf(n,D("Discord\u673A\u5668\u4EBA"))}var Rf=class extends Vl{constructor(t){super(t,{channel:"Discord",...hx})}};function iE(n){return typeof n=="string"&&n.trim()?n.trim():null}function oE(n,t){return Object.freeze({code:n,message:t})}var Wl=class{#e;#A;#t;#r;#a;#i;#c;#s;#I;#o=new Map;#n=new Map;#g=new Map;#l=0;#p=!1;constructor({descriptor:t,credentials:o,configStore:i,inspectToken:e,deriveIdentity:a,maskPlatformId:A,createRuntime:r,deleteState:s=async()=>{},logger:g=console}){if(!t?.key||!t?.label||!t?.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(`${t.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${t.label} requires a config store`);if(typeof e!="function"||typeof a!="function"||typeof A!="function"||typeof r!="function")throw new TypeError(`${t.label} controller dependencies are incomplete`);this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=A,this.#c=r,this.#s=s,this.#I=g}async initialize(){if(this.#p)return this.status();for(let t of this.#t.list())await this.#B(t.botId,async()=>{if(this.#p||this.#o.get(t.botId)?.status?.ready)return;let o=await this.#E(t.tokenRef);if(!o){this.#n.set(t.botId,oE("missing-token",D("{label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002",{label:this.#e.label})));return}try{await this.#d(t,o),this.#n.delete(t.botId)}catch(i){this.#n.set(t.botId,oE("connection-failed",D("{label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002",{label:this.#e.label}))),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${t.botId} failed to initialize:`,i)}finally{this.#f()}});return this.status()}async bindCredentials({token:t}={}){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let o=iE(t);if(!o)throw new TypeError(`${this.#e.label} Bot Token is required`);let i=await this.#r(o),e=iE(i?.platformId),a=iE(i?.name);if(!e||!a)throw new Error(`${this.#e.label} returned an invalid bot identity`);let A=this.#a(e);return await this.#B(A.botId,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let r=this.#t.getByPlatformId(e),s=await this.#A.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:a,username:iE(i.username),createdAt:r?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#u(A.tokenRef,s),c}try{await this.#d(g,o),this.#n.delete(A.botId)}catch(c){this.#n.set(A.botId,oE("connection-failed",D("{label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002",{label:this.#e.label}))),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${A.botId} credential connection failed:`,c)}this.#f()}),this.status()}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(t,async()=>{let i=await this.#E(o.tokenRef);if(!i)throw new Error(`${this.#e.label} bot token is missing`);try{await this.#d(o,i),this.#n.delete(t)}catch(e){throw this.#n.set(t,oE("connection-failed",D("{label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{label:this.#e.label}))),e}finally{this.#f()}}),this.status()}async updateBotConfig(t,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(typeof o!="function")throw new TypeError("Bot config update must be a function");return await this.#B(t,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=this.#t.get(t);if(!i)throw new Error(`Unknown ${this.#e.label} bot`);let e=await this.#E(i.tokenRef);if(!e)throw new Error(`${this.#e.label} bot token is missing`);if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let a=o(i),A=await this.#t.save(a);try{await this.#d(A,e),this.#n.delete(t)}catch(r){throw this.#n.set(t,oE("connection-failed",D("{label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{label:this.#e.label}))),r}finally{this.#f()}}),this.status()}async sendConnectionTest(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return this.#B(t,async()=>{let i=this.#o.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let a=new Error(D("{label}\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5",{label:this.#e.label}));throw a.code="test-target-unavailable",a}let e=D("{name}\uFF08{id}\uFF09",{name:o.name,id:this.#i(o.platformId)});return await i.sendConnectionTest(ma(e,D("{label}\u673A\u5668\u4EBA",{label:this.#e.label}))),{sent:!0}})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(t,async()=>{let i=await this.#A.resolve(o.tokenRef).catch(()=>{});await this.#h(t);try{await this.#A.unset(o.tokenRef),await this.#t.remove(t)}catch(e){throw i?.value&&(await this.#A.set(o.tokenRef,i.value).catch(()=>{}),await this.#d(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#e.label} bot safely.`,{cause:e})}await this.#s({botId:t,config:o}).catch(e=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${t} state cleanup failed:`,e)}),this.#n.delete(t),this.#f()}),this.status()}status(){let t=this.#t.list().map(i=>{let e=this.#o.get(i.botId)?.status??null,a=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=a?"connected":e?.connectionState==="connecting"?"connecting":this.#n.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:a,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#i(i.platformId)},health:{status:a?"healthy":A==="error"?"error":"offline",summary:a?D("{label}{connectionLabel}\u8FD0\u884C\u6B63\u5E38",{label:this.#e.label,connectionLabel:D(this.#e.connectionLabel)}):A==="error"?D("{label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5",{label:this.#e.label}):D("{label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",{label:this.#e.label}),lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},lastMessageError:qr(e?.lastMessageError),error:structuredClone(this.#n.get(i.botId)??null)}}),o=t.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#l,state:t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o}}}async close(){this.#p||(this.#p=!0,await Promise.allSettled([...this.#g.values()]),await Promise.allSettled([...this.#o.keys()].map(t=>this.#h(t))))}async#d(t,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(await this.#h(t.botId),this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=await this.#c({botId:t.botId,config:t,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#e.label} runtime`);this.#o.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#o.delete(t.botId),e}}async#h(t){let o=this.#o.get(t);this.#o.delete(t),await o?.stop().catch(i=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${t} failed to stop cleanly:`,i)})}async#E(t){let o=await this.#A.resolve(t).catch(()=>{});return iE(o?.value)}async#u(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#B(t,o){let a=(this.#g.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#g.get(t)===a&&this.#g.delete(t)});return this.#g.set(t,a),a}#f(){this.#l+=1}};import{createHash as cde}from"node:crypto";var Ide="https://discord.com/api/v10/",lde=12e4,pde=new Set([50001,50013]),dde=new Set([40005]);function vn(n){return typeof n=="string"&&n.trim()?n.trim():null}function ux(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}function BM(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}function hde(n,t){if(!Number.isInteger(n)||n<1)throw new TypeError(`${t} must be a positive integer`);return n}function fx(n,t){return t?.providerCode!==void 0&&(n.providerCode=t.providerCode),t?.retry_after!==void 0&&(n.retry_after=t.retry_after,n.retryAfter=t.retry_after),Number.isInteger(t?.status)&&(n.status=t.status),n}function Ede(n){let t=Number(n?.providerCode),o=Number(n?.status),i=vn(n?.message)??"",e="artifact-provider-rejected",a="Discord rejected the attachment.";o===401||o===403||pde.has(t)?(e="artifact-permission-required",a="Discord denied permission to send the attachment."):o===413||dde.has(t)||/(?:request|attachment|file).{0,24}too large/i.test(i)?(e="artifact-too-large",a="The attachment exceeds Discord's size limit."):o===429?(e="artifact-rate-limited",a="Discord rate-limited attachment delivery."):o>=500&&(e="artifact-delivery-uncertain",a="Discord attachment delivery result is uncertain.");let A=new Error(a,{cause:n});return A.code=e,fx(A,n)}function Cde(n){let t=new Error("Discord attachment delivery result is uncertain",{cause:n});return t.code="artifact-delivery-uncertain",fx(t,n)}function ude(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),t?.addEventListener("abort",()=>{clearTimeout(e),i(t.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function Ga(n,t){let o=vn(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${t}`);return o}function Bx(n){let t=vn(n);if(!t)throw new TypeError("A Discord reaction emoji is required");return t}function Bde(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var nE=class{#e;#A;#t;#r;constructor({token:t,fetchImpl:o=fetch,baseUrl:i=Ide,fileUploadTimeoutMs:e=lde}){if(!Bde(t))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#e=t.trim(),this.#A=o,this.#t=new URL(i),this.#r=hde(e,"fileUploadTimeoutMs")}getCurrentUser(t={}){return this.#a("users/@me",{...t,method:"GET"})}getGatewayBot(t={}){return this.#a("gateway/bot",{...t,method:"GET"})}getChannel({channelId:t,signal:o}={}){return this.#a(`channels/${Ga(t,"channel id")}`,{method:"GET",signal:o})}startThreadFromMessage({channelId:t,messageId:o,name:i,signal:e}={}){let a=vn(i);if(!a||[...a].length>100)throw new TypeError("Discord thread name must contain 1-100 characters");if(e?.aborted)throw BM(e);return this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}/threads`,{method:"POST",signal:e,body:{name:a}})}createMessage({channelId:t,content:o,replyToMessageId:i,signal:e}){return this.#a(`channels/${Ga(t,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:Ga(i,"message id"),channel_id:Ga(t,"channel id"),fail_if_not_exists:!1}}:{}}})}async createFileMessage({channelId:t,file:o,replyToMessageId:i,signal:e}){if(!o||typeof o!="object"||typeof o.fileName!="string"||!o.fileName||!Buffer.isBuffer(o.bytes))throw new TypeError("A Discord attachment is required");let a=vn(o.deliveryKey)??vn(o.artifactId),A=a?cde("sha256").update(a).digest("hex").slice(0,25):void 0,r=new FormData;r.append("payload_json",JSON.stringify({allowed_mentions:{parse:[],replied_user:!1},attachments:[{id:0,filename:o.fileName}],...A?{nonce:A,enforce_nonce:!0}:{},...i?{message_reference:{message_id:Ga(i,"message id"),channel_id:Ga(t,"channel id"),fail_if_not_exists:!1}}:{}})),r.append("files[0]",new Blob([o.bytes],{type:o.mediaType??"application/octet-stream"}),o.fileName);let s=Ga(t,"channel id");if(e?.aborted)throw BM(e);let g=ux(e,this.#r);try{return await this.#a(`channels/${s}/messages`,{method:"POST",signal:g,timeoutMs:this.#r,body:r,multipart:!0})}catch(c){throw e?.aborted?BM(e):c?.code?.startsWith?.("discord-")?Ede(c):Cde(c)}}editMessage({channelId:t,messageId:o,content:i,signal:e}){return this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:t,signal:o}){return this.#a(`channels/${Ga(t,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async addOwnReaction({channelId:t,messageId:o,emoji:i,signal:e}={}){let a=Bx(i);return await this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}/reactions/${encodeURIComponent(a)}/@me`,{method:"PUT",signal:e,expectBody:!1,retry:!1}),a}removeOwnReaction({channelId:t,messageId:o,emoji:i,signal:e}={}){let a=Bx(i);return this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}/reactions/${encodeURIComponent(a)}/@me`,{method:"DELETE",signal:e,expectBody:!1,retry:!1})}async#a(t,{method:o,body:i,signal:e,timeoutMs:a=15e3,expectBody:A=!0,retry:r=!0,multipart:s=!1}){let g;try{g=await this.#A(new URL(t,this.#t),{method:o,headers:{authorization:`Bot ${this.#e}`,...s?{}:{"content-type":"application/json"},"user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.1.0)"},...i===void 0?{}:{body:s?i:JSON.stringify(i)},signal:ux(e,a),redirect:"error"})}catch(I){throw I?.name==="AbortError"||I?.name==="TimeoutError"?I:new Error(`Discord ${o} transport failed`)}let c=null;if(A||g.status===429||!g.ok)try{c=await g.json()}catch{if(A){let I=new Error(`Discord ${o} returned invalid JSON`);throw I.status=g?.status,I}}if(g.status===429&&r){let I=Math.min(1e4,Math.max(50,Number(c?.retry_after)*1e3||1e3));return await ude(I,e),this.#a(t,{method:o,body:i,signal:e,timeoutMs:a,expectBody:A,retry:!1,multipart:s})}if(!g.ok){let I=new Error(vn(c?.message)??`Discord API failed with HTTP ${g.status}`);I.code=`discord-${g.status}`,I.status=g.status,(Number.isInteger(c?.code)||typeof c?.code=="string")&&(I.providerCode=c.code);let d=Number(c?.retry_after);throw Number.isFinite(d)&&d>=0&&(I.retry_after=d,I.retryAfter=d),I}return A?c:null}};async function Qx(n,t={}){let i=await new nE({token:n,...t}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:vn(i.global_name)??vn(i.username)??D("Discord\u673A\u5668\u4EBA"),username:vn(i.username)}}var fde=Object.freeze({success(){},error(){},clear(){},settled:()=>Promise.resolve()});function yx(n,t){!n||typeof n!="object"||(n[t]=(n[t]??0)+1)}async function Qde(n,t){let o=AbortSignal.timeout(t),i,e=new Promise((a,A)=>{i=()=>A(o.reason??new DOMException("Timed out","TimeoutError")),o.addEventListener("abort",i,{once:!0})});try{return await Promise.race([n(o),e])}finally{o.removeEventListener("abort",i)}}function kf({adapter:n,target:t,reactions:o,status:i,logger:e=console,label:a="channel",timeoutMs:A=2e3}={}){if(!t||typeof n?.addReaction!="function"||typeof n?.removeReaction!="function"||typeof o?.processing!="string"||!o.processing||!Number.isSafeInteger(A)||A<=0)return fde;let r=null,s=!1,g=async(B,f)=>{try{let Q=await Qde(f,A);return yx(i,B==="add"?"reactionsAdded":"reactionsRemoved"),{ok:!0,value:Q}}catch(Q){return yx(i,"reactionErrors"),e.warn?.(`[dsh-im:${a}] status reaction ${B} failed:`,Q?.message??Q?.name??String(Q)),{ok:!1,value:null}}},c=async B=>{if(r!==null){let Q=r;r=null,await g("remove",y=>n.removeReaction(t,Q,{signal:y}))}if(typeof B!="string"||!B)return;let f=await g("add",Q=>n.addReaction(t,B,{signal:Q}));f.ok&&f.value!==void 0&&f.value!==null&&(r=f.value)},I=c(o.processing),d=B=>{s||(s=!0,I=I.then(()=>c(B),()=>c(B)),I.catch(()=>{}))};return Object.freeze({success:()=>d(o.success),error:()=>d(o.error),clear:()=>d(null),settled:()=>I})}var mx="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002",yde="\u4EFB\u52A1\u5DF2\u5B8C\u6210\u3002";function Ci(n){return typeof n=="string"?n.trim():""}function mde(n,t,o){return t.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!qt(n)&&!Gt(n)&&!!Ci(n.content)}function Sde(n,t,o){let i=String(n??D("\u7ED3\u679C\u6587\u4EF6")).replace(/[\r\n]+/g," ").trim().slice(0,255)||D("\u7ED3\u679C\u6587\u4EF6");switch(t?.code){case"artifact-delivery-uncertain":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u7684\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u804A\u5929\u5185\u662F\u5426\u5DF2\u6536\u5230\uFF0C\u4E0D\u8981\u7ACB\u5373\u91CD\u8BD5\u3002",{name:i});case"artifact-permission-required":return o?.key==="slack"?D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46 Slack \u5E94\u7528\u7F3A\u5C11 files:write \u6743\u9650\u3002\u8BF7\u66F4\u65B0 Manifest\u3001\u91CD\u65B0\u5B89\u88C5\u5E94\u7528\u5E76\u91CD\u65B0\u8FDE\u63A5\u673A\u5668\u4EBA\u540E\u91CD\u8BD5\u3002",{name:i}):o?.key==="discord"?D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u673A\u5668\u4EBA\u7F3A\u5C11 Discord \u7684 Send Messages\u3001Attach Files \u6216 Read Message History \u6743\u9650\u3002",{name:i}):o?.key==="telegram"?D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46 Telegram \u4E0D\u5141\u8BB8\u673A\u5668\u4EBA\u5728\u5F53\u524D\u804A\u5929\u53D1\u9001\u6587\u6863\uFF0C\u8BF7\u68C0\u67E5\u804A\u5929\u6743\u9650\u3002",{name:i}):D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u673A\u5668\u4EBA\u6CA1\u6709\u6587\u4EF6\u53D1\u9001\u6743\u9650\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u6743\u9650\u3002",{name:i});case"artifact-too-large":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u8D85\u8FC7\u5F53\u524D\u6E20\u9053\u5927\u5C0F\u4E0A\u9650\uFF0C\u672A\u53D1\u9001\u3002",{name:i});case"artifact-empty":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001\u3002",{name:i});case"artifact-invalid":case"artifact-changed":case"artifact-unavailable":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u6216\u51C6\u5907\u53D1\u9001\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u4ECD\u53EF\u8BBF\u95EE\u540E\u91CD\u8BD5\u3002",{name:i});case"artifact-rate-limited":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u88AB\u5F53\u524D\u6E20\u9053\u9650\u6D41\uFF0C\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:i});case"artifact-provider-rejected":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6E20\u9053\u62D2\u7EDD\u4E86\u8BE5\u6587\u4EF6\u6216\u6587\u4EF6\u6D88\u606F\u3002",{name:i});default:return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6E20\u9053\u6682\u65F6\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:i})}}function Ui(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null,lastMessageError:null,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0}}var Pn=class{#e;#A;#t;#r;#a;#i;#c;#s;#I=new Map;#o=new Map;#n=new Map;#g=new Set;#l=new Set;#p=new Set;#d;#h=new Ii;constructor({descriptor:t,bot:o,harness:i,state:e,status:a=Ui(),logger:A=console,replyTimeoutMs:r=6e5,signal:s}){if(!t?.key||!t?.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.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=A,this.#c=r,this.#s=s,this.#d=new ii({label:t.key,logger:A})}get status(){return structuredClone(this.#a)}accept(t){if(this.#s?.aborted)return Promise.resolve();let o=Ci(t?.conversationId),i=t?.kind==="group"?"group":"direct",e={...t,kind:i,conversationId:o},a=Ci(e.messageId),A=Ci(e.senderId);if(!a||!A||!o||e.senderIsBot===!0||this.#r.hasSeen(a)||this.#g.has(a))return Promise.resolve();this.#g.add(a);let r=kf({adapter:this.#A,target:e.kind==="direct"||e.addressed===!0?e.reactionTarget:null,reactions:this.#e.reactions,status:this.#a,logger:this.#i,label:this.#e.key});e.statusReaction=r;let s=this.#E(e,a,A);return s.then(()=>r.success(),()=>r.error()),s}#E(t,o,i){t.kind==="direct"&&io(this.#r,t.connectionTestTarget??t.replyTarget);let e=`${t.kind}:${t.conversationId}`,a=this.#o.get(e),A=Ci(t.content),r=lo(A);if(r&&t.kind==="group"&&t.addressed===!0)return this.#u(t,o,Tn());if(r&&t.kind==="direct"){if(/^\/batch$/iu.test(A)&&(this.#I.has(e)||a||this.#d.hasPending(e)))return this.#u(t,o,po());let d=this.#h.handle(e,A,{plainText:!!A&&t.plainText!==!1&&!qt(t)&&!Gt(t)});if(d.handled)return d.kind==="submit"?this.#B({...t,content:d.prompt,batchSubmission:{token:d.token}},o,i,e):this.#u(t,o,d.message)}else if(t.kind==="direct"&&this.#h.status(e).phase==="collecting"){let I=this.#h.handle(e,A,{plainText:!!A&&t.plainText!==!1&&!qt(t)&&!Gt(t)});if(I.handled)return this.#u(t,o,I.message)}let g=t.kind==="direct"&&this.#h.status(e).phase==="collecting"||Gt(t)?null:Pi(A)?gi:Gi(A)?Fi:Li(A)?ci:null;if(g&&(t.kind!=="group"||t.addressed===!0)){let I;return I=this.#f(t,o,e,g).finally(()=>{this.#g.delete(o),this.#p.delete(I)}),this.#p.add(I),I}let c=this.#d.claimReply({key:e,actor:i,messageId:o,text:qt(t)||Gt(t)?"":t.content,addressed:t.kind!=="group"||t.addressed===!0,hasPendingQuestion:!!a,questionCompletion:a?.submitting||a?.claimedReplyMessageId?a.queue:null,isQuestionPending:()=>this.#o.has(e),send:I=>this.#A.sendText(t.replyTarget,I)});if(c){let I;return I=c.process(async()=>this.#r.hasSeen(o)?!1:(await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#g.delete(o),this.#l.delete(I)}),this.#l.add(I),I}if(a&&a.actor!==i)return this.#B(t,o,i,e);if(a?.submitting||a?.claimedReplyMessageId)return this.#B(t,o,i,e);if(a){mde(t,a,i)&&(a.claimedReplyMessageId=o);let d=(a.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#Q(t,o,i,e,a)).finally(()=>{this.#g.delete(o),a.claimedReplyMessageId===o&&(a.claimedReplyMessageId=null),a.queue===d&&(a.queue=null)});return a.queue=d,d}return this.#B(t,o,i,e)}#u(t,o,i){let e;return e=(async()=>{this.#r.hasSeen(o)||(await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),i&&await this.#A.sendText(t.replyTarget,i),this.#a.lastError=null)})().catch(async a=>{if(this.#s?.aborted){t.statusReaction?.clear();return}t.statusReaction?.error(),this.#a.lastError=a?.message??String(a);let A=At(this.#a,a);this.#i.error?.(`[dsh-im:${this.#e.key}] failed to process a batch input message [${A.referenceId}]:`,a)}).finally(()=>{this.#g.delete(o),this.#p.delete(e)}),this.#p.add(e),e}#B(t,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1}={}){let s=(this.#I.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#y(t,o,i,e,{alreadyRecorded:A})).finally(()=>{a&&this.#g.delete(o),this.#I.get(e)===s&&this.#I.delete(e)});return this.#I.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#o.values()].flatMap(t=>t.queue?[t.queue]:[]),...this.#l,...this.#p])}async#f(t,o,i,e){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString();let a=t.replyTarget;try{let A=await e(Ci(t.content),this.#t,this.#r,i,{signal:this.#s,hasImages:qt(t),hasFiles:Gt(t),pendingInteraction:this.#o.has(i)||this.#d.hasPending(i),control:{owner:this,key:i}});A?.stopped&&await Promise.allSettled([this.#k(i),this.#d.closeRoute(i)]);for(let r of A?.messages??[A?.message])r&&await this.#A.sendText(a,r);this.#a.lastError=null}catch(A){if(A?.code==="turn-stopped"||this.#s?.aborted){t.statusReaction?.clear();return}t.statusReaction?.error(),this.#a.lastError=A?.message??String(A);let r=At(this.#a,A);this.#i.error?.(`[dsh-im:${this.#e.key}] failed to process a command [${r.referenceId}]:`,A),await this.#A.sendText(a,dt(r)).catch(()=>{})}}sendConnectionTest(t){return Tg({state:this.#r,text:t,channelLabel:D("{label}\u673A\u5668\u4EBA",{label:this.#e.label}),send:(o,i)=>this.#A.sendText(o,i)})}async#m(t,o,i=[],e){let a=await Co({artifacts:i,baseReceipt:e,deliveryId:o,channelKey:this.#e.key,signal:this.#s,sendImage:typeof this.#A.sendImage=="function"?A=>this.#A.sendImage(t,A):void 0,sendFile:typeof this.#A.sendFile=="function"?A=>this.#A.sendFile(t,A):void 0,onFailure:(A,r)=>At(this.#a,r,{userMessage:Sde(A?.fileName,r,this.#e),reason:r?.code}),sendFailureNotice:(A,r,s)=>this.#A.sendText(t,dt(s)),logger:this.#i});return this.#a.artifactsSent=(this.#a.artifactsSent??0)+a.artifactsSent,this.#a.artifactSendErrors=(this.#a.artifactSendErrors??0)+a.artifactSendErrors,{receipt:a.receipt,userVisible:a.userVisible,artifactSendErrors:a.artifactSendErrors}}async#y(t,o,i,e,{alreadyRecorded:a=!1}={}){if(!a){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString()}let A=t.replyTarget,r=Ci(t.content),s=t.batchSubmission,g=null,c=!1;try{if(this.#s?.throwIfAborted(),t.kind==="group"&&t.addressed!==!0){this.#a.messagesRejected+=1,this.#a.lastRejectedAt=new Date().toISOString();return}let I=qt(t),d=Gt(t);if(!r&&!I&&!d){await this.#A.sendText(A,D("\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u6587\u4EF6\u6D88\u606F\u3002"));return}let B=r.toLowerCase();if(!I&&!d&&B==="/help"){await this.#A.sendText(A,[D("{label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002",{label:this.#e.label}),"",D("\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u3001\u56FE\u7247\u6216\u6587\u4EF6\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002"),D("/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD"),D("/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587"),D("/workspace \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A"),D("/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84"),D("/sessionlist [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"),D("/session Session ID \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD"),D("/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B"),D("/reasoninglist \u6216 /reasonings \u6309\u5E8F\u53F7\u5217\u51FA\u5F53\u524D\u6A21\u578B\u53EF\u7528\u63A8\u7406\u7B49\u7EA7"),D("/reasoning [\u5E8F\u53F7\u3001\u7B49\u7EA7ID\u6216 --default] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u63A8\u7406\u7B49\u7EA7"),D("/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] [\u63A8\u7406\u7B49\u7EA7ID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B"),D("\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2 [\u63A8\u7406\u7B49\u7EA7ID]"),D("/presetlist \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset"),D("/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset"),D("\u7EAF\u6570\u5B57 ID\uFF1A/preset id:<ID>"),D("/preset --default \u8DDF\u968F Host \u9ED8\u8BA4"),D("/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1"),D("/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1"),D("/batch \u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF0C\u6700\u591A 10 \u6761\u6587\u5B57\uFF09"),D("/send \u63D0\u4EA4\u5F53\u524D\u6279\u6B21"),D("/cancel \u53D6\u6D88\u5F53\u524D\u6279\u6B21"),D("/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001"),D("/version \u67E5\u770B\u63D2\u4EF6\u7248\u672C"),D("/help \u663E\u793A\u672C\u5E2E\u52A9")].join(`
216
216
  `));return}if(!I&&!d&&B==="/status"){await this.#t.ensureRunning({signal:this.#s}),await this.#A.sendText(A,D("{label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002",{label:this.#e.label}));return}let f=!I&&!d?await Io(r,this.#t,e):null;if(f){for(let R of f.messages??[f.message])await this.#A.sendText(A,R);return}if(!I&&!d&&B==="/new"){await this.#r.clearSession(e),await this.#A.sendText(A,D("\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"));return}let Q=!I&&!d?await si(r,this.#t,this.#r,e,{signal:this.#s}):null;if(Q){await this.#A.sendText(A,Q.message);return}await this.#A.sendTyping?.(A).catch(R=>{this.#i.warn?.(`[dsh-im:${this.#e.key}] typing indicator failed:`,R)});let y=!1;if(typeof this.#A.openDeliveryStream=="function")try{g=await this.#A.openDeliveryStream(A),c=!0}catch(R){this.#i.warn?.(`[dsh-im:${this.#e.key}] unable to start a semantic reply stream; using final delivery:`,R)}else if(typeof this.#A.openStream=="function")try{g=await this.#A.openStream(A)}catch(R){this.#i.warn?.(`[dsh-im:${this.#e.key}] unable to start a streamed reply; using text:`,R)}let m=I?await so(t,{signal:this.#s}):void 0,{answer:_,artifacts:N=[]}=await ni({harness:this.#t,state:this.#r,key:e,text:r,content:m,createOptions:this.#s?{signal:this.#s}:void 0,existsOptions:this.#s?{signal:this.#s}:void 0,askOptions:{timeoutMs:this.#c,signal:this.#s,control:{owner:this,key:e},onUpdate:g?async R=>{let V=R.type==="text"?R.text:R.type==="tool"?D("\u6B63\u5728\u4F7F\u7528{name}\u2026",{name:R.name}):R.text;if(V){let L=R.type==="text"?"markdown":"plain";await g.update(c?Rn(V,L):V)}}:void 0,onInteraction:R=>this.#C(R,{key:e,actor:i,target:A,requiresMention:t.kind==="group"&&t.requiresMention!==!1}),onInteractionResolved:R=>this.#b(R),files:t.files}});s&&this.#h.complete(e,s.token);let G=!Ci(_)&&N.length>0,Y=G?D(yde):_,J=G?"plain":"markdown",H=null,j=null;if(g)try{let R=await g.finish(c?Rn(Y,J):Y);y=!0,j=zt({deliveryId:o,presentation:R?.presentation??g.presentation??`${this.#e.key}-stream`,providerMessageIds:[...li(g),...li(R)],deliveryOutcome:R?.deliveryOutcome,reason:R?.reason})}catch(R){g.cancel?.(),this.#i.warn?.(`[dsh-im:${this.#e.key}] streamed reply finalization failed; using text:`,R)}if(!y)try{let R=typeof this.#A.sendDelivery=="function"?await this.#A.sendDelivery(A,Rn(Y,J)):await this.#A.sendText(A,Y);j=zt({deliveryId:o,presentation:R?.presentation??`${this.#e.key}-text`,providerMessageIds:li(R),deliveryOutcome:R?.deliveryOutcome,reason:R?.reason})}catch(R){H=Sa(R)}let q=j?.deliveryOutcome==="unknown";j?.deliveryOutcome==="failed"?H=Sa(new Error(`Final text delivery failed (${j.reason??"unknown"})`),{uncertain:!1}):q&&(H=Sa(new Error(`Final text delivery outcome is unknown (${j.reason??"unknown"})`)));let U=await this.#m(A,o,N,j);if(H&&(!U.userVisible||q))throw H.deliveryReceipt=U.receipt,H;return H&&U.artifactSendErrors===0&&At(this.#a,H),U.userVisible&&(this.#a.messagesReplied+=1,this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null,!H&&U.artifactSendErrors===0&&oo(this.#a)),U.receipt}catch(I){let d=I?.code==="turn-stopped";s&&d&&this.#h.complete(e,s.token);let B=s&&!d?this.#h.fail(e,s.token):null;if(d){if(t.statusReaction?.clear(),g)try{await g.finish(D("\u5DF2\u505C\u6B62\u3002"))}catch{g.cancel?.()}return}if(this.#s?.aborted){t.statusReaction?.clear(),g?.cancel?.();return}t.statusReaction?.error(),this.#a.lastError=I?.message??String(I);let f=async N=>{let G=typeof g?.fail=="function"?"fail":typeof g?.finish=="function"?"finish":null;if(!G)return!1;try{let Y=await g[G](N);return G==="fail"?!!Y&&Y.deliveryOutcome!=="failed":Y!==!1&&Y?.deliveryOutcome!=="failed"}catch(Y){return this.#i.warn?.(`[dsh-im:${this.#e.key}] unable to finalize the failed stream:`,Y),!1}},Q=go(I),y=Eo(I),m=At(this.#a,I,{userMessage:y??Q,reason:vi(I)?.reason}),_=B?.retained?`${dt(m)}
217
217
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmanrui/dsh-im",
3
- "version": "3.0.6",
3
+ "version": "3.0.7",
4
4
  "description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -12,10 +12,30 @@ export function createHarnessCommandExecutor(ctx, provided) {
12
12
  if (typeof gateway.invoke !== 'function') {
13
13
  throw new TypeError('dsh-im requires a callable ctx.typertGateway');
14
14
  }
15
- return (sessionId, line, options = {}) => gateway.invoke({
16
- namespace: 'commands',
17
- method: 'execute',
18
- args: { agentId: sessionId, line },
19
- signal: options.signal,
20
- });
15
+ return async (sessionId, line, options = {}) => {
16
+ const request = {
17
+ namespace: 'commands',
18
+ method: 'execute',
19
+ args: { agentId: sessionId, line, images: [] },
20
+ signal: options.signal,
21
+ };
22
+ try {
23
+ return await gateway.invoke(request);
24
+ } catch (error) {
25
+ // Newer Hosts require images; older Hosts reject that field before
26
+ // invoking the command. Retry only that exact pre-dispatch failure so
27
+ // a business failure can never cause compaction to run twice.
28
+ if (error?.name !== 'TypertGatewayError'
29
+ || error.code !== 'arguments-invalid'
30
+ || error.endpoint !== 'commands/execute'
31
+ || error.message !== 'typert gateway: commands/execute: args fields do not match the descriptor: unexpected "images"') {
32
+ throw error;
33
+ }
34
+ options.signal?.throwIfAborted();
35
+ return gateway.invoke({
36
+ ...request,
37
+ args: { agentId: sessionId, line },
38
+ });
39
+ }
40
+ };
21
41
  }