From f0bb6db79f488faf7be1fc3ae599d2d8cc4c7fc7 Mon Sep 17 00:00:00 2001 From: xmanrui <841206367@qq.com> Date: Tue, 18 Aug 2026 16:49:31 +0800 Subject: [PATCH] release: prepare dsh-im 0.7.2 --- lib/index.js | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- src/channels/discord/discord-api.mjs | 2 +- src/channels/weixin/weixin-api.mjs | 2 +- test/channels/weixin/weixin-api.test.mjs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/index.js b/lib/index.js index c840ed0..96234d7 100644 --- a/lib/index.js +++ b/lib/index.js @@ -82,7 +82,7 @@ ${hP}`:["session-not-registered","session-not-found"].includes(n?.code)?"\u672A\ `).trim();c&&c!==this.#n&&(this.#n=c,o={type:"text",text:c});continue}if(e.type==="assistant/message"){let A=Yee(e);A&&A!==this.#n&&(this.#n=A,o={type:"text",text:A});continue}e.type==="tool/call"?o={type:"tool",name:e.data?.name??"\u5DE5\u5177"}:e.type==="tool/result"&&(o={type:"status",text:"\u6B63\u5728\u6574\u7406\u7ED3\u679C\u2026"})}}}}return o}},zs=class extends Error{constructor(a,o){super(`${a}: ${o?.message??"unknown Harness RPC error"}`),this.name="HarnessRpcError",this.method=a,this.code=o?.code??"internal",this.details=o?.details??{}}},kc=class extends Error{constructor(a,o){super(o),this.name="HarnessInteractionError",this.code=a}},Kt=class{#A;#e;#t;#a;#s;#n;#E;#g;#c;#r;#i=null;#o;#I;#l;constructor({baseUrl:a,workspace:o,agentPreset:i="standard",autostart:e=!1,dshBin:r="dsh",fetchImpl:A=fetch,createWebSocket:t=l=>new WebSocket(l),interactionReconnectDelayMs:s=500,rpcIdPrefix:g="im",logPrefix:c="dsh-im"}){if(typeof t!="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");this.#A=new URL(a),this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#c=g.trim(),this.#r=c.trim(),this.#o=Lee(this.#A.origin),this.#I=this.#o.ownerships,this.#l=this.#o.claims}async rpc(a,o={},i=3e4,e={}){let r=e.rpcId??`${this.#c}-${yP()}`,A=AbortSignal.timeout(i),t=e.signal?AbortSignal.any([e.signal,A]):A,s=await this.#n(new URL(`/api/${a}`,this.#A),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-request",rpcId:r,method:a,payload:o}),signal:t});if(!s.ok)throw new Error(`Harness transport ${a} failed: HTTP ${s.status}`);let g=await s.json();if(g?.type!=="server-response"||g?.rpcId!==r)throw new Error(`Harness returned an invalid response for ${a}`);if(!g.result?.ok)throw new zs(a,g.result?.error);return g.result.value}async health(a={}){return await this.rpc("host.describe",{},5e3,a),!0}async ensureRunning(a={}){try{return await this.health(a)}catch(e){if(!this.#a)throw e}if(!this.#i||this.#i.exitCode!==null){let e=this.#A.port||(this.#A.protocol==="https:"?"443":"80");this.#i=Gee(this.#s,["web","--host",this.#A.hostname,"--port",e],{cwd:this.#e,env:process.env,stdio:["ignore","inherit","inherit"]}),this.#i.on("error",r=>{console.error(`[${this.#r}] failed to start Harness:`,r.message)})}let o=Date.now()+6e4,i;for(;Date.now()t.path===o);return r?r.workspaceId:(await this.rpc("workspace.create",{path:o},3e4,i)).workspace.workspaceId}async createSession(a={}){await this.ensureRunning(a);let o=await this.workspaceId(a);return(await this.rpc("session.create",{workspaceId:o,agentPreset:this.#t},3e4,a)).sessionId}async sessionExists(a,o={}){try{return await this.rpc("session.history",{sessionId:a,maxMessages:1},3e4,o),!0}catch(i){if(i instanceof zs&&i.code==="session-not-found")return!1;throw i}}async respondInteraction(a,o,i={}){if(typeof a!="string"||!a)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),r=i.signal?AbortSignal.any([i.signal,e]):e,A=await this.#n(new URL("/api/respond",this.#A),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-response",rpcId:a,result:o}),signal:r});if(!A.ok)throw new Error(`Harness transport respond failed: HTTP ${A.status}`);let t=await A.json();if(t?.accepted===!0)return t;if(t?.accepted!==!1||t.reason!=="bad-response"&&t.reason!=="not-pending")throw new Error("Harness returned an invalid interaction response receipt");let s=t.reason;throw new kc(`interaction-${s}`,`Harness interaction response was rejected (${s})`)}async watchInteractions(a,{signal:o,onInteraction:i,onResolved:e,onOpen:r,ownership:A}={}){if(typeof a!="string"||!a)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(r!==void 0&&typeof r!="function")throw new TypeError("onOpen must be a function");for(;!o.aborted;){try{await this.#u(a,{signal:o,onInteraction:i,onResolved:e,onOpen:r,ownership:A})}catch(t){if(o.aborted)return;console.warn(`[${this.#r}] Harness interaction stream disconnected:`,t.message)}if(o.aborted)return;try{await sd(this.#g,o)}catch{if(o.aborted)return;throw new Error("Harness interaction reconnect wait failed")}}}#p(a,o){let i=this.#I.get(a)??new Set;o.order=this.#o.nextOrder,this.#o.nextOrder+=1,i.add(o),this.#I.set(a,i)}#h(a,o){let i=this.#I.get(a);i?.delete(o),i?.size===0&&this.#I.delete(a);for(let[e,r]of this.#l)r.ownership===o&&this.#l.delete(e)}#C(a,o){for(let i of this.#I.get(a)??[])xee(i,o)}async#d(a,o){let i=await this.rpc("session.history",{sessionId:a,maxMessages:50},3e4,{signal:o});this.#C(a,i.events??[])}#B(a,o,i){let e=this.#l.get(o);if(e&&this.#I.get(a)?.has(e.ownership))return e;let r=[...this.#I.get(a)??[]],A=r.filter(s=>s.active).sort((s,g)=>s.order-g.order);if(A.length>0)return{ownership:A[0],recovered:!1};let t=r.filter(s=>!s.started&&!s.completed).sort((s,g)=>s.order-g.order)[0]??null;return t?{ownership:t,recovered:!0}:null}async ask(a,o,i={}){typeof i=="number"&&(i={timeoutMs:i});let e=i.timeoutMs??6e5,r=i.signal,A=typeof i.onUpdate=="function"?i.onUpdate:null,t=typeof i.onInteraction=="function"?i.onInteraction:void 0,s=typeof i.onInteractionResolved=="function"?i.onInteractionResolved:void 0;await this.ensureRunning({signal:r});let g=await this.rpc("session.history",{sessionId:a,maxMessages:1},3e4,{signal:r}),c=Math.max(-1,...(g.events??[]).map(({event:m})=>m.seq??-1)),l=`${this.#c}-${yP()}`,C=new Rc({promptRpcId:l,afterSeq:c}),B=t||s?new AbortController:null,Q=B?r?AbortSignal.any([r,B.signal]):B.signal:null,f=B?{promptRpcId:l,active:!1,started:!1,completed:!1,turn:null,openTurn:null,lastSeq:c,reconnect:null,order:-1,toolCalls:new Map}:null,y=null;f&&this.#p(a,f);try{if(Q){let T,k=new Promise(F=>{T=F});y=this.watchInteractions(a,{signal:Q,onInteraction:t,onResolved:s,onOpen:T,ownership:f}),y.catch(()=>{}),await Promise.race([k,sd(3e4,Q).then(()=>{throw new Error("Harness interaction stream did not open within 30 seconds")})])}await this.rpc("session.prompt",{sessionId:a,mode:"queue",content:[{type:"text",text:o}],clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,{rpcId:l,signal:r});let m=Date.now()+e;for(;Date.now(){}),f&&this.#h(a,f)}}#u(a,{signal:o,onInteraction:i,onResolved:e,onOpen:r,ownership:A}){let t=new URL("/api/events.mux",this.#A);return t.protocol=t.protocol==="https:"?"wss:":"ws:",new Promise((s,g)=>{let c;try{c=this.#E(t.toString())}catch(G){g(G);return}let l=!1,C=!1,B=null,Q=Promise.resolve(),f=A==null,y=[],m=G=>{C||(C=!0,c.removeEventListener("open",k),c.removeEventListener("message",x),c.removeEventListener("close",H),c.removeEventListener("error",J),o.removeEventListener("abort",K),A?.reconnect===T&&(A.reconnect=null),Q.then(()=>{let R=G??B;R?g(R):s()},g))},T=()=>{try{(c.readyState===0||c.readyState===1)&&c.close()}catch{}},k=()=>{l=!0,A&&(A.reconnect=T);try{r?.()}catch(G){console.warn(`[${this.#r}] ignored an interaction open callback failure:`,G.message)}A&&this.#d(a,o).then(()=>{if(!C){f=!0;for(let G of y.splice(0))j(G)}}).catch(G=>{B??=G,T(),m(G)})},F=(G,R)=>{G&&(Q=Q.then(()=>G(R)).catch(Z=>{B??=Z,T(),m(B)}))},j=G=>{let R=G.payload;if(A&&R.type==="session/event"){this.#C(a,[R.event]);return}if(R.type==="question/requested"||R.type==="approval/requested"){let Z=R.type==="question/requested"?"question":"approval",U=Z==="question"?G.rpcId:R.approvalId,b=`${Z}:${U}`;if(A){let ee=this.#B(a,b,Z);if(ee?.ownership!==A)return;this.#l.set(b,ee)}let L=Z==="approval"&&A&&typeof R.callId=="string"?this.#l.get(b)?.ownership.toolCalls.get(R.callId):void 0;F(i,Object.freeze({kind:Z,interactionId:U,rpcId:G.rpcId,sessionId:a,payload:R,recovered:A?this.#l.get(b)?.recovered===!0:!1,...L?{toolCall:L}:{},reconnect:T,respond:(ee,fe={})=>this.respondInteraction(G.rpcId,ee,{...fe,signal:fe.signal??o})}));return}if(R.type==="question/resolved"||R.type==="approval/resolved"){let Z=R.type==="question/resolved"?"question":"approval",U=Z==="question"?R.questionRpcId:R.approvalId,b=`${Z}:${U}`;if(A){if(this.#l.get(b)?.ownership!==A)return;this.#l.delete(b)}F(e,Object.freeze({kind:Z,interactionId:U,sessionId:a,outcome:R.outcome,payload:R}))}},x=G=>{try{if(typeof G.data!="string")throw new Error("binary WebSocket frame");let R=JSON.parse(G.data),Z=R?.payload;if(R?.type!=="server-request"||typeof R.rpcId!="string"||!Z||typeof Z!="object"||R.method!==Z.type)throw new Error("invalid server-request envelope");if(Z.sessionId!==a)return;f?j(R):y.push(R)}catch(R){console.warn(`[${this.#r}] ignored a malformed Harness interaction frame:`,R.message)}},H=()=>m(l?null:new Error("Harness interaction WebSocket closed before opening")),J=()=>{m(new Error(l?"Harness interaction WebSocket failed":"Harness interaction WebSocket failed before opening")),T()},K=()=>{T(),m()};c.addEventListener("open",k),c.addEventListener("message",x),c.addEventListener("close",H,{once:!0}),c.addEventListener("error",J,{once:!0}),o.addEventListener("abort",K,{once:!0}),o.aborted&&K()})}stopManagedProcess(){this.#i?.exitCode===null&&this.#i.kill("SIGTERM")}};var gd=class extends Kt{constructor(a){super({...a,rpcIdPrefix:"dingtalk",logPrefix:"dsh-dingtalk"})}};import{randomUUID as jee}from"node:crypto";import{mkdir as Jee,readFile as qee,rename as Vee,unlink as zee,writeFile as Wee}from"node:fs/promises";import{dirname as Zee}from"node:path";var cd=Object.freeze({version:1,sessions:{},seenMessageIds:[],pendingSenders:{}});function _t(n){return typeof n=="string"&&n.trim()?n.trim():null}function SP(n){return(_t(n)??"\u9489\u9489\u7528\u6237").slice(0,100)}function Xee(n,a){if(!n||typeof n!="object")return null;let o=_t(n.requestId)??_t(a),i=_t(n.staffId),e=_t(n.requestedAt)??_t(n.lastSeenAt),r=_t(n.lastSeenAt)??e;return!o||!i||!e||!r?null:{requestId:o,staffId:i,displayName:SP(n.displayName??n.nick),requestedAt:e,lastSeenAt:r}}function $ee(n){if(!n||typeof n!="object")return structuredClone(cd);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[e,r]of Object.entries(n.sessions)){let A=_t(e),t=_t(r);A&&t&&(a[A]=t)}let o={},i=Array.isArray(n.pendingSenders)?n.pendingSenders.map(e=>[e?.requestId,e]):Object.entries(n.pendingSenders&&typeof n.pendingSenders=="object"?n.pendingSenders:{});for(let[e,r]of i){let A=Xee(r,e);if(!A)continue;let t=Object.values(o).find(s=>s.staffId===A.staffId);(!t||t.lastSeenAtnew Date().toISOString()}={}){if(!_t(a))throw new TypeError("state path is required");if(typeof o!="function"||typeof i!="function")throw new TypeError("idFactory and now must be functions");this.#A=a,this.#a=o,this.#s=i}async load(){try{this.#e=$ee(JSON.parse(await qee(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(cd),await this.#n()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){let i=_t(a),e=_t(o);if(!i||!e)throw new TypeError("key and sessionId are required");this.#e.sessions[i]=e,await this.#n()}async clearSession(a){let o=_t(a);!o||!(o in this.#e.sessions)||(delete this.#e.sessions[o],await this.#n())}async clearSessions(){this.#e.sessions={},await this.#n()}hasSeen(a){let o=_t(a);return!!(o&&this.#e.seenMessageIds.includes(o))}async markSeen(a){let o=_t(a);if(!o)throw new TypeError("messageId is required");this.hasSeen(o)||(this.#e.seenMessageIds.push(o),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#n())}pendingSenders(){return Object.values(this.#e.pendingSenders).sort((a,o)=>a.requestedAt.localeCompare(o.requestedAt)).map(a=>structuredClone(a))}pendingSender(a){let o=_t(a),i=o?this.#e.pendingSenders[o]:null;return i?structuredClone(i):null}async recordPendingSender(a,o,i){let e=a&&typeof a=="object"?a:{staffId:a,displayName:o,lastSeenAt:i},r=_t(e.staffId);if(!r)throw new TypeError("staffId is required");let A=_t(e.lastSeenAt)??_t(e.requestedAt)??this.#s(),t=Object.values(this.#e.pendingSenders).find(g=>g.staffId===r),s={requestId:t?.requestId??`ding_sender_${this.#a()}`,staffId:r,displayName:SP(e.displayName??e.nick??o),requestedAt:t?.requestedAt??A,lastSeenAt:A};return this.#e.pendingSenders[s.requestId]=s,await this.#n(),structuredClone(s)}async removePendingSender(a){let o=_t(a);return!o||!this.#e.pendingSenders[o]?!1:(delete this.#e.pendingSenders[o],await this.#n(),!0)}async removePendingSenderByStaffId(a){let o=_t(a),i=o?Object.values(this.#e.pendingSenders).find(e=>e.staffId===o):null;return i?this.removePendingSender(i.requestId):!1}snapshot(){return structuredClone(this.#e)}async remove(){await this.#t;try{await zee(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(cd)}async#n(){let a=`${JSON.stringify(this.#e,null,2)} `,o=this.#t.then(async()=>{await Jee(Zee(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await Wee(i,a,{encoding:"utf8",mode:384}),await Vee(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};import{mkdir as eAe,readFile as AAe,realpath as tAe,rename as aAe,stat as rAe,unlink as iAe,writeFile as oAe}from"node:fs/promises";import{dirname as nAe,isAbsolute as OP,resolve as hE}from"node:path";var NFe=Object.freeze({version:1,workspaces:Object.freeze({})});function ld(n){let a=new Error(n);return a.code=_c,a}async function US(n){return hE(await tAe(n))}async function sAe(n,a){if(n===a)return!0;try{return await US(n)===await US(a)}catch{return!1}}function Jr(n){if(typeof n!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n))throw new TypeError("Invalid bot id");return n}function gAe(n){if(!n||n.version!==1||!n.workspaces||typeof n.workspaces!="object"||Array.isArray(n.workspaces))return null;let a={};for(let[o,i]of Object.entries(n.workspaces)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(o)||typeof i!="string"||!OP(i))return null;a[o]=hE(i)}return{version:1,workspaces:a}}async function DP(n){if(typeof n!="string"||!n.trim()||!OP(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 a=hE(n.trim()),o;try{o=await rAe(a)}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 a}var Ia=class{#A;#e;#t={};#a=new Map;#s=1;#n=new Map;#E=1;#g=new Map;#c=new WeakMap;#r=new Set;#i=Promise.resolve();#o=new Map;constructor(a,{defaultWorkspace:o=process.cwd()}={}){if(typeof a!="string"||!a)throw new TypeError("workspace store path is required");this.#A=a,this.#e=hE(o)}async load(){try{let a=gAe(JSON.parse(await AAe(this.#A,"utf8")));if(!a)throw new Error("dsh-im workspace config is invalid");this.#t=a.workspaces}catch(a){if(a?.code!=="ENOENT")throw a;this.#t={}}this.#a.clear(),this.#s=1,this.#n.clear(),this.#E=1,this.#g.clear(),this.#r.clear();for(let a of Object.keys(this.#t))this.#a.set(a,this.#I()),this.#n.set(a,this.#l());return this}has(a){let o=Jr(a);return Object.hasOwn(this.#t,o)&&!this.#g.has(o)}incarnationFor(a){return this.#n.get(Jr(a))??null}workspaceFor(a){return this.#t[Jr(a)]??this.#e}generationFor(a){return this.#a.get(Jr(a))??null}async whenIdle(){await this.#i}async whenBotIdle(a){let o=Jr(a);for(;;){let i=this.#o.get(o);if(!i||(await i,this.#o.get(o)===i))return}}async ensure(a,{workspace:o=this.#e}={}){let i=Jr(a),e=hE(o);return this.#C(i,async()=>{if(this.#t[i])this.#a.has(i)||this.#a.set(i,this.#I());else{this.#t[i]=e,this.#a.set(i,this.#I()),this.#n.set(i,this.#l());try{await this.#d()}catch(r){throw delete this.#t[i],this.#a.delete(i),this.#n.delete(i),r}}return this.#t[i]})}async setWorkspace(a,o,{clearSessions:i,incarnation:e}={}){let r=Jr(a);if(!this.has(r)||e!==void 0&&e!==this.incarnationFor(r)){let t=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw t.code="workspace-bot-not-found",t}let A=await DP(o);return this.#C(r,async()=>{if(!this.has(r)||e!==void 0&&e!==this.incarnationFor(r)){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(r))return A;let t=this.#t[r];this.#a.set(r,this.#I()),await i?.(),this.#t[r]=A;try{await this.#d()}catch(s){throw this.#t[r]=t,s}return A})}async bindWorkspaceSession(a,o,{conversationKey:i,sessionId:e,clearSessions:r,setSession:A,incarnation:t,expectedGeneration:s}={}){let g=Jr(a);if(typeof i!="string"||!i||typeof e!="string"||!e)throw new TypeError("conversationKey and sessionId are required");if(typeof r!="function"||typeof A!="function")throw new TypeError("session state callbacks are required");if(!this.has(g)||t!==void 0&&t!==this.incarnationFor(g)){let l=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw l.code="workspace-bot-not-found",l}let c=await US(await DP(o));return this.#C(g,async()=>{if(!this.has(g)||t!==void 0&&t!==this.incarnationFor(g)){let l=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw l.code="workspace-bot-not-found",l}if(s!==void 0&&s!==this.generationFor(g))throw ld("The bot workspace changed before the session binding could be committed.");if(!await sAe(c,this.workspaceFor(g))){let l=this.#t[g];this.#a.set(g,this.#I()),await r(),this.#t[g]=c;try{await this.#d()}catch(C){throw this.#t[g]=l,C}}return await A(i,e),{workspace:c,sessionId:e,generation:this.#a.get(g)}})}async invalidateSessions(a,{clearSessions:o}={}){let i=Jr(a);return this.#C(i,async()=>{this.#a.set(i,this.#I()),await o?.()})}async beginRemoval(a,{clearSessions:o}={}){let i=Jr(a);return this.#C(i,async()=>{let e=this.#g.get(i);if(e)return e;let r=Object.freeze({});this.#g.set(i,r),this.#c.set(r,{botId:i,incarnation:this.incarnationFor(i)}),this.#a.set(i,this.#I());try{await o?.()}catch(A){throw this.#g.get(i)===r&&this.#g.delete(i),A}return r})}async abortRemoval(a){let{botId:o}=this.#p(a);return this.#C(o,async()=>this.#g.get(o)!==a?!1:(this.#g.delete(o),Object.hasOwn(this.#t,o)&&(this.#a.set(o,this.#I()),this.#n.has(o)||this.#n.set(o,this.#l())),!0))}async finishRemoval(a){let{botId:o,incarnation:i}=this.#p(a);return this.#C(o,async()=>this.#g.get(o)!==a?{removed:!1,persisted:!0,error:null,stale:!0}:this.incarnationFor(o)!==i?(this.#g.delete(o),{removed:!1,persisted:!0,error:null,stale:!0}):(this.#g.delete(o),this.#h(o)))}async retireAfterConfigCommit(a){let o=Jr(a);return this.#C(o,async()=>(this.#g.delete(o),this.#h(o)))}async remove(a){let o=await this.retireAfterConfigCommit(a);if(o.error)throw o.error;return o.removed}async reconcile(a){let o=new Set([...a].map(Jr)),i=new Set([...Object.keys(this.#t),...this.#r]);for(let e of i)o.has(e)||await this.remove(e)}decorateStatus(a){return!a||typeof a!="object"||!Array.isArray(a.bots)?a:{...a,bots:a.bots.map(o=>o?.botId?{...o,workspace:this.workspaceFor(o.botId)}:o)}}#I(){let a=this.#s;return this.#s+=1,a}#l(){let a=this.#E;return this.#E+=1,a}#p(a){if(!a||typeof a!="object")throw new TypeError("Invalid workspace removal transaction");let o=this.#c.get(a);if(!o)throw new TypeError("Invalid workspace removal transaction");return o}async#h(a){let o=Object.hasOwn(this.#t,a),i=o||this.#r.has(a);if(delete this.#t[a],this.#a.delete(a),this.#n.delete(a),!i)return{removed:!1,persisted:!0,error:null,stale:!1};try{return await this.#B(),{removed:o,persisted:!0,error:null,stale:!1}}catch(e){return this.#r.add(a),{removed:o,persisted:!1,error:e,stale:!1}}}async#C(a,o){let i=this.#i.then(o,o),e=i.then(()=>{},()=>{});return this.#i=e,this.#o.set(a,e),e.finally(()=>{this.#o.get(a)===e&&this.#o.delete(a)}),i}async#d(){let a={version:1,workspaces:this.#t};await eAe(nAe(this.#A),{recursive:!0,mode:448});let o=`${this.#A}.tmp`;await oAe(o,`${JSON.stringify(a,null,2)} `,{encoding:"utf8",mode:384}),await aAe(o,this.#A),this.#r.clear()}async#B(){if(Object.keys(this.#t).length>0){await this.#d();return}try{await iAe(this.#A),this.#r.clear()}catch(a){if(a?.code!=="ENOENT")throw a;this.#r.clear()}}};function wP(n,a){return a&&typeof a.then=="function"?a.then(o=>n.decorateStatus(o)):n.decorateStatus(a)}function cAe(n){return Promise.resolve(n.status())}function Ua(n,{workspaces:a,method:o="remove",botIdFromRemoved:i=e=>e?.botId}){if(!n||!a||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(e,r){let A=Reflect.get(e,r,e);return r===o?async(...t)=>{let s=await A.apply(e,t),g=s?i(s,t):null;return g&&await a.retireAfterConfigCommit(g),s}:typeof A=="function"?A.bind(e):A}})}function Ha(n,{botId:a,workspaces:o,state:i}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let e=o.incarnationFor(a),r=()=>o.has(a)&&o.incarnationFor(a)===e,A=new Map,t=new Proxy(n,{get(g,c){if(c==="currentWorkspace")return()=>{if(!r()){let C=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw C.code="workspace-bot-not-found",C}return o.workspaceFor(a)};if(c==="assertWorkspaceScope")return()=>{if(!r()){let C=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw C.code="workspace-bot-not-found",C}};if((c==="listWorkspaces"||c==="listWorkspaceSessions")&&typeof g[c]=="function")return async(...C)=>{if(!r()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}let B=await g[c](...C);if(!r()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}return B};if(c==="switchWorkspace")return C=>{if(!r()){let B=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return B.code="workspace-bot-not-found",Promise.reject(B)}return o.setWorkspace(a,C,{clearSessions:()=>i.clearSessions(),incarnation:e})};if(c==="bindWorkspaceSession")return async(C,B)=>{if(typeof C!="string"||!C||typeof B!="string"||!B)throw new TypeError("conversationKey and sessionId are required");if(!r()){let m=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw m.code="workspace-bot-not-found",m}if(typeof g.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let Q=o.generationFor(a),f=await g.adoptWorkspaceSession(B);if(!r()){let m=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw m.code="workspace-bot-not-found",m}if(Q!==o.generationFor(a))throw ld("The bot workspace changed while the session was being adopted.");if(!f||typeof f!="object"||f.sessionId!==B||typeof f.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let y=await o.bindWorkspaceSession(a,f.workspace,{conversationKey:C,sessionId:B,clearSessions:()=>i.clearSessions(),setSession:(m,T)=>i.setSession(m,T),incarnation:e,expectedGeneration:Q});if(!r()){let m=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw m.code="workspace-bot-not-found",m}if(y.generation!==o.generationFor(a))throw ld("The bot workspace changed before the session binding completed.");return A.set(B,y.generation),{...f,workspace:y.workspace,sessionId:y.sessionId}};if(c==="createSession")return async(C={})=>{if(await o.whenBotIdle(a),!r()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}let B=o.generationFor(a),Q=await g.createSession({...C,workspace:o.workspaceFor(a)});return A.set(Q,B),Q};if(c==="workspaceSession")return C=>{if(typeof C!="string"||!C)throw new TypeError("sessionId is required");let B=A.get(C)??o.generationFor(a);A.delete(C);let Q=()=>r()&&B===o.generationFor(a);return Object.freeze({sessionId:C,async sessionExists(...f){if(!Q())return!1;let y=await g.sessionExists(C,...f);return Q()&&y},ask(...f){if(!Q())throw ld("The bot workspace changed before this prompt started.");return g.ask(C,...f)}})};if(c==="sessionExists")return(C,...B)=>{if(!r())return!1;let Q=A.get(C);return Q!==void 0&&Q!==o.generationFor(a)?(A.delete(C),!1):g.sessionExists(C,...B)};if(c==="ask")return(C,...B)=>{let Q=A.get(C);if(A.delete(C),!r()||Q!==void 0&&Q!==o.generationFor(a)){let f=new Error("The bot workspace changed before this prompt started.");throw f.code=_c,f}return g.ask(C,...B)};let l=Reflect.get(g,c,g);return typeof l=="function"?l.bind(g):l}}),s=new Proxy(i,{get(g,c){if(c==="sessionFor")return(C,...B)=>{if(!r())return null;let Q=g.sessionFor(C,...B);return Q&&!A.has(Q)&&A.set(Q,o.generationFor(a)),Q};if(c==="setSession")return(C,B,...Q)=>{let f=A.get(B);return!r()||f!==void 0&&f!==o.generationFor(a)?(A.delete(B),!1):g.setSession(C,B,...Q)};let l=Reflect.get(g,c,g);return typeof l=="function"?l.bind(g):l}});return Object.freeze({harness:t,state:s})}function Ka(n,{workspaces:a,stateFor:o}){if(!n||!a||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let i=new Map,e=(t,s)=>{let c=(i.get(t)??Promise.resolve()).catch(()=>{}).then(s);return i.set(t,c),c.finally(()=>{i.get(t)===c&&i.delete(t)})},r=(t,s)=>{let g=a.incarnationFor(t);return e(t,async()=>{if(!(await n.status())?.bots?.some(C=>C?.botId===t)){let C=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw C.code="workspace-bot-not-found",C}let l=await o(t);return await a.setWorkspace(t,s,{clearSessions:()=>l.clearSessions(),incarnation:g}),a.decorateStatus(await n.status())})},A=(t,s)=>e(t,async()=>{let g=await a.beginRemoval(t,{clearSessions:async()=>{try{let c=await o(t);if(!c||typeof c.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await c.clearSessions()}catch(c){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${t}:`,c?.message??c)}}});try{let c=await s();return await a.finishRemoval(g),a.decorateStatus(c)}catch(c){let l=await cAe(n).catch(()=>null);throw Array.isArray(l?.bots)&&!l.bots.some(B=>B?.botId===t)?await a.finishRemoval(g):await a.abortRemoval(g),c}});return new Proxy(n,{get(t,s){if(s==="updateWorkspace")return r;let g=Reflect.get(t,s,t);return typeof g!="function"?g:s==="deleteBot"?(c,...l)=>A(c,()=>g.call(t,c,...l)):s==="disconnect"?async(...c)=>{let C=(await t.status())?.bots?.[0]?.botId;return C?A(C,()=>g.apply(t,c)):wP(a,g.apply(t,c))}:(...c)=>wP(a,g.apply(t,c))}})}var MP=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function IAe(n){if(!Array.isArray(n)||n.length===0)return[...MP];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...MP]}var Ed=class{#A;#e;#t;#a;#s;#n;#E;#g=null;#c=null;#r=0;#i=!1;#o=!1;#I;#l;constructor({controller:a,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:r=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!a||typeof a.initialize!="function"||typeof a.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=IAe(e),this.#s=Number.isFinite(r)&&r>=0?r:15e3,this.#n=A,this.#E=t,this.#I=new Promise(s=>{this.#l=s})}get ready(){return this.#I}start(){return this.#o||this.#i?this:(this.#o=!0,this.#p(0),this)}async close(){this.#i||(this.#i=!0,this.#g!==null&&this.#E(this.#g),this.#g=null,await this.#c?.catch(()=>{}),this.#l?.(null),this.#l=null)}#p(a){this.#i||(this.#g=this.#n(()=>{this.#g=null,this.#h()},a),this.#g?.unref?.())}async#h(){if(this.#i||this.#c)return;let a=this.#C();this.#c=a;try{await a}finally{this.#c===a&&(this.#c=null)}}async#C(){try{if(await this.#e.ensureRunning(),this.#i)return;let a=await this.#A.initialize();if(this.#i)return;this.#l?.(a),this.#l=null;let{configured:o,connected:i}=a.totals;if(i65535)throw new Error("dsh-dingtalk requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function pAe(n){let a=Ws(n.dshHome??process.env.DSH_HOME??dE(EAe(),".dsh")),o=Ws(n.dataDir??dE(a,"integrations","dsh-dingtalk"));return{root:o,config:Ws(n.configPath??dE(o,"config.json")),bots:Ws(n.botsDir??dE(o,"bots")),workspaces:Ws(n.workspacesPath??dE(o,"workspaces.json"))}}async function KS(n,a={},o={}){if(!n?.credentials)throw new TypeError("dsh-dingtalk requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-dingtalk requires ctx.webServer");let i=o.ConfigStore??Xh,e=o.DeviceAuth??ed,r=o.StateStore??Id,A=o.HarnessClient??gd,t=o.Controller??IE,s=o.Runtime??CE,g=o.createConnectionSupervisor??HS,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,l=pAe(a),C=await new i(l.config).load(),B=Ws(a.workspace??process.cwd()),Q=o.WorkspaceStore??Ia,f=o.workspaces??await new Q(l.workspaces,{defaultWorkspace:B}).load(),y=typeof C.list=="function",m=y?C.list():[];y&&await f.reconcile(m.map(R=>R.botId)),await Promise.all(m.map(R=>f.ensure(R.botId)));let T=typeof C.remove=="function"?Ua(C,{workspaces:f}):C,k=o.deviceAuth??new e({baseUrl:a.registrationBaseUrl}),F=new Map,j=R=>Ws(l.bots,R,"state.json"),x=async R=>{let Z=F.get(R);return Z||(Z=await new r(j(R)).load(),F.set(R,Z)),Z},H=new A({baseUrl:CAe(n.webServer,a.harnessBaseUrl),workspace:B,agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),J=new t({deviceAuth:k,credentials:n.credentials,configStore:T,logger:c,createRuntime:async({botId:R,config:Z,clientSecret:U})=>{let b=await x(R);await f.ensure(R);let L=Ha(H,{botId:R,workspaces:f,state:b});return new s({config:Z,clientSecret:U,harness:L.harness,state:L.state,replyTimeoutMs:a.replyTimeoutMs??6e5,maxMessageChars:a.maxMessageChars??4e3,connectTimeoutMs:a.connectTimeoutMs??15e3,logger:{error:(...ee)=>c.error?.(`[${R}]`,...ee),warn:(...ee)=>c.warn?.(`[${R}]`,...ee),info:(...ee)=>c.info?.(`[${R}]`,...ee),debug:(...ee)=>c.debug?.(`[${R}]`,...ee)}})},deleteState:async({botId:R})=>{let Z=F.get(R);if(F.delete(R),Z&&typeof Z.remove=="function")await Z.remove();else try{await lAe(j(R))}catch(U){if(U?.code!=="ENOENT")throw U}}}),K=Ka(J,{workspaces:f,stateFor:x}),G=g({controller:K,harness:H,logger:c,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:K,ready:G.ready,async close(){await G.close(),await K.close(),H.stopManagedProcess()}}}import uAe from"qrcode";var hAe=new Set(["loopback","trusted-host"]);function Ya(n){if(n===void 0)return"loopback";if(hAe.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as dAe}from"node:path";var cr="bot.workspace.set";function xa(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(a=>["botId","workspace"].includes(a))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&dAe(n.workspace.trim())}function ja(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found"].includes(n?.code)?{code:n.code,message:n.message}:null}var _P="/dingtalk",Lt=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:cr,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),NP=Object.freeze(Object.values(Lt)),BAe=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function xS(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Fn(n,a){return xS(n)&&Object.keys(n).every(o=>a.includes(o))}function Zs(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function bP(n,a){return typeof n=="string"&&n.trim().length>0&&n.length<=a}function QAe(n,a){return xS(a)?n===Lt.status?Fn(a,[])?null:"connection.status does not accept fields.":n===Lt.beginProvisioning?Fn(a,["locale"])&&(a.locale===void 0||a.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Lt.pollProvisioning,Lt.cancelProvisioning].includes(n)?Fn(a,["attemptId"])&&Zs(a.attemptId)?null:`${n} requires an attemptId.`:n===Lt.bindCredentials?Fn(a,["clientId","clientSecret"])&&bP(a.clientId,256)&&bP(a.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===Lt.reconnectBot?Fn(a,["botId"])&&Zs(a.botId)?null:"bot.reconnect requires a botId.":n===Lt.deleteBot?Fn(a,["botId","confirm"])&&Zs(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===Lt.setWorkspace?xa(a)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Lt.approveSender?Fn(a,["botId","requestId","confirm"])&&Zs(a.botId)&&Zs(a.requestId)&&a.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===Lt.revokeSender?Fn(a,["botId","senderKey","confirm"])&&Zs(a.botId)&&Zs(a.senderKey)&&a.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function Cd(n){return{ok:!1,error:{code:"bad-request",message:n}}}function pd(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function fAe(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function vc(n){if(Array.isArray(n))return n.map(vc);if(!xS(n))return n;let a={};for(let[o,i]of Object.entries(n))BAe.has(o)||(a[o]=vc(i));return a}async function yAe(n){return uAe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function YS(n,a){return!n||typeof n.verificationUrl!="string"?vc(n):vc({...n,qrCodeDataUrl:await a(n.verificationUrl)})}async function Xs(n,a){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await YS(o.provisioning,a)),vc(o)}function mAe(n){for(let a of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[a]!="function")throw new TypeError(`A complete DingTalk controller is required (${a})`)}function TP(n,{encodeQr:a=yAe}={}){mAe(n);let o=new Map,i=e=>{let r=o.get(e);return r||(o.size>=16&&o.delete(o.keys().next().value),r=Promise.resolve().then(()=>a(e)),o.set(e,r)),r};return async(e,r,A)=>{if(A?.aborted)return pd();if(!NP.includes(e))return Cd("Unknown DingTalk endpoint.");let t=QAe(e,r);if(t)return Cd(t);try{let s;if(e===Lt.status)s=await Xs(await n.status(),i);else if(e===Lt.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),pd();s=await YS(g,i)}else if(e===Lt.pollProvisioning){let g=await n.registrationStatus(r.attemptId);if(!g)return Cd("The provisioning attempt no longer exists.");s=await YS(g,i)}else if(e===Lt.cancelProvisioning){if(s=await n.cancelProvisioning(r.attemptId),!s)return Cd("The provisioning attempt no longer exists.");s=vc(s)}else if(e===Lt.bindCredentials)s=await Xs(await n.bindCredentials(r),i);else if(e===Lt.reconnectBot)s=await Xs(await n.reconnectBot(r.botId),i);else if(e===Lt.deleteBot)s=await Xs(await n.deleteBot(r.botId),i);else if(e===Lt.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await Xs(await n.updateWorkspace(r.botId,r.workspace),i)}else e===Lt.approveSender?s=await Xs(await n.approveSender(r.botId,r.requestId),i):s=await Xs(await n.revokeSender(r.botId,r.senderKey),i);return A?.aborted?pd():{ok:!0,value:s}}catch(s){let g=ja(s);return A?.aborted?pd():g?{ok:!1,error:g}:fAe()}}}function hd(n,a,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(_P,TP(a,o),{authority:Ya(i)})}async function RP(n,a={}){if(a?.controller)return hd(n,a.controller,a.rpcOptions,a.rpcAuthority);let o=await KS(n,a,a.internals),i=hd(n,o.controller,a.rpcOptions,a.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as SAe}from"node:crypto";import{mkdir as DAe,readFile as wAe,rename as OAe,unlink as MAe,writeFile as bAe}from"node:fs/promises";import{dirname as _Ae}from"node:path";var jS=Object.freeze({version:1,bots:Object.freeze([])});function qo(n){return typeof n=="string"&&n.trim()?n.trim():null}function kP(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function uE(n,{botPrefix:a,tokenRefPrefix:o}){let i=qo(n);if(!i)throw new TypeError("platformId is required");let e=SAe("sha256").update(i).digest("hex").slice(0,24);return{botId:`${a}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function dd(n,a){let o=qo(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:a:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var Pc=class{#A;#e;#t;#a;#s;#n;#E=jS;#g=Promise.resolve();constructor(a,{channel:o,botPrefix:i,tokenRefPrefix:e}){this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=new RegExp(`^${kP(i)}_[a-f0-9]{24}$`),this.#n=new RegExp(`^${kP(e)}_[A-F0-9]{24}$`)}async load(){try{let a=this.#r(JSON.parse(await wAe(this.#A,"utf8")));if(!a)throw new Error(`dsh-im ${this.#e} config contains invalid bot data`);this.#E=a}catch(a){if(a?.code!=="ENOENT")throw a;this.#E=jS}return this}list(){return structuredClone(this.#E.bots)}get(a){let o=this.#E.bots.find(i=>i.botId===a);return o?structuredClone(o):null}getByPlatformId(a){let o=this.#E.bots.find(i=>i.platformId===a);return o?structuredClone(o):null}async save(a){let o=this.#c(a);if(!o)throw new Error(`Refusing to persist incomplete ${this.#e} bot data`);return this.#i(i=>{let e=i.find(t=>t.platformId===o.platformId&&t.botId!==o.botId),r=i.find(t=>t.tokenRef===o.tokenRef&&t.botId!==o.botId);if(e||r)throw new Error(`Duplicate ${this.#e} bot identity`);let A=i.findIndex(t=>t.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(a){if(!this.#s.test(a))throw new TypeError(`Invalid ${this.#e} bot id`);return this.#i(o=>{let i=o.findIndex(r=>r.botId===a);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let a=this.#g.then(async()=>{try{await MAe(this.#A)}catch(o){if(o?.code!=="ENOENT")throw o}this.#E=jS});this.#g=a.then(()=>{},()=>{}),await a}#c(a){if(!a||typeof a!="object")return null;let o=qo(a.platformId),i=qo(a.botId),e=qo(a.tokenRef),r=qo(a.name);if(!o||!i||!e||!r||!this.#s.test(i)||!this.#n.test(e))return null;let A=uE(o,{botPrefix:this.#t,tokenRefPrefix:this.#a});return A.botId!==i||A.tokenRef!==e?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:r,username:qo(a.username),createdAt:qo(a.createdAt)??new Date().toISOString(),connectedAt:qo(a.connectedAt)})}#r(a){if(!a||a.version!==1||!Array.isArray(a.bots))return null;let o=a.bots.map(A=>this.#c(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,r=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||r.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),r.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#i(a){let o,i=this.#g.then(async()=>{let e=[...this.#E.bots];o=a(e);let r=Object.freeze({version:1,bots:Object.freeze(e)});await this.#o(r),this.#E=r});return this.#g=i.then(()=>{},()=>{}),await i,o}async#o(a){await DAe(_Ae(this.#A),{recursive:!0,mode:448});let o=`${this.#A}.tmp`;await bAe(o,`${JSON.stringify(a,null,2)} -`,{encoding:"utf8",mode:384}),await OAe(o,this.#A)}};var vP=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function PP(n){return uE(n,vP)}function GP(n){return dd(n,"Discord\u673A\u5668\u4EBA")}var ud=class extends Pc{constructor(a){super(a,{channel:"Discord",...vP})}};function BE(n){return typeof n=="string"&&n.trim()?n.trim():null}function Bd(n,a){return Object.freeze({code:n,message:a})}var Gc=class{#A;#e;#t;#a;#s;#n;#E;#g;#c;#r=new Map;#i=new Map;#o=new Map;#I=0;#l=!1;constructor({descriptor:a,credentials:o,configStore:i,inspectToken:e,deriveIdentity:r,maskPlatformId:A,createRuntime:t,deleteState:s=async()=>{},logger:g=console}){if(!a?.key||!a?.label||!a?.connectionLabel)throw new TypeError("TokenBotController requires a channel descriptor");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError(`${a.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${a.label} requires a config store`);if(typeof e!="function"||typeof r!="function"||typeof A!="function"||typeof t!="function")throw new TypeError(`${a.label} controller dependencies are incomplete`);this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#c=g}async initialize(){if(this.#l)return this.status();for(let a of this.#t.list())await this.#B(a.botId,async()=>{if(this.#l||this.#r.get(a.botId)?.status?.ready)return;let o=await this.#C(a.tokenRef);if(!o){this.#i.set(a.botId,Bd("missing-token",`${this.#A.label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002`));return}try{await this.#p(a,o),this.#i.delete(a.botId)}catch(i){this.#i.set(a.botId,Bd("connection-failed",`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002`)),this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${a.botId} failed to initialize:`,i)}finally{this.#u()}});return this.status()}async bindCredentials({token:a}={}){if(this.#l)throw new Error(`${this.#A.label} controller is closed`);let o=BE(a);if(!o)throw new TypeError(`${this.#A.label} Bot Token is required`);let i=await this.#a(o),e=BE(i?.platformId),r=BE(i?.name);if(!e||!r)throw new Error(`${this.#A.label} returned an invalid bot identity`);let A=this.#s(e);return await this.#B(A.botId,async()=>{if(this.#l)throw new Error(`${this.#A.label} controller is closed`);let t=this.#t.getByPlatformId(e),s=await this.#e.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:r,username:BE(i.username),createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#e.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#d(A.tokenRef,s),c}try{await this.#p(g,o),this.#i.delete(A.botId)}catch(c){this.#i.set(A.botId,Bd("connection-failed",`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002`)),this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${A.botId} credential connection failed:`,c)}this.#u()}),this.status()}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#B(a,async()=>{let i=await this.#C(o.tokenRef);if(!i)throw new Error(`${this.#A.label} bot token is missing`);try{await this.#p(o,i),this.#i.delete(a)}catch(e){throw this.#i.set(a,Bd("connection-failed",`${this.#A.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),e}finally{this.#u()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#B(a,async()=>{let i=await this.#e.resolve(o.tokenRef).catch(()=>{});await this.#h(a);try{await this.#e.unset(o.tokenRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.tokenRef,i.value).catch(()=>{}),await this.#p(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#A.label} bot safely.`,{cause:e})}await this.#g({botId:a,config:o}).catch(e=>{this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${a} state cleanup failed:`,e)}),this.#i.delete(a),this.#u()}),this.status()}status(){let a=this.#t.list().map(i=>{let e=this.#r.get(i.botId)?.status??null,r=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=r?"connected":e?.connectionState==="connecting"?"connecting":this.#i.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:r,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#n(i.platformId)},health:{status:r?"healthy":A==="error"?"error":"offline",summary:r?`${this.#A.label}${this.#A.connectionLabel}\u8FD0\u884C\u6B63\u5E38`:A==="error"?`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5`:`${this.#A.label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF`,lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},error:structuredClone(this.#i.get(i.botId)??null)}}),o=a.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#I,state:a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o}}}async close(){this.#l||(this.#l=!0,await Promise.allSettled([...this.#o.values()]),await Promise.allSettled([...this.#r.keys()].map(a=>this.#h(a))))}async#p(a,o){if(this.#l)throw new Error(`${this.#A.label} controller is closed`);if(await this.#h(a.botId),this.#l)throw new Error(`${this.#A.label} controller is closed`);let i=await this.#E({botId:a.botId,config:a,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#A.label} runtime`);this.#r.set(a.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#r.delete(a.botId),e}}async#h(a){let o=this.#r.get(a);this.#r.delete(a),await o?.stop().catch(i=>{this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${a} failed to stop cleanly:`,i)})}async#C(a){let o=await this.#e.resolve(a).catch(()=>{});return BE(o?.value)}async#d(a,o){o?.value?await this.#e.set(a,o.value).catch(()=>{}):await this.#e.unset(a).catch(()=>{})}#B(a,o){let r=(this.#o.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#o.get(a)===r&&this.#o.delete(a)});return this.#o.set(a,r),r}#u(){this.#I+=1}};var NAe="https://discord.com/api/v10/";function QE(n){return typeof n=="string"&&n.trim()?n.trim():null}function TAe(n,a){let o=AbortSignal.timeout(a);return n?AbortSignal.any([n,o]):o}function RAe(n,a){return new Promise((o,i)=>{if(a?.aborted){i(a.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),a?.addEventListener("abort",()=>{clearTimeout(e),i(a.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function Fc(n,a){let o=QE(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${a}`);return o}function kAe(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var fE=class{#A;#e;#t;constructor({token:a,fetchImpl:o=fetch,baseUrl:i=NAe}){if(!kAe(a))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#A=a.trim(),this.#e=o,this.#t=new URL(i)}getCurrentUser(a={}){return this.#a("users/@me",{...a,method:"GET"})}getGatewayBot(a={}){return this.#a("gateway/bot",{...a,method:"GET"})}createMessage({channelId:a,content:o,replyToMessageId:i,signal:e}){return this.#a(`channels/${Fc(a,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:Fc(i,"message id"),channel_id:Fc(a,"channel id"),fail_if_not_exists:!1}}:{}}})}editMessage({channelId:a,messageId:o,content:i,signal:e}){return this.#a(`channels/${Fc(a,"channel id")}/messages/${Fc(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:a,signal:o}){return this.#a(`channels/${Fc(a,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async#a(a,{method:o,body:i,signal:e,timeoutMs:r=15e3,expectBody:A=!0,retry:t=!0}){let s;try{s=await this.#e(new URL(a,this.#t),{method:o,headers:{authorization:`Bot ${this.#A}`,"content-type":"application/json","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.7.1)"},...i===void 0?{}:{body:JSON.stringify(i)},signal:TAe(e,r),redirect:"error"})}catch(c){throw c?.name==="AbortError"||c?.name==="TimeoutError"?c:new Error(`Discord ${o} transport failed`)}let g=null;if(A||s.status===429||!s.ok)try{g=await s.json()}catch{if(A)throw new Error(`Discord ${o} returned invalid JSON`)}if(s.status===429&&t){let c=Math.min(1e4,Math.max(50,Number(g?.retry_after)*1e3||1e3));return await RAe(c,e),this.#a(a,{method:o,body:i,signal:e,timeoutMs:r,expectBody:A,retry:!1})}if(!s.ok){let c=new Error(QE(g?.message)??`Discord API failed with HTTP ${s.status}`);throw c.code=`discord-${s.status}`,c}return A?g:null}};async function FP(n,a={}){let i=await new fE({token:n,...a}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:QE(i.global_name)??QE(i.username)??"Discord\u673A\u5668\u4EBA",username:QE(i.username)}}var LP="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002";function mi(n){return typeof n=="string"?n.trim():""}function vAe(n,a,o){return a.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!!mi(n.content)}function Or(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var eo=class{#A;#e;#t;#a;#s;#n;#E;#g;#c=new Map;#r=new Map;#i=new Map;#o=new Set;#I=new Set;#l;constructor({descriptor:a,bot:o,harness:i,state:e,status:r=Or(),logger:A=console,replyTimeoutMs:t=6e5,signal:s}){if(!a?.key||!a?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#l=new nr({label:a.key,logger:A})}get status(){return structuredClone(this.#s)}accept(a){if(this.#g?.aborted)return Promise.resolve();let o=mi(a?.conversationId),i=a?.kind==="group"?"group":"direct",e={...a,kind:i,conversationId:o},r=mi(e.messageId),A=mi(e.senderId);if(!r||!A||!o||e.senderIsBot===!0||this.#a.hasSeen(r)||this.#o.has(r))return Promise.resolve();this.#o.add(r);let t=`${i}:${o}`,s=this.#r.get(t),g=this.#l.claimReply({key:t,actor:A,messageId:r,text:e.content,addressed:e.kind!=="group"||e.addressed===!0,hasPendingQuestion:!!s,questionCompletion:s?.submitting||s?.claimedReplyMessageId?s.queue:null,isQuestionPending:()=>this.#r.has(t),send:c=>this.#e.sendText(e.replyTarget,c)});if(g){let c;return c=g.process(async()=>this.#a.hasSeen(r)?!1:(await this.#a.markSeen(r),this.#s.messagesReceived+=1,this.#s.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#o.delete(r),this.#I.delete(c)}),this.#I.add(c),c}if(s&&s.actor!==A)return this.#p(e,r,A,t);if(s?.submitting||s?.claimedReplyMessageId)return this.#p(e,r,A,t);if(s){vAe(e,s,A)&&(s.claimedReplyMessageId=r);let l=(s.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#C(e,r,A,t,s)).finally(()=>{this.#o.delete(r),s.claimedReplyMessageId===r&&(s.claimedReplyMessageId=null),s.queue===l&&(s.queue=null)});return s.queue=l,l}return this.#p(e,r,A,t)}#p(a,o,i,e,{releaseMessageId:r=!0,alreadyRecorded:A=!1}={}){let s=(this.#c.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#h(a,o,i,e,{alreadyRecorded:A})).finally(()=>{r&&this.#o.delete(o),this.#c.get(e)===s&&this.#c.delete(e)});return this.#c.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#c.values(),...[...this.#r.values()].flatMap(a=>a.queue?[a.queue]:[]),...this.#I])}async#h(a,o,i,e,{alreadyRecorded:r=!1}={}){if(!r){if(this.#a.hasSeen(o))return;await this.#a.markSeen(o),this.#s.messagesReceived+=1,this.#s.lastMessageAt=new Date().toISOString()}let A=a.replyTarget,t=mi(a.content),s=null;try{if(this.#g?.throwIfAborted(),a.kind==="group"&&a.addressed!==!0){this.#s.messagesRejected+=1,this.#s.lastRejectedAt=new Date().toISOString();return}if(!t){await this.#e.sendText(A,"\u76EE\u524D\u4EC5\u652F\u6301\u6587\u5B57\u6D88\u606F\u3002");return}let g=t.toLowerCase();if(g==="/help"){await this.#e.sendText(A,[`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002`,"","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/workspace \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A","/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84","/sessionlist [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898","/session Session ID \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` +`,{encoding:"utf8",mode:384}),await OAe(o,this.#A)}};var vP=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function PP(n){return uE(n,vP)}function GP(n){return dd(n,"Discord\u673A\u5668\u4EBA")}var ud=class extends Pc{constructor(a){super(a,{channel:"Discord",...vP})}};function BE(n){return typeof n=="string"&&n.trim()?n.trim():null}function Bd(n,a){return Object.freeze({code:n,message:a})}var Gc=class{#A;#e;#t;#a;#s;#n;#E;#g;#c;#r=new Map;#i=new Map;#o=new Map;#I=0;#l=!1;constructor({descriptor:a,credentials:o,configStore:i,inspectToken:e,deriveIdentity:r,maskPlatformId:A,createRuntime:t,deleteState:s=async()=>{},logger:g=console}){if(!a?.key||!a?.label||!a?.connectionLabel)throw new TypeError("TokenBotController requires a channel descriptor");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError(`${a.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${a.label} requires a config store`);if(typeof e!="function"||typeof r!="function"||typeof A!="function"||typeof t!="function")throw new TypeError(`${a.label} controller dependencies are incomplete`);this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#c=g}async initialize(){if(this.#l)return this.status();for(let a of this.#t.list())await this.#B(a.botId,async()=>{if(this.#l||this.#r.get(a.botId)?.status?.ready)return;let o=await this.#C(a.tokenRef);if(!o){this.#i.set(a.botId,Bd("missing-token",`${this.#A.label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002`));return}try{await this.#p(a,o),this.#i.delete(a.botId)}catch(i){this.#i.set(a.botId,Bd("connection-failed",`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002`)),this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${a.botId} failed to initialize:`,i)}finally{this.#u()}});return this.status()}async bindCredentials({token:a}={}){if(this.#l)throw new Error(`${this.#A.label} controller is closed`);let o=BE(a);if(!o)throw new TypeError(`${this.#A.label} Bot Token is required`);let i=await this.#a(o),e=BE(i?.platformId),r=BE(i?.name);if(!e||!r)throw new Error(`${this.#A.label} returned an invalid bot identity`);let A=this.#s(e);return await this.#B(A.botId,async()=>{if(this.#l)throw new Error(`${this.#A.label} controller is closed`);let t=this.#t.getByPlatformId(e),s=await this.#e.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:r,username:BE(i.username),createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#e.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#d(A.tokenRef,s),c}try{await this.#p(g,o),this.#i.delete(A.botId)}catch(c){this.#i.set(A.botId,Bd("connection-failed",`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002`)),this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${A.botId} credential connection failed:`,c)}this.#u()}),this.status()}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#B(a,async()=>{let i=await this.#C(o.tokenRef);if(!i)throw new Error(`${this.#A.label} bot token is missing`);try{await this.#p(o,i),this.#i.delete(a)}catch(e){throw this.#i.set(a,Bd("connection-failed",`${this.#A.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),e}finally{this.#u()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error(`Unknown ${this.#A.label} bot`);return await this.#B(a,async()=>{let i=await this.#e.resolve(o.tokenRef).catch(()=>{});await this.#h(a);try{await this.#e.unset(o.tokenRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.tokenRef,i.value).catch(()=>{}),await this.#p(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#A.label} bot safely.`,{cause:e})}await this.#g({botId:a,config:o}).catch(e=>{this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${a} state cleanup failed:`,e)}),this.#i.delete(a),this.#u()}),this.status()}status(){let a=this.#t.list().map(i=>{let e=this.#r.get(i.botId)?.status??null,r=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=r?"connected":e?.connectionState==="connecting"?"connecting":this.#i.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:r,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#n(i.platformId)},health:{status:r?"healthy":A==="error"?"error":"offline",summary:r?`${this.#A.label}${this.#A.connectionLabel}\u8FD0\u884C\u6B63\u5E38`:A==="error"?`${this.#A.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5`:`${this.#A.label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF`,lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},error:structuredClone(this.#i.get(i.botId)??null)}}),o=a.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#I,state:a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o}}}async close(){this.#l||(this.#l=!0,await Promise.allSettled([...this.#o.values()]),await Promise.allSettled([...this.#r.keys()].map(a=>this.#h(a))))}async#p(a,o){if(this.#l)throw new Error(`${this.#A.label} controller is closed`);if(await this.#h(a.botId),this.#l)throw new Error(`${this.#A.label} controller is closed`);let i=await this.#E({botId:a.botId,config:a,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#A.label} runtime`);this.#r.set(a.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#r.delete(a.botId),e}}async#h(a){let o=this.#r.get(a);this.#r.delete(a),await o?.stop().catch(i=>{this.#c.warn?.(`[dsh-im:${this.#A.key}] bot ${a} failed to stop cleanly:`,i)})}async#C(a){let o=await this.#e.resolve(a).catch(()=>{});return BE(o?.value)}async#d(a,o){o?.value?await this.#e.set(a,o.value).catch(()=>{}):await this.#e.unset(a).catch(()=>{})}#B(a,o){let r=(this.#o.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#o.get(a)===r&&this.#o.delete(a)});return this.#o.set(a,r),r}#u(){this.#I+=1}};var NAe="https://discord.com/api/v10/";function QE(n){return typeof n=="string"&&n.trim()?n.trim():null}function TAe(n,a){let o=AbortSignal.timeout(a);return n?AbortSignal.any([n,o]):o}function RAe(n,a){return new Promise((o,i)=>{if(a?.aborted){i(a.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),a?.addEventListener("abort",()=>{clearTimeout(e),i(a.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function Fc(n,a){let o=QE(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${a}`);return o}function kAe(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var fE=class{#A;#e;#t;constructor({token:a,fetchImpl:o=fetch,baseUrl:i=NAe}){if(!kAe(a))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#A=a.trim(),this.#e=o,this.#t=new URL(i)}getCurrentUser(a={}){return this.#a("users/@me",{...a,method:"GET"})}getGatewayBot(a={}){return this.#a("gateway/bot",{...a,method:"GET"})}createMessage({channelId:a,content:o,replyToMessageId:i,signal:e}){return this.#a(`channels/${Fc(a,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:Fc(i,"message id"),channel_id:Fc(a,"channel id"),fail_if_not_exists:!1}}:{}}})}editMessage({channelId:a,messageId:o,content:i,signal:e}){return this.#a(`channels/${Fc(a,"channel id")}/messages/${Fc(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:a,signal:o}){return this.#a(`channels/${Fc(a,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async#a(a,{method:o,body:i,signal:e,timeoutMs:r=15e3,expectBody:A=!0,retry:t=!0}){let s;try{s=await this.#e(new URL(a,this.#t),{method:o,headers:{authorization:`Bot ${this.#A}`,"content-type":"application/json","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.7.2)"},...i===void 0?{}:{body:JSON.stringify(i)},signal:TAe(e,r),redirect:"error"})}catch(c){throw c?.name==="AbortError"||c?.name==="TimeoutError"?c:new Error(`Discord ${o} transport failed`)}let g=null;if(A||s.status===429||!s.ok)try{g=await s.json()}catch{if(A)throw new Error(`Discord ${o} returned invalid JSON`)}if(s.status===429&&t){let c=Math.min(1e4,Math.max(50,Number(g?.retry_after)*1e3||1e3));return await RAe(c,e),this.#a(a,{method:o,body:i,signal:e,timeoutMs:r,expectBody:A,retry:!1})}if(!s.ok){let c=new Error(QE(g?.message)??`Discord API failed with HTTP ${s.status}`);throw c.code=`discord-${s.status}`,c}return A?g:null}};async function FP(n,a={}){let i=await new fE({token:n,...a}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:QE(i.global_name)??QE(i.username)??"Discord\u673A\u5668\u4EBA",username:QE(i.username)}}var LP="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002";function mi(n){return typeof n=="string"?n.trim():""}function vAe(n,a,o){return a.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!!mi(n.content)}function Or(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var eo=class{#A;#e;#t;#a;#s;#n;#E;#g;#c=new Map;#r=new Map;#i=new Map;#o=new Set;#I=new Set;#l;constructor({descriptor:a,bot:o,harness:i,state:e,status:r=Or(),logger:A=console,replyTimeoutMs:t=6e5,signal:s}){if(!a?.key||!a?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#l=new nr({label:a.key,logger:A})}get status(){return structuredClone(this.#s)}accept(a){if(this.#g?.aborted)return Promise.resolve();let o=mi(a?.conversationId),i=a?.kind==="group"?"group":"direct",e={...a,kind:i,conversationId:o},r=mi(e.messageId),A=mi(e.senderId);if(!r||!A||!o||e.senderIsBot===!0||this.#a.hasSeen(r)||this.#o.has(r))return Promise.resolve();this.#o.add(r);let t=`${i}:${o}`,s=this.#r.get(t),g=this.#l.claimReply({key:t,actor:A,messageId:r,text:e.content,addressed:e.kind!=="group"||e.addressed===!0,hasPendingQuestion:!!s,questionCompletion:s?.submitting||s?.claimedReplyMessageId?s.queue:null,isQuestionPending:()=>this.#r.has(t),send:c=>this.#e.sendText(e.replyTarget,c)});if(g){let c;return c=g.process(async()=>this.#a.hasSeen(r)?!1:(await this.#a.markSeen(r),this.#s.messagesReceived+=1,this.#s.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#o.delete(r),this.#I.delete(c)}),this.#I.add(c),c}if(s&&s.actor!==A)return this.#p(e,r,A,t);if(s?.submitting||s?.claimedReplyMessageId)return this.#p(e,r,A,t);if(s){vAe(e,s,A)&&(s.claimedReplyMessageId=r);let l=(s.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#C(e,r,A,t,s)).finally(()=>{this.#o.delete(r),s.claimedReplyMessageId===r&&(s.claimedReplyMessageId=null),s.queue===l&&(s.queue=null)});return s.queue=l,l}return this.#p(e,r,A,t)}#p(a,o,i,e,{releaseMessageId:r=!0,alreadyRecorded:A=!1}={}){let s=(this.#c.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#h(a,o,i,e,{alreadyRecorded:A})).finally(()=>{r&&this.#o.delete(o),this.#c.get(e)===s&&this.#c.delete(e)});return this.#c.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#c.values(),...[...this.#r.values()].flatMap(a=>a.queue?[a.queue]:[]),...this.#I])}async#h(a,o,i,e,{alreadyRecorded:r=!1}={}){if(!r){if(this.#a.hasSeen(o))return;await this.#a.markSeen(o),this.#s.messagesReceived+=1,this.#s.lastMessageAt=new Date().toISOString()}let A=a.replyTarget,t=mi(a.content),s=null;try{if(this.#g?.throwIfAborted(),a.kind==="group"&&a.addressed!==!0){this.#s.messagesRejected+=1,this.#s.lastRejectedAt=new Date().toISOString();return}if(!t){await this.#e.sendText(A,"\u76EE\u524D\u4EC5\u652F\u6301\u6587\u5B57\u6D88\u606F\u3002");return}let g=t.toLowerCase();if(g==="/help"){await this.#e.sendText(A,[`${this.#A.label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002`,"","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/workspace \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A","/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84","/sessionlist [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898","/session Session ID \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` `));return}if(g==="/status"){await this.#t.ensureRunning({signal:this.#g}),await this.#e.sendText(A,`${this.#A.label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002`);return}let c=await xr(t,this.#t,e);if(c){for(let B of c.messages??[c.message])await this.#e.sendText(A,B);return}if(g==="/new"){await this.#a.clearSession(e),await this.#e.sendText(A,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002");return}await this.#e.sendTyping?.(A).catch(B=>{this.#n.warn?.(`[dsh-im:${this.#A.key}] typing indicator failed:`,B)});let l=!1;if(typeof this.#e.openStream=="function")try{s=await this.#e.openStream(A)}catch(B){this.#n.warn?.(`[dsh-im:${this.#A.key}] unable to start a streamed reply; using text:`,B)}let{answer:C}=await sr({harness:this.#t,state:this.#a,key:e,text:t,createOptions:this.#g?{signal:this.#g}:void 0,existsOptions:this.#g?{signal:this.#g}:void 0,askOptions:{timeoutMs:this.#E,signal:this.#g,onUpdate:s?async B=>{let Q=B.type==="text"?B.text:B.type==="tool"?`\u6B63\u5728\u4F7F\u7528${B.name}\u2026`:B.text;Q&&await s.update(Q)}:void 0,onInteraction:B=>this.#d(B,{key:e,actor:i,target:A,requiresMention:a.kind==="group"}),onInteractionResolved:B=>this.#B(B)}});if(s)try{await s.finish(C),l=!0}catch(B){s.cancel?.(),this.#n.warn?.(`[dsh-im:${this.#A.key}] streamed reply finalization failed; using text:`,B)}l||await this.#e.sendText(A,C),this.#s.messagesReplied+=1,this.#s.lastReplyAt=new Date().toISOString(),this.#s.lastError=null}catch(g){if(s?.cancel?.(),this.#g?.aborted)return;this.#s.lastError=g?.message??String(g),this.#n.error?.(`[dsh-im:${this.#A.key}] failed to process a message:`,g);try{await this.#e.sendText(A,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}catch(c){this.#n.error?.(`[dsh-im:${this.#A.key}] failed to send the safe error reply:`,c)}}finally{await Promise.allSettled([this.#m(e),this.#l.closeRoute(e)])}}async#C(a,o,i,e,r){if(this.#g?.aborted)return;let A=this.#r.get(e),t=r.claimedReplyMessageId===o;if(!A||A!==r||A.submitting)return t&&(!A||A!==r)?this.#Q(a,o):this.#p(a,o,i,e,{releaseMessageId:!1});if(this.#a.hasSeen(o))return;if(await this.#a.markSeen(o),this.#s.messagesReceived+=1,this.#s.lastMessageAt=new Date().toISOString(),a.kind==="group"&&a.addressed!==!0){this.#s.messagesRejected+=1,this.#s.lastRejectedAt=new Date().toISOString();return}let s=a.replyTarget,g=mi(a.content);if(!g){try{await this.#e.sendText(s,"\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002")}catch(C){this.#n.error?.(`[dsh-im:${this.#A.key}] failed to reject a non-text interaction reply:`,C)}return}let c=this.#r.get(e);if(!c||c!==r||c.submitting)return t&&(!c||c!==r)?this.#Q(a,o,{alreadyRecorded:!0}):this.#p(a,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0});if(c.target=s,c.needsPresentation){let C=c.presentationTask!==null;try{await this.#u(c)}catch(Q){this.#s.lastError=`${this.#A.label}\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002`,this.#n.error?.(`[dsh-im:${this.#A.key}] failed to retry an interaction question:`,Q),c.interaction.reconnect?.();return}let B=this.#r.get(e);if(!B||B!==r||B.submitting)return t&&(!B||B!==r)?this.#Q(a,o,{alreadyRecorded:!0}):this.#p(a,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0});if(!C)return}let l=c.questions[c.index];if(l){if(c.answers.push(Yr(l,g)),c.index+=1,c.indexthis.#e.sendText(e,c)});if(a?.kind!=="question")return;let A=a?.payload?.questions,t=mi(a?.interactionId)||mi(a?.rpcId);if(!mi(a?.rpcId)||!t||!mi(a?.sessionId)||!Array.isArray(A)||A.length===0||A.some(c=>!Hr(c))){this.#n.warn?.(`[dsh-im:${this.#A.key}] ignored an invalid Harness question interaction`);return}if(a.recovered===!0){await this.#D(a,`${this.#A.label} safely cancelled an interaction left by an earlier client.`);try{await this.#e.sendText(e,"\u68C0\u6D4B\u5230\u8FD9\u4E2A Session \u4E2D\u9057\u7559\u7684\u5F85\u56DE\u7B54\u95EE\u9898\uFF0C\u5DF2\u5B89\u5168\u53D6\u6D88\u5E76\u7EE7\u7EED\u5904\u7406\u4F60\u521A\u624D\u7684\u6D88\u606F\u3002")}catch(c){this.#n.error?.(`[dsh-im:${this.#A.key}] failed to send an interaction recovery notice:`,c)}return}let s=this.#r.get(o);if(s?.interactionId===t){s.interaction=a,s.needsPresentation&&await this.#u(s);return}if(this.#i.has(t))return;if(s){this.#n.warn?.(`[dsh-im:${this.#A.key}] cancelled a second pending Harness question`),await this.#D(a,`${this.#A.label} is already handling another user interaction.`);return}let g={kind:"question",interactionId:t,sessionId:a.sessionId,interaction:a,actor:i,requiresMention:r,questions:A,answers:[],index:0,target:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationTask:null};this.#r.set(o,g),this.#i.set(t,o),await this.#u(g)}async#B(a){if(a?.kind==="approval"){await this.#l.handleResolved(a);return}let o=mi(a?.interactionId);if(a?.kind!=="question"||!o)return;let i=this.#i.get(o);i&&this.#f(i,o)}#u(a){if(a.presentationTask)return a.presentationTask;let o=a.questions[a.index];if(!o)return Promise.resolve();let i=(async()=>{await this.#e.sendText(a.target,Kr(o,a.index,a.questions.length,{requiresMention:a.requiresMention})),a.needsPresentation=!1})();return a.presentationTask=i,i.then(()=>{a.presentationTask===i&&(a.presentationTask=null)},()=>{a.presentationTask===i&&(a.presentationTask=null)}),i}async#Q(a,o,{alreadyRecorded:i=!1}={}){if(!i){if(this.#a.hasSeen(o))return;await this.#a.markSeen(o),this.#s.messagesReceived+=1,this.#s.lastMessageAt=new Date().toISOString()}try{await this.#e.sendText(a.replyTarget,LP)}catch(e){this.#n.error?.(`[dsh-im:${this.#A.key}] failed to send an expired interaction notice:`,e)}}#y(a,o){let i=this.#r.get(a);return!i||o!==void 0&&i.interactionId!==o?null:(this.#r.delete(a),this.#i.delete(i.interactionId),i)}#f(a,o){return this.#y(a,o)!==null}async#D(a,o){try{await a.respond({ok:!1,error:{code:"cancelled",message:o,details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){if(i?.code!=="interaction-not-pending")throw i}}async#m(a){let o=this.#y(a);if(!(!o||o.kind!=="question"))try{await this.#D(o.interaction,`The ${this.#A.label} interaction ended before the user answered.`)}catch(i){this.#n.warn?.(`[dsh-im:${this.#A.key}] failed to cancel a pending Harness interaction:`,i)}}};var JS=Object.freeze({key:"discord",label:"Discord",connectionLabel:" Gateway \u957F\u8FDE\u63A5"}),Qd=class extends eo{constructor(a){super({descriptor:JS,...a})}};var yE=class extends Gc{constructor(a){super({...a,descriptor:JS,inspectToken:a.inspectToken??FP,deriveIdentity:PP,maskPlatformId:GP})}};var fd=class extends Kt{constructor(a){super({...a,rpcIdPrefix:"discord",logPrefix:"dsh-discord"})}};function qr(n,a){let o=typeof n=="string"?n.trim():"";if(!o)return[];let i=[],e=o;for(;e.length>a;){let r=e.lastIndexOf(` `,a);r{l||g!==null||c||!s||(g=setTimeout(()=>{g=null;let Q=s;s=null;let f=qr(Q,a)[0]??n;c=Promise.resolve(f===C?void 0:e(t,f)).then(()=>{C=f}).catch(y=>A.warn?.("[dsh-im] streamed message update failed:",y)).finally(()=>{c=null,B()})},o),g?.unref?.())};return{async start(){return t=await i(n),this},update(Q){l||typeof Q!="string"||!Q.trim()||(s=Q,B())},async finish(Q){if(l)throw new Error("Message stream is already closed");l=!0,g!==null&&clearTimeout(g),g=null,s=null,await c?.catch(()=>{});let f=qr(Q,a),y=f[0]??"\u5904\u7406\u5B8C\u6210\u3002";y!==C&&await e(t,y),C=y;for(let m of f.slice(1))await r(m)},cancel(){l=!0,s=null,g!==null&&clearTimeout(g),g=null}}}var PAe=4609,UP=Object.freeze([1e3,3e3,5e3,1e4,3e4]);function GAe(n){let a=new URL(n);if(a.protocol!=="wss:")throw new Error("Discord returned an insecure Gateway URL");return a.searchParams.set("v","10"),a.searchParams.set("encoding","json"),a.href}function qS(n,a,o){if(typeof n.addEventListener=="function")n.addEventListener(a,o);else if(typeof n.on=="function")n.on(a,o);else throw new TypeError("Discord WebSocket does not support events")}function FAe(n){return typeof n=="string"?n:typeof n?.data=="string"?n.data:Buffer.isBuffer(n)?n.toString("utf8"):Buffer.isBuffer(n?.data)?n.data.toString("utf8"):null}function LAe(n){if(n===4004){let o=new Error("Discord Bot Token \u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u586B\u5199\u3002");return o.code="discord-401",o}if(n===4013||n===4014){let o=new Error("Discord Gateway Intents \u914D\u7F6E\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5 Developer Portal \u7684 Bot \u8BBE\u7F6E\u3002");return o.code="discord-intents",o}let a=new Error(`Discord Gateway closed (${n||"unknown"})`);return a.code="discord-gateway-closed",a}function UAe(n,a){return typeof n!="string"?"":n.replace(new RegExp(`<@!?${a}>`,"g"),"").trim()}function HAe(n,a){if(!n?.id||!n?.channel_id||!n?.author?.id)return null;let o=!n.guild_id,i=o||n.mentions?.some(e=>String(e?.id)===String(a));return{messageId:String(n.id),senderId:String(n.author.id),senderIsBot:n.author.bot===!0,kind:o?"direct":"group",conversationId:String(n.channel_id),content:UAe(n.content??"",a),addressed:i,replyTarget:{channelId:String(n.channel_id),replyToMessageId:String(n.id)}}}var VS=class{#A;#e;constructor({api:a,signal:o}){this.#A=a,this.#e=o}async sendText(a,o){let i=qr(o,1900),e=null;for(let[r,A]of i.entries())e=await this.#A.createMessage({channelId:a.channelId,content:A,replyToMessageId:r===0?a.replyToMessageId:void 0,signal:this.#e});return e}sendTyping(a){return this.#A.sendTyping({channelId:a.channelId,signal:this.#e})}async openStream(a){return yd({limit:1900,create:async i=>(await this.#A.createMessage({channelId:a.channelId,content:i,replyToMessageId:a.replyToMessageId,signal:this.#e})).id,edit:(i,e)=>this.#A.editMessage({channelId:a.channelId,messageId:i,content:e,signal:this.#e}),sendRemainder:i=>this.#A.createMessage({channelId:a.channelId,content:i,signal:this.#e})}).start()}};function KAe(){return{startedAt:null,ready:!1,connectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...Or()}}var mE=class{#A;#e;#t;#a;#s;#n;#E;#g;#c;#r;#i=KAe();#o=null;#I=null;#l=null;#p=null;#h=null;#C=null;#d=null;#B=null;#u=null;#Q=!0;#y=null;#f=0;#D=0;#m=!0;#w=null;constructor({config:a,token:o,harness:i,state:e,logger:r=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,createApi:s=l=>new fE(l),createWebSocket:g=l=>new WebSocket(l),random:c=Math.random}){if(!a||!o||!i||!e)throw new TypeError("DiscordRuntime requires config, token, Harness, and state");if(typeof g!="function")throw new TypeError("DiscordRuntime requires WebSocket");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#c=g,this.#r=c}get status(){return structuredClone(this.#i)}async start(){return this.#i.ready&&this.#p?this.status:this.#w?this.#w:(this.#w=this.#N().finally(()=>{this.#w=null}),this.#w)}async#N(){await this.stop(),this.#m=!1,this.#d=null,this.#C=null,this.#B=null,this.#f=0,this.#i.startedAt=new Date().toISOString(),this.#i.connectionState="connecting",this.#i.lastError=null,await this.#t.ensureRunning(),this.#i.harnessReachable=!0;let a=new AbortController;this.#l=a;let o=this.#g({token:this.#e});this.#o=o;try{let[i,e]=await Promise.all([o.getCurrentUser({signal:a.signal}),o.getGatewayBot({signal:a.signal})]);if(String(i?.id??"")!==this.#A.platformId||i?.bot!==!0)throw new Error("Discord token identity does not match the saved bot");this.#h=e?.url;let r=new VS({api:o,signal:a.signal});this.#I=new Qd({bot:r,harness:this.#t,state:this.#a,status:this.#i,logger:this.#s,replyTimeoutMs:this.#n,signal:a.signal});let A;try{await Promise.race([this.#S(!1),new Promise((t,s)=>{A=setTimeout(()=>s(new Error("Discord Gateway did not become ready in time")),this.#E)})])}finally{clearTimeout(A)}return this.status}catch(i){throw this.#i.ready=!1,this.#i.connectionState="failed",this.#i.lastError=i?.message??String(i),await this.stop(),i}}#S(a){if(this.#m)return Promise.reject(new Error("Discord runtime is stopped"));let o=++this.#D,i=GAe(a&&this.#C?this.#C:this.#h),e=this.#c(i);this.#p=e;let r=!1;return new Promise((A,t)=>{let s=()=>{if(r||o!==this.#D)return;r=!0,this.#f=0;let g=Date.now();this.#i.ready=!0,this.#i.connectionState="connected",this.#i.lastCheckedAt=g,this.#i.lastConnectedAt=g,this.#i.lastError=null,A()};qS(e,"message",g=>{if(o!==this.#D||this.#m)return;let c=FAe(g);if(!c)return;let l;try{l=JSON.parse(c)}catch{this.#s.warn?.("[dsh-im:discord] ignored malformed Gateway JSON");return}if(Number.isSafeInteger(l.s)&&(this.#B=l.s),l.op===10){this.#M(l.d?.heartbeat_interval,e,o),a&&this.#d?this.#O(e,{op:6,d:{token:this.#e,session_id:this.#d,seq:this.#B}}):this.#O(e,{op:2,d:{token:this.#e,intents:PAe,properties:{os:process.platform,browser:"dsh-im",device:"dsh-im"}}});return}if(l.op===11){this.#Q=!0,this.#i.lastCheckedAt=Date.now();return}if(l.op===1){this.#F(e);return}if(l.op===7){e.close(4e3,"Reconnect requested");return}if(l.op===9){l.d!==!0&&(this.#d=null,this.#C=null,this.#B=null),e.close(4e3,"Invalid session");return}if(l.op===0){if(l.t==="READY")this.#d=l.d?.session_id??null,this.#C=l.d?.resume_gateway_url??null,s();else if(l.t==="RESUMED")s();else if(l.t==="MESSAGE_CREATE"){let C=HAe(l.d,this.#A.platformId),B=this.#I;C&&B&&B.accept(C).catch(Q=>{o!==this.#D||this.#m||this.#s.error?.(`[dsh-im:discord] bot ${this.#A.botId} message handling failed:`,Q)})}}}),qS(e,"close",(g={})=>{if(o!==this.#D)return;if(this.#T(),this.#p===e&&(this.#p=null),this.#m){r||t(new DOMException("Stopped","AbortError"));return}let c=LAe(Number(g.code)||0);if(this.#i.ready=!1,this.#i.connectionState="connecting",this.#i.lastError=c.message,r||(r=!0,t(c)),c.code==="discord-401"||c.code==="discord-intents"){this.#i.connectionState="failed";return}this.#L()}),qS(e,"error",()=>{o!==this.#D||this.#m||(this.#i.lastError="Discord Gateway WebSocket error")})})}#O(a,o){a.readyState===1&&a.send(JSON.stringify(o))}#M(a,o,i){if(this.#T(),!Number.isFinite(a)||a<1e3){o.close(4e3,"Invalid heartbeat interval");return}this.#Q=!0;let e=r=>{this.#u=setTimeout(()=>{if(!(this.#m||i!==this.#D||this.#p!==o)){if(!this.#Q){o.close(4e3,"Heartbeat was not acknowledged");return}this.#F(o),e(a)}},r),this.#u?.unref?.()};e(Math.floor(a*this.#r()))}#F(a){this.#Q=!1,this.#O(a,{op:1,d:this.#B})}#T(){this.#u!==null&&clearTimeout(this.#u),this.#u=null,this.#Q=!0}#L(){if(this.#m||this.#y!==null)return;let a=UP[Math.min(this.#f,UP.length-1)];this.#f+=1,this.#y=setTimeout(()=>{this.#y=null,this.#S(!!this.#d).catch(o=>{this.#m||(this.#s.warn?.("[dsh-im:discord] Gateway reconnect failed:",o),this.#L())})},a),this.#y?.unref?.()}async stop(){this.#m=!0,this.#D+=1,this.#l?.abort(),this.#l=null,this.#y!==null&&clearTimeout(this.#y),this.#y=null,this.#T();let a=this.#p,o=this.#I;this.#p=null,this.#I=null,this.#o=null;try{a&&a.readyState<2&&a.close(1e3,"Plugin stopped")}catch(i){this.#s.warn?.(`[dsh-im:discord] bot ${this.#A.botId} failed to close Gateway:`,i)}return await Promise.race([o?.waitForIdle()??Promise.resolve(),new Promise(i=>setTimeout(i,2e3))]),this.#i.ready=!1,this.#i.connectionState="idle",this.status}};import{mkdir as YAe,readFile as xAe,rename as jAe,unlink as JAe,writeFile as qAe}from"node:fs/promises";import{dirname as VAe}from"node:path";var md=Object.freeze({version:1,sessions:{},seenMessageIds:[],cursor:null});function zAe(n){if(!n||typeof n!="object")return structuredClone(md);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[o,i]of Object.entries(n.sessions))typeof o=="string"&&o&&typeof i=="string"&&i&&(a[o]=i);return{version:1,sessions:a,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string"&&o).slice(-1e3):[],cursor:Number.isSafeInteger(n.cursor)&&n.cursor>=0?n.cursor:null}}var Ao=class{#A;#e=structuredClone(md);#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{this.#e=zAe(JSON.parse(await xAe(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(md),await this.#a()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){this.#e.sessions[a]=o,await this.#a()}async clearSession(a){delete this.#e.sessions[a],await this.#a()}async clearSessions(){this.#e.sessions={},await this.#a()}hasSeen(a){return this.#e.seenMessageIds.includes(a)}async markSeen(a){this.hasSeen(a)||(this.#e.seenMessageIds.push(a),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#a())}cursor(){return this.#e.cursor}async setCursor(a){if(!Number.isSafeInteger(a)||a<0)throw new TypeError("Invalid update cursor");this.#e.cursor=a,await this.#a()}snapshot(){return structuredClone(this.#e)}async remove(){try{await JAe(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(md)}async#a(){let a=`${JSON.stringify(this.#e,null,2)} `,o=this.#t.then(async()=>{await YAe(VAe(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await qAe(i,a,{encoding:"utf8",mode:384}),await jAe(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};var Sd=class extends Ao{};import{unlink as ZAe}from"node:fs/promises";import{homedir as XAe}from"node:os";import{join as SE,resolve as $s}from"node:path";var HP=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function WAe(n){if(!Array.isArray(n)||n.length===0)return[...HP];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...HP]}var zS=class{#A;#e;#t;#a;#s;#n;#E;#g;#c=null;#r=null;#i=0;#o=!1;#I=!1;#l;#p;constructor({channel:a,controller:o,harness:i,logger:e=console,retryDelaysMs:r,healthyIntervalMs:A=15e3,setTimeoutImpl:t=setTimeout,clearTimeoutImpl:s=clearTimeout}){if(!a)throw new TypeError("TokenConnectionSupervisor requires a channel");if(!o||typeof o.initialize!="function"||typeof o.status!="function")throw new TypeError("TokenConnectionSupervisor requires a controller");if(!i||typeof i.ensureRunning!="function")throw new TypeError("TokenConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=WAe(r),this.#n=Number.isFinite(A)&&A>=0?A:15e3,this.#E=t,this.#g=s,this.#l=new Promise(g=>{this.#p=g})}get ready(){return this.#l}start(){return this.#I||this.#o?this:(this.#I=!0,this.#h(0),this)}async close(){this.#o||(this.#o=!0,this.#c!==null&&this.#g(this.#c),this.#c=null,await this.#r?.catch(()=>{}),this.#p?.(null),this.#p=null)}#h(a){this.#o||(this.#c=this.#E(()=>{this.#c=null,this.#C()},a),this.#c?.unref?.())}async#C(){if(this.#o||this.#r)return;let a=this.#d();this.#r=a;try{await a}finally{this.#r===a&&(this.#r=null)}}async#d(){try{if(await this.#t.ensureRunning(),this.#o)return;let a=await this.#e.initialize();if(this.#o)return;this.#p?.(a),this.#p=null;let{configured:o,connected:i}=a.totals;if(i65535)throw new Error("dsh-im token channel requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function ZS(n,a){let o=$s(n.dshHome??process.env.DSH_HOME??SE(XAe(),".dsh")),i=$s(n.dataDir??SE(o,"integrations",`dsh-${a}`));return{config:$s(n.configPath??SE(i,"config.json")),bots:$s(n.botsDir??SE(i,"bots")),workspaces:$s(n.workspacesPath??SE(i,"workspaces.json"))}}async function Dd(n,a,o,i){let{channel:e,ConfigStore:r,StateStore:A,HarnessClient:t,Controller:s,Runtime:g}=i;if(!n?.credentials)throw new TypeError(`dsh-im ${e} requires ctx.credentials`);if(!n?.webServer)throw new TypeError(`dsh-im ${e} requires ctx.webServer`);let c=o.ConfigStore??r,l=o.StateStore??A,C=o.HarnessClient??t,B=o.Controller??s,Q=o.Runtime??g,f=o.createConnectionSupervisor??Lc,y=typeof n.logger=="function"?n.logger(`dsh-im:${e}`):n.logger??console,m=ZS(a,e),T=await new c(m.config).load(),k=$s(a.workspace??process.cwd()),F=o.WorkspaceStore??Ia,j=o.workspaces??await new F(m.workspaces,{defaultWorkspace:k}).load(),x=T.list();await j.reconcile(x.map(L=>L.botId)),await Promise.all(x.map(L=>j.ensure(L.botId)));let H=typeof T.remove=="function"?Ua(T,{workspaces:j}):T,J=new Map,K=L=>$s(m.bots,L,"state.json"),G=async L=>{let ee=J.get(L);return ee||(ee=await new l(K(L)).load(),J.set(L,ee)),ee},R=new C({baseUrl:WS(n.webServer,a.harnessBaseUrl),workspace:k,agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),Z=new B({credentials:n.credentials,configStore:H,logger:y,...o.inspectToken?{inspectToken:o.inspectToken}:{},createRuntime:async({botId:L,config:ee,token:fe})=>{let Se=await G(L);await j.ensure(L);let Le=Ha(R,{botId:L,workspaces:j,state:Se});return new Q({config:ee,token:fe,harness:Le.harness,state:Le.state,replyTimeoutMs:a.replyTimeoutMs??6e5,connectTimeoutMs:a.connectTimeoutMs??2e4,logger:{error:(...we)=>y.error?.(`[${L}]`,...we),warn:(...we)=>y.warn?.(`[${L}]`,...we),info:(...we)=>y.info?.(`[${L}]`,...we),debug:(...we)=>y.debug?.(`[${L}]`,...we)}})},deleteState:async({botId:L})=>{let ee=J.get(L);if(J.delete(L),ee&&typeof ee.remove=="function")await ee.remove();else try{await ZAe(K(L))}catch(fe){if(fe?.code!=="ENOENT")throw fe}}}),U=Ka(Z,{workspaces:j,stateFor:G}),b=f({channel:e,controller:U,harness:R,logger:y,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:U,ready:b.ready,async close(){await b.close(),await U.close(),R.stopManagedProcess()}}}function XS(n,a={},o={}){return Dd(n,a,o,{channel:"discord",ConfigStore:ud,StateStore:Sd,HarnessClient:fd,Controller:yE,Runtime:mE})}var Ir=Object.freeze({status:"connection.status",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:cr}),$Ae=Object.freeze(Object.values(Ir)),ete=new Set(["token","botToken","tokenRef","platformId","secret","secretRef"]);function eD(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function wd(n,a){return eD(n)&&Object.keys(n).every(o=>a.includes(o))}function KP(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function Ate(n){return typeof n=="string"&&n.trim().length>=20&&n.length<=4096}function tte(n,a){return eD(a)?n===Ir.status?wd(a,[])?null:"connection.status does not accept fields.":n===Ir.bindCredentials?wd(a,["token"])&&Ate(a.token)?null:"bot.bind-credentials requires a Bot Token.":n===Ir.reconnectBot?wd(a,["botId"])&&KP(a.botId)?null:"bot.reconnect requires a botId.":n===Ir.deleteBot?wd(a,["botId","confirm"])&&KP(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===Ir.setWorkspace?xa(a)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Unknown bot endpoint.":"Payload must be an object."}function $S(n){if(Array.isArray(n))return n.map($S);if(!eD(n))return n;let a={};for(let[o,i]of Object.entries(n))ete.has(o)||(a[o]=$S(i));return a}function ate(n,a){let o=ja(a);return o||(a?.code==="webhook-configured"?{code:"webhook-configured",message:a.message}:a?.code==="telegram-401"||a?.code==="discord-401"?{code:"invalid-token",message:`${n} Bot Token \u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u586B\u5199\u3002`}:a?.code==="discord-intents"?{code:"discord-intents",message:a.message}:{code:`${n.toLowerCase()}-operation-failed`,message:`${n} \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`})}function AD(n,{channel:a}){for(let o of["status","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[o]!="function")throw new TypeError(`A complete ${a} controller is required (${o})`);return async(o,i,e)=>{if(e?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!$Ae.includes(o))return{ok:!1,error:{code:"bad-request",message:`Unknown ${a} endpoint.`}};let r=tte(o,i);if(r)return{ok:!1,error:{code:"bad-request",message:r}};try{let A;if(o===Ir.status)A=await n.status();else if(o===Ir.bindCredentials)A=await n.bindCredentials(i);else if(o===Ir.reconnectBot)A=await n.reconnectBot(i.botId);else if(o===Ir.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");A=await n.updateWorkspace(i.botId,i.workspace)}else A=await n.deleteBot(i.botId);return e?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:$S(A)}}catch(A){return e?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:ate(a,A)}}}}function Od(n,a,{channel:o,rpcChannel:i,authority:e}){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(i,AD(a,{channel:o}),{authority:Ya(e)})}var YP="/discord",xP=Ir,rte=Object.freeze(Object.values(xP));function Md(n,a,o){return Od(n,a,{channel:"Discord",rpcChannel:YP,authority:o})}async function jP(n,a={}){if(a?.controller)return Md(n,a.controller,a.rpcAuthority);let o=await XS(n,a,a.internals??{}),i=Md(n,o.controller,a.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Discord bot connections"),i}var ite=new Set(["starting","qr_ready","polling","slow_down","domain_switched"]);function ote(n){let a=n?.client_id??n?.appId,o=n?.client_secret??n?.appSecret;if(typeof a!="string"||a.length===0||typeof o!="string"||o.length===0)throw new TypeError("Feishu registration returned invalid credentials");return{appId:a,appSecret:o,userInfo:n?.user_info??n?.userInfo}}async function nte(n){return typeof n.status!="function"?{}:await n.status()}function ste(n){return n?.connected===!0?!0:n?.ready===!0&&n?.feishuLongConnectionState==="connected"&&n?.harnessReachable===!0}var bd=class{#A;#e;#t;#a;#s=!1;#n=null;constructor({createProvisioningManager:a,credentialStore:o,connectionManager:i,registrationOptions:e={}}={}){if(typeof a!="function")throw new TypeError("createProvisioningManager is required");if(!o||typeof o.save!="function"||typeof o.clear!="function")throw new TypeError("credentialStore.save/clear are required");if(!i||typeof i.connect!="function"||typeof i.disconnect!="function")throw new TypeError("connectionManager.connect/disconnect are required");if(e===null||typeof e!="object"||Array.isArray(e))throw new TypeError("registrationOptions must be an object");if(this.#A=o,this.#e=i,this.#t=structuredClone(e),this.#a=a({onCredentials:r=>this.#E(r)}),!this.#a||typeof this.#a.start!="function"||typeof this.#a.status!="function"||typeof this.#a.cancel!="function")throw new TypeError("The provisioning manager must implement start/status/cancel")}async startRegistration(){return this.#n=null,await this.#a.start(structuredClone(this.#t)),this.status()}async cancelRegistration(){return await this.#a.cancel(),this.status()}async disconnect(){await this.#a.cancel(),await this.#e.disconnect();try{await this.#A.clear(),this.#s=!1,this.#n=null}catch{this.#n={code:"credential_removal_failed",message:"Unable to remove the Feishu credentials."}}return this.status()}async status(){let a=await this.#a.status(),o=await nte(this.#e),i=ste(o),e=this.#s;if(typeof this.#A.configured=="function")try{e=await this.#A.configured()}catch{e=this.#s}let r="unconfigured";return i?r="connected":ite.has(a?.state)?r="registering":a?.state==="saving"?r="connecting":this.#n||a?.state==="error"?r="error":e&&(r="disconnected"),{phase:r,connected:i,configured:e,registration:a,connection:o,error:this.#n??a?.error??null}}async close(){await this.#a.cancel(),await this.#e.disconnect()}async#E(a){let o=ote(a);try{await this.#A.save(o),this.#s=!0,await this.#e.connect(o),this.#n=null}catch{throw this.#n={code:"connection_failed",message:"The bot was created, but its connection could not be started."},new Error("Unable to activate the Feishu connection.")}}};function tD(n){return new bd(n)}import{homedir as Sde}from"node:os";import{join as MI,resolve as As}from"node:path";import{unlink as Dde}from"node:fs/promises";var Z_={};zt(Z_,{AESCipher:()=>PC,AccessTokenError:()=>wI,Aily:()=>O_,AppType:()=>co,CAppTicket:()=>vC,CTenantAccessToken:()=>_C,CardActionHandler:()=>m_,Client:()=>IB,ClientAssertionError:()=>qa,DefaultCache:()=>sB,Domain:()=>Io,EventDispatcher:()=>EB,LarkChannel:()=>BB,LarkChannelError:()=>ct,LoggerLevel:()=>Tr,LoggerProxy:()=>es,WSClient:()=>pB,adaptDefault:()=>XCe,adaptExpress:()=>$Ce,adaptKoa:()=>epe,adaptKoaRouter:()=>Ape,createLarkChannel:()=>Lhe,defaultHttpInstance:()=>OI,defaultLogger:()=>sn,generateChallenge:()=>FC,internalCache:()=>GC,messageCard:()=>ape,normalize:()=>Rx,normalizeBotAdded:()=>Nx,normalizeCardAction:()=>_x,normalizeComment:()=>Tx,normalizeReaction:()=>U_,registerApp:()=>Cpe,withAll:()=>JCe,withHelpDeskCredential:()=>VCe,withTenantKey:()=>qCe,withTenantToken:()=>zCe,withUserAccessToken:()=>WCe});function DE(n,a){return function(){return n.apply(a,arguments)}}var{toString:gte}=Object.prototype,{getPrototypeOf:Uc}=Object,{iterator:OE,toStringTag:VP}=Symbol,Nd=(({hasOwnProperty:n})=>(a,o)=>n.call(a,o))(Object.prototype),wE=(n,a)=>{let o=n,i=[];for(;o!=null&&o!==Object.prototype;){if(i.indexOf(o)!==-1)return!1;if(i.push(o),Nd(o,a))return!0;o=Uc(o)}return!1},cte=(n,a)=>n!=null&&wE(n,a)?n[a]:void 0,rD=(n=>a=>{let o=gte.call(a);return n[o]||(n[o]=o.slice(8,-1).toLowerCase())})(Object.create(null)),Vr=n=>(n=n.toLowerCase(),a=>rD(a)===n),Td=n=>a=>typeof a===n,{isArray:Ag}=Array,tg=Td("undefined");function Hc(n){return n!==null&&!tg(n)&&n.constructor!==null&&!tg(n.constructor)&&lr(n.constructor.isBuffer)&&n.constructor.isBuffer(n)}var zP=Vr("ArrayBuffer");function Ite(n){let a;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?a=ArrayBuffer.isView(n):a=n&&n.buffer&&zP(n.buffer),a}var lte=Td("string"),lr=Td("function"),WP=Td("number"),Kc=n=>n!==null&&typeof n=="object",Ete=n=>n===!0||n===!1,_d=n=>{if(!Kc(n))return!1;let a=Uc(n);return(a===null||a===Object.prototype||Uc(a)===null)&&!wE(n,VP)&&!wE(n,OE)},Cte=n=>{if(!Kc(n)||Hc(n))return!1;try{return Object.keys(n).length===0&&Object.getPrototypeOf(n)===Object.prototype}catch{return!1}},pte=Vr("Date"),hte=Vr("File"),dte=n=>!!(n&&typeof n.uri<"u"),ute=n=>n&&typeof n.getParts<"u",Bte=Vr("Blob"),Qte=Vr("FileList"),fte=Vr("Set"),yte=n=>Kc(n)&&lr(n.pipe);function mte(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}}var JP=mte(),qP=typeof JP.FormData<"u"?JP.FormData:void 0,Ste=n=>{if(!n)return!1;if(qP&&n instanceof qP)return!0;let a=Uc(n);if(!a||a===Object.prototype||!lr(n.append))return!1;let o=rD(n);return o==="formdata"||o==="object"&&lr(n.toString)&&n.toString()==="[object FormData]"},Dte=Vr("URLSearchParams"),[wte,Ote,Mte,bte]=["ReadableStream","Request","Response","Headers"].map(Vr),_te=n=>n.trim?n.trim():n.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function ME(n,a,{allOwnKeys:o=!1}={}){if(n===null||typeof n>"u")return;let i,e;if(typeof n!="object"&&(n=[n]),Ag(n))for(i=0,e=n.length;i0;)if(e=o[i],a===e.toLowerCase())return e;return null}var eg=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,XP=n=>!tg(n)&&n!==eg;function aD(...n){let{caseless:a,skipUndefined:o}=XP(this)&&this||{},i={},e=(r,A)=>{if(A==="__proto__"||A==="constructor"||A==="prototype")return;let t=a&&typeof A=="string"&&ZP(i,A)||A,s=Nd(i,t)?i[t]:void 0;_d(s)&&_d(r)?i[t]=aD(s,r):_d(r)?i[t]=aD({},r):Ag(r)?i[t]=r.slice():(!o||!tg(r))&&(i[t]=r)};for(let r=0,A=n.length;r(ME(a,(e,r)=>{o&&lr(e)?Object.defineProperty(n,r,{__proto__:null,value:DE(e,o),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(n,r,{__proto__:null,value:e,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:i}),n),Tte=n=>(n.charCodeAt(0)===65279&&(n=n.slice(1)),n),Rte=(n,a,o,i)=>{n.prototype=Object.create(a.prototype,i),Object.defineProperty(n.prototype,"constructor",{__proto__:null,value:n,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(n,"super",{__proto__:null,value:a.prototype}),o&&Object.assign(n.prototype,o)},kte=(n,a,o,i)=>{let e,r,A,t={};if(a=a||{},n==null)return a;do{for(e=Object.getOwnPropertyNames(n),r=e.length;r-- >0;)A=e[r],(!i||i(A,n,a))&&!t[A]&&(a[A]=n[A],t[A]=!0);n=o!==!1&&Uc(n)}while(n&&(!o||o(n,a))&&n!==Object.prototype);return a},vte=(n,a,o)=>{n=String(n),(o===void 0||o>n.length)&&(o=n.length),o-=a.length;let i=n.indexOf(a,o);return i!==-1&&i===o},Pte=n=>{if(!n)return null;if(Ag(n))return n;let a=n.length;if(!WP(a))return null;let o=new Array(a);for(;a-- >0;)o[a]=n[a];return o},Gte=(n=>a=>n&&a instanceof n)(typeof Uint8Array<"u"&&Uc(Uint8Array)),Fte=(n,a)=>{let i=(n&&n[OE]).call(n),e;for(;(e=i.next())&&!e.done;){let r=e.value;a.call(n,r[0],r[1])}},Lte=(n,a)=>{let o,i=[];for(;(o=n.exec(a))!==null;)i.push(o);return i},Ute=Vr("HTMLFormElement"),Hte=n=>n.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(o,i,e){return i.toUpperCase()+e}),{propertyIsEnumerable:Kte}=Object.prototype,Yte=Vr("RegExp"),$P=(n,a)=>{let o=Object.getOwnPropertyDescriptors(n),i={};ME(o,(e,r)=>{let A;(A=a(e,r,n))!==!1&&(i[r]=A||e)}),Object.defineProperties(n,i)},xte=n=>{$P(n,(a,o)=>{if(lr(n)&&["arguments","caller","callee"].includes(o))return!1;let i=n[o];if(lr(i)){if(a.enumerable=!1,"writable"in a){a.writable=!1;return}a.set||(a.set=()=>{throw Error("Can not rewrite read-only method '"+o+"'")})}})},jte=(n,a)=>{let o={},i=e=>{e.forEach(r=>{o[r]=!0})};return Ag(n)?i(n):i(String(n).split(a)),o},Jte=()=>{},qte=(n,a)=>n!=null&&Number.isFinite(n=+n)?n:a;function Vte(n){return!!(n&&lr(n.append)&&n[VP]==="FormData"&&n[OE])}var zte=n=>{let a=new WeakSet,o=i=>{if(Kc(i)){if(a.has(i))return;if(Hc(i))return i;if(!("toJSON"in i)){a.add(i);let e;if(fte(i)){e=[];for(let r of i){let A=o(r);!tg(A)&&e.push(A)}}else e=Ag(i)?[]:{},ME(i,(r,A)=>{let t=o(r);!tg(t)&&(e[A]=t)});return a.delete(i),e}}return i};return o(n)},Wte=Vr("AsyncFunction"),Zte=n=>n&&(Kc(n)||lr(n))&&lr(n.then)&&lr(n.catch),eG=((n,a)=>n?setImmediate:a?((o,i)=>(eg.addEventListener("message",({source:e,data:r})=>{e===eg&&r===o&&i.length&&i.shift()()},!1),e=>{i.push(e),eg.postMessage(o,"*")}))(`axios@${Math.random()}`,[]):o=>setTimeout(o))(typeof setImmediate=="function",lr(eg.postMessage)),Xte=typeof queueMicrotask<"u"?queueMicrotask.bind(eg):typeof process<"u"&&process.nextTick||eG,AG=n=>n!=null&&lr(n[OE]),$te=n=>n!=null&&wE(n,OE)&&AG(n),q={isArray:Ag,isArrayBuffer:zP,isBuffer:Hc,isFormData:Ste,isArrayBufferView:Ite,isString:lte,isNumber:WP,isBoolean:Ete,isObject:Kc,isPlainObject:_d,isEmptyObject:Cte,isReadableStream:wte,isRequest:Ote,isResponse:Mte,isHeaders:bte,isUndefined:tg,isDate:pte,isFile:hte,isReactNativeBlob:dte,isReactNative:ute,isBlob:Bte,isRegExp:Yte,isFunction:lr,isStream:yte,isURLSearchParams:Dte,isTypedArray:Gte,isFileList:Qte,forEach:ME,merge:aD,extend:Nte,trim:_te,stripBOM:Tte,inherits:Rte,toFlatObject:kte,kindOf:rD,kindOfTest:Vr,endsWith:vte,toArray:Pte,forEachEntry:Fte,matchAll:Lte,isHTMLForm:Ute,hasOwnProperty:Nd,hasOwnProp:Nd,hasOwnInPrototypeChain:wE,getSafeProp:cte,reduceDescriptors:$P,freezeMethods:xte,toObjectSet:jte,toCamelCase:Hte,noop:Jte,toFiniteNumber:qte,findKey:ZP,global:eg,isContextDefined:XP,isSpecCompliantForm:Vte,toJSONObject:zte,isAsyncFn:Wte,isThenable:Zte,setImmediate:eG,asap:Xte,isIterable:AG,isSafeIterable:$te};var eae=q.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),tG=n=>{let a={},o,i,e;return n&&n.split(` @@ -182,7 +182,7 @@ ${r.join(` `,{encoding:"utf8",mode:384}),await sBe(o,this.#A)}};var gQ=class extends Kt{constructor(a){super({...a,rpcIdPrefix:"wecom",logPrefix:"dsh-wecom"})}};var CBe="https://work.weixin.qq.com/ai/qc/generate",pBe="https://work.weixin.qq.com/ai/qc/query_result";function H1(){return process.platform==="win32"?2:process.platform==="linux"?3:1}function NI(n){return typeof n=="string"&&n.trim()?n.trim():null}function hBe(n){let a=NI(n);if(!a)return null;try{let o=new URL(a);return o.protocol==="https:"&&o.hostname==="work.weixin.qq.com"&&(!o.port||o.port==="443")?o.href:null}catch{return null}}function dBe(n,a){return n?AbortSignal.any([n,AbortSignal.timeout(a)]):AbortSignal.timeout(a)}async function K1(n,a,o){let i=await n(a,{method:"GET",redirect:"error",signal:dBe(o,1e4),headers:{accept:"application/json"}});if(!i.ok)throw new Error(`Enterprise WeChat QR service returned HTTP ${i.status}`);return i.json()}var cQ=class{#A;#e;#t;#a;constructor({fetch:a=globalThis.fetch,clock:o=()=>Date.now(),source:i="deepseek-harness",platform:e=H1()}={}){if(typeof a!="function")throw new TypeError("A fetch implementation is required");this.#A=a,this.#e=o,this.#t=i,this.#a=[1,2,3].includes(e)?e:H1()}async start({signal:a}={}){let o=new URL(CBe);o.searchParams.set("source",this.#t),o.searchParams.set("plat",String(this.#a));let i=await K1(this.#A,o,a),e=NI(i?.data?.scode),r=hBe(i?.data?.auth_url);if(!e||!r)throw new Error("Enterprise WeChat QR service returned invalid data");return{scode:e,verificationUrl:r,expiresAt:this.#e()+3e5,pollIntervalMs:3e3}}async poll({scode:a,signal:o}={}){let i=NI(a);if(!i)throw new TypeError("Enterprise WeChat QR poll code is required");let e=new URL(pBe);e.searchParams.set("scode",i);let r=await K1(this.#A,e,o),A=NI(r?.data?.status)?.toLowerCase();if(A==="success"){let t=NI(r?.data?.bot_info?.botid),s=NI(r?.data?.bot_info?.secret);if(!t||!s)throw new Error("Enterprise WeChat QR result omitted bot credentials");return{status:"success",remoteBotId:t,secret:s}}return["expired","timeout"].includes(A)?{status:"expired"}:["fail","failed","error"].includes(A)?{status:"failed"}:{status:"waiting"}}};import{mkdir as uBe,readFile as BBe,rename as QBe,unlink as fBe,writeFile as yBe}from"node:fs/promises";import{dirname as mBe}from"node:path";var IQ=Object.freeze({version:1,sessions:{},seenMessageIds:[]});function SBe(n){if(!n||typeof n!="object")return structuredClone(IQ);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[o,i]of Object.entries(n.sessions))typeof o=="string"&&typeof i=="string"&&i&&(a[o]=i);return{version:1,sessions:a,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[]}}var lQ=class{#A;#e=structuredClone(IQ);#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{this.#e=SBe(JSON.parse(await BBe(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(IQ),await this.#a()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){this.#e.sessions[a]=o,await this.#a()}async clearSession(a){delete this.#e.sessions[a],await this.#a()}async clearSessions(){this.#e.sessions={},await this.#a()}hasSeen(a){return this.#e.seenMessageIds.includes(a)}async markSeen(a){this.hasSeen(a)||(this.#e.seenMessageIds.push(a),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#a())}async remove(){try{await fBe(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(IQ)}async#a(){let a=`${JSON.stringify(this.#e,null,2)} `,o=this.#t.then(async()=>{await uBe(mBe(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await yBe(i,a,{encoding:"utf8",mode:384}),await QBe(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};import{randomUUID as DBe}from"node:crypto";var Y1=new Set(["pending","connecting"]),tp=new Set(["connected","failed","cancelled","expired"]);function Gg(n){return typeof n=="string"&&n.trim()?n.trim():null}function ur(n,a){return Object.freeze({code:n,message:a})}function Fg(n){return n?{attemptId:n.id,status:n.state,pollIntervalMs:n.pollIntervalMs,qrRevision:n.qrRevision,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},...n.botId?{botId:n.botId}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}var ap=class{#A;#e;#t;#a;#s;#n;#E=new Map;#g=new Map;#c=new Map;#r=null;#i=new Map;#o=0;#I=!1;constructor({qrAuth:a,credentials:o,configStore:i,createRuntime:e,deleteState:r=async()=>{},logger:A=console}){if(!a||typeof a.start!="function"||typeof a.poll!="function")throw new TypeError("Enterprise WeChat QR auth is required");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("WecomController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("WecomController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A}async initialize(){if(this.#I)return this.status();for(let a of this.#t.list())await this.#Q(a.botId,async()=>{let o=this.#E.get(a.botId)?.status;if(this.#I||o?.ready||o?.wecomConnectionState==="connecting")return;let i=await this.#B(a.secretRef);if(!i){this.#g.set(a.botId,ur("missing-secret","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u626B\u7801\u3002"));return}try{await this.#C(a,i),this.#g.delete(a.botId)}catch{this.#g.set(a.botId,ur("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002")),this.#n.warn?.(`[dsh-im:wecom] bot ${a.botId} failed to initialize`)}finally{this.#f()}});return this.status()}async startProvisioning(){if(this.#I)throw new Error("Enterprise WeChat controller is closed");this.#r&&await this.cancelProvisioning(this.#r);let a={id:DBe(),state:"pending",createdAt:Date.now(),expiresAt:null,pollIntervalMs:3e3,qrRevision:1,verificationUrl:null,scode:null,botId:null,error:null,controller:new AbortController,polling:null,transition:null};this.#c.set(a.id,a),this.#r=a.id,this.#f();try{let o=await this.#A.start({signal:a.controller.signal});if(a.scode=Gg(o.scode),a.verificationUrl=Gg(o.verificationUrl),a.expiresAt=Number(o.expiresAt),a.pollIntervalMs=Math.min(1e4,Math.max(500,Number(o.pollIntervalMs)||3e3)),!a.scode||!a.verificationUrl||!Number.isFinite(a.expiresAt))throw new Error("Enterprise WeChat QR auth returned incomplete data");return this.#f(),Fg(a)}catch(o){throw a.state=a.controller.signal.aborted?"cancelled":"failed",a.error=a.controller.signal.aborted?ur("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"):ur("qr-start-failed","\u65E0\u6CD5\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),this.#y(a),o}}async registrationStatus(a){let o=this.#c.get(a);if(!o||tp.has(o.state))return Fg(o);if(o.state==="connecting")return await o.transition?.catch(()=>{}),Fg(o);if(Date.now()>=o.expiresAt)return o.state="expired",o.error=ur("expired","\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"),o.controller.abort(),this.#y(o),Fg(o);if(!o.polling){let i=this.#l(o).finally(()=>{o.polling===i&&(o.polling=null)});o.polling=i}return await o.polling.catch(()=>{}),Fg(o)}async bindCredentials({botId:a,secret:o}={}){if(this.#I)throw new Error("Enterprise WeChat controller is closed");let i=Gg(a),e=Gg(o);if(!i||!e)throw new TypeError("Enterprise WeChat Bot ID and Secret are required");if(this.#r&&await this.cancelProvisioning(this.#r),this.#I)throw new Error("Enterprise WeChat controller is closed");let r=sQ(i);return await this.#Q(r.botId,async()=>{if(this.#I)throw new Error("Enterprise WeChat controller is closed");let A=this.#t.getByRemoteBotId(i),t=await this.#e.resolve(r.secretRef).catch(()=>{});if(this.#I)throw new Error("Enterprise WeChat controller is closed");let s={botId:r.botId,remoteBotId:i,secretRef:r.secretRef,createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#e.set(r.secretRef,e);try{await this.#t.save(s)}catch(g){throw await this.#u(r.secretRef,t),g}try{await this.#C(s,e),this.#g.delete(r.botId)}catch{this.#g.set(r.botId,ur("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002")),this.#n.warn?.(`[dsh-im:wecom] bot ${r.botId} credential connection failed`)}this.#f()}),this.status()}async cancelProvisioning(a){let o=this.#c.get(a);return o?(tp.has(o.state)||(o.controller.abort(),await Promise.allSettled([o.polling,o.transition].filter(Boolean)),tp.has(o.state)||(o.state="cancelled"),o.error??=ur("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"),this.#y(o)),Fg(o)):null}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(a,async()=>{let i=await this.#B(o.secretRef);if(!i)throw new Error("Enterprise WeChat bot secret is missing");try{await this.#C(o,i),this.#g.delete(a)}catch(e){throw this.#g.set(a,ur("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),e}finally{this.#f()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(a,async()=>{let i=await this.#e.resolve(o.secretRef).catch(()=>{});await this.#d(a);try{await this.#e.unset(o.secretRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.secretRef,i.value).catch(()=>{}),await this.#C(o,i.value).catch(()=>{})),new Error("Unable to remove the Enterprise WeChat bot safely.",{cause:e})}await this.#s({botId:a,config:o}).catch(e=>{this.#n.warn?.(`[dsh-im:wecom] bot ${a} state cleanup failed:`,e)}),this.#g.delete(a),this.#f()}),this.status()}status(){let a=this.#t.list().map(e=>{let r=this.#E.get(e.botId)?.status??null,A=r?.ready===!0&&r.wecomConnectionState==="connected"&&r.harnessReachable===!0,t=A?"connected":r?.wecomConnectionState==="connecting"?"connecting":this.#g.has(e.botId)||r?.wecomConnectionState==="failed"?"error":"offline";return{botId:e.botId,state:t,connected:A,configured:!0,bot:{name:"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA",appIdMasked:L1(e.remoteBotId)},health:{status:A?"healthy":t==="error"?"error":"offline",summary:A?"\u4F01\u4E1A\u5FAE\u4FE1 WebSocket \u957F\u8FDE\u63A5\u8FD0\u884C\u6B63\u5E38":t==="error"?"\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",lastCheckedAt:r?.lastCheckedAt??null,lastConnectedAt:r?.lastConnectedAt??null},stats:{messagesReceived:r?.messagesReceived??0,messagesReplied:r?.messagesReplied??0},error:structuredClone(this.#g.get(e.botId)??null)}}),o=a.filter(e=>e.connected).length,i=this.#r?this.#c.get(this.#r):null;return{schemaVersion:1,revision:this.#o,state:i&&Y1.has(i.state)?"provisioning":a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o},...i&&Y1.has(i.state)?{provisioning:Fg(i)}:{}}}async close(){this.#I||(this.#I=!0,this.#r&&await this.cancelProvisioning(this.#r),await Promise.allSettled([...this.#i.values()]),await Promise.allSettled([...this.#E.keys()].map(a=>this.#d(a))))}async#l(a){try{let o=await this.#A.poll({scode:a.scode,signal:a.controller.signal});if(a.controller.signal.aborted||tp.has(a.state)||o.status==="waiting")return;if(o.status==="expired"){a.state="expired",a.error=ur("expired","\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"),this.#y(a);return}if(o.status!=="success"){a.state="failed",a.error=ur("qr-connect-failed","\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u6CA1\u6709\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002"),this.#y(a);return}a.state="connecting",a.verificationUrl=null,a.expiresAt=null,a.scode=null,this.#f();let i=this.#p(a,o);a.transition=i,await i}catch{if(a.controller.signal.aborted)return;a.state="failed",a.error=ur("qr-connect-failed","\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002"),this.#n.warn?.("[dsh-im:wecom] QR polling failed"),this.#y(a)}}async#p(a,o){try{let i=Gg(o.remoteBotId),e=Gg(o.secret);if(!i||!e)throw new Error("Enterprise WeChat authorization returned incomplete credentials");a.botId=await this.#h(a,{remoteBotId:i,secret:e}),a.state="connected",a.error=null}catch{a.controller.signal.aborted?(a.state="cancelled",a.error=ur("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(a.state="failed",a.error=ur("activation-failed","\u4F01\u4E1A\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002"),this.#n.error?.("[dsh-im:wecom] provisioning failed"))}finally{this.#y(a)}}async#h(a,{remoteBotId:o,secret:i}){let e=sQ(o),r=this.#t.getByRemoteBotId(o),A=await this.#e.resolve(e.secretRef).catch(()=>{}),t={botId:e.botId,remoteBotId:o,secretRef:e.secretRef,createdAt:r?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};return this.#Q(e.botId,async()=>{await this.#e.set(e.secretRef,i);try{if(a.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#t.save(t)}catch(s){throw await this.#u(e.secretRef,A),s}try{if(a.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#C(t,i),this.#g.delete(e.botId)}catch(s){if(a.controller.signal.aborted)throw await this.#d(e.botId),r?await this.#t.save(r).catch(()=>{}):await this.#t.remove(e.botId).catch(()=>null)&&await this.#s({botId:e.botId,config:t}).catch(c=>{this.#n.warn?.("[dsh-im:wecom] cancelled bot state cleanup failed:",c)}),await this.#u(e.secretRef,A),s;this.#g.set(e.botId,ur("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002")),this.#n.warn?.(`[dsh-im:wecom] bot ${e.botId} activation connection failed`)}return this.#f(),e.botId})}async#C(a,o){if(this.#I)throw new Error("Enterprise WeChat controller is closed");if(await this.#d(a.botId),this.#I)throw new Error("Enterprise WeChat controller is closed");let i=await this.#a({botId:a.botId,config:a,secret:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid Enterprise WeChat runtime");this.#E.set(a.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#E.delete(a.botId),e}}async#d(a){let o=this.#E.get(a);this.#E.delete(a),await o?.stop().catch(i=>{this.#n.warn?.(`[dsh-im:wecom] bot ${a} failed to stop cleanly:`,i)})}async#B(a){let o=await this.#e.resolve(a).catch(()=>{});return Gg(o?.value)}async#u(a,o){o?.value?await this.#e.set(a,o.value).catch(()=>{}):await this.#e.unset(a).catch(()=>{})}#Q(a,o){let r=(this.#i.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#i.get(a)===r&&this.#i.delete(a)});return this.#i.set(a,r),r}#y(a){a.scode=null,a.verificationUrl=null,a.expiresAt=null,this.#r===a.id&&(this.#r=null),this.#f();let o=[...this.#c.values()].filter(i=>tp.has(i.state));for(;o.length>16;)this.#c.delete(o.shift().id)}#f(){this.#o+=1}};import{WSAuthFailureError as NBe,WSClient as TBe,WSReconnectExhaustedError as RBe}from"@wecom/aibot-node-sdk";import{generateReqId as wBe}from"@wecom/aibot-node-sdk";var OBe=["\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/workspace \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A","/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84","/sessionlist [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898","/session Session ID \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` `),MBe=18e3,EQ="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002";function TI(n){return typeof n=="string"&&n.trim()?n.trim():null}function rp(n){return n?.body&&typeof n.body=="object"?n.body:{}}function x1(n){let a=rp(n);return a.chattype==="group"?`group:${a.chatid}`:`direct:${a.from?.userid}`}function pQ(n){let a=rp(n),o="";return a.msgtype==="text"?o=typeof a.text?.content=="string"?a.text.content.trim():"":a.msgtype==="voice"?o=typeof a.voice?.content=="string"?a.voice.content.trim():"":a.msgtype==="mixed"&&Array.isArray(a.mixed?.msg_item)&&(o=a.mixed.msg_item.filter(i=>i?.msgtype==="text"&&typeof i.text?.content=="string").map(i=>i.text.content).join(` -`).trim()),a.chattype==="group"?o.replace(/^\s*@\S+(?:\s+|$)/u,"").trim():o}function CQ(n,a=MBe){let o=String(n??"").trim();if(!o)return[];let i=[],e="",r=0;for(let A of o){let t=Buffer.byteLength(A);e&&r+t>a?(i.push(e),e=A,r=t):(e+=A,r+=t)}return e&&i.push(e),i}function bBe(n){return n?.type==="text"?n.text:n?.type==="tool"?`\u6B63\u5728\u4F7F\u7528${n.name}\u2026`:n?.text}function _Be(n,a){return a.questions[a.index]&&TI(rp(n).from?.userid)===a.actor&&TI(pQ(n))}function _N(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var hQ=class{#A;#e;#t;#a;#s;#n;#E;#g;#c=new Map;#r=new Map;#i=new Map;#o=new Set;#I=new Set;#l;constructor({client:a,harness:o,state:i,status:e=_N(),logger:r=console,replyTimeoutMs:A=6e5,generateStreamId:t=wBe,signal:s}){if(!a||typeof a.replyStream!="function"||typeof a.sendMessage!="function")throw new TypeError("Enterprise WeChat client is required");if(!o||!i)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#l=new nr({label:"wecom",logger:r})}get status(){return structuredClone(this.#a)}accept(a){if(this.#g?.aborted)return Promise.resolve();let o=rp(a),i=TI(o.msgid),e=TI(o.from?.userid),r=o.chattype==="group"?TI(o.chatid):e;if(!i||!e||!r||!["single","group"].includes(o.chattype)||this.#t.hasSeen(i)||this.#o.has(i))return Promise.resolve();let A=x1(a);this.#o.add(i);let t=this.#r.get(A),s=this.#l.claimReply({key:A,actor:e,messageId:i,text:pQ(a),addressed:!0,hasPendingQuestion:!!t,questionCompletion:t?.submitting||t?.claimedReplyMessageId?t.queue:null,isQuestionPending:()=>this.#r.has(A),send:g=>this.#C(a,r,g)});if(s){let g;return g=s.process(async()=>this.#t.hasSeen(i)?!1:(await this.#t.markSeen(i),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#o.delete(i),this.#I.delete(g)}),this.#I.add(g),g}if(t&&t.actor!==e)return this.#p(a,i,A);if(t?.submitting||t?.claimedReplyMessageId)return this.#p(a,i,A);if(t){_Be(a,t)&&(t.claimedReplyMessageId=i);let c=(t.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#B(a,i,e,r,A,t)).finally(()=>{this.#o.delete(i),t.claimedReplyMessageId===i&&(t.claimedReplyMessageId=null),t.queue===c&&(t.queue=null)});return t.queue=c,c}return this.#p(a,i,A)}#p(a,o,i,{releaseMessageId:e=!0,alreadyRecorded:r=!1}={}){let t=(this.#c.get(i)??Promise.resolve()).catch(()=>{}).then(()=>this.#d(a,{alreadyRecorded:r})).finally(()=>{e&&this.#o.delete(o),this.#c.get(i)===t&&this.#c.delete(i)});return this.#c.set(i,t),t}async waitForIdle(){await Promise.allSettled([...this.#c.values(),...[...this.#r.values()].flatMap(a=>a.queue?[a.queue]:[]),...this.#I])}async#h(a,o){for(let i of CQ(o))this.#g?.throwIfAborted(),await this.#A.sendMessage(a,{msgtype:"markdown",markdown:{content:i}})}async#C(a,o,i){this.#g?.throwIfAborted();let e=CQ(i);if(e.length!==0)try{await this.#A.replyStream(a,this.#E("stream"),e[0],!0);for(let r of e.slice(1))await this.#A.sendMessage(o,{msgtype:"markdown",markdown:{content:r}})}catch{await this.#h(o,i)}}async#d(a,{alreadyRecorded:o=!1}={}){if(this.#g?.aborted)return;let i=rp(a),e=typeof i.msgid=="string"?i.msgid:"",r=typeof i.from?.userid=="string"?i.from.userid:"",A=i.chattype==="group"?i.chatid:r;if(!e||!r||!A||!["single","group"].includes(i.chattype))return;if(!o){if(this.#t.hasSeen(e))return;this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString()}let t=pQ(a),s=x1(a),g=null,c=!1;try{if(!t){await this.#C(a,A,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u8BED\u97F3\u8F6C\u5199\u548C\u56FE\u6587\u6DF7\u6392\u4E2D\u7684\u6587\u5B57\u6D88\u606F\u3002"),await this.#t.markSeen(e);return}let l=t.toLowerCase();if(l==="/help"){await this.#C(a,A,OBe),await this.#t.markSeen(e);return}if(l==="/status"){await this.#e.ensureRunning({signal:this.#g}),await this.#C(a,A,"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),await this.#t.markSeen(e);return}if(l==="/new"){await this.#t.clearSession(s),await this.#C(a,A,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#t.markSeen(e);return}let C=await xr(t,this.#e,s);if(C){for(let y of C.messages??[C.message])await this.#C(a,A,y);await this.#t.markSeen(e);return}g=this.#E("stream");try{await this.#A.replyStream(a,g,"\u6B63\u5728\u601D\u8003\u4E2D\u2026",!1),c=!0}catch(y){this.#s.warn?.("[dsh-im:wecom] unable to start a stream; using an active reply:",y)}let{answer:B}=await sr({harness:this.#e,state:this.#t,key:s,text:t,createOptions:{signal:this.#g},existsOptions:{signal:this.#g},askOptions:{timeoutMs:this.#n,signal:this.#g,onUpdate:c&&typeof this.#A.replyStreamNonBlocking=="function"?async y=>{let m=CQ(bBe(y))[0];m&&await this.#A.replyStreamNonBlocking(a,g,m,!1)}:void 0,onInteraction:y=>this.#u(y,{key:s,actor:r,chatId:A,requiresMention:i.chattype==="group"}),onInteractionResolved:y=>this.#Q(y)}}),Q=CQ(B||"\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u4F46\u6CA1\u6709\u751F\u6210\u53EF\u663E\u793A\u7684\u6587\u672C\u3002"),f=!1;if(c&&Q.length>0)try{await this.#A.replyStream(a,g,Q[0],!0);for(let y of Q.slice(1))await this.#A.sendMessage(A,{msgtype:"markdown",markdown:{content:y}});f=!0}catch(y){this.#s.warn?.("[dsh-im:wecom] stream finalization failed; using an active reply:",y)}f||await this.#h(A,B),await this.#t.markSeen(e),this.#a.messagesReplied+=1,this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null}catch(l){if(this.#g?.aborted)return;this.#a.lastError=l?.message??String(l),this.#s.error?.("[dsh-im:wecom] failed to process an inbound message");try{c&&g?await this.#A.replyStream(a,g,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",!0):await this.#C(a,A,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),await this.#t.markSeen(e)}catch{this.#s.error?.("[dsh-im:wecom] failed to send the safe error reply")}}finally{await Promise.allSettled([this.#w(s),this.#l.closeRoute(s)])}}async#B(a,o,i,e,r,A){if(this.#g?.aborted)return;let t=this.#r.get(r),s=A.claimedReplyMessageId===o;if(!t||t!==A||t.submitting)return s&&(!t||t!==A)?this.#f(a,o,e):this.#p(a,o,r,{releaseMessageId:!1});if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString();let g=TI(pQ(a));if(!g){await this.#C(a,e,"\u8BF7\u7528\u6587\u5B57\u6216\u8BED\u97F3\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002").catch(()=>{});return}let c=this.#r.get(r);if(!c||c!==A||c.submitting){if(s&&(!c||c!==A)){await this.#C(a,e,EQ).catch(()=>{});return}return this.#p(a,o,r,{releaseMessageId:!1,alreadyRecorded:!0})}if(c.actor!==i)return this.#p(a,o,r,{releaseMessageId:!1,alreadyRecorded:!0});if(c.chatId=e,c.needsPresentation){try{await this.#y(c)}catch{this.#a.lastError="\u4F01\u4E1A\u5FAE\u4FE1\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002",this.#s.error?.("[dsh-im:wecom] failed to retry an interaction question"),c.interaction.reconnect?.();return}let C=this.#r.get(r);if(!C||C!==A||C.submitting){if(s&&(!C||C!==A)){await this.#C(a,e,EQ).catch(()=>{});return}return this.#p(a,o,r,{releaseMessageId:!1,alreadyRecorded:!0})}}let l=c.questions[c.index];if(l){if(c.answers.push(Yr(l,g)),c.index+=1,c.index{});return}if(this.#r.get(r)!==c)return;c.submitting=!1,c.answers.pop(),c.index-=1,this.#a.lastError="\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\u3002",this.#s.error?.("[dsh-im:wecom] failed to answer a Harness interaction"),await this.#C(a,e,"\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u5F53\u524D\u95EE\u9898\u7684\u7B54\u6848\u3002").catch(()=>{})}}}async#u(a,{key:o,actor:i,chatId:e,requiresMention:r}){if(a?.kind==="approval")return this.#l.handleRequested(a,{key:o,actor:i,requiresMention:r,send:c=>this.#h(e,c)});if(a?.kind!=="question")return;let A=a?.payload?.questions,t=typeof a?.interactionId=="string"?a.interactionId:a?.rpcId;if(typeof a?.rpcId!="string"||typeof t!="string"||typeof a.sessionId!="string"||!Array.isArray(A)||A.length===0||A.some(c=>!Hr(c))){this.#s.warn?.("[dsh-im:wecom] ignored an invalid Harness question interaction");return}if(a.recovered===!0){await a.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat safely cancelled an interaction left by an earlier client.",details:{}}}),await this.#h(e,"\u68C0\u6D4B\u5230\u8FD9\u4E2A Session \u4E2D\u9057\u7559\u7684\u5F85\u56DE\u7B54\u95EE\u9898\uFF0C\u5DF2\u5B89\u5168\u53D6\u6D88\u5E76\u7EE7\u7EED\u5904\u7406\u4F60\u521A\u624D\u7684\u6D88\u606F\u3002").catch(()=>{});return}let s=this.#r.get(o);if(s?.interactionId===t){s.interaction=a,s.needsPresentation&&await this.#y(s);return}if(this.#i.has(t))return;if(s){this.#s.warn?.("[dsh-im:wecom] cancelled a second pending Harness question"),await a.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat is already handling another user interaction.",details:{}}});return}let g={kind:"question",interactionId:t,sessionId:a.sessionId,interaction:a,actor:i,requiresMention:r,questions:A,answers:[],index:0,chatId:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationPromise:null};this.#r.set(o,g),this.#i.set(g.interactionId,o),await this.#y(g)}async#Q(a){if(a?.kind==="approval"){await this.#l.handleResolved(a);return}let o=a?.interactionId;if(a?.kind!=="question"||typeof o!="string")return;let i=this.#i.get(o);i&&this.#m(i,o)}#y(a){if(!a.needsPresentation)return Promise.resolve();if(a.presentationPromise)return a.presentationPromise;let o=a.questions[a.index];if(!o)return Promise.resolve();let i=this.#h(a.chatId,Kr(o,a.index,a.questions.length,{requiresMention:a.requiresMention})).then(()=>{a.needsPresentation=!1}).finally(()=>{a.presentationPromise===i&&(a.presentationPromise=null)});return a.presentationPromise=i,i}async#f(a,o,i){this.#t.hasSeen(o)||(await this.#t.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),await this.#C(a,i,EQ).catch(()=>{}))}#D(a,o){let i=this.#r.get(a);return!i||o!==void 0&&i.interactionId!==o?null:(this.#r.delete(a),this.#i.delete(i.interactionId),i)}#m(a,o){return this.#D(a,o)!==null}async#w(a){let o=this.#D(a);if(!(!o||o.kind!=="question"))try{await o.interaction.respond({ok:!1,error:{code:"cancelled",message:"The Enterprise WeChat interaction ended before the user answered.",details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){i?.code!=="interaction-not-pending"&&this.#s.warn?.("[dsh-im:wecom] failed to cancel a pending Harness interaction")}}};function kBe(){let n=new Error("Enterprise WeChat WebSocket authentication timed out");return n.code="connect-timeout",n}function vBe(){return{startedAt:null,ready:!1,wecomConnectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,..._N()}}var ip=class{#A;#e;#t;#a;#s;#n;#E;#g;#c;#r=vBe();#i=null;#o=null;#I=null;#l=null;#p=null;constructor({config:a,secret:o,harness:i,state:e,logger:r=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,maxReconnectAttempts:s=10,createClient:g=c=>new TBe(c)}){if(!a||!o||!i||!e)throw new TypeError("WecomRuntime requires config, secret, Harness, and state");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#c=g}get status(){return structuredClone(this.#r)}async start(){if(this.#r.ready&&this.#i)return this.status;if(this.#I)return this.#I;this.#p?.abort(new DOMException("Enterprise WeChat runtime replaced","AbortError"));let a=new AbortController;return this.#l=a,this.#p=a,this.#I=this.#h(a.signal).finally(()=>{this.#l===a&&(this.#l=null),this.#I=null}),this.#I}async#h(a){await this.#C(),a.throwIfAborted(),this.#r.startedAt=new Date().toISOString(),this.#r.wecomConnectionState="connecting",this.#r.lastError=null,await this.#t.ensureRunning(),this.#r.harnessReachable=!0;let o={debug(){},info(){},warn(){},error(){}},i=this.#c({botId:this.#A.remoteBotId,secret:this.#e,logger:o,maxReconnectAttempts:this.#g});if(!i||typeof i.connect!="function"||typeof i.disconnect!="function")throw new TypeError("Enterprise WeChat client factory returned an invalid client");this.#i=i,this.#o=new hQ({client:i,harness:this.#t,state:this.#a,status:this.#r,logger:this.#s,replyTimeoutMs:this.#n,signal:a});let e,r,A=!1,t=new Promise((Q,f)=>{e=Q,r=f}),s=()=>{if(this.#i!==i||a.aborted)return;A=!0;let Q=Date.now();this.#r.ready=!0,this.#r.wecomConnectionState="connected",this.#r.lastCheckedAt=Q,this.#r.lastConnectedAt=Q,this.#r.lastError=null,e()},g=()=>{this.#i===i&&(this.#r.ready=!1,this.#r.wecomConnectionState="connecting",this.#r.lastCheckedAt=Date.now())},c=()=>{this.#i===i&&(this.#r.ready=!1,this.#r.wecomConnectionState="connecting",this.#r.lastCheckedAt=Date.now())},l=Q=>{if(this.#i!==i)return;let f=Q instanceof NBe||Q instanceof RBe;!A&&f&&r(Q),f&&(this.#r.ready=!1,this.#r.wecomConnectionState="failed"),this.#r.lastError=f?Q.name:"connection-error",this.#s.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} connection error`)},C=Q=>this.#o?.accept(Q);i.on("authenticated",s),i.on("disconnected",g),i.on("reconnecting",c),i.on("error",l),i.on("message",C);let B;try{return i.connect(),await Promise.race([t,new Promise((Q,f)=>{a.addEventListener("abort",()=>f(a.reason),{once:!0})}),new Promise((Q,f)=>{B=setTimeout(()=>f(kBe()),this.#E)})]),this.status}catch(Q){throw a.aborted?(await this.#C(),Q):(this.#r.ready=!1,this.#r.wecomConnectionState="failed",this.#r.lastError=Q?.message??String(Q),await this.#C(),Q)}finally{clearTimeout(B)}}async stop(){let a=this.#I;return this.#l?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#p?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#p=null,await this.#C(),await a?.catch(()=>{}),this.status}async#C(){let a=this.#i,o=this.#o;this.#i=null,this.#o=null;try{a?.disconnect(),a?.removeAllListeners?.()}catch{this.#s.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} failed to stop cleanly`)}await o?.waitForIdle(),this.#r.ready=!1,this.#r.wecomConnectionState="idle"}};var j1=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function PBe(n){if(!Array.isArray(n)||n.length===0)return[...j1];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...j1]}var dQ=class{#A;#e;#t;#a;#s;#n;#E;#g=null;#c=null;#r=0;#i=!1;#o=!1;#I;#l;constructor({controller:a,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:r=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!a||typeof a.initialize!="function"||typeof a.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=PBe(e),this.#s=Number.isFinite(r)&&r>=0?r:15e3,this.#n=A,this.#E=t,this.#I=new Promise(s=>{this.#l=s})}get ready(){return this.#I}start(){return this.#o||this.#i?this:(this.#o=!0,this.#p(0),this)}async close(){this.#i||(this.#i=!0,this.#g!==null&&this.#E(this.#g),this.#g=null,await this.#c?.catch(()=>{}),this.#l?.(null),this.#l=null)}#p(a){this.#i||(this.#g=this.#n(()=>{this.#g=null,this.#h()},a),this.#g?.unref?.())}async#h(){if(this.#i||this.#c)return;let a=this.#C();this.#c=a;try{await a}finally{this.#c===a&&(this.#c=null)}}async#C(){try{if(await this.#e.ensureRunning(),this.#i)return;let a=await this.#A.initialize();if(this.#i)return;this.#l?.(a),this.#l=null;let{configured:o,connected:i}=a.totals;if(i65535)throw new Error("dsh-im Enterprise WeChat requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function UBe(n){let a=Lg(n.dshHome??process.env.DSH_HOME??op(FBe(),".dsh")),o=Lg(n.dataDir??op(a,"integrations","dsh-wecom"));return{config:Lg(n.configPath??op(o,"config.json")),bots:Lg(n.botsDir??op(o,"bots")),workspaces:Lg(n.workspacesPath??op(o,"workspaces.json"))}}async function TN(n,a={},o={}){if(!n?.credentials)throw new TypeError("dsh-im Enterprise WeChat requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-im Enterprise WeChat requires ctx.webServer");let i=o.ConfigStore??nQ,e=o.StateStore??lQ,r=o.HarnessClient??gQ,A=o.Controller??ap,t=o.Runtime??ip,s=o.QrAuth??cQ,g=o.createConnectionSupervisor??NN,c=typeof n.logger=="function"?n.logger("dsh-im:wecom"):n.logger??console,l=UBe(a),C=await new i(l.config).load(),B=Lg(a.workspace??process.cwd()),Q=o.WorkspaceStore??Ia,f=o.workspaces??await new Q(l.workspaces,{defaultWorkspace:B}).load(),y=C.list();await f.reconcile(y.map(G=>G.botId)),await Promise.all(y.map(G=>f.ensure(G.botId)));let m=typeof C.remove=="function"?Ua(C,{workspaces:f}):C,T=o.qrAuth??new s({source:a.qrSource??"deepseek-harness",platform:a.qrPlatform}),k=new Map,F=G=>Lg(l.bots,G,"state.json"),j=async G=>{let R=k.get(G);return R||(R=await new e(F(G)).load(),k.set(G,R)),R},x=new r({baseUrl:LBe(n.webServer,a.harnessBaseUrl),workspace:B,agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),H=new A({qrAuth:T,credentials:n.credentials,configStore:m,logger:c,createRuntime:async({botId:G,config:R,secret:Z})=>{let U=await j(G);await f.ensure(G);let b=Ha(x,{botId:G,workspaces:f,state:U});return new t({config:R,secret:Z,harness:b.harness,state:b.state,replyTimeoutMs:a.replyTimeoutMs??6e5,connectTimeoutMs:a.connectTimeoutMs??2e4,maxReconnectAttempts:a.maxReconnectAttempts??10,logger:{error:(...L)=>c.error?.(`[${G}]`,...L),warn:(...L)=>c.warn?.(`[${G}]`,...L),info:(...L)=>c.info?.(`[${G}]`,...L),debug:(...L)=>c.debug?.(`[${G}]`,...L)}})},deleteState:async({botId:G})=>{let R=k.get(G);if(k.delete(G),R&&typeof R.remove=="function")await R.remove();else try{await GBe(F(G))}catch(Z){if(Z?.code!=="ENOENT")throw Z}}}),J=Ka(H,{workspaces:f,stateFor:j}),K=g({controller:J,harness:x,logger:c,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:J,ready:K.ready,async close(){await K.close(),await J.close(),x.stopManagedProcess()}}}import HBe from"qrcode";var q1="/wecom",wa=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:cr}),V1=Object.freeze(Object.values(wa)),KBe=new Set(["secret","secretRef","scode","remoteBotId","verificationUrl","bot_info","botid"]);function vN(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function RI(n,a){return vN(n)&&Object.keys(n).every(o=>a.includes(o))}function RN(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function J1(n,a){return typeof n=="string"&&n.trim().length>0&&n.length<=a}function YBe(n,a){return vN(a)?n===wa.status?RI(a,[])?null:"connection.status does not accept fields.":n===wa.beginProvisioning?RI(a,["locale"])&&(a.locale===void 0||a.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[wa.pollProvisioning,wa.cancelProvisioning].includes(n)?RI(a,["attemptId"])&&RN(a.attemptId)?null:`${n} requires an attemptId.`:n===wa.bindCredentials?RI(a,["botId","secret"])&&J1(a.botId,512)&&J1(a.secret,1024)?null:"bot.bind-credentials requires Bot ID and Secret.":n===wa.reconnectBot?RI(a,["botId"])&&RN(a.botId)?null:"bot.reconnect requires a botId.":n===wa.deleteBot?RI(a,["botId","confirm"])&&RN(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===wa.setWorkspace?xa(a)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Unknown Enterprise WeChat endpoint.":"Payload must be an object."}function kI(n){if(Array.isArray(n))return n.map(kI);if(!vN(n))return n;let a={};for(let[o,i]of Object.entries(n))KBe.has(o)||(a[o]=kI(i));return a}async function xBe(n){return HBe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function kN(n,a){return!n||typeof n.verificationUrl!="string"?kI(n):kI({...n,qrCodeDataUrl:await a(n.verificationUrl)})}async function np(n,a){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await kN(o.provisioning,a)),kI(o)}function z1(n,{encodeQr:a=xBe}={}){for(let e of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[e]!="function")throw new TypeError(`A complete Enterprise WeChat controller is required (${e})`);let o=new Map,i=e=>{let r=o.get(e);return r||(o.size>=16&&o.delete(o.keys().next().value),r=Promise.resolve().then(()=>a(e)),o.set(e,r)),r};return async(e,r,A)=>{if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!V1.includes(e))return{ok:!1,error:{code:"bad-request",message:"Unknown Enterprise WeChat endpoint."}};let t=YBe(e,r);if(t)return{ok:!1,error:{code:"bad-request",message:t}};try{let s;if(e===wa.status)s=await np(await n.status(),i);else if(e===wa.beginProvisioning)s=await kN(await n.startProvisioning(),i);else if(e===wa.pollProvisioning){let g=await n.registrationStatus(r.attemptId);if(!g)return{ok:!1,error:{code:"bad-request",message:"The provisioning attempt no longer exists."}};s=await kN(g,i)}else if(e===wa.cancelProvisioning)s=kI(await n.cancelProvisioning(r.attemptId));else if(e===wa.bindCredentials)s=await np(await n.bindCredentials(r),i);else if(e===wa.reconnectBot)s=await np(await n.reconnectBot(r.botId),i);else if(e===wa.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await np(await n.updateWorkspace(r.botId,r.workspace),i)}else s=await np(await n.deleteBot(r.botId),i);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:s}}catch(s){let g=ja(s);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:g??{code:"wecom-operation-failed",message:"\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}}}function uQ(n,a,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(q1,z1(a,o),{authority:Ya(i)})}async function W1(n,a={}){if(a?.controller)return uQ(n,a.controller,a.rpcOptions,a.rpcAuthority);let o=await TN(n,a,a.internals),i=uQ(n,o.controller,a.rpcOptions,a.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Enterprise WeChat bot connections"),i}import{unlink as MQe}from"node:fs/promises";import{homedir as bQe}from"node:os";import{join as lp,resolve as Ug}from"node:path";import{createHash as tQe}from"node:crypto";import{mkdir as aQe,readFile as rQe,rename as iQe,unlink as oQe,writeFile as nQe}from"node:fs/promises";import{dirname as sQe}from"node:path";import{randomBytes as jBe,randomUUID as JBe}from"node:crypto";var QQ="https://ilinkai.weixin.qq.com/",qBe="2.4.6",VBe="3",zBe="bot",WBe=2<<16|1024|6,ZBe=15e3,Z1=35e3,XBe=new Set(["wait","scaned","confirmed","expired","scaned_but_redirect","need_verifycode","verify_code_blocked","binded_redirect"]),ot=class extends Error{constructor(a,o,i={}){super(o,i),this.name="WeixinApiError",this.code=a,this.status=i.status}};function ki(n){return typeof n=="string"&&n.trim()?n.trim():null}function PN(n){let a=n.toLowerCase().replace(/\.$/,"");return a==="weixin.qq.com"||a.endsWith(".weixin.qq.com")}function PI(n){let a;try{a=new URL(n)}catch{throw new ot("invalid-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002")}if(a.protocol!=="https:"||!PN(a.hostname)||a.port!==""&&a.port!=="443")throw new ot("untrusted-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002");return a.username="",a.password="",a.search="",a.hash="",a.pathname.endsWith("/")||(a.pathname+="/"),a.toString()}function $Be(n){let a=ki(n);if(!a)throw new ot("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u5730\u5740\u3002");let o;try{o=new URL(a)}catch{throw new ot("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u626B\u7801\u5730\u5740\u3002")}if(o.protocol!=="https:"||!PN(o.hostname))throw new ot("untrusted-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002");return o.toString()}function $1(){return{"iLink-App-Id":zBe,"iLink-App-ClientVersion":String(WBe)}}function eQe(n){let a={...$1(),"content-type":"application/json",AuthorizationType:"ilink_bot_token","X-WECHAT-UIN":Buffer.from(String(jBe(4).readUInt32BE(0)),"utf8").toString("base64")};return ki(n)&&(a.Authorization=`Bearer ${n.trim()}`),a}function BQ(){return{channel_version:qBe,bot_agent:"DeepSeekHarness/0.7.1"}}function X1(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}async function vI(n,{method:a,baseUrl:o,endpoint:i,body:e,token:r,timeoutMs:A=ZBe,signal:t,authenticated:s=!0}){let g=PI(o),c=new URL(i,g);if(!PN(c.hostname))throw new ot("untrusted-endpoint","\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002");let l=new AbortController,C=!1,B=()=>l.abort(t?.reason);if(t?.aborted)throw X1(t);t?.addEventListener("abort",B,{once:!0});let Q=A>0?setTimeout(()=>{C=!0,l.abort()},A):null;try{let f=await n(c,{method:a,headers:s?eQe(r):$1(),...e===void 0?{}:{body:JSON.stringify(e)},signal:l.signal});if(!f.ok)throw new ot("http-error",`\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${f.status}\uFF09\u3002`,{status:f.status});try{return await f.json()}catch(y){throw new ot("invalid-response","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002",{cause:y})}}catch(f){throw t?.aborted?X1(t):C?new ot("timeout","\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002",{cause:f}):f instanceof ot?f:new ot("network-error","\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002",{cause:f})}finally{Q&&clearTimeout(Q),t?.removeEventListener("abort",B)}}function AQe(n){if(!n||typeof n!="object"||!XBe.has(n.status))throw new ot("invalid-login-status","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002");return n}function e3({fetchImpl:n=fetch}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");return Object.freeze({async beginLogin({localTokens:a=[],botType:o=VBe,signal:i}={}){let e=[...new Set(a.map(ki).filter(Boolean))].slice(-10),r=await vI(n,{method:"POST",baseUrl:QQ,endpoint:`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(o)}`,body:{local_token_list:e},timeoutMs:1e4,signal:i}),A=ki(r?.qrcode);if(!A)throw new ot("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4EE4\u724C\u3002");return{qrcode:A,qrcodeUrl:$Be(r.qrcode_img_content)}},async pollLogin({qrcode:a,baseUrl:o=QQ,verifyCode:i,signal:e}){let r=ki(a);if(!r)throw new TypeError("qrcode is required");let A=`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(r)}`;ki(i)&&(A+=`&verify_code=${encodeURIComponent(i.trim())}`);let t=await vI(n,{method:"GET",baseUrl:o,endpoint:A,timeoutMs:Z1,signal:e,authenticated:!1});return AQe(t)},async getUpdates({baseUrl:a,token:o,getUpdatesBuf:i="",timeoutMs:e,signal:r}){try{return await vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/getupdates",body:{get_updates_buf:i,base_info:BQ()},token:o,timeoutMs:e??Z1,signal:r})}catch(A){if(A instanceof ot&&A.code==="timeout")return{ret:0,msgs:[],get_updates_buf:i};throw A}},async sendText({baseUrl:a,token:o,toUserId:i,text:e,contextToken:r,runId:A,signal:t}){let s=ki(i),g=ki(e);if(!s||!g)throw new TypeError("toUserId and text are required");let c=await vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/sendmessage",token:o,signal:t,body:{msg:{from_user_id:"",to_user_id:s,client_id:`dsh-weixin-${JBe()}`,message_type:2,message_state:2,item_list:[{type:1,text_item:{text:g}}],...ki(r)?{context_token:r.trim()}:{},...ki(A)?{run_id:A.trim()}:{}},base_info:BQ()}});if(c?.ret!==void 0&&c.ret!==0)throw new ot("send-rejected","\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async notifyStart({baseUrl:a,token:o,signal:i}){let e=await vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystart",token:o,signal:i,timeoutMs:1e4,body:{base_info:BQ()}});if(e?.ret!==void 0&&e.ret!==0)throw new ot("start-rejected","\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002");return e},async notifyStop({baseUrl:a,token:o,signal:i}){return vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystop",token:o,signal:i,timeoutMs:1e4,body:{base_info:BQ()}})}})}function sp(n){for(let a of n?.item_list??[]){if(a?.type===1&&typeof a.text_item?.text=="string"){let o=a.text_item.text.trim();if(o)return o}if(a?.type===3&&typeof a.voice_item?.text=="string"){let o=a.voice_item.text.trim();if(o)return o}}return null}function GN(n){return n?.message_id!==void 0&&n.message_id!==null?String(n.message_id):ki(n?.client_id)}function A3(n,a=4e3){if(n.length<=a)return[n];let o=[],i=n;for(;i.length>a;){let e=i.lastIndexOf(` +`).trim()),a.chattype==="group"?o.replace(/^\s*@\S+(?:\s+|$)/u,"").trim():o}function CQ(n,a=MBe){let o=String(n??"").trim();if(!o)return[];let i=[],e="",r=0;for(let A of o){let t=Buffer.byteLength(A);e&&r+t>a?(i.push(e),e=A,r=t):(e+=A,r+=t)}return e&&i.push(e),i}function bBe(n){return n?.type==="text"?n.text:n?.type==="tool"?`\u6B63\u5728\u4F7F\u7528${n.name}\u2026`:n?.text}function _Be(n,a){return a.questions[a.index]&&TI(rp(n).from?.userid)===a.actor&&TI(pQ(n))}function _N(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var hQ=class{#A;#e;#t;#a;#s;#n;#E;#g;#c=new Map;#r=new Map;#i=new Map;#o=new Set;#I=new Set;#l;constructor({client:a,harness:o,state:i,status:e=_N(),logger:r=console,replyTimeoutMs:A=6e5,generateStreamId:t=wBe,signal:s}){if(!a||typeof a.replyStream!="function"||typeof a.sendMessage!="function")throw new TypeError("Enterprise WeChat client is required");if(!o||!i)throw new TypeError("Harness client and state store are required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#l=new nr({label:"wecom",logger:r})}get status(){return structuredClone(this.#a)}accept(a){if(this.#g?.aborted)return Promise.resolve();let o=rp(a),i=TI(o.msgid),e=TI(o.from?.userid),r=o.chattype==="group"?TI(o.chatid):e;if(!i||!e||!r||!["single","group"].includes(o.chattype)||this.#t.hasSeen(i)||this.#o.has(i))return Promise.resolve();let A=x1(a);this.#o.add(i);let t=this.#r.get(A),s=this.#l.claimReply({key:A,actor:e,messageId:i,text:pQ(a),addressed:!0,hasPendingQuestion:!!t,questionCompletion:t?.submitting||t?.claimedReplyMessageId?t.queue:null,isQuestionPending:()=>this.#r.has(A),send:g=>this.#C(a,r,g)});if(s){let g;return g=s.process(async()=>this.#t.hasSeen(i)?!1:(await this.#t.markSeen(i),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#o.delete(i),this.#I.delete(g)}),this.#I.add(g),g}if(t&&t.actor!==e)return this.#p(a,i,A);if(t?.submitting||t?.claimedReplyMessageId)return this.#p(a,i,A);if(t){_Be(a,t)&&(t.claimedReplyMessageId=i);let c=(t.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#B(a,i,e,r,A,t)).finally(()=>{this.#o.delete(i),t.claimedReplyMessageId===i&&(t.claimedReplyMessageId=null),t.queue===c&&(t.queue=null)});return t.queue=c,c}return this.#p(a,i,A)}#p(a,o,i,{releaseMessageId:e=!0,alreadyRecorded:r=!1}={}){let t=(this.#c.get(i)??Promise.resolve()).catch(()=>{}).then(()=>this.#d(a,{alreadyRecorded:r})).finally(()=>{e&&this.#o.delete(o),this.#c.get(i)===t&&this.#c.delete(i)});return this.#c.set(i,t),t}async waitForIdle(){await Promise.allSettled([...this.#c.values(),...[...this.#r.values()].flatMap(a=>a.queue?[a.queue]:[]),...this.#I])}async#h(a,o){for(let i of CQ(o))this.#g?.throwIfAborted(),await this.#A.sendMessage(a,{msgtype:"markdown",markdown:{content:i}})}async#C(a,o,i){this.#g?.throwIfAborted();let e=CQ(i);if(e.length!==0)try{await this.#A.replyStream(a,this.#E("stream"),e[0],!0);for(let r of e.slice(1))await this.#A.sendMessage(o,{msgtype:"markdown",markdown:{content:r}})}catch{await this.#h(o,i)}}async#d(a,{alreadyRecorded:o=!1}={}){if(this.#g?.aborted)return;let i=rp(a),e=typeof i.msgid=="string"?i.msgid:"",r=typeof i.from?.userid=="string"?i.from.userid:"",A=i.chattype==="group"?i.chatid:r;if(!e||!r||!A||!["single","group"].includes(i.chattype))return;if(!o){if(this.#t.hasSeen(e))return;this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString()}let t=pQ(a),s=x1(a),g=null,c=!1;try{if(!t){await this.#C(a,A,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u8BED\u97F3\u8F6C\u5199\u548C\u56FE\u6587\u6DF7\u6392\u4E2D\u7684\u6587\u5B57\u6D88\u606F\u3002"),await this.#t.markSeen(e);return}let l=t.toLowerCase();if(l==="/help"){await this.#C(a,A,OBe),await this.#t.markSeen(e);return}if(l==="/status"){await this.#e.ensureRunning({signal:this.#g}),await this.#C(a,A,"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),await this.#t.markSeen(e);return}if(l==="/new"){await this.#t.clearSession(s),await this.#C(a,A,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#t.markSeen(e);return}let C=await xr(t,this.#e,s);if(C){for(let y of C.messages??[C.message])await this.#C(a,A,y);await this.#t.markSeen(e);return}g=this.#E("stream");try{await this.#A.replyStream(a,g,"\u6B63\u5728\u601D\u8003\u4E2D\u2026",!1),c=!0}catch(y){this.#s.warn?.("[dsh-im:wecom] unable to start a stream; using an active reply:",y)}let{answer:B}=await sr({harness:this.#e,state:this.#t,key:s,text:t,createOptions:{signal:this.#g},existsOptions:{signal:this.#g},askOptions:{timeoutMs:this.#n,signal:this.#g,onUpdate:c&&typeof this.#A.replyStreamNonBlocking=="function"?async y=>{let m=CQ(bBe(y))[0];m&&await this.#A.replyStreamNonBlocking(a,g,m,!1)}:void 0,onInteraction:y=>this.#u(y,{key:s,actor:r,chatId:A,requiresMention:i.chattype==="group"}),onInteractionResolved:y=>this.#Q(y)}}),Q=CQ(B||"\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u4F46\u6CA1\u6709\u751F\u6210\u53EF\u663E\u793A\u7684\u6587\u672C\u3002"),f=!1;if(c&&Q.length>0)try{await this.#A.replyStream(a,g,Q[0],!0);for(let y of Q.slice(1))await this.#A.sendMessage(A,{msgtype:"markdown",markdown:{content:y}});f=!0}catch(y){this.#s.warn?.("[dsh-im:wecom] stream finalization failed; using an active reply:",y)}f||await this.#h(A,B),await this.#t.markSeen(e),this.#a.messagesReplied+=1,this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null}catch(l){if(this.#g?.aborted)return;this.#a.lastError=l?.message??String(l),this.#s.error?.("[dsh-im:wecom] failed to process an inbound message");try{c&&g?await this.#A.replyStream(a,g,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",!0):await this.#C(a,A,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),await this.#t.markSeen(e)}catch{this.#s.error?.("[dsh-im:wecom] failed to send the safe error reply")}}finally{await Promise.allSettled([this.#w(s),this.#l.closeRoute(s)])}}async#B(a,o,i,e,r,A){if(this.#g?.aborted)return;let t=this.#r.get(r),s=A.claimedReplyMessageId===o;if(!t||t!==A||t.submitting)return s&&(!t||t!==A)?this.#f(a,o,e):this.#p(a,o,r,{releaseMessageId:!1});if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString();let g=TI(pQ(a));if(!g){await this.#C(a,e,"\u8BF7\u7528\u6587\u5B57\u6216\u8BED\u97F3\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002").catch(()=>{});return}let c=this.#r.get(r);if(!c||c!==A||c.submitting){if(s&&(!c||c!==A)){await this.#C(a,e,EQ).catch(()=>{});return}return this.#p(a,o,r,{releaseMessageId:!1,alreadyRecorded:!0})}if(c.actor!==i)return this.#p(a,o,r,{releaseMessageId:!1,alreadyRecorded:!0});if(c.chatId=e,c.needsPresentation){try{await this.#y(c)}catch{this.#a.lastError="\u4F01\u4E1A\u5FAE\u4FE1\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002",this.#s.error?.("[dsh-im:wecom] failed to retry an interaction question"),c.interaction.reconnect?.();return}let C=this.#r.get(r);if(!C||C!==A||C.submitting){if(s&&(!C||C!==A)){await this.#C(a,e,EQ).catch(()=>{});return}return this.#p(a,o,r,{releaseMessageId:!1,alreadyRecorded:!0})}}let l=c.questions[c.index];if(l){if(c.answers.push(Yr(l,g)),c.index+=1,c.index{});return}if(this.#r.get(r)!==c)return;c.submitting=!1,c.answers.pop(),c.index-=1,this.#a.lastError="\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\u3002",this.#s.error?.("[dsh-im:wecom] failed to answer a Harness interaction"),await this.#C(a,e,"\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u5F53\u524D\u95EE\u9898\u7684\u7B54\u6848\u3002").catch(()=>{})}}}async#u(a,{key:o,actor:i,chatId:e,requiresMention:r}){if(a?.kind==="approval")return this.#l.handleRequested(a,{key:o,actor:i,requiresMention:r,send:c=>this.#h(e,c)});if(a?.kind!=="question")return;let A=a?.payload?.questions,t=typeof a?.interactionId=="string"?a.interactionId:a?.rpcId;if(typeof a?.rpcId!="string"||typeof t!="string"||typeof a.sessionId!="string"||!Array.isArray(A)||A.length===0||A.some(c=>!Hr(c))){this.#s.warn?.("[dsh-im:wecom] ignored an invalid Harness question interaction");return}if(a.recovered===!0){await a.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat safely cancelled an interaction left by an earlier client.",details:{}}}),await this.#h(e,"\u68C0\u6D4B\u5230\u8FD9\u4E2A Session \u4E2D\u9057\u7559\u7684\u5F85\u56DE\u7B54\u95EE\u9898\uFF0C\u5DF2\u5B89\u5168\u53D6\u6D88\u5E76\u7EE7\u7EED\u5904\u7406\u4F60\u521A\u624D\u7684\u6D88\u606F\u3002").catch(()=>{});return}let s=this.#r.get(o);if(s?.interactionId===t){s.interaction=a,s.needsPresentation&&await this.#y(s);return}if(this.#i.has(t))return;if(s){this.#s.warn?.("[dsh-im:wecom] cancelled a second pending Harness question"),await a.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat is already handling another user interaction.",details:{}}});return}let g={kind:"question",interactionId:t,sessionId:a.sessionId,interaction:a,actor:i,requiresMention:r,questions:A,answers:[],index:0,chatId:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationPromise:null};this.#r.set(o,g),this.#i.set(g.interactionId,o),await this.#y(g)}async#Q(a){if(a?.kind==="approval"){await this.#l.handleResolved(a);return}let o=a?.interactionId;if(a?.kind!=="question"||typeof o!="string")return;let i=this.#i.get(o);i&&this.#m(i,o)}#y(a){if(!a.needsPresentation)return Promise.resolve();if(a.presentationPromise)return a.presentationPromise;let o=a.questions[a.index];if(!o)return Promise.resolve();let i=this.#h(a.chatId,Kr(o,a.index,a.questions.length,{requiresMention:a.requiresMention})).then(()=>{a.needsPresentation=!1}).finally(()=>{a.presentationPromise===i&&(a.presentationPromise=null)});return a.presentationPromise=i,i}async#f(a,o,i){this.#t.hasSeen(o)||(await this.#t.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),await this.#C(a,i,EQ).catch(()=>{}))}#D(a,o){let i=this.#r.get(a);return!i||o!==void 0&&i.interactionId!==o?null:(this.#r.delete(a),this.#i.delete(i.interactionId),i)}#m(a,o){return this.#D(a,o)!==null}async#w(a){let o=this.#D(a);if(!(!o||o.kind!=="question"))try{await o.interaction.respond({ok:!1,error:{code:"cancelled",message:"The Enterprise WeChat interaction ended before the user answered.",details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){i?.code!=="interaction-not-pending"&&this.#s.warn?.("[dsh-im:wecom] failed to cancel a pending Harness interaction")}}};function kBe(){let n=new Error("Enterprise WeChat WebSocket authentication timed out");return n.code="connect-timeout",n}function vBe(){return{startedAt:null,ready:!1,wecomConnectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,..._N()}}var ip=class{#A;#e;#t;#a;#s;#n;#E;#g;#c;#r=vBe();#i=null;#o=null;#I=null;#l=null;#p=null;constructor({config:a,secret:o,harness:i,state:e,logger:r=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,maxReconnectAttempts:s=10,createClient:g=c=>new TBe(c)}){if(!a||!o||!i||!e)throw new TypeError("WecomRuntime requires config, secret, Harness, and state");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A,this.#E=t,this.#g=s,this.#c=g}get status(){return structuredClone(this.#r)}async start(){if(this.#r.ready&&this.#i)return this.status;if(this.#I)return this.#I;this.#p?.abort(new DOMException("Enterprise WeChat runtime replaced","AbortError"));let a=new AbortController;return this.#l=a,this.#p=a,this.#I=this.#h(a.signal).finally(()=>{this.#l===a&&(this.#l=null),this.#I=null}),this.#I}async#h(a){await this.#C(),a.throwIfAborted(),this.#r.startedAt=new Date().toISOString(),this.#r.wecomConnectionState="connecting",this.#r.lastError=null,await this.#t.ensureRunning(),this.#r.harnessReachable=!0;let o={debug(){},info(){},warn(){},error(){}},i=this.#c({botId:this.#A.remoteBotId,secret:this.#e,logger:o,maxReconnectAttempts:this.#g});if(!i||typeof i.connect!="function"||typeof i.disconnect!="function")throw new TypeError("Enterprise WeChat client factory returned an invalid client");this.#i=i,this.#o=new hQ({client:i,harness:this.#t,state:this.#a,status:this.#r,logger:this.#s,replyTimeoutMs:this.#n,signal:a});let e,r,A=!1,t=new Promise((Q,f)=>{e=Q,r=f}),s=()=>{if(this.#i!==i||a.aborted)return;A=!0;let Q=Date.now();this.#r.ready=!0,this.#r.wecomConnectionState="connected",this.#r.lastCheckedAt=Q,this.#r.lastConnectedAt=Q,this.#r.lastError=null,e()},g=()=>{this.#i===i&&(this.#r.ready=!1,this.#r.wecomConnectionState="connecting",this.#r.lastCheckedAt=Date.now())},c=()=>{this.#i===i&&(this.#r.ready=!1,this.#r.wecomConnectionState="connecting",this.#r.lastCheckedAt=Date.now())},l=Q=>{if(this.#i!==i)return;let f=Q instanceof NBe||Q instanceof RBe;!A&&f&&r(Q),f&&(this.#r.ready=!1,this.#r.wecomConnectionState="failed"),this.#r.lastError=f?Q.name:"connection-error",this.#s.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} connection error`)},C=Q=>this.#o?.accept(Q);i.on("authenticated",s),i.on("disconnected",g),i.on("reconnecting",c),i.on("error",l),i.on("message",C);let B;try{return i.connect(),await Promise.race([t,new Promise((Q,f)=>{a.addEventListener("abort",()=>f(a.reason),{once:!0})}),new Promise((Q,f)=>{B=setTimeout(()=>f(kBe()),this.#E)})]),this.status}catch(Q){throw a.aborted?(await this.#C(),Q):(this.#r.ready=!1,this.#r.wecomConnectionState="failed",this.#r.lastError=Q?.message??String(Q),await this.#C(),Q)}finally{clearTimeout(B)}}async stop(){let a=this.#I;return this.#l?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#p?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#p=null,await this.#C(),await a?.catch(()=>{}),this.status}async#C(){let a=this.#i,o=this.#o;this.#i=null,this.#o=null;try{a?.disconnect(),a?.removeAllListeners?.()}catch{this.#s.warn?.(`[dsh-im:wecom] bot ${this.#A.botId} failed to stop cleanly`)}await o?.waitForIdle(),this.#r.ready=!1,this.#r.wecomConnectionState="idle"}};var j1=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function PBe(n){if(!Array.isArray(n)||n.length===0)return[...j1];let a=n.filter(o=>Number.isFinite(o)&&o>=0);return a.length>0?a:[...j1]}var dQ=class{#A;#e;#t;#a;#s;#n;#E;#g=null;#c=null;#r=0;#i=!1;#o=!1;#I;#l;constructor({controller:a,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:r=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!a||typeof a.initialize!="function"||typeof a.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#A=a,this.#e=o,this.#t=i,this.#a=PBe(e),this.#s=Number.isFinite(r)&&r>=0?r:15e3,this.#n=A,this.#E=t,this.#I=new Promise(s=>{this.#l=s})}get ready(){return this.#I}start(){return this.#o||this.#i?this:(this.#o=!0,this.#p(0),this)}async close(){this.#i||(this.#i=!0,this.#g!==null&&this.#E(this.#g),this.#g=null,await this.#c?.catch(()=>{}),this.#l?.(null),this.#l=null)}#p(a){this.#i||(this.#g=this.#n(()=>{this.#g=null,this.#h()},a),this.#g?.unref?.())}async#h(){if(this.#i||this.#c)return;let a=this.#C();this.#c=a;try{await a}finally{this.#c===a&&(this.#c=null)}}async#C(){try{if(await this.#e.ensureRunning(),this.#i)return;let a=await this.#A.initialize();if(this.#i)return;this.#l?.(a),this.#l=null;let{configured:o,connected:i}=a.totals;if(i65535)throw new Error("dsh-im Enterprise WeChat requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function UBe(n){let a=Lg(n.dshHome??process.env.DSH_HOME??op(FBe(),".dsh")),o=Lg(n.dataDir??op(a,"integrations","dsh-wecom"));return{config:Lg(n.configPath??op(o,"config.json")),bots:Lg(n.botsDir??op(o,"bots")),workspaces:Lg(n.workspacesPath??op(o,"workspaces.json"))}}async function TN(n,a={},o={}){if(!n?.credentials)throw new TypeError("dsh-im Enterprise WeChat requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-im Enterprise WeChat requires ctx.webServer");let i=o.ConfigStore??nQ,e=o.StateStore??lQ,r=o.HarnessClient??gQ,A=o.Controller??ap,t=o.Runtime??ip,s=o.QrAuth??cQ,g=o.createConnectionSupervisor??NN,c=typeof n.logger=="function"?n.logger("dsh-im:wecom"):n.logger??console,l=UBe(a),C=await new i(l.config).load(),B=Lg(a.workspace??process.cwd()),Q=o.WorkspaceStore??Ia,f=o.workspaces??await new Q(l.workspaces,{defaultWorkspace:B}).load(),y=C.list();await f.reconcile(y.map(G=>G.botId)),await Promise.all(y.map(G=>f.ensure(G.botId)));let m=typeof C.remove=="function"?Ua(C,{workspaces:f}):C,T=o.qrAuth??new s({source:a.qrSource??"deepseek-harness",platform:a.qrPlatform}),k=new Map,F=G=>Lg(l.bots,G,"state.json"),j=async G=>{let R=k.get(G);return R||(R=await new e(F(G)).load(),k.set(G,R)),R},x=new r({baseUrl:LBe(n.webServer,a.harnessBaseUrl),workspace:B,agentPreset:a.agentPreset??"standard",autostart:!1,dshBin:a.dshBin??"dsh"}),H=new A({qrAuth:T,credentials:n.credentials,configStore:m,logger:c,createRuntime:async({botId:G,config:R,secret:Z})=>{let U=await j(G);await f.ensure(G);let b=Ha(x,{botId:G,workspaces:f,state:U});return new t({config:R,secret:Z,harness:b.harness,state:b.state,replyTimeoutMs:a.replyTimeoutMs??6e5,connectTimeoutMs:a.connectTimeoutMs??2e4,maxReconnectAttempts:a.maxReconnectAttempts??10,logger:{error:(...L)=>c.error?.(`[${G}]`,...L),warn:(...L)=>c.warn?.(`[${G}]`,...L),info:(...L)=>c.info?.(`[${G}]`,...L),debug:(...L)=>c.debug?.(`[${G}]`,...L)}})},deleteState:async({botId:G})=>{let R=k.get(G);if(k.delete(G),R&&typeof R.remove=="function")await R.remove();else try{await GBe(F(G))}catch(Z){if(Z?.code!=="ENOENT")throw Z}}}),J=Ka(H,{workspaces:f,stateFor:j}),K=g({controller:J,harness:x,logger:c,retryDelaysMs:a.retryDelaysMs,healthyIntervalMs:a.healthyIntervalMs}).start();return{controller:J,ready:K.ready,async close(){await K.close(),await J.close(),x.stopManagedProcess()}}}import HBe from"qrcode";var q1="/wecom",wa=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:cr}),V1=Object.freeze(Object.values(wa)),KBe=new Set(["secret","secretRef","scode","remoteBotId","verificationUrl","bot_info","botid"]);function vN(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function RI(n,a){return vN(n)&&Object.keys(n).every(o=>a.includes(o))}function RN(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function J1(n,a){return typeof n=="string"&&n.trim().length>0&&n.length<=a}function YBe(n,a){return vN(a)?n===wa.status?RI(a,[])?null:"connection.status does not accept fields.":n===wa.beginProvisioning?RI(a,["locale"])&&(a.locale===void 0||a.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[wa.pollProvisioning,wa.cancelProvisioning].includes(n)?RI(a,["attemptId"])&&RN(a.attemptId)?null:`${n} requires an attemptId.`:n===wa.bindCredentials?RI(a,["botId","secret"])&&J1(a.botId,512)&&J1(a.secret,1024)?null:"bot.bind-credentials requires Bot ID and Secret.":n===wa.reconnectBot?RI(a,["botId"])&&RN(a.botId)?null:"bot.reconnect requires a botId.":n===wa.deleteBot?RI(a,["botId","confirm"])&&RN(a.botId)&&a.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===wa.setWorkspace?xa(a)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":"Unknown Enterprise WeChat endpoint.":"Payload must be an object."}function kI(n){if(Array.isArray(n))return n.map(kI);if(!vN(n))return n;let a={};for(let[o,i]of Object.entries(n))KBe.has(o)||(a[o]=kI(i));return a}async function xBe(n){return HBe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function kN(n,a){return!n||typeof n.verificationUrl!="string"?kI(n):kI({...n,qrCodeDataUrl:await a(n.verificationUrl)})}async function np(n,a){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await kN(o.provisioning,a)),kI(o)}function z1(n,{encodeQr:a=xBe}={}){for(let e of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[e]!="function")throw new TypeError(`A complete Enterprise WeChat controller is required (${e})`);let o=new Map,i=e=>{let r=o.get(e);return r||(o.size>=16&&o.delete(o.keys().next().value),r=Promise.resolve().then(()=>a(e)),o.set(e,r)),r};return async(e,r,A)=>{if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!V1.includes(e))return{ok:!1,error:{code:"bad-request",message:"Unknown Enterprise WeChat endpoint."}};let t=YBe(e,r);if(t)return{ok:!1,error:{code:"bad-request",message:t}};try{let s;if(e===wa.status)s=await np(await n.status(),i);else if(e===wa.beginProvisioning)s=await kN(await n.startProvisioning(),i);else if(e===wa.pollProvisioning){let g=await n.registrationStatus(r.attemptId);if(!g)return{ok:!1,error:{code:"bad-request",message:"The provisioning attempt no longer exists."}};s=await kN(g,i)}else if(e===wa.cancelProvisioning)s=kI(await n.cancelProvisioning(r.attemptId));else if(e===wa.bindCredentials)s=await np(await n.bindCredentials(r),i);else if(e===wa.reconnectBot)s=await np(await n.reconnectBot(r.botId),i);else if(e===wa.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await np(await n.updateWorkspace(r.botId,r.workspace),i)}else s=await np(await n.deleteBot(r.botId),i);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:s}}catch(s){let g=ja(s);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:g??{code:"wecom-operation-failed",message:"\u4F01\u4E1A\u5FAE\u4FE1\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}}}function uQ(n,a,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(q1,z1(a,o),{authority:Ya(i)})}async function W1(n,a={}){if(a?.controller)return uQ(n,a.controller,a.rpcOptions,a.rpcAuthority);let o=await TN(n,a,a.internals),i=uQ(n,o.controller,a.rpcOptions,a.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Enterprise WeChat bot connections"),i}import{unlink as MQe}from"node:fs/promises";import{homedir as bQe}from"node:os";import{join as lp,resolve as Ug}from"node:path";import{createHash as tQe}from"node:crypto";import{mkdir as aQe,readFile as rQe,rename as iQe,unlink as oQe,writeFile as nQe}from"node:fs/promises";import{dirname as sQe}from"node:path";import{randomBytes as jBe,randomUUID as JBe}from"node:crypto";var QQ="https://ilinkai.weixin.qq.com/",qBe="2.4.6",VBe="3",zBe="bot",WBe=2<<16|1024|6,ZBe=15e3,Z1=35e3,XBe=new Set(["wait","scaned","confirmed","expired","scaned_but_redirect","need_verifycode","verify_code_blocked","binded_redirect"]),ot=class extends Error{constructor(a,o,i={}){super(o,i),this.name="WeixinApiError",this.code=a,this.status=i.status}};function ki(n){return typeof n=="string"&&n.trim()?n.trim():null}function PN(n){let a=n.toLowerCase().replace(/\.$/,"");return a==="weixin.qq.com"||a.endsWith(".weixin.qq.com")}function PI(n){let a;try{a=new URL(n)}catch{throw new ot("invalid-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002")}if(a.protocol!=="https:"||!PN(a.hostname)||a.port!==""&&a.port!=="443")throw new ot("untrusted-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002");return a.username="",a.password="",a.search="",a.hash="",a.pathname.endsWith("/")||(a.pathname+="/"),a.toString()}function $Be(n){let a=ki(n);if(!a)throw new ot("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u5730\u5740\u3002");let o;try{o=new URL(a)}catch{throw new ot("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u626B\u7801\u5730\u5740\u3002")}if(o.protocol!=="https:"||!PN(o.hostname))throw new ot("untrusted-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002");return o.toString()}function $1(){return{"iLink-App-Id":zBe,"iLink-App-ClientVersion":String(WBe)}}function eQe(n){let a={...$1(),"content-type":"application/json",AuthorizationType:"ilink_bot_token","X-WECHAT-UIN":Buffer.from(String(jBe(4).readUInt32BE(0)),"utf8").toString("base64")};return ki(n)&&(a.Authorization=`Bearer ${n.trim()}`),a}function BQ(){return{channel_version:qBe,bot_agent:"DeepSeekHarness/0.7.2"}}function X1(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}async function vI(n,{method:a,baseUrl:o,endpoint:i,body:e,token:r,timeoutMs:A=ZBe,signal:t,authenticated:s=!0}){let g=PI(o),c=new URL(i,g);if(!PN(c.hostname))throw new ot("untrusted-endpoint","\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002");let l=new AbortController,C=!1,B=()=>l.abort(t?.reason);if(t?.aborted)throw X1(t);t?.addEventListener("abort",B,{once:!0});let Q=A>0?setTimeout(()=>{C=!0,l.abort()},A):null;try{let f=await n(c,{method:a,headers:s?eQe(r):$1(),...e===void 0?{}:{body:JSON.stringify(e)},signal:l.signal});if(!f.ok)throw new ot("http-error",`\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${f.status}\uFF09\u3002`,{status:f.status});try{return await f.json()}catch(y){throw new ot("invalid-response","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002",{cause:y})}}catch(f){throw t?.aborted?X1(t):C?new ot("timeout","\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002",{cause:f}):f instanceof ot?f:new ot("network-error","\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002",{cause:f})}finally{Q&&clearTimeout(Q),t?.removeEventListener("abort",B)}}function AQe(n){if(!n||typeof n!="object"||!XBe.has(n.status))throw new ot("invalid-login-status","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002");return n}function e3({fetchImpl:n=fetch}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");return Object.freeze({async beginLogin({localTokens:a=[],botType:o=VBe,signal:i}={}){let e=[...new Set(a.map(ki).filter(Boolean))].slice(-10),r=await vI(n,{method:"POST",baseUrl:QQ,endpoint:`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(o)}`,body:{local_token_list:e},timeoutMs:1e4,signal:i}),A=ki(r?.qrcode);if(!A)throw new ot("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4EE4\u724C\u3002");return{qrcode:A,qrcodeUrl:$Be(r.qrcode_img_content)}},async pollLogin({qrcode:a,baseUrl:o=QQ,verifyCode:i,signal:e}){let r=ki(a);if(!r)throw new TypeError("qrcode is required");let A=`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(r)}`;ki(i)&&(A+=`&verify_code=${encodeURIComponent(i.trim())}`);let t=await vI(n,{method:"GET",baseUrl:o,endpoint:A,timeoutMs:Z1,signal:e,authenticated:!1});return AQe(t)},async getUpdates({baseUrl:a,token:o,getUpdatesBuf:i="",timeoutMs:e,signal:r}){try{return await vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/getupdates",body:{get_updates_buf:i,base_info:BQ()},token:o,timeoutMs:e??Z1,signal:r})}catch(A){if(A instanceof ot&&A.code==="timeout")return{ret:0,msgs:[],get_updates_buf:i};throw A}},async sendText({baseUrl:a,token:o,toUserId:i,text:e,contextToken:r,runId:A,signal:t}){let s=ki(i),g=ki(e);if(!s||!g)throw new TypeError("toUserId and text are required");let c=await vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/sendmessage",token:o,signal:t,body:{msg:{from_user_id:"",to_user_id:s,client_id:`dsh-weixin-${JBe()}`,message_type:2,message_state:2,item_list:[{type:1,text_item:{text:g}}],...ki(r)?{context_token:r.trim()}:{},...ki(A)?{run_id:A.trim()}:{}},base_info:BQ()}});if(c?.ret!==void 0&&c.ret!==0)throw new ot("send-rejected","\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async notifyStart({baseUrl:a,token:o,signal:i}){let e=await vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystart",token:o,signal:i,timeoutMs:1e4,body:{base_info:BQ()}});if(e?.ret!==void 0&&e.ret!==0)throw new ot("start-rejected","\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002");return e},async notifyStop({baseUrl:a,token:o,signal:i}){return vI(n,{method:"POST",baseUrl:a,endpoint:"ilink/bot/msg/notifystop",token:o,signal:i,timeoutMs:1e4,body:{base_info:BQ()}})}})}function sp(n){for(let a of n?.item_list??[]){if(a?.type===1&&typeof a.text_item?.text=="string"){let o=a.text_item.text.trim();if(o)return o}if(a?.type===3&&typeof a.voice_item?.text=="string"){let o=a.voice_item.text.trim();if(o)return o}}return null}function GN(n){return n?.message_id!==void 0&&n.message_id!==null?String(n.message_id):ki(n?.client_id)}function A3(n,a=4e3){if(n.length<=a)return[n];let o=[],i=n;for(;i.length>a;){let e=i.lastIndexOf(` `,a);er===null))return null;let o=new Set,i=new Set,e=new Set;for(let r of a){if(o.has(r.botId)||i.has(r.accountId)||e.has(r.tokenRef))return null;o.add(r.botId),i.add(r.accountId),e.add(r.tokenRef)}return Object.freeze({version:1,accounts:Object.freeze(a)})}var fQ=class{#A;#e=FN;#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{let a=cQe(JSON.parse(await rQe(this.#A,"utf8")));if(!a)throw new Error("dsh-weixin config contains invalid account data");this.#e=a}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=FN}return this}list(){return structuredClone(this.#e.accounts)}get(a){let o=this.#e.accounts.find(i=>i.botId===a);return o?structuredClone(o):null}getByAccountId(a){let o=this.#e.accounts.find(i=>i.accountId===a);return o?structuredClone(o):null}async save(a){let o=r3(a);if(!o)throw new Error("Refusing to persist incomplete dsh-weixin account data");return this.#a(i=>{let e=i.find(t=>t.accountId===o.accountId&&t.botId!==o.botId),r=i.find(t=>t.tokenRef===o.tokenRef&&t.botId!==o.botId);if(e||r)throw new Error("Duplicate Weixin account identity");let A=i.findIndex(t=>t.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(a){if(!t3(a))throw new TypeError("Invalid Weixin bot id");return this.#a(o=>{let i=o.findIndex(r=>r.botId===a);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let a=this.#t.then(async()=>{try{await oQe(this.#A)}catch(o){if(o?.code!=="ENOENT")throw o}this.#e=FN});this.#t=a.then(()=>{},()=>{}),await a}async#a(a){let o,i=this.#t.then(async()=>{let e=[...this.#e.accounts];o=a(e);let r=Object.freeze({version:1,accounts:Object.freeze(e)});await this.#s(r),this.#e=r});return this.#t=i.then(()=>{},()=>{}),await i,o}async#s(a){await aQe(sQe(this.#A),{recursive:!0,mode:448});let o=`${this.#A}.tmp`;await nQe(o,`${JSON.stringify(a,null,2)} `,{encoding:"utf8",mode:384}),await iQe(o,this.#A)}};var yQ=class extends Kt{constructor(a){super({...a,rpcIdPrefix:"weixin",logPrefix:"dsh-weixin"})}};import{mkdir as IQe,readFile as lQe,rename as EQe,unlink as CQe,writeFile as pQe}from"node:fs/promises";import{dirname as hQe}from"node:path";var mQ=Object.freeze({version:1,sessions:{},seenMessageIds:[],getUpdatesBuf:""});function dQe(n){if(!n||typeof n!="object")return structuredClone(mQ);let a={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[o,i]of Object.entries(n.sessions))typeof o=="string"&&typeof i=="string"&&i&&(a[o]=i);return{version:1,sessions:a,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[],getUpdatesBuf:typeof n.getUpdatesBuf=="string"?n.getUpdatesBuf:""}}var SQ=class{#A;#e=structuredClone(mQ);#t=Promise.resolve();constructor(a){this.#A=a}async load(){try{this.#e=dQe(JSON.parse(await lQe(this.#A,"utf8")))}catch(a){if(a?.code!=="ENOENT")throw a;this.#e=structuredClone(mQ),await this.#a()}return this}sessionFor(a){return this.#e.sessions[a]??null}async setSession(a,o){this.#e.sessions[a]=o,await this.#a()}async clearSession(a){delete this.#e.sessions[a],await this.#a()}async clearSessions(){this.#e.sessions={},await this.#a()}hasSeen(a){return this.#e.seenMessageIds.includes(a)}async markSeen(a){this.hasSeen(a)||(this.#e.seenMessageIds.push(a),this.#e.seenMessageIds.length>1e3&&this.#e.seenMessageIds.splice(0,this.#e.seenMessageIds.length-1e3),await this.#a())}getUpdatesBuf(){return this.#e.getUpdatesBuf}async setGetUpdatesBuf(a){typeof a!="string"||a===this.#e.getUpdatesBuf||(this.#e.getUpdatesBuf=a,await this.#a())}snapshot(){return structuredClone(this.#e)}async remove(){try{await CQe(this.#A)}catch(a){if(a?.code!=="ENOENT")throw a}this.#e=structuredClone(mQ)}async#a(){let a=`${JSON.stringify(this.#e,null,2)} `,o=this.#t.then(async()=>{await IQe(hQe(this.#A),{recursive:!0,mode:448});let i=`${this.#A}.tmp`;await pQe(i,a,{encoding:"utf8",mode:384}),await EQe(i,this.#A)});this.#t=o.then(()=>{},()=>{}),await o}};import{randomUUID as uQe}from"node:crypto";var i3=new Set(["starting","pending","scanned","needs_verification","connecting"]),DQ=new Set(["connected","expired","failed","cancelled"]),o3=5*6e4;function GI(n){return typeof n=="string"&&n.trim()?n.trim():null}function BQe(){return new DOMException("Provisioning was cancelled","AbortError")}function n3(n,a){let o=GI(n);return o?PI(o.includes("://")?o:`https://${o}`):PI(a)}function gp(n){return n?{attemptId:n.id,status:n.state,...n.verificationUrl?{verificationUrl:n.verificationUrl}:{},...n.expiresAt?{expiresAt:n.expiresAt}:{},pollIntervalMs:1e3,...n.state==="needs_verification"?{verificationRequired:!0}:{},...n.botId?{botId:n.botId}:{},...n.alreadyConnected?{alreadyConnected:!0}:{},...n.error?{error:structuredClone(n.error)}:{}}:null}function Rr(n,a){return Object.freeze({code:n,message:a})}var cp=class{#A;#e;#t;#a;#s;#n;#E=new Map;#g=new Map;#c=new Map;#r=null;#i=new Map;#o=0;#I=!1;constructor({api:a,credentials:o,configStore:i,createRuntime:e,deleteState:r=async()=>{},logger:A=console}){if(!a||typeof a.beginLogin!="function"||typeof a.pollLogin!="function")throw new TypeError("WeixinController requires a Weixin API client");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError("WeixinController requires the DSH credential provider");if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError("WeixinController requires a config store");if(typeof e!="function")throw new TypeError("createRuntime is required");this.#A=a,this.#e=o,this.#t=i,this.#a=e,this.#s=r,this.#n=A}async initialize(){if(this.#I)return this.status();for(let a of this.#t.list())this.#E.get(a.botId)?.status?.ready!==!0&&await this.#Q(a.botId,async()=>{let i=this.#t.get(a.botId);if(!(!i||this.#I))try{let e=await this.#d(i.tokenRef);if(!e){this.#g.set(i.botId,Rr("missing-token","\u767B\u5F55\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u8D26\u53F7\u540E\u91CD\u65B0\u626B\u7801\u3002"));return}await this.#h(i,e),this.#g.delete(i.botId)}catch(e){this.#g.set(i.botId,Rr("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002")),this.#n.warn?.(`[dsh-weixin] account ${i.botId} failed to initialize:`,e)}finally{this.#f()}});return this.status()}async startProvisioning(){if(this.#I)throw new Error("dsh-weixin controller is closed");this.#r&&await this.cancelProvisioning(this.#r);let a={id:uQe(),state:"starting",createdAt:Date.now(),expiresAt:Date.now()+o3,controller:new AbortController,pendingVerifyCode:null,verifyResolve:null,currentBaseUrl:QQ,error:null,botId:null,task:null};this.#c.set(a.id,a),this.#r=a.id,this.#f();try{let o=(await Promise.all(this.#t.list().slice(-10).map(async e=>this.#d(e.tokenRef)))).filter(Boolean),i=await this.#A.beginLogin({localTokens:o,signal:a.controller.signal});return this.#u(a),a.qrcode=i.qrcode,a.verificationUrl=i.qrcodeUrl,a.state="pending",a.expiresAt=Date.now()+o3,this.#f(),a.task=this.#l(a),gp(a)}catch(o){throw a.controller.signal.aborted?(a.state="cancelled",a.error=Rr("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(a.state="failed",a.error=Rr(o instanceof ot?o.code:"qr-start-failed",o instanceof ot?o.message:"\u65E0\u6CD5\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),this.#r===a.id&&(this.#r=null),this.#f(),o}}registrationStatus(a){return gp(this.#c.get(a))}async submitVerification(a,o){let i=this.#c.get(a);if(!i||i.state!=="needs_verification")throw new Error("The provisioning attempt is not waiting for a verification code");let e=GI(o);if(!e||!/^\d{4,8}$/.test(e))throw new TypeError("Verification code must contain 4 to 8 digits");return i.pendingVerifyCode=e,i.state="scanned",i.verifyResolve?.(),i.verifyResolve=null,this.#f(),gp(i)}async cancelProvisioning(a){let o=this.#c.get(a);return o?(DQ.has(o.state)||(o.controller.abort(),o.verifyResolve?.(),o.verifyResolve=null,await o.task?.catch(()=>{}),DQ.has(o.state)||(o.state="cancelled"),o.error??=Rr("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")),this.#r===o.id&&(this.#r=null),this.#f(),gp(o)):null}async reconnectBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Weixin account");return await this.#Q(a,async()=>{let i=await this.#d(o.tokenRef);if(!i)throw new Error("The Weixin token is missing");try{await this.#h(o,i),this.#g.delete(a)}catch(e){throw this.#g.set(a,Rr("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),e}finally{this.#f()}}),this.status()}async deleteBot(a){let o=this.#t.get(a);if(!o)throw new Error("Unknown Weixin account");return await this.#Q(a,async()=>{let i=await this.#e.resolve(o.tokenRef).catch(()=>{});await this.#C(a);try{await this.#e.unset(o.tokenRef),await this.#t.remove(a)}catch(e){throw i?.value&&(await this.#e.set(o.tokenRef,i.value).catch(()=>{}),await this.#h(o,i.value).catch(()=>{})),new Error("Unable to remove the Weixin account safely.",{cause:e})}try{await this.#s({botId:a,config:o})}catch(e){this.#n.warn?.(`[dsh-weixin] account ${a} state cleanup failed:`,e)}this.#g.delete(a),this.#f()}),this.status()}status(){let a=this.#t.list().map(e=>{let r=this.#E.get(e.botId)?.status??null,A=r?.ready===!0&&r.weixinConnectionState==="connected"&&r.harnessReachable===!0,t=A?"connected":r?.weixinConnectionState==="connecting"?"connecting":this.#g.has(e.botId)||r?.weixinConnectionState==="failed"?"error":"offline",s=this.#g.get(e.botId)??(t==="error"?Rr("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002"):null);return{botId:e.botId,state:t,connected:A,configured:!0,bot:{name:"\u5FAE\u4FE1\u673A\u5668\u4EBA",accountIdMasked:a3(e.accountId)},health:{status:A?"healthy":t==="error"?"error":"offline",summary:A?"\u5FAE\u4FE1\u6D88\u606F\u957F\u8F6E\u8BE2\u8FD0\u884C\u6B63\u5E38":t==="error"?"\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5":"\u5FAE\u4FE1\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",lastCheckedAt:r?.lastCheckedAt??null},stats:{messagesReceived:r?.messagesReceived??0,messagesReplied:r?.messagesReplied??0},error:s?structuredClone(s):null}}),o=a.filter(e=>e.connected).length,i=this.#r?this.#c.get(this.#r):null;return{schemaVersion:1,revision:this.#o,state:i&&i3.has(i.state)?"provisioning":a.length===0?"disconnected":o===a.length?"connected":o>0?"degraded":"offline",bots:a,totals:{configured:a.length,connected:o},...i&&i3.has(i.state)?{provisioning:gp(i)}:{}}}async close(){this.#I||(this.#I=!0,this.#r&&await this.cancelProvisioning(this.#r),await Promise.allSettled([...this.#E.keys()].map(a=>this.#C(a))))}async#l(a){try{for(;!a.controller.signal.aborted&&Date.now(){a.verifyResolve=i,a.controller.signal.aborted&&i()}),a.verifyResolve=null,this.#u(a));let o=await this.#A.pollLogin({qrcode:a.qrcode,baseUrl:a.currentBaseUrl,verifyCode:a.pendingVerifyCode,signal:a.controller.signal});if(this.#u(a),o.status==="wait")a.state="pending";else if(o.status==="scaned")a.pendingVerifyCode=null,a.state="scanned";else if(o.status==="need_verifycode")a.pendingVerifyCode=null,a.state="needs_verification";else if(o.status==="verify_code_blocked"){a.state="failed",a.error=Rr("verification-blocked","\u914D\u5BF9\u7801\u591A\u6B21\u9519\u8BEF\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002");break}else if(o.status==="expired"){a.state="expired",a.error=Rr("expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002");break}else if(o.status==="scaned_but_redirect")a.currentBaseUrl=n3(o.redirect_host,a.currentBaseUrl),a.state="scanned";else if(o.status==="binded_redirect"){let i=this.#t.list().find(e=>this.#E.get(e.botId)?.status?.ready===!0)??this.#t.list()[0];i?(a.state="connected",a.botId=i.botId,a.alreadyConnected=!0):(a.state="failed",a.error=Rr("already-bound","\u8BE5\u5FAE\u4FE1\u8D26\u53F7\u5DF2\u7ED1\u5B9A\uFF0C\u4F46\u672C\u673A\u6CA1\u6709\u53EF\u6062\u590D\u7684\u51ED\u636E\u3002"));break}else if(o.status==="confirmed"){let i=GI(o.bot_token),e=GI(o.ilink_bot_id),r=GI(o.ilink_user_id);if(!i||!e||!r)throw new ot("incomplete-login","\u5FAE\u4FE1\u6388\u6743\u6210\u529F\uFF0C\u4F46\u8FD4\u56DE\u7684\u8D26\u53F7\u51ED\u636E\u4E0D\u5B8C\u6574\u3002");a.state="connecting",this.#f();let A=n3(o.baseurl,a.currentBaseUrl);a.botId=await this.#p(a,{token:i,accountId:e,ownerUserId:r,baseUrl:A}),a.state="connected",a.error=null;break}this.#f()}!a.controller.signal.aborted&&Date.now()>=a.expiresAt&&!DQ.has(a.state)&&(a.state="expired",a.error=Rr("expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"))}catch(o){a.controller.signal.aborted||o?.name==="AbortError"?(a.state="cancelled",a.error=Rr("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(a.state="failed",a.error=Rr(o instanceof ot?o.code:"activation-failed",o instanceof ot?o.message:"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u4FDD\u5B58\u51ED\u636E\u6216\u542F\u52A8\u6D88\u606F\u8FDE\u63A5\u3002"),this.#n.error?.("[dsh-weixin] provisioning failed:",o))}finally{a.pendingVerifyCode=null,a.verifyResolve?.(),a.verifyResolve=null,this.#r===a.id&&(this.#r=null),this.#f(),this.#y()}}async#p(a,{token:o,accountId:i,ownerUserId:e,baseUrl:r}){let A=LN(i),t=this.#t.getByAccountId(i),s={botId:A.botId,accountId:i,tokenRef:A.tokenRef,ownerUserId:e,baseUrl:r,createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()},g=await this.#e.resolve(A.tokenRef).catch(()=>{});return this.#Q(A.botId,async()=>{await this.#e.set(A.tokenRef,o);try{return this.#u(a),await this.#t.save(s),this.#u(a),await this.#h(s,o),this.#u(a),this.#g.delete(A.botId),this.#f(),A.botId}catch(c){throw await this.#C(A.botId),t?await this.#t.save(t).catch(()=>{}):this.#t.get(A.botId)&&await this.#t.remove(A.botId).catch(()=>null)&&await this.#s({botId:A.botId,config:s}).catch(C=>{this.#n.warn?.("[dsh-weixin] failed to clean up cancelled bot state:",C)}),await this.#B(A.tokenRef,g),t&&g?.value&&await this.#h(t,g.value).catch(()=>{}),c}})}async#h(a,o){await this.#C(a.botId);let i=await this.#a({botId:a.botId,config:a,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid Weixin runtime");try{await i.start(),this.#E.set(a.botId,i)}catch(e){throw await i.stop().catch(()=>{}),e}}async#C(a){let o=this.#E.get(a);this.#E.delete(a),await o?.stop().catch(i=>{this.#n.warn?.(`[dsh-weixin] account ${a} failed to stop cleanly:`,i)})}async#d(a){let o=await this.#e.resolve(a).catch(()=>{});return GI(o?.value)}async#B(a,o){try{o?.value?await this.#e.set(a,o.value):await this.#e.unset(a)}catch(i){this.#n.error?.(`[dsh-weixin] failed to restore credential ${a}:`,i)}}#u(a){if(a.controller.signal.aborted||this.#r!==a.id)throw BQe()}#Q(a,o){let r=(this.#i.get(a)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#i.get(a)===r&&this.#i.delete(a)});return this.#i.set(a,r),r}#y(){for(let[a,o]of this.#c)a!==this.#r&&DQ.has(o.state)&&this.#c.size>16&&this.#c.delete(a)}#f(){this.#o+=1}};var wQ="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002",QQe=["\u5FAE\u4FE1\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u6216\u5E26\u6587\u5B57\u8BC6\u522B\u7ED3\u679C\u7684\u8BED\u97F3\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/workspace \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A","/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84","/sessionlist [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898","/session Session ID \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` diff --git a/package-lock.json b/package-lock.json index 9eddaf7..9d7249f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@xmanrui/dsh-im", - "version": "0.7.1", + "version": "0.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@xmanrui/dsh-im", - "version": "0.7.1", + "version": "0.7.2", "license": "MIT", "dependencies": { "@tencent-connect/qqbot-connector": "1.2.0", diff --git a/package.json b/package.json index 9c0f5bf..a9ef182 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xmanrui/dsh-im", - "version": "0.7.1", + "version": "0.7.2", "description": "通过扫码、App Manifest或机器人凭据把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord和WhatsApp)。", "license": "MIT", "type": "module", diff --git a/src/channels/discord/discord-api.mjs b/src/channels/discord/discord-api.mjs index f760478..8bd0e13 100644 --- a/src/channels/discord/discord-api.mjs +++ b/src/channels/discord/discord-api.mjs @@ -108,7 +108,7 @@ export class DiscordApi { headers: { authorization: `Bot ${this.#token}`, 'content-type': 'application/json', - 'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.7.1)', + 'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 0.7.2)', }, ...(body === undefined ? {} : { body: JSON.stringify(body) }), signal: requestSignal(signal, timeoutMs), diff --git a/src/channels/weixin/weixin-api.mjs b/src/channels/weixin/weixin-api.mjs index e08b523..4435070 100644 --- a/src/channels/weixin/weixin-api.mjs +++ b/src/channels/weixin/weixin-api.mjs @@ -92,7 +92,7 @@ function authenticatedHeaders(token) { function baseInfo() { return { channel_version: WEIXIN_PROTOCOL_VERSION, - bot_agent: 'DeepSeekHarness/0.7.1', + bot_agent: 'DeepSeekHarness/0.7.2', }; } diff --git a/test/channels/weixin/weixin-api.test.mjs b/test/channels/weixin/weixin-api.test.mjs index 4e8d076..afcd70f 100644 --- a/test/channels/weixin/weixin-api.test.mjs +++ b/test/channels/weixin/weixin-api.test.mjs @@ -93,7 +93,7 @@ test('sendText emits the iLink message envelope without reflecting the token in assert.equal(body.msg.context_token, 'message-context'); assert.equal(body.msg.item_list[0].text_item.text, 'Harness reply'); assert.equal(body.base_info.channel_version, '2.4.6'); - assert.equal(body.base_info.bot_agent, 'DeepSeekHarness/0.7.1'); + assert.equal(body.base_info.bot_agent, 'DeepSeekHarness/0.7.2'); assert.doesNotMatch(calls[0].init.body, /host-only-token/); });