diff --git a/lib/index.js b/lib/index.js index 8099845..1434d4d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -123,7 +123,7 @@ ${SO}`)}}try{return await YI(o,i,async()=>wo(Goe(await Yoe(r,g,A))))}catch(c){re `).trim();c&&c!==this.#o&&(this.#o=c,o={type:"text",text:c});continue}if(e.type==="assistant/message"){let A=mne(e);A&&A!==this.#o&&(this.#o=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}},Oo=class extends Error{constructor(r,o){super(`${r}: ${o?.message??"unknown Harness RPC error"}`),this.name="HarnessRpcError",this.method=r,this.code=o?.code??"internal",this.details=o?.details??{}}},Js=class extends Error{constructor(r,o,{cause:i,status:e}={}){let a=Number.isInteger(e)?`, HTTP ${e}`:"";super(`Harness ${o} transport failed (${r}${a})`,{cause:i}),this.name="HarnessTransportError",this.code=r,this.method=o,Number.isInteger(e)&&(this.status=e)}},_O=class extends Error{constructor(r){super("Harness health RPC was rejected",{cause:r}),this.name="HarnessHealthError",this.code="harness-rpc-rejected",this.method="host.describe"}},VI=class extends Error{constructor(r,o){super(o),this.name="HarnessInteractionError",this.code=r}},rr=class{#e;#A;#r;#t;#n;#o;#l;#s;#I;#a;#i;#c;#g;#p=null;#h;#C;#E;#d;constructor({baseUrl:r,workspace:o,agentPreset:i,autostart:e=!1,dshBin:a="dsh",fetchImpl:A=fetch,createWebSocket:t=f=>new WebSocket(f),interactionReconnectDelayMs:s=500,rpcIdPrefix:g="im",logPrefix:c="dsh-im",commandExecutor:I,controlExecutor:E,sessionMaintenanceExecutor:B}){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");if(I!==void 0&&typeof I!="function")throw new TypeError("commandExecutor must be a function");if(E!==void 0&&typeof E!="function")throw new TypeError("controlExecutor must be a function");if(B!==void 0&&typeof B!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");this.#e=new URL(r),this.#A=o,this.#r=i??void 0,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#I=g.trim(),this.#a=c.trim(),this.#i=I,this.#c=E,this.#g=B,this.#h=dne(this.#e.origin),this.#C=this.#h.ownerships,this.#E=this.#h.claims,this.#d=this.#h.controls}async rpc(r,o={},i=3e4,e={}){let a=e.rpcId??`${this.#I}-${P2()}`,A=AbortSignal.timeout(i),t=e.signal?AbortSignal.any([e.signal,A]):A,s;try{s=await this.#o(new URL(`/api/${r}`,this.#e),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-request",rpcId:a,method:r,payload:o}),signal:t})}catch(c){throw e.signal?.aborted?c:new Js(A.aborted?"harness-timeout":"harness-connect-failed",r,{cause:c})}if(!s.ok){let c=s.status===401||s.status===403?"harness-access-denied":s.status===404?"harness-api-not-found":"harness-http-failed";throw new Js(c,r,{status:s.status})}let g;try{g=await s.json()}catch(c){throw new Js("harness-response-invalid",r,{cause:c})}if(g?.type!=="server-response"||g?.rpcId!==a)throw new Js("harness-response-invalid",r,{cause:new Error(`Harness returned an invalid response for ${r}`)});if(!g.result||typeof g.result!="object"||typeof g.result.ok!="boolean")throw new Js("harness-response-invalid",r,{cause:new Error(`Harness returned an invalid result for ${r}`)});if(!g.result?.ok)throw new Oo(r,g.result?.error);return g.result.value}async health(r={}){try{return await this.rpc("host.describe",{},5e3,r),!0}catch(o){throw o instanceof Oo?new _O(o):o}}async ensureRunning(r={}){try{return await this.health(r)}catch(e){if(!this.#t)throw e}if(!this.#p||this.#p.exitCode!==null){let e=this.#e.port||(this.#e.protocol==="https:"?"443":"80");this.#p=Cne(this.#n,["web","--host",this.#e.hostname,"--port",e],{cwd:this.#A,env:process.env,stdio:["ignore","inherit","inherit"]}),this.#p.on("error",a=>{console.error(`[${this.#a}] failed to start Harness:`,a.message)})}let o=Date.now()+6e4,i;for(;Date.now(){let t=A&&i.signal?AbortSignal.any([A,i.signal]):A??i.signal;return this.rpc("session.selectModel",{sessionId:r,provider:o.provider,model:o.model},3e4,t?{...i,signal:t}:i)},a=this.#g?await this.#g({sessionId:r,operation:e}):await e();if(!a||typeof a!="object"||!MO(a.selected))throw new Error("Harness returned an invalid response for session.selectModel");return a}async isSessionRunning(r,o={}){if(typeof r!="string"||!r)throw new TypeError("sessionId is required");await this.ensureRunning(o);let i=await this.rpc("session.list",{},3e4,o);if(!i||typeof i!="object"||!Array.isArray(i.items))throw new Error("Harness returned an invalid response for session.list");for(let e of i.items)if(!e||typeof e!="object"||typeof e.sessionId!="string"||!e.sessionId||typeof e.running!="boolean")throw new Error("Harness returned an invalid response for session.list");return i.items.find(e=>e.sessionId===r)?.running??!1}async adoptWorkspaceSession(r,o={}){return v2(this,r,o)}async workspaceId(r={}){let{workspace:o=this.#A,...i}=r,{items:e}=await this.rpc("workspace.list",{},3e4,i),a=e.find(t=>t.path===o);return a?a.workspaceId:(await this.rpc("workspace.create",{path:o},3e4,i)).workspace.workspaceId}async createSession(r={}){let{agentPreset:o,...i}=r;await this.ensureRunning(i);let a={workspaceId:await this.workspaceId(i)},A=o!==void 0?o:this.#r;return A!=null&&(a.agentPreset=A),(await this.rpc("session.create",a,3e4,i)).sessionId}async executeCommand(r,o,i={}){if(typeof r!="string"||!r)throw new TypeError("sessionId is required");if(typeof o!="string"||!o)throw new TypeError("command line is required");if(!this.#i){let e=new Error("Harness command execution is unavailable");throw e.code="commands-unavailable",e}try{return await this.#i(r,o,i)}catch(e){throw e?.failure&&typeof e.failure=="object"?new Oo("commands.execute",e.failure):e}}async sessionExists(r,o={}){try{return await this.rpc("session.history",{sessionId:r,maxMessages:1},3e4,o),!0}catch(i){if(i instanceof Oo&&i.code==="session-not-found")return!1;throw i}}async respondInteraction(r,o,i={}){if(typeof r!="string"||!r)throw new TypeError("rpcId is required");if(!o||typeof o!="object"||typeof o.ok!="boolean")throw new TypeError("A Harness RPC result is required");let e=AbortSignal.timeout(i.timeoutMs??3e4),a=i.signal?AbortSignal.any([i.signal,e]):e,A=await this.#o(new URL("/api/respond",this.#e),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-response",rpcId:r,result:o}),signal:a});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 VI(`interaction-${s}`,`Harness interaction response was rejected (${s})`)}async watchInteractions(r,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A}={}){if(typeof r!="string"||!r)throw new TypeError("sessionId is required");if(!o||typeof o.addEventListener!="function")throw new TypeError("watchInteractions requires an AbortSignal");if(i!==void 0&&typeof i!="function")throw new TypeError("onInteraction must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("onResolved must be a function");if(a!==void 0&&typeof a!="function")throw new TypeError("onOpen must be a function");for(;!o.aborted;){try{await this.#T(r,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A})}catch(t){if(o.aborted)return;console.warn(`[${this.#a}] Harness interaction stream disconnected:`,t.message)}if(o.aborted)return;try{await JE(this.#s,o)}catch{if(o.aborted)return;throw new Error("Harness interaction reconnect wait failed")}}}#B(r,o){let i=this.#C.get(r)??new Set;o.order=this.#h.nextOrder,this.#h.nextOrder+=1,i.add(o),this.#C.set(r,i)}#u(r,o){let i=this.#C.get(r);i?.delete(o),i?.size===0&&this.#C.delete(r);for(let[e,a]of this.#E)a.ownership===o&&this.#E.delete(e)}#Q(r){if(!r.control)return;let o=this.#d.get(r.control.owner);o||(o=new Map,this.#d.set(r.control.owner,o));let i=o.get(r.control.key)??new Set;i.add(r),o.set(r.control.key,i)}#f(r){if(!r.control)return;let o=this.#d.get(r.control.owner),i=o?.get(r.control.key);i?.delete(r),i?.size===0&&o.delete(r.control.key),o?.size===0&&this.#d.delete(r.control.owner)}#m(r,o){let i=F2(o);return i?[...this.#d.get(i.owner)?.get(i.key)??[]].filter(a=>a.sessionId===r).sort((a,A)=>a.order-A.order):[]}#y(r,o){return this.#m(r,o).find(i=>i.started&&i.active&&!i.completed&&i.turn!==null)??null}async#S(r,o,i){let e=this.#m(r,o);if(e.length===0)return null;try{let a=await this.rpc("session.history",{sessionId:r,maxMessages:50},3e4,i);this.#w(r,a.events??[])}catch(a){if(!(a instanceof Oo)||a.code!=="session-not-found")throw a;for(let A of e)A.active=!1,A.completed=!0;return null}return this.#y(r,o)}async hasActiveTurn(r,o,i={}){if(typeof r!="string"||!r)throw new TypeError("sessionId is required");return!!await this.#S(r,o,i)}async stopActiveTurn(r,o,i={}){if(typeof r!="string"||!r)throw new TypeError("sessionId is required");let e=await this.#S(r,o,i);if(!e)return!1;if(e.stopRequested)return!0;if(this.#y(r,o)!==e)return!1;e.stopRequested=!0;try{if(this.#c){let a=this.#c({sessionId:r,expectedTurn:e.turn,promptRpcId:e.promptRpcId,action:"stop"});if(a&&typeof a.then=="function")throw new TypeError("controlExecutor must return synchronously");if(a!==void 0){if(typeof a!="boolean")throw new TypeError("controlExecutor must return a boolean or undefined");return a||(e.stopRequested=!1),a}}return await this.rpc("session.cancel",{sessionId:r,keepInbox:!0},3e4,i),!0}catch(a){if(this.#y(r,o)===e&&(e.stopRequested=!1),a instanceof Oo&&a.code==="session-not-found")return!1;throw a}}async steerActiveTurn(r,o,i,e={}){if(typeof r!="string"||!r)throw new TypeError("sessionId is required");if(typeof o!="string"||!o.trim())throw new TypeError("Steering text is required");let a=await this.#S(r,i,e);if(!a||a.stopRequested||this.#y(r,i)!==a)return!1;if(this.#c){let A=this.#c({sessionId:r,expectedTurn:a.turn,promptRpcId:a.promptRpcId,action:"steer",text:o});if(A&&typeof A.then=="function")throw new TypeError("controlExecutor must return synchronously");if(A!==void 0){if(typeof A!="boolean")throw new TypeError("controlExecutor must return a boolean or undefined");return A}}return await this.rpc("session.prompt",{sessionId:r,mode:"steer",content:[{type:"text",text:o}],clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,e),!0}#w(r,o){for(let i of this.#C.get(r)??[])Sne(i,o)}async#R(r,o){let i=await this.rpc("session.history",{sessionId:r,maxMessages:50},3e4,{signal:o});this.#w(r,i.events??[])}#M(r,o,i){let e=this.#E.get(o);if(e&&this.#C.get(r)?.has(e.ownership))return e;let a=[...this.#C.get(r)??[]],A=a.filter(s=>s.active).sort((s,g)=>s.order-g.order);if(A.length>0)return{ownership:A[0],recovered:!1};let t=a.filter(s=>!s.started&&!s.completed).sort((s,g)=>s.order-g.order)[0]??null;return t?{ownership:t,recovered:!0}:null}async ask(r,o,i={}){typeof i=="number"&&(i={timeoutMs:i});let e=i.timeoutMs??6e5,a=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,g=F2(i.control);await this.ensureRunning({signal:a});let c=await this.rpc("session.history",{sessionId:r,maxMessages:1},3e4,{signal:a}),I=Math.max(-1,...(c.events??[]).map(({event:R})=>R.seq??-1)),E=`${this.#I}-${P2()}`,B=new qI({promptRpcId:E,afterSeq:I}),f=t||s?new AbortController:null,Q=f?a?AbortSignal.any([a,f.signal]):f.signal:null,y=f||g?{sessionId:r,promptRpcId:E,active:!1,started:!1,completed:!1,stopRequested:!1,turn:null,openTurn:null,lastSeq:I,reconnect:null,order:-1,toolCalls:new Map,control:g}:null,m=null;y&&(this.#B(r,y),this.#Q(y));try{if(Q){let _,P=new Promise(Y=>{_=Y});m=this.watchInteractions(r,{signal:Q,onInteraction:t,onResolved:s,onOpen:_,ownership:y}),m.catch(()=>{}),await Promise.race([P,JE(3e4,Q).then(()=>{throw new Error("Harness interaction stream did not open within 30 seconds")})])}let R=typeof o=="string"?[{type:"text",text:o}]:o;if(!Array.isArray(R)||R.length===0)throw new TypeError("Harness prompt content is required");await this.rpc("session.prompt",{sessionId:r,mode:"queue",content:R,clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,{rpcId:E,signal:a});try{let _=Date.now()+e;for(;Date.now()<_;){await JE(300,a);let P=await this.rpc("session.history",{sessionId:r,maxMessages:50},3e4,{signal:a}),Y=y?.active===!0;y&&(this.#w(r,P.events??[]),!Y&&y.active&&y.reconnect?.());let j=B.consume(P.events??[]);if(j&&A)try{await A(j)}catch(K){console.warn(`[${this.#a}] ignored a progress update failure:`,K.message)}if(B.finished){if(B.answer)return B.answer;throw y?.stopRequested?U2():new Error(`Harness turn ended without a text reply${B.reason?` (${JSON.stringify(B.reason)})`:""}`)}}throw new Error(`Harness reply timed out after ${Math.round(e/1e3)} seconds`)}catch(_){if(!y?.stopRequested)throw _;if(B.answer)return B.answer;throw _?.code==="turn-stopped"?_:U2()}}finally{y&&(this.#f(y),this.#u(r,y)),f?.abort(new DOMException("Harness turn finished","AbortError")),m&&await m.catch(()=>{})}}#T(r,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A}){let t=new URL("/api/events.mux",this.#e);return t.protocol=t.protocol==="https:"?"wss:":"ws:",new Promise((s,g)=>{let c;try{c=this.#l(t.toString())}catch(H){g(H);return}let I=!1,E=!1,B=null,f=Promise.resolve(),Q=A==null,y=[],m=H=>{if(!E){if(E=!0,c.removeEventListener("open",_),c.removeEventListener("message",j),c.removeEventListener("close",K),c.removeEventListener("error",q),o.removeEventListener("abort",V),A?.reconnect===R&&(A.reconnect=null),o.aborted){s();return}f.then(()=>{let v=H??B;v?g(v):s()},g)}},R=()=>{try{(c.readyState===0||c.readyState===1)&&c.close()}catch{}},_=()=>{I=!0,A&&(A.reconnect=R);try{a?.()}catch(H){console.warn(`[${this.#a}] ignored an interaction open callback failure:`,H.message)}A&&this.#R(r,o).then(()=>{if(!E){Q=!0;for(let H of y.splice(0))Y(H)}}).catch(H=>{B??=H,R(),m(H)})},P=(H,v)=>{H&&(f=f.then(()=>H(v)).catch(Z=>{B??=Z,R(),m(B)}))},Y=H=>{let v=H.payload;if(A&&v.type==="session/event"){this.#w(r,[v.event]);return}if(v.type==="question/requested"||v.type==="approval/requested"){let Z=v.type==="question/requested"?"question":"approval",U=Z==="question"?H.rpcId:v.approvalId,M=`${Z}:${U}`;if(A){let te=this.#M(r,M,Z);if(te?.ownership!==A)return;this.#E.set(M,te)}let G=Z==="approval"&&A&&typeof v.callId=="string"?this.#E.get(M)?.ownership.toolCalls.get(v.callId):void 0;P(i,Object.freeze({kind:Z,interactionId:U,rpcId:H.rpcId,sessionId:r,payload:v,recovered:A?this.#E.get(M)?.recovered===!0:!1,...G?{toolCall:G}:{},reconnect:R,respond:(te,se={})=>this.respondInteraction(H.rpcId,te,{...se,signal:se.signal??o})}));return}if(v.type==="question/resolved"||v.type==="approval/resolved"){let Z=v.type==="question/resolved"?"question":"approval",U=Z==="question"?v.questionRpcId:v.approvalId,M=`${Z}:${U}`;if(A){if(this.#E.get(M)?.ownership!==A)return;this.#E.delete(M)}P(e,Object.freeze({kind:Z,interactionId:U,sessionId:r,outcome:v.outcome,payload:v}))}},j=H=>{try{if(typeof H.data!="string")throw new Error("binary WebSocket frame");let v=JSON.parse(H.data),Z=v?.payload;if(v?.type!=="server-request"||typeof v.rpcId!="string"||!Z||typeof Z!="object"||v.method!==Z.type)throw new Error("invalid server-request envelope");if(Z.sessionId!==r)return;Q?Y(v):y.push(v)}catch(v){console.warn(`[${this.#a}] ignored a malformed Harness interaction frame:`,v.message)}},K=()=>m(I?null:new Error("Harness interaction WebSocket closed before opening")),q=()=>{m(new Error(I?"Harness interaction WebSocket failed":"Harness interaction WebSocket failed before opening")),R()},V=()=>{R(),m()};c.addEventListener("open",_),c.addEventListener("message",j),c.addEventListener("close",K,{once:!0}),c.addEventListener("error",q,{once:!0}),o.addEventListener("abort",V,{once:!0}),o.aborted&&V()})}async watchHarnessEvents({signal:r,onSessionEvent:o,onReconnect:i}={}){if(typeof o!="function")throw new TypeError("watchHarnessEvents requires onSessionEvent");if(!r||typeof r.addEventListener!="function")throw new TypeError("watchHarnessEvents requires an AbortSignal");if(i!==void 0&&typeof i!="function")throw new TypeError("onReconnect must be a function");let e=new URL("/api/events.mux",this.#e);for(e.protocol=e.protocol==="https:"?"wss:":"ws:";!r.aborted;){try{await this.#O(e.toString(),{signal:r,onSessionEvent:o,onReconnect:i})}catch(a){if(r.aborted)return;console.warn(`[${this.#a}] Harness event mux disconnected:`,a.message)}if(r.aborted)return;try{await JE(this.#s,r)}catch{if(r.aborted)return;throw new Error("Harness event mux reconnect wait failed")}}}#O(r,{signal:o,onSessionEvent:i,onReconnect:e}){return new Promise((a,A)=>{let t;try{t=this.#l(r)}catch(m){A(m);return}let s=!1,g=!1,c=()=>{try{t.close()}catch{}},I=m=>{g||(g=!0,t.removeEventListener("open",E),t.removeEventListener("message",B),t.removeEventListener("close",f),t.removeEventListener("error",Q),o.removeEventListener("abort",y),m?A(m):a())},E=()=>{s=!0;try{e?.()}catch(m){console.warn(`[${this.#a}] mux reconnect hook failed:`,m.message)}},B=m=>{try{if(typeof m.data!="string")return;let R=JSON.parse(m.data),_=R?.payload;if(R?.type!=="server-request"||!_||typeof _!="object"||R.method!==_.type||_.type!=="session/event"||typeof _.sessionId!="string"||!_.event||typeof _.event!="object")return;i({sessionId:_.sessionId,event:_.event})}catch(R){console.warn(`[${this.#a}] ignored a malformed global mux frame:`,R.message)}},f=()=>I(s?null:new Error("Harness event mux WebSocket closed before opening")),Q=()=>{I(new Error(s?"Harness event mux WebSocket failed":"Harness event mux WebSocket failed before opening")),c()},y=()=>{c(),I()};t.addEventListener("open",E),t.addEventListener("message",B),t.addEventListener("close",f,{once:!0}),t.addEventListener("error",Q,{once:!0}),o.addEventListener("abort",y,{once:!0}),o.aborted&&y()})}stopManagedProcess(){this.#p?.exitCode===null&&this.#p.kill("SIGTERM")}};var tB=class extends rr{constructor(r){super({...r,rpcIdPrefix:"dingtalk",logPrefix:"dsh-dingtalk"})}};import{randomUUID as Dne}from"node:crypto";import{mkdir as wne,readFile as One,rename as bne,unlink as Mne,writeFile as _ne}from"node:fs/promises";import{dirname as Nne}from"node:path";var rB=Object.freeze({version:1,sessions:{},seenMessageIds:[],pendingSenders:{}});function ar(n){return typeof n=="string"&&n.trim()?n.trim():null}function H2(n){return(ar(n)??"\u9489\u9489\u7528\u6237").slice(0,100)}function Tne(n,r){if(!n||typeof n!="object")return null;let o=ar(n.requestId)??ar(r),i=ar(n.staffId),e=ar(n.requestedAt)??ar(n.lastSeenAt),a=ar(n.lastSeenAt)??e;return!o||!i||!e||!a?null:{requestId:o,staffId:i,displayName:H2(n.displayName??n.nick),requestedAt:e,lastSeenAt:a}}function Rne(n){if(!n||typeof n!="object")return structuredClone(rB);let r={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[e,a]of Object.entries(n.sessions)){let A=ar(e),t=ar(a);A&&t&&(r[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,a]of i){let A=Tne(a,e);if(!A)continue;let t=Object.values(o).find(s=>s.staffId===A.staffId);(!t||t.lastSeenAtnew Date().toISOString()}={}){if(!ar(r))throw new TypeError("state path is required");if(typeof o!="function"||typeof i!="function")throw new TypeError("idFactory and now must be functions");this.#e=r,this.#t=o,this.#n=i}async load(){try{this.#A=Rne(JSON.parse(await One(this.#e,"utf8")))}catch(r){if(r?.code!=="ENOENT")throw r;this.#A=structuredClone(rB),await this.#o()}return this}sessionFor(r){return this.#A.sessions[r]??null}async setSession(r,o){let i=ar(r),e=ar(o);if(!i||!e)throw new TypeError("key and sessionId are required");this.#A.sessions[i]=e,await this.#o()}async clearSession(r){let o=ar(r);!o||!(o in this.#A.sessions)||(delete this.#A.sessions[o],await this.#o())}async clearSessions(){this.#A.sessions={},await this.#o()}hasSeen(r){let o=ar(r);return!!(o&&this.#A.seenMessageIds.includes(o))}async markSeen(r){let o=ar(r);if(!o)throw new TypeError("messageId is required");this.hasSeen(o)||(this.#A.seenMessageIds.push(o),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#o())}pendingSenders(){return Object.values(this.#A.pendingSenders).sort((r,o)=>r.requestedAt.localeCompare(o.requestedAt)).map(r=>structuredClone(r))}pendingSender(r){let o=ar(r),i=o?this.#A.pendingSenders[o]:null;return i?structuredClone(i):null}async recordPendingSender(r,o,i){let e=r&&typeof r=="object"?r:{staffId:r,displayName:o,lastSeenAt:i},a=ar(e.staffId);if(!a)throw new TypeError("staffId is required");let A=ar(e.lastSeenAt)??ar(e.requestedAt)??this.#n(),t=Object.values(this.#A.pendingSenders).find(g=>g.staffId===a),s={requestId:t?.requestId??`ding_sender_${this.#t()}`,staffId:a,displayName:H2(e.displayName??e.nick??o),requestedAt:t?.requestedAt??A,lastSeenAt:A};return this.#A.pendingSenders[s.requestId]=s,await this.#o(),structuredClone(s)}async removePendingSender(r){let o=ar(r);return!o||!this.#A.pendingSenders[o]?!1:(delete this.#A.pendingSenders[o],await this.#o(),!0)}async removePendingSenderByStaffId(r){let o=ar(r),i=o?Object.values(this.#A.pendingSenders).find(e=>e.staffId===o):null;return i?this.removePendingSender(i.requestId):!1}snapshot(){return structuredClone(this.#A)}async remove(){await this.#r;try{await Mne(this.#e)}catch(r){if(r?.code!=="ENOENT")throw r}this.#A=structuredClone(rB)}async#o(){let r=`${JSON.stringify(this.#A,null,2)} `,o=this.#r.then(async()=>{await wne(Nne(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await _ne(i,r,{encoding:"utf8",mode:384}),await bne(i,this.#e)});this.#r=o.then(()=>{},()=>{}),await o}};import{mkdir as kne,readFile as vne,realpath as Pne,rename as Gne,stat as Fne,unlink as Lne,writeFile as Une}from"node:fs/promises";import{dirname as Hne,isAbsolute as x2,resolve as qE}from"node:path";var fje=Object.freeze({version:1,workspaces:Object.freeze({})});function sc(n){let r=new Error(n);return r.code=Ja,r}async function NO(n){return qE(await Pne(n))}async function Kne(n,r){if(n===r)return!0;try{return await NO(n)===await NO(r)}catch{return!1}}function Va(n){if(typeof n!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n))throw new TypeError("Invalid bot id");return n}function Yne(n){if(!n||n.version!==1||!n.workspaces||typeof n.workspaces!="object"||Array.isArray(n.workspaces))return null;let r={};for(let[i,e]of Object.entries(n.workspaces)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(i)||typeof e!="string"||!x2(e))return null;r[i]=qE(e)}let o={};if(n.agentPresets!==void 0){if(!n.agentPresets||typeof n.agentPresets!="object"||Array.isArray(n.agentPresets))return null;for(let[i,e]of Object.entries(n.agentPresets)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(i))return null;try{let a=JI(e);if(!a)return null;o[i]=a}catch{return null}}}return{version:1,workspaces:r,agentPresets:o}}async function K2(n){if(typeof n!="string"||!n.trim()||!x2(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 r=qE(n.trim()),o;try{o=await Fne(r)}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 r}var Fr=class{#e;#A;#r={};#t={};#n=new Map;#o=1;#l=new Map;#s=1;#I=new Map;#a=new WeakMap;#i=new Set;#c=Promise.resolve();#g=new Map;constructor(r,{defaultWorkspace:o=process.cwd()}={}){if(typeof r!="string"||!r)throw new TypeError("workspace store path is required");this.#e=r,this.#A=qE(o)}async load(){try{let r=Yne(JSON.parse(await vne(this.#e,"utf8")));if(!r)throw new Error("dsh-im workspace config is invalid");this.#r=r.workspaces,this.#t=r.agentPresets}catch(r){if(r?.code!=="ENOENT")throw r;this.#r={},this.#t={}}this.#n.clear(),this.#o=1,this.#l.clear(),this.#s=1,this.#I.clear(),this.#i.clear();for(let r of Object.keys(this.#r))this.#n.set(r,this.#p()),this.#l.set(r,this.#h());return this}has(r){let o=Va(r);return Object.hasOwn(this.#r,o)&&!this.#I.has(o)}incarnationFor(r){return this.#l.get(Va(r))??null}workspaceFor(r){return this.#r[Va(r)]??this.#A}agentPresetFor(r){return this.#t[Va(r)]??null}generationFor(r){return this.#n.get(Va(r))??null}async whenIdle(){await this.#c}async whenBotIdle(r){let o=Va(r);for(;;){let i=this.#g.get(o);if(!i||(await i,this.#g.get(o)===i))return}}async ensure(r,{workspace:o=this.#A,defaultAgentPreset:i}={}){let e=Va(r),a=qE(o);return this.#d(e,async()=>{if(this.#r[e])this.#n.has(e)||this.#n.set(e,this.#p());else{let A=JI(i),t=Object.hasOwn(this.#t,e),s=this.#t[e];this.#r[e]=a,A&&(this.#t[e]=A),this.#n.set(e,this.#p()),this.#l.set(e,this.#h());try{await this.#B()}catch(g){throw delete this.#r[e],t?this.#t[e]=s:delete this.#t[e],this.#n.delete(e),this.#l.delete(e),g}}return this.#r[e]})}async setWorkspace(r,o,{clearSessions:i,incarnation:e}={}){let a=Va(r);if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){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 K2(o);return this.#d(a,async()=>{if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let s=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw s.code="workspace-bot-not-found",s}if(A===this.workspaceFor(a))return A;let t=this.#r[a];this.#n.set(a,this.#p()),await i?.(),this.#r[a]=A;try{await this.#B()}catch(s){throw this.#r[a]=t,s}return A})}async setAgentPreset(r,o,{incarnation:i}={}){let e=Va(r);if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let A=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw A.code="workspace-bot-not-found",A}let a=JI(o);return this.#d(e,async()=>{if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){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=this.#t[e]??null;if(A===a)return a;a?this.#t[e]=a:delete this.#t[e];try{await this.#B()}catch(t){throw A?this.#t[e]=A:delete this.#t[e],t}return a})}async bindWorkspaceSession(r,o,{conversationKey:i,sessionId:e,clearSessions:a,setSession:A,incarnation:t,expectedGeneration:s}={}){let g=Va(r);if(typeof i!="string"||!i||typeof e!="string"||!e)throw new TypeError("conversationKey and sessionId are required");if(typeof a!="function"||typeof A!="function")throw new TypeError("session state callbacks are required");if(!this.has(g)||t!==void 0&&t!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}let c=await NO(await K2(o));return this.#d(g,async()=>{if(!this.has(g)||t!==void 0&&t!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}if(s!==void 0&&s!==this.generationFor(g))throw sc("The bot workspace changed before the session binding could be committed.");if(!await Kne(c,this.workspaceFor(g))){let I=this.#r[g];this.#n.set(g,this.#p()),await a(),this.#r[g]=c;try{await this.#B()}catch(E){throw this.#r[g]=I,E}}return await A(i,e),{workspace:c,sessionId:e,generation:this.#n.get(g)}})}async invalidateSessions(r,{clearSessions:o}={}){let i=Va(r);return this.#d(i,async()=>{this.#n.set(i,this.#p()),await o?.()})}async beginRemoval(r,{clearSessions:o}={}){let i=Va(r);return this.#d(i,async()=>{let e=this.#I.get(i);if(e)return e;let a=Object.freeze({});this.#I.set(i,a),this.#a.set(a,{botId:i,incarnation:this.incarnationFor(i)}),this.#n.set(i,this.#p());try{await o?.()}catch(A){throw this.#I.get(i)===a&&this.#I.delete(i),A}return a})}async abortRemoval(r){let{botId:o}=this.#C(r);return this.#d(o,async()=>this.#I.get(o)!==r?!1:(this.#I.delete(o),Object.hasOwn(this.#r,o)&&(this.#n.set(o,this.#p()),this.#l.has(o)||this.#l.set(o,this.#h())),!0))}async finishRemoval(r){let{botId:o,incarnation:i}=this.#C(r);return this.#d(o,async()=>this.#I.get(o)!==r?{removed:!1,persisted:!0,error:null,stale:!0}:this.incarnationFor(o)!==i?(this.#I.delete(o),{removed:!1,persisted:!0,error:null,stale:!0}):(this.#I.delete(o),this.#E(o)))}async retireAfterConfigCommit(r){let o=Va(r);return this.#d(o,async()=>(this.#I.delete(o),this.#E(o)))}async remove(r){let o=await this.retireAfterConfigCommit(r);if(o.error)throw o.error;return o.removed}async reconcile(r){let o=new Set([...r].map(Va)),i=new Set([...Object.keys(this.#r),...Object.keys(this.#t),...this.#i]);for(let e of i)o.has(e)||await this.remove(e)}decorateStatus(r){return!r||typeof r!="object"||!Array.isArray(r.bots)?r:{...r,bots:r.bots.map(o=>o?.botId?{...o,workspace:this.workspaceFor(o.botId),agentPreset:this.agentPresetFor(o.botId)}:o)}}#p(){let r=this.#o;return this.#o+=1,r}#h(){let r=this.#s;return this.#s+=1,r}#C(r){if(!r||typeof r!="object")throw new TypeError("Invalid workspace removal transaction");let o=this.#a.get(r);if(!o)throw new TypeError("Invalid workspace removal transaction");return o}async#E(r){let o=Object.hasOwn(this.#r,r),i=Object.hasOwn(this.#t,r),e=o||i||this.#i.has(r);if(delete this.#r[r],delete this.#t[r],this.#n.delete(r),this.#l.delete(r),!e)return{removed:!1,persisted:!0,error:null,stale:!1};try{return await this.#u(),{removed:o,persisted:!0,error:null,stale:!1}}catch(a){return this.#i.add(r),{removed:o,persisted:!1,error:a,stale:!1}}}async#d(r,o){let i=this.#c.then(o,o),e=i.then(()=>{},()=>{});return this.#c=e,this.#g.set(r,e),e.finally(()=>{this.#g.get(r)===e&&this.#g.delete(r)}),i}async#B(){let r={version:1,workspaces:this.#r};Object.keys(this.#t).length>0&&(r.agentPresets=this.#t),await kne(Hne(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await Une(o,`${JSON.stringify(r,null,2)} `,{encoding:"utf8",mode:384}),await Gne(o,this.#e),this.#i.clear()}async#u(){if(Object.keys(this.#r).length>0||Object.keys(this.#t).length>0){await this.#B();return}try{await Lne(this.#e),this.#i.clear()}catch(r){if(r?.code!=="ENOENT")throw r;this.#i.clear()}}};function TO(n){if(!n)return null;let r=typeof n=="function"?n():n;return r&&typeof r.then=="function"?r.then(tn):tn(r)}function j2(){let n=new Error("Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002");return n.code="agent-preset-unavailable",n}function zI(n){if(n())return;let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}function Y2(n,r,o){let i=e=>{let a=n.decorateStatus(e);if(!o||!a||typeof a!="object")return a;let A=s=>s?{...a,agentPresetCatalog:s}:a,t=TO(o);return t&&typeof t.then=="function"?t.then(A):A(t)};return r&&typeof r.then=="function"?r.then(i):i(r)}function xne(n){return Promise.resolve(n.status())}function Ea(n,{workspaces:r,method:o="remove",botIdFromRemoved:i=e=>e?.botId}){if(!n||!r||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(e,a){let A=Reflect.get(e,a,e);return a===o?async(...t)=>{let s=await A.apply(e,t),g=s?i(s,t):null;return g&&await r.retireAfterConfigCommit(g),s}:typeof A=="function"?A.bind(e):A}})}function Ca(n,{botId:r,workspaces:o,state:i,agentPresetCatalog:e}={}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let a=o.incarnationFor(r),A=()=>o.has(r)&&o.incarnationFor(r)===a,t=async(I=e)=>{let E;try{E=await TO(I)??tn(null)}catch(B){throw zI(A),B}return zI(A),{agentPreset:o.agentPresetFor(r),agentPresetCatalog:E}},s=new Map,g=new Proxy(n,{get(I,E){if(E==="agentPresetSettings")return async(f={})=>{f?.signal?.throwIfAborted(),zI(A);let Q=await t();return f?.signal?.throwIfAborted(),Q};if(E==="updateAgentPreset")return async(f,Q={})=>{Q?.signal?.throwIfAborted(),zI(A);let y=f==="--default"?null:JI(f),m=null;if(y&&({agentPresetCatalog:m}=await t(),Q?.signal?.throwIfAborted(),!m.items.some(R=>R.id===y)))throw j2();if(await o.setAgentPreset(r,y,{incarnation:a}),zI(A),m)return{agentPreset:o.agentPresetFor(r),agentPresetCatalog:m};try{return await t()}catch(R){if(R?.code==="workspace-bot-not-found")throw R;return zI(A),{agentPreset:o.agentPresetFor(r),agentPresetCatalog:tn(null)}}};if(E==="currentWorkspace")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}return o.workspaceFor(r)};if(E==="assertWorkspaceScope")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}};if((E==="listWorkspaces"||E==="listWorkspaceSessions"||E==="listModels")&&typeof I[E]=="function")return async(...f)=>{if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=await I[E](...f);if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}return Q};if(E==="switchWorkspace")return f=>{if(!A()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return Q.code="workspace-bot-not-found",Promise.reject(Q)}return o.setWorkspace(r,f,{clearSessions:()=>i.clearSessions(),incarnation:a})};if(E==="bindWorkspaceSession")return async(f,Q)=>{if(typeof f!="string"||!f||typeof Q!="string"||!Q)throw new TypeError("conversationKey and sessionId are required");if(!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}if(typeof I.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let y=o.generationFor(r),m=await I.adoptWorkspaceSession(Q);if(!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}if(y!==o.generationFor(r))throw sc("The bot workspace changed while the session was being adopted.");if(!m||typeof m!="object"||m.sessionId!==Q||typeof m.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let R=await o.bindWorkspaceSession(r,m.workspace,{conversationKey:f,sessionId:Q,clearSessions:()=>i.clearSessions(),setSession:(_,P)=>i.setSession(_,P),incarnation:a,expectedGeneration:y});if(!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}if(R.generation!==o.generationFor(r))throw sc("The bot workspace changed before the session binding completed.");return s.set(Q,R.generation),{...m,workspace:R.workspace,sessionId:R.sessionId}};if(E==="createSession")return async(f={})=>{if(await o.whenBotIdle(r),!A()){let R=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw R.code="workspace-bot-not-found",R}let Q=o.generationFor(r),y=o.agentPresetFor(r),m=await I.createSession({...f,workspace:o.workspaceFor(r),...y==null?{}:{agentPreset:y}});return s.set(m,Q),m};if(E==="workspaceSession")return f=>{if(typeof f!="string"||!f)throw new TypeError("sessionId is required");let Q=s.get(f)??o.generationFor(r);s.delete(f);let y=()=>A()&&Q===o.generationFor(r),m=async(_,P,Y)=>{if(!y())throw sc(`The bot workspace changed before this ${Y} started.`);let j=await I[_](f,...P);if(!y())throw sc(`The bot workspace changed while this ${Y} was running.`);return j},R=async(_,P,Y)=>{if(!y())throw sc(`The bot workspace changed before this ${Y} started.`);return I[_](f,...P)};return Object.freeze({sessionId:f,async sessionExists(..._){if(!y())return!1;let P=await I.sessionExists(f,..._);return y()&&P},models(..._){return m("getSessionModels",_,"model listing")},selectModel(..._){return m("selectSessionModel",_,"model selection")},isRunning(..._){return m("isSessionRunning",_,"run-state check")},hasActiveTurn(..._){return m("hasActiveTurn",_,"turn ownership check")},stopActiveTurn(..._){return R("stopActiveTurn",_,"turn stop")},steerActiveTurn(..._){return R("steerActiveTurn",_,"turn steering")},ask(..._){if(!y())throw sc("The bot workspace changed before this prompt started.");return I.ask(f,..._)}})};if(E==="sessionExists")return(f,...Q)=>{if(!A())return!1;let y=s.get(f);return y!==void 0&&y!==o.generationFor(r)?(s.delete(f),!1):I.sessionExists(f,...Q)};if(E==="ask")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(r)){let m=new Error("The bot workspace changed before this prompt started.");throw m.code=Ja,m}return I.ask(f,...Q)};if(E==="executeCommand"&&typeof I.executeCommand=="function")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(r)){let m=new Error("The bot workspace changed before this command started.");throw m.code=Ja,m}return I.executeCommand(f,...Q)};let B=Reflect.get(I,E,I);return typeof B=="function"?B.bind(I):B}}),c=new Proxy(i,{get(I,E){if(E===rO)return I;if(E==="sessionFor")return(f,...Q)=>{if(!A())return null;let y=I.sessionFor(f,...Q);return y&&!s.has(y)&&s.set(y,o.generationFor(r)),y};if(E==="setSession")return(f,Q,...y)=>{let m=s.get(Q);return!A()||m!==void 0&&m!==o.generationFor(r)?(s.delete(Q),!1):I.setSession(f,Q,...y)};let B=Reflect.get(I,E,I);return typeof B=="function"?B.bind(I):B}});return Object.freeze({harness:g,state:c})}function ha(n,{workspaces:r,stateFor:o,agentPresetCatalog:i}={}){if(!n||!r||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let e=new Map,a=(c,I)=>{let B=(e.get(c)??Promise.resolve()).catch(()=>{}).then(I);return e.set(c,B),B.finally(()=>{e.get(c)===B&&e.delete(c)})},A=c=>Y2(r,c,i),t=(c,I)=>{let E=r.incarnationFor(c);return a(c,async()=>{if(!(await n.status())?.bots?.some(Q=>Q?.botId===c)){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}let f=await o(c);return await r.setWorkspace(c,I,{clearSessions:()=>f.clearSessions(),incarnation:E}),A(await n.status())})},s=(c,I)=>{let E=r.incarnationFor(c),B=JI(I);return a(c,async()=>{if(!(await n.status())?.bots?.some(y=>y?.botId===c)){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=B&&i?await TO(i):null;if(B&&i&&!Q?.items.some(y=>y.id===B))throw j2();return await r.setAgentPreset(c,B,{incarnation:E}),Y2(r,await n.status(),Q??i)})},g=(c,I)=>a(c,async()=>{let E=await r.beginRemoval(c,{clearSessions:async()=>{try{let B=await o(c);if(!B||typeof B.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await B.clearSessions()}catch(B){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${c}:`,B?.message??B)}}});try{let B=await I();return await r.finishRemoval(E),A(B)}catch(B){let f=await xne(n).catch(()=>null);throw Array.isArray(f?.bots)&&!f.bots.some(y=>y?.botId===c)?await r.finishRemoval(E):await r.abortRemoval(E),B}});return new Proxy(n,{get(c,I){if(I==="updateWorkspace")return t;if(I==="updateAgentPreset")return s;let E=Reflect.get(c,I,c);return typeof E!="function"?E:I==="deleteBot"?(B,...f)=>g(B,()=>E.call(c,B,...f)):I==="disconnect"?async(...B)=>{let Q=(await c.status())?.bots?.[0]?.botId;return Q?g(Q,()=>E.apply(c,B)):A(E.apply(c,B))}:(...B)=>A(E.apply(c,B))}})}var J2=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function jne(n){if(!Array.isArray(n)||n.length===0)return[...J2];let r=n.filter(o=>Number.isFinite(o)&&o>=0);return r.length>0?r:[...J2]}var iB=class{#e;#A;#r;#t;#n;#o;#l;#s=null;#I=null;#a=0;#i=!1;#c=!1;#g;#p;constructor({controller:r,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!r||typeof r.initialize!="function"||typeof r.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=r,this.#A=o,this.#r=i,this.#t=jne(e),this.#n=Number.isFinite(a)&&a>=0?a:15e3,this.#o=A,this.#l=t,this.#g=new Promise(s=>{this.#p=s})}get ready(){return this.#g}start(){return this.#c||this.#i?this:(this.#c=!0,this.#h(0),this)}async close(){this.#i||(this.#i=!0,this.#s!==null&&this.#l(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#h(r){this.#i||(this.#s=this.#o(()=>{this.#s=null,this.#C()},r),this.#s?.unref?.())}async#C(){if(this.#i||this.#I)return;let r=this.#E();this.#I=r;try{await r}finally{this.#I===r&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#i)return;let r=await this.#e.initialize();if(this.#i)return;this.#p?.(r),this.#p=null;let{configured:o,connected:i}=r.totals;if(io.invoke({namespace:"commands",method:"execute",args:{agentId:i,line:e},signal:a.signal})}}import{randomUUID as Jne}from"node:crypto";function qne(n){if(typeof n?.get!="function")return;let r;try{r=n.get("agents")}catch{return}if(r!=null){if(typeof r.get!="function")throw new TypeError('dsh-im requires a callable AgentRegistry when ctx.get("agents") is present');return r}}function Vne(n,r,o){if(n?.status!=="running")return!1;let i=n?.session?.events;if(!Array.isArray(i))return!1;let e=null,a=!1;for(let A of i){if(A?.type==="turn/start"){e=A.data?.turn??null,a=!1;continue}if(A?.type==="turn/end"&&A.data?.turn===e){e=null,a=!1;continue}e===r&&A?.type==="user/message"&&A.data?.source?.rpcId===o&&(a=!0)}return e===r&&a}function q2(n){if(!n||typeof n!="object"||Object.isFrozen(n))return n;for(let r of Object.values(n))q2(r);return Object.freeze(n)}function zne(n){return q2({id:Jne(),role:"user",content:[{type:"text",text:n}],source:{kind:"user"}})}function Wne(n){let r=new Error("Session is busy with an active turn or maintenance task",{cause:n});return r.code="agent-busy",r}function Zne(n){return({sessionId:r,expectedTurn:o,promptRpcId:i,action:e,text:a})=>{let A=n.get(r);if(A){if(!Vne(A,o,i))return!1;if(e==="stop")return A.cancel({kind:"user"},{keepInbox:!0}),!0;if(e==="steer")return typeof a!="string"||!a.trim()?!1:(A.inject(zne(a)),!0);throw new TypeError(`Unsupported Harness control action: ${String(e)}`)}}}function Xne(n){return({sessionId:r,operation:o})=>{if(typeof o!="function")throw new TypeError("maintenance operation is required");let i=n.get(r);if(!i)return o();try{return i.runMaintenance(e=>{if(n.get(r)!==i){let a=new Error("Session agent changed before maintenance started");throw a.code="agent-unavailable",a}return o(e)})}catch(e){throw Wne(e)}}}function ua(n,r={}){let{controlExecutor:o,sessionMaintenanceExecutor:i}=r;if(o!==void 0&&typeof o!="function")throw new TypeError("controlExecutor must be a function");if(i!==void 0&&typeof i!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");let e=o&&i?void 0:qne(n);return{controlExecutor:o??(e?Zne(e):void 0),sessionMaintenanceExecutor:i??(e?Xne(e):void 0)}}function Ase(n,r){if(r!==void 0)return new URL(r);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-dingtalk requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function tse(n){let r=gc(n.dshHome??process.env.DSH_HOME??VE(ese(),".dsh")),o=gc(n.dataDir??VE(r,"integrations","dsh-dingtalk"));return{root:o,config:gc(n.configPath??VE(o,"config.json")),bots:gc(n.botsDir??VE(o,"bots")),workspaces:gc(n.workspacesPath??VE(o,"workspaces.json"))}}async function kO(n,r={},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??xu,e=o.DeviceAuth??Ju,a=o.StateStore??aB,A=o.HarnessClient??tB,t=o.Controller??UE,s=o.Runtime??xE,g=o.createConnectionSupervisor??RO,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,I=()=>pa(n),E=tse(r),B=await new i(E.config).load(),f=gc(r.workspace??process.cwd()),Q=o.WorkspaceStore??Fr,y=o.workspaces??await new Q(E.workspaces,{defaultWorkspace:f}).load(),m=typeof B.list=="function",R=m?B.list():[];m&&await y.reconcile(R.map(G=>G.botId)),await Promise.all(R.map(G=>y.ensure(G.botId,{defaultAgentPreset:r.agentPreset})));let _=typeof B.remove=="function"?Ea(B,{workspaces:y}):B,P=o.deviceAuth??new e({baseUrl:r.registrationBaseUrl}),Y=new Map,j=G=>gc(E.bots,G,"state.json"),K=async G=>{let te=Y.get(G);return te||(te=await new a(j(G)).load(),Y.set(G,te)),te},q=da(n,o.commandExecutor),{controlExecutor:V,sessionMaintenanceExecutor:H}=ua(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor}),v=new A({baseUrl:Ase(n.webServer,r.harnessBaseUrl),workspace:f,autostart:!1,dshBin:r.dshBin??"dsh",...q?{commandExecutor:q}:{},...V?{controlExecutor:V}:{},...H?{sessionMaintenanceExecutor:H}:{}}),Z=new t({deviceAuth:P,credentials:n.credentials,configStore:_,logger:c,createRuntime:async({botId:G,config:te,clientSecret:se})=>{let ne=await K(G);await y.ensure(G,{defaultAgentPreset:r.agentPreset});let Me=Ca(v,{botId:G,workspaces:y,state:ne,agentPresetCatalog:I});return new s({config:te,clientSecret:se,harness:Me.harness,state:Me.state,replyTimeoutMs:r.replyTimeoutMs??6e5,maxMessageChars:r.maxMessageChars??4e3,connectTimeoutMs:r.connectTimeoutMs??15e3,logger:{error:(...Oe)=>c.error?.(`[${G}]`,...Oe),warn:(...Oe)=>c.warn?.(`[${G}]`,...Oe),info:(...Oe)=>c.info?.(`[${G}]`,...Oe),debug:(...Oe)=>c.debug?.(`[${G}]`,...Oe)}})},deleteState:async({botId:G})=>{let te=Y.get(G);if(Y.delete(G),te&&typeof te.remove=="function")await te.remove();else try{await $ne(j(G))}catch(se){if(se?.code!=="ENOENT")throw se}}}),U=ha(Z,{workspaces:y,stateFor:K,agentPresetCatalog:I}),M=g({controller:U,harness:v,logger:c,retryDelaysMs:r.retryDelaysMs,healthyIntervalMs:r.healthyIntervalMs}).start();return{controller:U,ready:M.ready,async close(){await M.close(),await U.close(),v.stopManagedProcess()}}}import ose from"qrcode";var rse=new Set(["loopback","trusted-host"]);function Er(n){if(n===void 0)return"loopback";if(rse.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as ase}from"node:path";var za="bot.workspace.set";function Ba(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(r=>["botId","workspace"].includes(r))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&ase(n.workspace.trim())}function fa(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found","agent-preset-invalid","agent-preset-unavailable"].includes(n?.code)?{code:n.code,message:n.message}:null}var Wa="bot.preset.set";function ise(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Qa(n){return ise(n)&&Object.keys(n).every(r=>["botId","agentPreset"].includes(r))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&(n.agentPreset===null||typeof n.agentPreset=="string"&&yO.test(n.agentPreset))}var z2="/dingtalk",zt=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:za,setAgentPreset:Wa,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),W2=Object.freeze(Object.values(zt)),nse=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function PO(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function qs(n,r){return PO(n)&&Object.keys(n).every(o=>r.includes(o))}function cc(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function V2(n,r){return typeof n=="string"&&n.trim().length>0&&n.length<=r}function sse(n,r){return PO(r)?n===zt.status?qs(r,[])?null:"connection.status does not accept fields.":n===zt.beginProvisioning?qs(r,["locale"])&&(r.locale===void 0||r.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[zt.pollProvisioning,zt.cancelProvisioning].includes(n)?qs(r,["attemptId"])&&cc(r.attemptId)?null:`${n} requires an attemptId.`:n===zt.bindCredentials?qs(r,["clientId","clientSecret"])&&V2(r.clientId,256)&&V2(r.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===zt.reconnectBot?qs(r,["botId","sendTest"])&&cc(r.botId)&&(r.sendTest===void 0||r.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===zt.deleteBot?qs(r,["botId","confirm"])&&cc(r.botId)&&r.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===zt.setWorkspace?Ba(r)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===zt.setAgentPreset?Qa(r)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===zt.approveSender?qs(r,["botId","requestId","confirm"])&&cc(r.botId)&&cc(r.requestId)&&r.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===zt.revokeSender?qs(r,["botId","senderKey","confirm"])&&cc(r.botId)&&cc(r.senderKey)&&r.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function oB(n){return{ok:!1,error:{code:"bad-request",message:n}}}function zE(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function gse(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function WI(n){if(Array.isArray(n))return n.map(WI);if(!PO(n))return n;let r={};for(let[o,i]of Object.entries(n))nse.has(o)||(r[o]=WI(i));return r}async function cse(n){return ose.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function vO(n,r){return!n||typeof n.verificationUrl!="string"?WI(n):WI({...n,qrCodeDataUrl:await r(n.verificationUrl)})}async function Vs(n,r){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await vO(o.provisioning,r)),WI(o)}function Ise(n){for(let r of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[r]!="function")throw new TypeError(`A complete DingTalk controller is required (${r})`)}function Z2(n,{encodeQr:r=cse}={}){Ise(n);let o=new Map,i=e=>{let a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>r(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return zE();if(!W2.includes(e))return oB("Unknown DingTalk endpoint.");let t=sse(e,a);if(t)return oB(t);try{let s;if(e===zt.status)s=await Vs(await n.status(),i);else if(e===zt.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),zE();s=await vO(g,i)}else if(e===zt.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return oB("The provisioning attempt no longer exists.");s=await vO(g,i)}else if(e===zt.cancelProvisioning){if(s=await n.cancelProvisioning(a.attemptId),!s)return oB("The provisioning attempt no longer exists.");s=WI(s)}else if(e===zt.bindCredentials)s=await Vs(await n.bindCredentials(a),i);else if(e===zt.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return zE();let c;if(a.sendTest===!0)if(!g?.bots?.some(E=>E?.botId===a.botId&&E?.connected===!0)||typeof n.sendConnectionTest!="function")c=qt(tr("\u9489\u9489\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=qt()}catch(E){c=qt(E)}s=await Vs({...g,...c?{testMessage:c}:{}},i)}else if(e===zt.deleteBot)s=await Vs(await n.deleteBot(a.botId),i);else if(e===zt.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await Vs(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===zt.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await Vs(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else e===zt.approveSender?s=await Vs(await n.approveSender(a.botId,a.requestId),i):s=await Vs(await n.revokeSender(a.botId,a.senderKey),i);return A?.aborted?zE():{ok:!0,value:s}}catch(s){let g=fa(s);return A?.aborted?zE():g?{ok:!1,error:g}:gse()}}}function nB(n,r,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(z2,Z2(r,o),{authority:Er(i)})}async function X2(n,r={}){if(r?.controller)return nB(n,r.controller,r.rpcOptions,r.rpcAuthority);let o=await kO(n,r,r.internals),i=nB(n,o.controller,r.rpcOptions,r.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as lse}from"node:crypto";import{mkdir as pse,readFile as Ese,rename as Cse,unlink as hse,writeFile as dse}from"node:fs/promises";import{dirname as use}from"node:path";var GO=Object.freeze({version:1,bots:Object.freeze([])});function Zn(n){return typeof n=="string"&&n.trim()?n.trim():null}function $2(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function WE(n,{botPrefix:r,tokenRefPrefix:o}){let i=Zn(n);if(!i)throw new TypeError("platformId is required");let e=lse("sha256").update(i).digest("hex").slice(0,24);return{botId:`${r}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function sB(n,r){let o=Zn(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:r:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var ZI=class{#e;#A;#r;#t;#n;#o;#l;#s=GO;#I=Promise.resolve();constructor(r,{channel:o,botPrefix:i,tokenRefPrefix:e,normalizeBotExtension:a=()=>({})}){if(typeof a!="function")throw new TypeError("normalizeBotExtension must be a function");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=new RegExp(`^${$2(i)}_[a-f0-9]{24}$`),this.#l=new RegExp(`^${$2(e)}_[A-F0-9]{24}$`)}async load(){try{let r=this.#i(JSON.parse(await Ese(this.#e,"utf8")));if(!r)throw new Error(`dsh-im ${this.#A} config contains invalid bot data`);this.#s=r}catch(r){if(r?.code!=="ENOENT")throw r;this.#s=GO}return this}list(){return structuredClone(this.#s.bots)}get(r){let o=this.#s.bots.find(i=>i.botId===r);return o?structuredClone(o):null}getByPlatformId(r){let o=this.#s.bots.find(i=>i.platformId===r);return o?structuredClone(o):null}async save(r){let o=this.#a(r);if(!o)throw new Error(`Refusing to persist incomplete ${this.#A} bot data`);return this.#c(i=>{let e=i.find(t=>t.platformId===o.platformId&&t.botId!==o.botId),a=i.find(t=>t.tokenRef===o.tokenRef&&t.botId!==o.botId);if(e||a)throw new Error(`Duplicate ${this.#A} bot identity`);let A=i.findIndex(t=>t.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(r){if(!this.#o.test(r))throw new TypeError(`Invalid ${this.#A} bot id`);return this.#c(o=>{let i=o.findIndex(a=>a.botId===r);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let r=this.#I.then(async()=>{try{await hse(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#s=GO});this.#I=r.then(()=>{},()=>{}),await r}#a(r){if(!r||typeof r!="object")return null;let o=Zn(r.platformId),i=Zn(r.botId),e=Zn(r.tokenRef),a=Zn(r.name);if(!o||!i||!e||!a||!this.#o.test(i)||!this.#l.test(e))return null;let A=WE(o,{botPrefix:this.#r,tokenRefPrefix:this.#t});if(A.botId!==i||A.tokenRef!==e)return null;let t=this.#n(r);return!t||typeof t!="object"||Array.isArray(t)?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:a,username:Zn(r.username),createdAt:Zn(r.createdAt)??new Date().toISOString(),connectedAt:Zn(r.connectedAt),...t})}#i(r){if(!r||r.version!==1||!Array.isArray(r.bots))return null;let o=r.bots.map(A=>this.#a(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||a.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),a.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#c(r){let o,i=this.#I.then(async()=>{let e=[...this.#s.bots];o=r(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#g(a),this.#s=a});return this.#I=i.then(()=>{},()=>{}),await i,o}async#g(r){await pse(use(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await dse(o,`${JSON.stringify(r,null,2)} -`,{encoding:"utf8",mode:384}),await Cse(o,this.#e)}};var eU=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function AU(n){return WE(n,eU)}function tU(n){return sB(n,"Discord\u673A\u5668\u4EBA")}var gB=class extends ZI{constructor(r){super(r,{channel:"Discord",...eU})}};function ZE(n){return typeof n=="string"&&n.trim()?n.trim():null}function XE(n,r){return Object.freeze({code:n,message:r})}var XI=class{#e;#A;#r;#t;#n;#o;#l;#s;#I;#a=new Map;#i=new Map;#c=new Map;#g=0;#p=!1;constructor({descriptor:r,credentials:o,configStore:i,inspectToken:e,deriveIdentity:a,maskPlatformId:A,createRuntime:t,deleteState:s=async()=>{},logger:g=console}){if(!r?.key||!r?.label||!r?.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(`${r.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${r.label} requires a config store`);if(typeof e!="function"||typeof a!="function"||typeof A!="function"||typeof t!="function")throw new TypeError(`${r.label} controller dependencies are incomplete`);this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#I=g}async initialize(){if(this.#p)return this.status();for(let r of this.#r.list())await this.#B(r.botId,async()=>{if(this.#p||this.#a.get(r.botId)?.status?.ready)return;let o=await this.#E(r.tokenRef);if(!o){this.#i.set(r.botId,XE("missing-token",`${this.#e.label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002`));return}try{await this.#h(r,o),this.#i.delete(r.botId)}catch(i){this.#i.set(r.botId,XE("connection-failed",`${this.#e.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002`)),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${r.botId} failed to initialize:`,i)}finally{this.#u()}});return this.status()}async bindCredentials({token:r}={}){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let o=ZE(r);if(!o)throw new TypeError(`${this.#e.label} Bot Token is required`);let i=await this.#t(o),e=ZE(i?.platformId),a=ZE(i?.name);if(!e||!a)throw new Error(`${this.#e.label} returned an invalid bot identity`);let A=this.#n(e);return await this.#B(A.botId,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let t=this.#r.getByPlatformId(e),s=await this.#A.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:a,username:ZE(i.username),createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(A.tokenRef,o);try{await this.#r.save(g)}catch(c){throw await this.#d(A.tokenRef,s),c}try{await this.#h(g,o),this.#i.delete(A.botId)}catch(c){this.#i.set(A.botId,XE("connection-failed",`${this.#e.label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002`)),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${A.botId} credential connection failed:`,c)}this.#u()}),this.status()}async reconnectBot(r){let o=this.#r.get(r);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(r,async()=>{let i=await this.#E(o.tokenRef);if(!i)throw new Error(`${this.#e.label} bot token is missing`);try{await this.#h(o,i),this.#i.delete(r)}catch(e){throw this.#i.set(r,XE("connection-failed",`${this.#e.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),e}finally{this.#u()}}),this.status()}async updateBotConfig(r,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(typeof o!="function")throw new TypeError("Bot config update must be a function");return await this.#B(r,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=this.#r.get(r);if(!i)throw new Error(`Unknown ${this.#e.label} bot`);let e=await this.#E(i.tokenRef);if(!e)throw new Error(`${this.#e.label} bot token is missing`);if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let a=o(i),A=await this.#r.save(a);try{await this.#h(A,e),this.#i.delete(r)}catch(t){throw this.#i.set(r,XE("connection-failed",`${this.#e.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),t}finally{this.#u()}}),this.status()}async sendConnectionTest(r){let o=this.#r.get(r);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return this.#B(r,async()=>{let i=this.#a.get(r);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let a=new Error(`${this.#e.label}\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5`);throw a.code="test-target-unavailable",a}let e=`${o.name}\uFF08${this.#o(o.platformId)}\uFF09`;return await i.sendConnectionTest(ga(e,`${this.#e.label}\u673A\u5668\u4EBA`)),{sent:!0}})}async deleteBot(r){let o=this.#r.get(r);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(r,async()=>{let i=await this.#A.resolve(o.tokenRef).catch(()=>{});await this.#C(r);try{await this.#A.unset(o.tokenRef),await this.#r.remove(r)}catch(e){throw i?.value&&(await this.#A.set(o.tokenRef,i.value).catch(()=>{}),await this.#h(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#e.label} bot safely.`,{cause:e})}await this.#s({botId:r,config:o}).catch(e=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${r} state cleanup failed:`,e)}),this.#i.delete(r),this.#u()}),this.status()}status(){let r=this.#r.list().map(i=>{let e=this.#a.get(i.botId)?.status??null,a=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=a?"connected":e?.connectionState==="connecting"?"connecting":this.#i.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:a,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#o(i.platformId)},health:{status:a?"healthy":A==="error"?"error":"offline",summary:a?`${this.#e.label}${this.#e.connectionLabel}\u8FD0\u884C\u6B63\u5E38`:A==="error"?`${this.#e.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5`:`${this.#e.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=r.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#g,state:r.length===0?"disconnected":o===r.length?"connected":o>0?"degraded":"offline",bots:r,totals:{configured:r.length,connected:o}}}async close(){this.#p||(this.#p=!0,await Promise.allSettled([...this.#c.values()]),await Promise.allSettled([...this.#a.keys()].map(r=>this.#C(r))))}async#h(r,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(await this.#C(r.botId),this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=await this.#l({botId:r.botId,config:r,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#e.label} runtime`);this.#a.set(r.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#a.delete(r.botId),e}}async#C(r){let o=this.#a.get(r);this.#a.delete(r),await o?.stop().catch(i=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${r} failed to stop cleanly:`,i)})}async#E(r){let o=await this.#A.resolve(r).catch(()=>{});return ZE(o?.value)}async#d(r,o){o?.value?await this.#A.set(r,o.value).catch(()=>{}):await this.#A.unset(r).catch(()=>{})}#B(r,o){let a=(this.#c.get(r)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#c.get(r)===a&&this.#c.delete(r)});return this.#c.set(r,a),a}#u(){this.#g+=1}};var Bse="https://discord.com/api/v10/";function $E(n){return typeof n=="string"&&n.trim()?n.trim():null}function fse(n,r){let o=AbortSignal.timeout(r);return n?AbortSignal.any([n,o]):o}function Qse(n,r){return new Promise((o,i)=>{if(r?.aborted){i(r.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),r?.addEventListener("abort",()=>{clearTimeout(e),i(r.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function $I(n,r){let o=$E(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${r}`);return o}function yse(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var eC=class{#e;#A;#r;constructor({token:r,fetchImpl:o=fetch,baseUrl:i=Bse}){if(!yse(r))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#e=r.trim(),this.#A=o,this.#r=new URL(i)}getCurrentUser(r={}){return this.#t("users/@me",{...r,method:"GET"})}getGatewayBot(r={}){return this.#t("gateway/bot",{...r,method:"GET"})}createMessage({channelId:r,content:o,replyToMessageId:i,signal:e}){return this.#t(`channels/${$I(r,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:$I(i,"message id"),channel_id:$I(r,"channel id"),fail_if_not_exists:!1}}:{}}})}editMessage({channelId:r,messageId:o,content:i,signal:e}){return this.#t(`channels/${$I(r,"channel id")}/messages/${$I(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:r,signal:o}){return this.#t(`channels/${$I(r,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async#t(r,{method:o,body:i,signal:e,timeoutMs:a=15e3,expectBody:A=!0,retry:t=!0}){let s;try{s=await this.#A(new URL(r,this.#r),{method:o,headers:{authorization:`Bot ${this.#e}`,"content-type":"application/json","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.0.0)"},...i===void 0?{}:{body:JSON.stringify(i)},signal:fse(e,a),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 Qse(c,e),this.#t(r,{method:o,body:i,signal:e,timeoutMs:a,expectBody:A,retry:!1})}if(!s.ok){let c=new Error($E(g?.message)??`Discord API failed with HTTP ${s.status}`);throw c.code=`discord-${s.status}`,c}return A?g:null}};async function rU(n,r={}){let i=await new eC({token:n,...r}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:$E(i.global_name)??$E(i.username)??"Discord\u673A\u5668\u4EBA",username:$E(i.username)}}var aU="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002";function di(n){return typeof n=="string"?n.trim():""}function mse(n,r,o){return r.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!Ir(n)&&!!di(n.content)}function ui(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var rn=class{#e;#A;#r;#t;#n;#o;#l;#s;#I=new Map;#a=new Map;#i=new Map;#c=new Set;#g=new Set;#p=new Set;#h;constructor({descriptor:r,bot:o,harness:i,state:e,status:a=ui(),logger:A=console,replyTimeoutMs:t=6e5,signal:s}){if(!r?.key||!r?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#h=new ja({label:r.key,logger:A})}get status(){return structuredClone(this.#n)}accept(r){if(this.#s?.aborted)return Promise.resolve();let o=di(r?.conversationId),i=r?.kind==="group"?"group":"direct",e={...r,kind:i,conversationId:o},a=di(e.messageId),A=di(e.senderId);if(!a||!A||!o||e.senderIsBot===!0||this.#t.hasSeen(a)||this.#c.has(a))return Promise.resolve();this.#c.add(a),e.kind==="direct"&&Pi(this.#t,e.connectionTestTarget??e.replyTarget);let t=`${i}:${o}`,s=this.#a.get(t),g=di(e.content),c=pi(g)?Hi:Ei(g)?Yi:Ci(g)?xi:null;if(c&&(e.kind!=="group"||e.addressed===!0)){let E;return E=this.#E(e,a,t,c).finally(()=>{this.#c.delete(a),this.#p.delete(E)}),this.#p.add(E),E}let I=this.#h.claimReply({key:t,actor:A,messageId:a,text:Ir(e)?"":e.content,addressed:e.kind!=="group"||e.addressed===!0,hasPendingQuestion:!!s,questionCompletion:s?.submitting||s?.claimedReplyMessageId?s.queue:null,isQuestionPending:()=>this.#a.has(t),send:E=>this.#A.sendText(e.replyTarget,E)});if(I){let E;return E=I.process(async()=>this.#t.hasSeen(a)?!1:(await this.#t.markSeen(a),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#c.delete(a),this.#g.delete(E)}),this.#g.add(E),E}if(s&&s.actor!==A)return this.#C(e,a,A,t);if(s?.submitting||s?.claimedReplyMessageId)return this.#C(e,a,A,t);if(s){mse(e,s,A)&&(s.claimedReplyMessageId=a);let B=(s.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#B(e,a,A,t,s)).finally(()=>{this.#c.delete(a),s.claimedReplyMessageId===a&&(s.claimedReplyMessageId=null),s.queue===B&&(s.queue=null)});return s.queue=B,B}return this.#C(e,a,A,t)}#C(r,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1}={}){let s=(this.#I.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#d(r,o,i,e,{alreadyRecorded:A})).finally(()=>{a&&this.#c.delete(o),this.#I.get(e)===s&&this.#I.delete(e)});return this.#I.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#a.values()].flatMap(r=>r.queue?[r.queue]:[]),...this.#g,...this.#p])}async#E(r,o,i,e){if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString();let a=r.replyTarget;try{let A=await e(di(r.content),this.#r,this.#t,i,{signal:this.#s,hasImages:Ir(r),pendingInteraction:this.#a.has(i)||this.#h.hasPending(i),control:{owner:this,key:i}});A?.stopped&&await Promise.allSettled([this.#R(i),this.#h.closeRoute(i)]);for(let t of A?.messages??[A?.message])t&&await this.#A.sendText(a,t);this.#n.lastError=null}catch(A){if(A?.code==="turn-stopped"||this.#s?.aborted)return;this.#n.lastError=A?.message??String(A),this.#o.error?.(`[dsh-im:${this.#e.key}] failed to process a command:`,A),await this.#A.sendText(a,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002").catch(()=>{})}}sendConnectionTest(r){return Ys({state:this.#t,text:r,channelLabel:`${this.#e.label}\u673A\u5668\u4EBA`,send:(o,i)=>this.#A.sendText(o,i)})}async#d(r,o,i,e,{alreadyRecorded:a=!1}={}){if(!a){if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString()}let A=r.replyTarget,t=di(r.content),s=null;try{if(this.#s?.throwIfAborted(),r.kind==="group"&&r.addressed!==!0){this.#n.messagesRejected+=1,this.#n.lastRejectedAt=new Date().toISOString();return}let g=Ir(r);if(!t&&!g){await this.#A.sendText(A,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u548C\u56FE\u7247\u6D88\u606F\u3002");return}let c=t.toLowerCase();if(!g&&c==="/help"){await this.#A.sendText(A,[`${this.#e.label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002`,"","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u6216\u56FE\u7247\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587","/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 \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B","/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B","\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2","/presetlist \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset","/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset","\u7EAF\u6570\u5B57 ID\uFF1A/preset id:","/preset --default \u8DDF\u968F Host \u9ED8\u8BA4","/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1","/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` +`,{encoding:"utf8",mode:384}),await Cse(o,this.#e)}};var eU=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function AU(n){return WE(n,eU)}function tU(n){return sB(n,"Discord\u673A\u5668\u4EBA")}var gB=class extends ZI{constructor(r){super(r,{channel:"Discord",...eU})}};function ZE(n){return typeof n=="string"&&n.trim()?n.trim():null}function XE(n,r){return Object.freeze({code:n,message:r})}var XI=class{#e;#A;#r;#t;#n;#o;#l;#s;#I;#a=new Map;#i=new Map;#c=new Map;#g=0;#p=!1;constructor({descriptor:r,credentials:o,configStore:i,inspectToken:e,deriveIdentity:a,maskPlatformId:A,createRuntime:t,deleteState:s=async()=>{},logger:g=console}){if(!r?.key||!r?.label||!r?.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(`${r.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${r.label} requires a config store`);if(typeof e!="function"||typeof a!="function"||typeof A!="function"||typeof t!="function")throw new TypeError(`${r.label} controller dependencies are incomplete`);this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#I=g}async initialize(){if(this.#p)return this.status();for(let r of this.#r.list())await this.#B(r.botId,async()=>{if(this.#p||this.#a.get(r.botId)?.status?.ready)return;let o=await this.#E(r.tokenRef);if(!o){this.#i.set(r.botId,XE("missing-token",`${this.#e.label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002`));return}try{await this.#h(r,o),this.#i.delete(r.botId)}catch(i){this.#i.set(r.botId,XE("connection-failed",`${this.#e.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002`)),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${r.botId} failed to initialize:`,i)}finally{this.#u()}});return this.status()}async bindCredentials({token:r}={}){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let o=ZE(r);if(!o)throw new TypeError(`${this.#e.label} Bot Token is required`);let i=await this.#t(o),e=ZE(i?.platformId),a=ZE(i?.name);if(!e||!a)throw new Error(`${this.#e.label} returned an invalid bot identity`);let A=this.#n(e);return await this.#B(A.botId,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let t=this.#r.getByPlatformId(e),s=await this.#A.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:a,username:ZE(i.username),createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(A.tokenRef,o);try{await this.#r.save(g)}catch(c){throw await this.#d(A.tokenRef,s),c}try{await this.#h(g,o),this.#i.delete(A.botId)}catch(c){this.#i.set(A.botId,XE("connection-failed",`${this.#e.label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002`)),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${A.botId} credential connection failed:`,c)}this.#u()}),this.status()}async reconnectBot(r){let o=this.#r.get(r);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(r,async()=>{let i=await this.#E(o.tokenRef);if(!i)throw new Error(`${this.#e.label} bot token is missing`);try{await this.#h(o,i),this.#i.delete(r)}catch(e){throw this.#i.set(r,XE("connection-failed",`${this.#e.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),e}finally{this.#u()}}),this.status()}async updateBotConfig(r,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(typeof o!="function")throw new TypeError("Bot config update must be a function");return await this.#B(r,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=this.#r.get(r);if(!i)throw new Error(`Unknown ${this.#e.label} bot`);let e=await this.#E(i.tokenRef);if(!e)throw new Error(`${this.#e.label} bot token is missing`);if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let a=o(i),A=await this.#r.save(a);try{await this.#h(A,e),this.#i.delete(r)}catch(t){throw this.#i.set(r,XE("connection-failed",`${this.#e.label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`)),t}finally{this.#u()}}),this.status()}async sendConnectionTest(r){let o=this.#r.get(r);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return this.#B(r,async()=>{let i=this.#a.get(r);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let a=new Error(`${this.#e.label}\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5`);throw a.code="test-target-unavailable",a}let e=`${o.name}\uFF08${this.#o(o.platformId)}\uFF09`;return await i.sendConnectionTest(ga(e,`${this.#e.label}\u673A\u5668\u4EBA`)),{sent:!0}})}async deleteBot(r){let o=this.#r.get(r);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(r,async()=>{let i=await this.#A.resolve(o.tokenRef).catch(()=>{});await this.#C(r);try{await this.#A.unset(o.tokenRef),await this.#r.remove(r)}catch(e){throw i?.value&&(await this.#A.set(o.tokenRef,i.value).catch(()=>{}),await this.#h(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#e.label} bot safely.`,{cause:e})}await this.#s({botId:r,config:o}).catch(e=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${r} state cleanup failed:`,e)}),this.#i.delete(r),this.#u()}),this.status()}status(){let r=this.#r.list().map(i=>{let e=this.#a.get(i.botId)?.status??null,a=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=a?"connected":e?.connectionState==="connecting"?"connecting":this.#i.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:a,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#o(i.platformId)},health:{status:a?"healthy":A==="error"?"error":"offline",summary:a?`${this.#e.label}${this.#e.connectionLabel}\u8FD0\u884C\u6B63\u5E38`:A==="error"?`${this.#e.label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5`:`${this.#e.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=r.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#g,state:r.length===0?"disconnected":o===r.length?"connected":o>0?"degraded":"offline",bots:r,totals:{configured:r.length,connected:o}}}async close(){this.#p||(this.#p=!0,await Promise.allSettled([...this.#c.values()]),await Promise.allSettled([...this.#a.keys()].map(r=>this.#C(r))))}async#h(r,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(await this.#C(r.botId),this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=await this.#l({botId:r.botId,config:r,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#e.label} runtime`);this.#a.set(r.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#a.delete(r.botId),e}}async#C(r){let o=this.#a.get(r);this.#a.delete(r),await o?.stop().catch(i=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${r} failed to stop cleanly:`,i)})}async#E(r){let o=await this.#A.resolve(r).catch(()=>{});return ZE(o?.value)}async#d(r,o){o?.value?await this.#A.set(r,o.value).catch(()=>{}):await this.#A.unset(r).catch(()=>{})}#B(r,o){let a=(this.#c.get(r)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#c.get(r)===a&&this.#c.delete(r)});return this.#c.set(r,a),a}#u(){this.#g+=1}};var Bse="https://discord.com/api/v10/";function $E(n){return typeof n=="string"&&n.trim()?n.trim():null}function fse(n,r){let o=AbortSignal.timeout(r);return n?AbortSignal.any([n,o]):o}function Qse(n,r){return new Promise((o,i)=>{if(r?.aborted){i(r.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),r?.addEventListener("abort",()=>{clearTimeout(e),i(r.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function $I(n,r){let o=$E(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${r}`);return o}function yse(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var eC=class{#e;#A;#r;constructor({token:r,fetchImpl:o=fetch,baseUrl:i=Bse}){if(!yse(r))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#e=r.trim(),this.#A=o,this.#r=new URL(i)}getCurrentUser(r={}){return this.#t("users/@me",{...r,method:"GET"})}getGatewayBot(r={}){return this.#t("gateway/bot",{...r,method:"GET"})}createMessage({channelId:r,content:o,replyToMessageId:i,signal:e}){return this.#t(`channels/${$I(r,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:$I(i,"message id"),channel_id:$I(r,"channel id"),fail_if_not_exists:!1}}:{}}})}editMessage({channelId:r,messageId:o,content:i,signal:e}){return this.#t(`channels/${$I(r,"channel id")}/messages/${$I(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:r,signal:o}){return this.#t(`channels/${$I(r,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async#t(r,{method:o,body:i,signal:e,timeoutMs:a=15e3,expectBody:A=!0,retry:t=!0}){let s;try{s=await this.#A(new URL(r,this.#r),{method:o,headers:{authorization:`Bot ${this.#e}`,"content-type":"application/json","user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.0.1)"},...i===void 0?{}:{body:JSON.stringify(i)},signal:fse(e,a),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 Qse(c,e),this.#t(r,{method:o,body:i,signal:e,timeoutMs:a,expectBody:A,retry:!1})}if(!s.ok){let c=new Error($E(g?.message)??`Discord API failed with HTTP ${s.status}`);throw c.code=`discord-${s.status}`,c}return A?g:null}};async function rU(n,r={}){let i=await new eC({token:n,...r}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:$E(i.global_name)??$E(i.username)??"Discord\u673A\u5668\u4EBA",username:$E(i.username)}}var aU="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002";function di(n){return typeof n=="string"?n.trim():""}function mse(n,r,o){return r.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!Ir(n)&&!!di(n.content)}function ui(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var rn=class{#e;#A;#r;#t;#n;#o;#l;#s;#I=new Map;#a=new Map;#i=new Map;#c=new Set;#g=new Set;#p=new Set;#h;constructor({descriptor:r,bot:o,harness:i,state:e,status:a=ui(),logger:A=console,replyTimeoutMs:t=6e5,signal:s}){if(!r?.key||!r?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#h=new ja({label:r.key,logger:A})}get status(){return structuredClone(this.#n)}accept(r){if(this.#s?.aborted)return Promise.resolve();let o=di(r?.conversationId),i=r?.kind==="group"?"group":"direct",e={...r,kind:i,conversationId:o},a=di(e.messageId),A=di(e.senderId);if(!a||!A||!o||e.senderIsBot===!0||this.#t.hasSeen(a)||this.#c.has(a))return Promise.resolve();this.#c.add(a),e.kind==="direct"&&Pi(this.#t,e.connectionTestTarget??e.replyTarget);let t=`${i}:${o}`,s=this.#a.get(t),g=di(e.content),c=pi(g)?Hi:Ei(g)?Yi:Ci(g)?xi:null;if(c&&(e.kind!=="group"||e.addressed===!0)){let E;return E=this.#E(e,a,t,c).finally(()=>{this.#c.delete(a),this.#p.delete(E)}),this.#p.add(E),E}let I=this.#h.claimReply({key:t,actor:A,messageId:a,text:Ir(e)?"":e.content,addressed:e.kind!=="group"||e.addressed===!0,hasPendingQuestion:!!s,questionCompletion:s?.submitting||s?.claimedReplyMessageId?s.queue:null,isQuestionPending:()=>this.#a.has(t),send:E=>this.#A.sendText(e.replyTarget,E)});if(I){let E;return E=I.process(async()=>this.#t.hasSeen(a)?!1:(await this.#t.markSeen(a),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#c.delete(a),this.#g.delete(E)}),this.#g.add(E),E}if(s&&s.actor!==A)return this.#C(e,a,A,t);if(s?.submitting||s?.claimedReplyMessageId)return this.#C(e,a,A,t);if(s){mse(e,s,A)&&(s.claimedReplyMessageId=a);let B=(s.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#B(e,a,A,t,s)).finally(()=>{this.#c.delete(a),s.claimedReplyMessageId===a&&(s.claimedReplyMessageId=null),s.queue===B&&(s.queue=null)});return s.queue=B,B}return this.#C(e,a,A,t)}#C(r,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1}={}){let s=(this.#I.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#d(r,o,i,e,{alreadyRecorded:A})).finally(()=>{a&&this.#c.delete(o),this.#I.get(e)===s&&this.#I.delete(e)});return this.#I.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#a.values()].flatMap(r=>r.queue?[r.queue]:[]),...this.#g,...this.#p])}async#E(r,o,i,e){if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString();let a=r.replyTarget;try{let A=await e(di(r.content),this.#r,this.#t,i,{signal:this.#s,hasImages:Ir(r),pendingInteraction:this.#a.has(i)||this.#h.hasPending(i),control:{owner:this,key:i}});A?.stopped&&await Promise.allSettled([this.#R(i),this.#h.closeRoute(i)]);for(let t of A?.messages??[A?.message])t&&await this.#A.sendText(a,t);this.#n.lastError=null}catch(A){if(A?.code==="turn-stopped"||this.#s?.aborted)return;this.#n.lastError=A?.message??String(A),this.#o.error?.(`[dsh-im:${this.#e.key}] failed to process a command:`,A),await this.#A.sendText(a,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002").catch(()=>{})}}sendConnectionTest(r){return Ys({state:this.#t,text:r,channelLabel:`${this.#e.label}\u673A\u5668\u4EBA`,send:(o,i)=>this.#A.sendText(o,i)})}async#d(r,o,i,e,{alreadyRecorded:a=!1}={}){if(!a){if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString()}let A=r.replyTarget,t=di(r.content),s=null;try{if(this.#s?.throwIfAborted(),r.kind==="group"&&r.addressed!==!0){this.#n.messagesRejected+=1,this.#n.lastRejectedAt=new Date().toISOString();return}let g=Ir(r);if(!t&&!g){await this.#A.sendText(A,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u548C\u56FE\u7247\u6D88\u606F\u3002");return}let c=t.toLowerCase();if(!g&&c==="/help"){await this.#A.sendText(A,[`${this.#e.label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002`,"","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u6216\u56FE\u7247\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587","/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 \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B","/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B","\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2","/presetlist \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset","/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset","\u7EAF\u6570\u5B57 ID\uFF1A/preset id:","/preset --default \u8DDF\u968F Host \u9ED8\u8BA4","/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1","/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` `));return}if(!g&&c==="/status"){await this.#r.ensureRunning({signal:this.#s}),await this.#A.sendText(A,`${this.#e.label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002`);return}let I=g?null:await Ki(t,this.#r,e);if(I){for(let y of I.messages??[I.message])await this.#A.sendText(A,y);return}if(!g&&c==="/new"){await this.#t.clearSession(e),await this.#A.sendText(A,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002");return}let E=g?null:await Ui(t,this.#r,this.#t,e,{signal:this.#s});if(E){await this.#A.sendText(A,E.message);return}await this.#A.sendTyping?.(A).catch(y=>{this.#o.warn?.(`[dsh-im:${this.#e.key}] typing indicator failed:`,y)});let B=!1;if(typeof this.#A.openStream=="function")try{s=await this.#A.openStream(A)}catch(y){this.#o.warn?.(`[dsh-im:${this.#e.key}] unable to start a streamed reply; using text:`,y)}let f=g?await Fi(r,{signal:this.#s}):void 0,{answer:Q}=await qa({harness:this.#r,state:this.#t,key:e,text:t,content:f,createOptions:this.#s?{signal:this.#s}:void 0,existsOptions:this.#s?{signal:this.#s}:void 0,askOptions:{timeoutMs:this.#l,signal:this.#s,control:{owner:this,key:e},onUpdate:s?async y=>{let m=y.type==="text"?y.text:y.type==="tool"?`\u6B63\u5728\u4F7F\u7528${y.name}\u2026`:y.text;m&&await s.update(m)}:void 0,onInteraction:y=>this.#u(y,{key:e,actor:i,target:A,requiresMention:r.kind==="group"}),onInteractionResolved:y=>this.#Q(y)}});if(s)try{await s.finish(Q),B=!0}catch(y){s.cancel?.(),this.#o.warn?.(`[dsh-im:${this.#e.key}] streamed reply finalization failed; using text:`,y)}B||await this.#A.sendText(A,Q),this.#n.messagesReplied+=1,this.#n.lastReplyAt=new Date().toISOString(),this.#n.lastError=null}catch(g){if(g?.code==="turn-stopped"){if(s)try{await s.finish("\u5DF2\u505C\u6B62\u3002")}catch{s.cancel?.()}return}if(s?.cancel?.(),this.#s?.aborted)return;this.#n.lastError=g?.message??String(g);let c=Li(g);if(c){try{await this.#A.sendText(A,c)}catch(I){this.#o.error?.(`[dsh-im:${this.#e.key}] failed to send the image error reply:`,I)}return}this.#o.error?.(`[dsh-im:${this.#e.key}] failed to process a message:`,g);try{await this.#A.sendText(A,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")}catch(I){this.#o.error?.(`[dsh-im:${this.#e.key}] failed to send the safe error reply:`,I)}}finally{await Promise.allSettled([this.#R(e),this.#h.closeRoute(e)])}}async#B(r,o,i,e,a){if(this.#s?.aborted)return;let A=this.#a.get(e),t=a.claimedReplyMessageId===o;if(!A||A!==a||A.submitting)return t&&(!A||A!==a)?this.#m(r,o):this.#C(r,o,i,e,{releaseMessageId:!1});if(this.#t.hasSeen(o))return;if(await this.#t.markSeen(o),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString(),r.kind==="group"&&r.addressed!==!0){this.#n.messagesRejected+=1,this.#n.lastRejectedAt=new Date().toISOString();return}let s=r.replyTarget,g=di(r.content);if(!g||Ir(r)){try{await this.#A.sendText(s,"\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002")}catch(E){this.#o.error?.(`[dsh-im:${this.#e.key}] failed to reject a non-text interaction reply:`,E)}return}let c=this.#a.get(e);if(!c||c!==a||c.submitting)return t&&(!c||c!==a)?this.#m(r,o,{alreadyRecorded:!0}):this.#C(r,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0});if(c.target=s,c.needsPresentation){let E=c.presentationTask!==null;try{await this.#f(c)}catch(f){this.#n.lastError=`${this.#e.label}\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002`,this.#o.error?.(`[dsh-im:${this.#e.key}] failed to retry an interaction question:`,f),c.interaction.reconnect?.();return}let B=this.#a.get(e);if(!B||B!==a||B.submitting)return t&&(!B||B!==a)?this.#m(r,o,{alreadyRecorded:!0}):this.#C(r,o,i,e,{releaseMessageId:!1,alreadyRecorded:!0});if(!E)return}let I=c.questions[c.index];if(I){if(c.answers.push(xa(I,g)),c.index+=1,c.indexthis.#A.sendText(e,c)});if(r?.kind!=="question")return;let A=r?.payload?.questions,t=di(r?.interactionId)||di(r?.rpcId);if(!di(r?.rpcId)||!t||!di(r?.sessionId)||!Array.isArray(A)||A.length===0||A.some(c=>!Ka(c))){this.#o.warn?.(`[dsh-im:${this.#e.key}] ignored an invalid Harness question interaction`);return}if(r.recovered===!0){await this.#w(r,`${this.#e.label} safely cancelled an interaction left by an earlier client.`);try{await this.#A.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.#o.error?.(`[dsh-im:${this.#e.key}] failed to send an interaction recovery notice:`,c)}return}let s=this.#a.get(o);if(s?.interactionId===t){s.interaction=r,s.needsPresentation&&await this.#f(s);return}if(this.#i.has(t))return;if(s){this.#o.warn?.(`[dsh-im:${this.#e.key}] cancelled a second pending Harness question`),await this.#w(r,`${this.#e.label} is already handling another user interaction.`);return}let g={kind:"question",interactionId:t,sessionId:r.sessionId,interaction:r,actor:i,requiresMention:a,questions:A,answers:[],index:0,target:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationTask:null};this.#a.set(o,g),this.#i.set(t,o),await this.#f(g)}async#Q(r){if(r?.kind==="approval"){await this.#h.handleResolved(r);return}let o=di(r?.interactionId);if(r?.kind!=="question"||!o)return;let i=this.#i.get(o);i&&this.#S(i,o)}#f(r){if(r.presentationTask)return r.presentationTask;let o=r.questions[r.index];if(!o)return Promise.resolve();let i=(async()=>{await this.#A.sendText(r.target,Ya(o,r.index,r.questions.length,{requiresMention:r.requiresMention})),r.needsPresentation=!1})();return r.presentationTask=i,i.then(()=>{r.presentationTask===i&&(r.presentationTask=null)},()=>{r.presentationTask===i&&(r.presentationTask=null)}),i}async#m(r,o,{alreadyRecorded:i=!1}={}){if(!i){if(this.#t.hasSeen(o))return;await this.#t.markSeen(o),this.#n.messagesReceived+=1,this.#n.lastMessageAt=new Date().toISOString()}try{await this.#A.sendText(r.replyTarget,aU)}catch(e){this.#o.error?.(`[dsh-im:${this.#e.key}] failed to send an expired interaction notice:`,e)}}#y(r,o){let i=this.#a.get(r);return!i||o!==void 0&&i.interactionId!==o?null:(this.#a.delete(r),this.#i.delete(i.interactionId),i)}#S(r,o){return this.#y(r,o)!==null}async#w(r,o){try{await r.respond({ok:!1,error:{code:"cancelled",message:o,details:{}}},{signal:AbortSignal.timeout(5e3)})}catch(i){if(i?.code!=="interaction-not-pending")throw i}}async#R(r){let o=this.#y(r);if(!(!o||o.kind!=="question"))try{await this.#w(o.interaction,`The ${this.#e.label} interaction ended before the user answered.`)}catch(i){this.#o.warn?.(`[dsh-im:${this.#e.key}] failed to cancel a pending Harness interaction:`,i)}}};var FO=Object.freeze({key:"discord",label:"Discord",connectionLabel:" Gateway \u957F\u8FDE\u63A5"}),cB=class extends rn{constructor(r){super({descriptor:FO,...r})}};var AC=class extends XI{constructor(r){super({...r,descriptor:FO,inspectToken:r.inspectToken??rU,deriveIdentity:AU,maskPlatformId:tU})}};var IB=class extends rr{constructor(r){super({...r,rpcIdPrefix:"discord",logPrefix:"dsh-discord"})}};function ji(n,r){let o=typeof n=="string"?n.trim():"";if(!o)return[];let i=[],e=o;for(;e.length>r;){let a=e.lastIndexOf(` `,r);a{I||g!==null||c||!s||(g=setTimeout(()=>{g=null;let f=s;s=null;let Q=ji(f,r)[0]??n;c=Promise.resolve(Q===E?void 0:e(t,Q)).then(()=>{E=Q}).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(f){I||typeof f!="string"||!f.trim()||(s=f,B())},async finish(f){if(I)throw new Error("Message stream is already closed");I=!0,g!==null&&clearTimeout(g),g=null,s=null,await c?.catch(()=>{});let Q=ji(f,r),y=Q[0]??"\u5904\u7406\u5B8C\u6210\u3002";y!==E&&await e(t,y),E=y;for(let m of Q.slice(1))await a(m)},cancel(){I=!0,s=null,g!==null&&clearTimeout(g),g=null}}}var Sse=4609,iU=Object.freeze([1e3,3e3,5e3,1e4,3e4]),Dse=new Set(["image/jpeg","image/png","image/webp","image/gif"]),wse=new Map([[".jpg","image/jpeg"],[".jpeg","image/jpeg"],[".png","image/png"],[".webp","image/webp"],[".gif","image/gif"]]),Ose=Object.freeze(["cdn.discordapp.com"]);function bse(n){let r=new URL(n);if(r.protocol!=="wss:")throw new Error("Discord returned an insecure Gateway URL");return r.searchParams.set("v","10"),r.searchParams.set("encoding","json"),r.href}function LO(n,r,o){if(typeof n.addEventListener=="function")n.addEventListener(r,o);else if(typeof n.on=="function")n.on(r,o);else throw new TypeError("Discord WebSocket does not support events")}function Mse(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 _se(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 r=new Error(`Discord Gateway closed (${n||"unknown"})`);return r.code="discord-gateway-closed",r}function Nse(n,r){return typeof n!="string"?"":n.replace(new RegExp(`<@!?${r}>`,"g"),"").trim()}function Tse(n){let r=typeof n?.content_type=="string"?n.content_type.split(";",1)[0].trim().toLowerCase():"";if(Dse.has(r))return r;let o=typeof n?.filename=="string"?n.filename.toLowerCase():"";for(let[i,e]of wse)if(o.endsWith(i))return e;return null}function Rse(n){return Number.isSafeInteger(n)&&n>=0?n:void 0}function kse(n,r){let o=Tse(n);return!o||typeof n?.url!="string"?null:{name:typeof n.filename=="string"?n.filename:void 0,mediaType:o,size:Rse(n.size),load:i=>Gi(n.url,{...i,fetchImpl:r,allowedHosts:Ose})}}function vse(n,r,{fetchImpl:o=fetch}={}){if(!n?.id||!n?.channel_id||!n?.author?.id)return null;let i=!n.guild_id,e=i||n.mentions?.some(a=>String(a?.id)===String(r));return{messageId:String(n.id),senderId:String(n.author.id),senderIsBot:n.author.bot===!0,kind:i?"direct":"group",conversationId:String(n.channel_id),content:Nse(n.content??"",r),images:Array.isArray(n.attachments)?n.attachments.map(a=>kse(a,o)).filter(Boolean):[],addressed:e,replyTarget:{channelId:String(n.channel_id),replyToMessageId:String(n.id)},connectionTestTarget:{channelId:String(n.channel_id)}}}var UO=class{#e;#A;constructor({api:r,signal:o}){this.#e=r,this.#A=o}async sendText(r,o){let i=ji(o,1900),e=null;for(let[a,A]of i.entries())e=await this.#e.createMessage({channelId:r.channelId,content:A,replyToMessageId:a===0?r.replyToMessageId:void 0,signal:this.#A});return e}sendTyping(r){return this.#e.sendTyping({channelId:r.channelId,signal:this.#A})}async openStream(r){return lB({limit:1900,create:async i=>(await this.#e.createMessage({channelId:r.channelId,content:i,replyToMessageId:r.replyToMessageId,signal:this.#A})).id,edit:(i,e)=>this.#e.editMessage({channelId:r.channelId,messageId:i,content:e,signal:this.#A}),sendRemainder:i=>this.#e.createMessage({channelId:r.channelId,content:i,signal:this.#A})}).start()}};function Pse(){return{startedAt:null,ready:!1,connectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...ui()}}var tC=class{#e;#A;#r;#t;#n;#o;#l;#s;#I;#a;#i=Pse();#c=null;#g=null;#p=null;#h=null;#C=null;#E=null;#d=null;#B=null;#u=null;#Q=!0;#f=null;#m=0;#y=0;#S=!0;#w=null;constructor({config:r,token:o,harness:i,state:e,logger:a=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,createApi:s=I=>new eC(I),createWebSocket:g=I=>new WebSocket(I),random:c=Math.random}){if(!r||!o||!i||!e)throw new TypeError("DiscordRuntime requires config, token, Harness, and state");if(typeof g!="function")throw new TypeError("DiscordRuntime requires WebSocket");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#I=g,this.#a=c}get status(){return structuredClone(this.#i)}async sendConnectionTest(r){if(!this.#i.ready||!this.#g){let o=new Error("Discord bot is not connected");throw o.code="test-target-unavailable",o}return this.#g.sendConnectionTest(r)}async start(){return this.#i.ready&&this.#h?this.status:this.#w?this.#w:(this.#w=this.#R().finally(()=>{this.#w=null}),this.#w)}async#R(){await this.stop(),this.#S=!1,this.#d=null,this.#E=null,this.#B=null,this.#m=0,this.#i.startedAt=new Date().toISOString(),this.#i.connectionState="connecting",this.#i.lastError=null,await this.#r.ensureRunning(),this.#i.harnessReachable=!0;let r=new AbortController;this.#p=r;let o=this.#s({token:this.#A});this.#c=o;try{let[i,e]=await Promise.all([o.getCurrentUser({signal:r.signal}),o.getGatewayBot({signal:r.signal})]);if(String(i?.id??"")!==this.#e.platformId||i?.bot!==!0)throw new Error("Discord token identity does not match the saved bot");this.#C=e?.url;let a=new UO({api:o,signal:r.signal});this.#g=new cB({bot:a,harness:this.#r,state:this.#t,status:this.#i,logger:this.#n,replyTimeoutMs:this.#o,signal:r.signal});let A;try{await Promise.race([this.#M(!1),new Promise((t,s)=>{A=setTimeout(()=>s(new Error("Discord Gateway did not become ready in time")),this.#l)})])}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}}#M(r){if(this.#S)return Promise.reject(new Error("Discord runtime is stopped"));let o=++this.#y,i=bse(r&&this.#E?this.#E:this.#C),e=this.#I(i);this.#h=e;let a=!1;return new Promise((A,t)=>{let s=()=>{if(a||o!==this.#y)return;a=!0,this.#m=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()};LO(e,"message",g=>{if(o!==this.#y||this.#S)return;let c=Mse(g);if(!c)return;let I;try{I=JSON.parse(c)}catch{this.#n.warn?.("[dsh-im:discord] ignored malformed Gateway JSON");return}if(Number.isSafeInteger(I.s)&&(this.#B=I.s),I.op===10){this.#O(I.d?.heartbeat_interval,e,o),r&&this.#d?this.#T(e,{op:6,d:{token:this.#A,session_id:this.#d,seq:this.#B}}):this.#T(e,{op:2,d:{token:this.#A,intents:Sse,properties:{os:process.platform,browser:"dsh-im",device:"dsh-im"}}});return}if(I.op===11){this.#Q=!0,this.#i.lastCheckedAt=Date.now();return}if(I.op===1){this.#b(e);return}if(I.op===7){e.close(4e3,"Reconnect requested");return}if(I.op===9){I.d!==!0&&(this.#d=null,this.#E=null,this.#B=null),e.close(4e3,"Invalid session");return}if(I.op===0){if(I.t==="READY")this.#d=I.d?.session_id??null,this.#E=I.d?.resume_gateway_url??null,s();else if(I.t==="RESUMED")s();else if(I.t==="MESSAGE_CREATE"){let E=vse(I.d,this.#e.platformId),B=this.#g;E&&B&&B.accept(E).catch(f=>{o!==this.#y||this.#S||this.#n.error?.(`[dsh-im:discord] bot ${this.#e.botId} message handling failed:`,f)})}}}),LO(e,"close",(g={})=>{if(o!==this.#y)return;if(this.#_(),this.#h===e&&(this.#h=null),this.#S){a||t(new DOMException("Stopped","AbortError"));return}let c=_se(Number(g.code)||0);if(this.#i.ready=!1,this.#i.connectionState="connecting",this.#i.lastError=c.message,a||(a=!0,t(c)),c.code==="discord-401"||c.code==="discord-intents"){this.#i.connectionState="failed";return}this.#P()}),LO(e,"error",()=>{o!==this.#y||this.#S||(this.#i.lastError="Discord Gateway WebSocket error")})})}#T(r,o){r.readyState===1&&r.send(JSON.stringify(o))}#O(r,o,i){if(this.#_(),!Number.isFinite(r)||r<1e3){o.close(4e3,"Invalid heartbeat interval");return}this.#Q=!0;let e=a=>{this.#u=setTimeout(()=>{if(!(this.#S||i!==this.#y||this.#h!==o)){if(!this.#Q){o.close(4e3,"Heartbeat was not acknowledged");return}this.#b(o),e(r)}},a),this.#u?.unref?.()};e(Math.floor(r*this.#a()))}#b(r){this.#Q=!1,this.#T(r,{op:1,d:this.#B})}#_(){this.#u!==null&&clearTimeout(this.#u),this.#u=null,this.#Q=!0}#P(){if(this.#S||this.#f!==null)return;let r=iU[Math.min(this.#m,iU.length-1)];this.#m+=1,this.#f=setTimeout(()=>{this.#f=null,this.#M(!!this.#d).catch(o=>{this.#S||(this.#n.warn?.("[dsh-im:discord] Gateway reconnect failed:",o),this.#P())})},r),this.#f?.unref?.()}async stop(){this.#S=!0,this.#y+=1,this.#p?.abort(),this.#p=null,this.#f!==null&&clearTimeout(this.#f),this.#f=null,this.#_();let r=this.#h,o=this.#g;this.#h=null,this.#g=null,this.#c=null;try{r&&r.readyState<2&&r.close(1e3,"Plugin stopped")}catch(i){this.#n.warn?.(`[dsh-im:discord] bot ${this.#e.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 Gse,readFile as Fse,rename as Lse,unlink as Use,writeFile as Hse}from"node:fs/promises";import{dirname as Kse}from"node:path";var pB=Object.freeze({version:1,sessions:{},seenMessageIds:[],cursor:null});function Yse(n){if(!n||typeof n!="object")return structuredClone(pB);let r={};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&&(r[o]=i);return{version:1,sessions:r,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 an=class{#e;#A=structuredClone(pB);#r=Promise.resolve();constructor(r){this.#e=r}async load(){try{this.#A=Yse(JSON.parse(await Fse(this.#e,"utf8")))}catch(r){if(r?.code!=="ENOENT")throw r;this.#A=structuredClone(pB),await this.#t()}return this}sessionFor(r){return this.#A.sessions[r]??null}async setSession(r,o){this.#A.sessions[r]=o,await this.#t()}async clearSession(r){delete this.#A.sessions[r],await this.#t()}async clearSessions(){this.#A.sessions={},await this.#t()}hasSeen(r){return this.#A.seenMessageIds.includes(r)}async markSeen(r){this.hasSeen(r)||(this.#A.seenMessageIds.push(r),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#t())}cursor(){return this.#A.cursor}async setCursor(r){if(!Number.isSafeInteger(r)||r<0)throw new TypeError("Invalid update cursor");this.#A.cursor=r,await this.#t()}snapshot(){return structuredClone(this.#A)}async remove(){try{await Use(this.#e)}catch(r){if(r?.code!=="ENOENT")throw r}this.#A=structuredClone(pB)}async#t(){let r=`${JSON.stringify(this.#A,null,2)} `,o=this.#r.then(async()=>{await Gse(Kse(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await Hse(i,r,{encoding:"utf8",mode:384}),await Lse(i,this.#e)});this.#r=o.then(()=>{},()=>{}),await o}};var EB=class extends an{};import{unlink as jse}from"node:fs/promises";import{homedir as Jse}from"node:os";import{join as rC,resolve as Ic}from"node:path";var oU=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function xse(n){if(!Array.isArray(n)||n.length===0)return[...oU];let r=n.filter(o=>Number.isFinite(o)&&o>=0);return r.length>0?r:[...oU]}var HO=class{#e;#A;#r;#t;#n;#o;#l;#s;#I=null;#a=null;#i=0;#c=!1;#g=!1;#p;#h;constructor({channel:r,controller:o,harness:i,logger:e=console,retryDelaysMs:a,healthyIntervalMs:A=15e3,setTimeoutImpl:t=setTimeout,clearTimeoutImpl:s=clearTimeout}){if(!r)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.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=xse(a),this.#o=Number.isFinite(A)&&A>=0?A:15e3,this.#l=t,this.#s=s,this.#p=new Promise(g=>{this.#h=g})}get ready(){return this.#p}start(){return this.#g||this.#c?this:(this.#g=!0,this.#C(0),this)}async close(){this.#c||(this.#c=!0,this.#I!==null&&this.#s(this.#I),this.#I=null,await this.#a?.catch(()=>{}),this.#h?.(null),this.#h=null)}#C(r){this.#c||(this.#I=this.#l(()=>{this.#I=null,this.#E()},r),this.#I?.unref?.())}async#E(){if(this.#c||this.#a)return;let r=this.#d();this.#a=r;try{await r}finally{this.#a===r&&(this.#a=null)}}async#d(){try{if(await this.#r.ensureRunning(),this.#c)return;let r=await this.#A.initialize();if(this.#c)return;this.#h?.(r),this.#h=null;let{configured:o,connected:i}=r.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 KO(n,r){let o=Ic(n.dshHome??process.env.DSH_HOME??rC(Jse(),".dsh")),i=Ic(n.dataDir??rC(o,"integrations",`dsh-${r}`));return{config:Ic(n.configPath??rC(i,"config.json")),bots:Ic(n.botsDir??rC(i,"bots")),workspaces:Ic(n.workspacesPath??rC(i,"workspaces.json"))}}async function CB(n,r,o,i){let{channel:e,ConfigStore:a,StateStore:A,HarnessClient:t,Controller:s,Runtime:g,runtimeOptions:c}=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 I=o.ConfigStore??a,E=o.StateStore??A,B=o.HarnessClient??t,f=o.Controller??s,Q=o.Runtime??g,y=typeof c=="function"?c(r):{};if(!y||typeof y!="object"||Array.isArray(y))throw new TypeError(`dsh-im ${e} runtimeOptions must return an object`);let m=o.createConnectionSupervisor??el,R=typeof n.logger=="function"?n.logger(`dsh-im:${e}`):n.logger??console,_=()=>pa(n),P=KO(r,e),Y=await new I(P.config).load(),j=Ic(r.workspace??process.cwd()),K=o.WorkspaceStore??Fr,q=o.workspaces??await new K(P.workspaces,{defaultWorkspace:j}).load(),V=Y.list();await q.reconcile(V.map(_e=>_e.botId)),await Promise.all(V.map(_e=>q.ensure(_e.botId,{defaultAgentPreset:r.agentPreset})));let H=typeof Y.remove=="function"?Ea(Y,{workspaces:q}):Y,v=new Map,Z=_e=>Ic(P.bots,_e,"state.json"),U=async _e=>{let ke=v.get(_e);return ke||(ke=await new E(Z(_e)).load(),v.set(_e,ke)),ke},M=da(n,o.commandExecutor),{controlExecutor:G,sessionMaintenanceExecutor:te}=ua(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor}),se=new B({baseUrl:aC(n.webServer,r.harnessBaseUrl),workspace:j,autostart:!1,dshBin:r.dshBin??"dsh",...M?{commandExecutor:M}:{},...G?{controlExecutor:G}:{},...te?{sessionMaintenanceExecutor:te}:{}}),ne=new f({credentials:n.credentials,configStore:H,logger:R,...o.inspectToken?{inspectToken:o.inspectToken}:{},createRuntime:async({botId:_e,config:ke,token:Ve})=>{let $e=await U(_e);await q.ensure(_e,{defaultAgentPreset:r.agentPreset});let sA=Ca(se,{botId:_e,workspaces:q,state:$e,agentPresetCatalog:_});return new Q({...y,config:ke,token:Ve,harness:sA.harness,state:sA.state,replyTimeoutMs:r.replyTimeoutMs??6e5,connectTimeoutMs:r.connectTimeoutMs??2e4,logger:{error:(...Le)=>R.error?.(`[${_e}]`,...Le),warn:(...Le)=>R.warn?.(`[${_e}]`,...Le),info:(...Le)=>R.info?.(`[${_e}]`,...Le),debug:(...Le)=>R.debug?.(`[${_e}]`,...Le)}})},deleteState:async({botId:_e})=>{let ke=v.get(_e);if(v.delete(_e),ke&&typeof ke.remove=="function")await ke.remove();else try{await jse(Z(_e))}catch(Ve){if(Ve?.code!=="ENOENT")throw Ve}}}),Me=ha(ne,{workspaces:q,stateFor:U,agentPresetCatalog:_}),Oe=m({channel:e,controller:Me,harness:se,logger:R,retryDelaysMs:r.retryDelaysMs,healthyIntervalMs:r.healthyIntervalMs}).start();return{controller:Me,ready:Oe.ready,async close(){await Oe.close(),await Me.close(),se.stopManagedProcess()}}}function YO(n,r={},o={}){return CB(n,r,o,{channel:"discord",ConfigStore:gB,StateStore:EB,HarnessClient:IB,Controller:AC,Runtime:tC})}var ya=Object.freeze({status:"connection.status",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:za,setAgentPreset:Wa}),qse=Object.freeze(Object.values(ya)),Vse=new Set(["token","botToken","tokenRef","platformId","secret","secretRef"]);function jO(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function hB(n,r){return jO(n)&&Object.keys(n).every(o=>r.includes(o))}function nU(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function zse(n){return typeof n=="string"&&n.trim().length>=20&&n.length<=4096}function Wse(n,r){return jO(r)?n===ya.status?hB(r,[])?null:"connection.status does not accept fields.":n===ya.bindCredentials?hB(r,["token"])&&zse(r.token)?null:"bot.bind-credentials requires a Bot Token.":n===ya.reconnectBot?hB(r,["botId","sendTest"])&&nU(r.botId)&&(r.sendTest===void 0||typeof r.sendTest=="boolean")?null:"bot.reconnect requires a botId.":n===ya.deleteBot?hB(r,["botId","confirm"])&&nU(r.botId)&&r.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===ya.setWorkspace?Ba(r)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===ya.setAgentPreset?Qa(r)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":"Unknown bot endpoint.":"Payload must be an object."}function xO(n){if(Array.isArray(n))return n.map(xO);if(!jO(n))return n;let r={};for(let[o,i]of Object.entries(n))Vse.has(o)||(r[o]=xO(i));return r}function Zse(n,r){let o=fa(r);return o||(r?.code==="webhook-configured"?{code:"webhook-configured",message:r.message}:r?.code==="telegram-401"||r?.code==="discord-401"?{code:"invalid-token",message:`${n} Bot Token \u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u586B\u5199\u3002`}:r?.code==="discord-intents"?{code:"discord-intents",message:r.message}:{code:`${n.toLowerCase()}-operation-failed`,message:`${n} \u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002`})}function dB(n,{channel:r}){for(let o of["status","bindCredentials","reconnectBot","deleteBot"])if(typeof n?.[o]!="function")throw new TypeError(`A complete ${r} controller is required (${o})`);return async(o,i,e)=>{if(e?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!qse.includes(o))return{ok:!1,error:{code:"bad-request",message:`Unknown ${r} endpoint.`}};let a=Wse(o,i);if(a)return{ok:!1,error:{code:"bad-request",message:a}};try{let A;if(o===ya.status)A=await n.status();else if(o===ya.bindCredentials)A=await n.bindCredentials(i);else if(o===ya.reconnectBot){if(A=await n.reconnectBot(i.botId),e?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(i.sendTest===!0){let t=null;try{if(A?.bots?.find(s=>s?.botId===i.botId)?.connected!==!0){let s=new Error("Bot is not connected");throw s.code="test-target-unavailable",s}if(typeof n.sendConnectionTest!="function"){let s=new Error("Connection test is unavailable");throw s.code="test-target-unavailable",s}await n.sendConnectionTest(i.botId)}catch(s){t=s}A={...A,testMessage:qt(t)}}}else if(o===ya.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");A=await n.updateWorkspace(i.botId,i.workspace)}else if(o===ya.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");A=await n.updateAgentPreset(i.botId,i.agentPreset)}else A=await n.deleteBot(i.botId);return e?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:xO(A)}}catch(A){return e?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!1,error:Zse(r,A)}}}}function sU(n,r,{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,dB(r,{channel:o}),{authority:Er(e)})}var gU="/discord",cU=ya,Xse=Object.freeze(Object.values(cU));function uB(n,r,o){return sU(n,r,{channel:"Discord",rpcChannel:gU,authority:o})}async function IU(n,r={}){if(r?.controller)return uB(n,r.controller,r.rpcAuthority);let o=await YO(n,r,r.internals??{}),i=uB(n,o.controller,r.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Discord bot connections"),i}import{homedir as fge}from"node:os";import{join as zO,resolve as WO}from"node:path";import{mkdir as $se,readFile as ege,rename as Age,unlink as tge,writeFile as rge}from"node:fs/promises";import{dirname as age,isAbsolute as ige}from"node:path";var Al="office-harness.v1",lU="/office",tl=Object.freeze({status:"connection.status",configure:"connector.configure",reconnect:"connector.reconnect",test:"connector.test",remove:"connector.remove"}),bo=Object.freeze({stream:"/api/harness/connector/stream",heartbeat:"/api/harness/connector/heartbeat",job:"/api/harness/connector/jobs/:id",accept:"/api/harness/connector/jobs/:id/accept",renew:"/api/harness/connector/jobs/:id/renew",progress:"/api/harness/connector/jobs/:id/progress",approval:"/api/harness/connector/jobs/:id/approval",result:"/api/harness/connector/jobs/:id/result",fail:"/api/harness/connector/jobs/:id/fail"});function iC(n){let r=new URL(typeof n=="string"?n.trim():""),o=r.protocol==="http:"&&["localhost","127.0.0.1","[::1]"].includes(r.hostname);if(r.protocol!=="https:"&&!o)throw new TypeError("AI Office URL must use HTTPS (HTTP is allowed only for loopback testing)");if(r.username||r.password||r.search||r.hash)throw new TypeError("AI Office URL must be a bare origin");return r.pathname="/",r}function BB(n){let r=iC(n);return Object.fromEntries(Object.entries(bo).map(([o,i])=>[o,new URL(i,r).toString()]))}var oge=/^[a-z][a-z0-9-]{1,63}$/,nge=/^[a-z0-9][a-z0-9_-]{2,63}$/i;function rl(n){return typeof n=="string"&&n.trim()?n.trim():null}function pU(n,{kind:r}){if(!n||typeof n!="object"||Array.isArray(n))return null;let o={};for(let[i,e]of Object.entries(n)){let a=rl(i),A=rl(e);if(!a||!oge.test(a)||!A||r==="workspace"&&!ige(A)||r==="preset"&&A.length>8e3)return null;o[a]=A}return Object.freeze(o)}function fB(n){if(!n||typeof n!="object"||Array.isArray(n))return null;let r;try{r=iC(n.baseUrl).origin}catch{return null}let o=rl(n.deviceId),i=rl(n.deviceTokenRef),e=pU(n.workspaces??{},{kind:"workspace"}),a=pU(n.instructionPresets??{},{kind:"preset"}),A=Number(n.maxConcurrency??1),t=Number(n.heartbeatSeconds??30);return!o||!nge.test(o)||!i||!/^DSH_OFFICE_DEVICE_TOKEN_[A-F0-9]{24}$/.test(i)||!e||!a||!Number.isInteger(A)||A<1||A>4||!Number.isInteger(t)||t<10||t>300?null:Object.freeze({version:1,protocolVersion:Al,baseUrl:r,deviceId:o,deviceTokenRef:i,maxConcurrency:A,heartbeatSeconds:t,workspaces:e,instructionPresets:a,createdAt:rl(n.createdAt)??new Date().toISOString(),updatedAt:rl(n.updatedAt)??new Date().toISOString()})}var QB=class{#e;#A=null;#r=Promise.resolve();constructor(r){this.#e=r}async load(){try{let r=fB(JSON.parse(await ege(this.#e,"utf8")));if(!r)throw new Error("dsh-im AI Office config is invalid");this.#A=r}catch(r){if(r?.code!=="ENOENT")throw r;this.#A=null}return this}get(){return this.#A?structuredClone(this.#A):null}async save(r){let o=fB(r);if(!o)throw new Error("Refusing to persist invalid AI Office configuration");let i=this.#r.then(async()=>{await $se(age(this.#e),{recursive:!0,mode:448});let e=`${this.#e}.tmp`;await rge(e,`${JSON.stringify(o,null,2)} @@ -244,7 +244,7 @@ Generate a new one`,"\u4E8C\u7EF4\u7801\u56FE\u7247\u6B63\u5728\u751F\u6210\u202 `,{encoding:"utf8",mode:384}),await ebe(o,this.#e)}};var by=class extends rr{constructor(r){super({...r,rpcIdPrefix:"wecom",logPrefix:"dsh-wecom"})}};var obe="https://work.weixin.qq.com/ai/qc/generate",nbe="https://work.weixin.qq.com/ai/qc/query_result";function q4(){return process.platform==="win32"?2:process.platform==="linux"?3:1}function tp(n){return typeof n=="string"&&n.trim()?n.trim():null}function sbe(n){let r=tp(n);if(!r)return null;try{let o=new URL(r);return o.protocol==="https:"&&o.hostname==="work.weixin.qq.com"&&(!o.port||o.port==="443")?o.href:null}catch{return null}}function gbe(n,r){return n?AbortSignal.any([n,AbortSignal.timeout(r)]):AbortSignal.timeout(r)}async function V4(n,r,o){let i=await n(r,{method:"GET",redirect:"error",signal:gbe(o,1e4),headers:{accept:"application/json"}});if(!i.ok)throw new Error(`Enterprise WeChat QR service returned HTTP ${i.status}`);return i.json()}var My=class{#e;#A;#r;#t;constructor({fetch:r=globalThis.fetch,clock:o=()=>Date.now(),source:i="deepseek-harness",platform:e=q4()}={}){if(typeof r!="function")throw new TypeError("A fetch implementation is required");this.#e=r,this.#A=o,this.#r=i,this.#t=[1,2,3].includes(e)?e:q4()}async start({signal:r}={}){let o=new URL(obe);o.searchParams.set("source",this.#r),o.searchParams.set("plat",String(this.#t));let i=await V4(this.#e,o,r),e=tp(i?.data?.scode),a=sbe(i?.data?.auth_url);if(!e||!a)throw new Error("Enterprise WeChat QR service returned invalid data");return{scode:e,verificationUrl:a,expiresAt:this.#A()+3e5,pollIntervalMs:3e3}}async poll({scode:r,signal:o}={}){let i=tp(r);if(!i)throw new TypeError("Enterprise WeChat QR poll code is required");let e=new URL(nbe);e.searchParams.set("scode",i);let a=await V4(this.#e,e,o),A=tp(a?.data?.status)?.toLowerCase();if(A==="success"){let t=tp(a?.data?.bot_info?.botid),s=tp(a?.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 cbe,readFile as Ibe,rename as lbe,unlink as pbe,writeFile as Ebe}from"node:fs/promises";import{dirname as Cbe}from"node:path";var _y=Object.freeze({version:1,sessions:{},seenMessageIds:[]});function hbe(n){if(!n||typeof n!="object")return structuredClone(_y);let r={};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&&(r[o]=i);return{version:1,sessions:r,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[]}}var Ny=class{#e;#A=structuredClone(_y);#r=Promise.resolve();constructor(r){this.#e=r}async load(){try{this.#A=hbe(JSON.parse(await Ibe(this.#e,"utf8")))}catch(r){if(r?.code!=="ENOENT")throw r;this.#A=structuredClone(_y),await this.#t()}return this}sessionFor(r){return this.#A.sessions[r]??null}async setSession(r,o){this.#A.sessions[r]=o,await this.#t()}async clearSession(r){delete this.#A.sessions[r],await this.#t()}async clearSessions(){this.#A.sessions={},await this.#t()}hasSeen(r){return this.#A.seenMessageIds.includes(r)}async markSeen(r){this.hasSeen(r)||(this.#A.seenMessageIds.push(r),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#t())}async remove(){try{await pbe(this.#e)}catch(r){if(r?.code!=="ENOENT")throw r}this.#A=structuredClone(_y)}async#t(){let r=`${JSON.stringify(this.#A,null,2)} `,o=this.#r.then(async()=>{await cbe(Cbe(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await Ebe(i,r,{encoding:"utf8",mode:384}),await lbe(i,this.#e)});this.#r=o.then(()=>{},()=>{}),await o}};import{randomUUID as dbe}from"node:crypto";var z4=new Set(["pending","connecting"]),Hh=new Set(["connected","failed","cancelled","expired"]);function qc(n){return typeof n=="string"&&n.trim()?n.trim():null}function ri(n,r){return Object.freeze({code:n,message:r})}function Vc(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 Kh=class{#e;#A;#r;#t;#n;#o;#l=new Map;#s=new Map;#I=new Map;#a=null;#i=new Map;#c=0;#g=!1;constructor({qrAuth:r,credentials:o,configStore:i,createRuntime:e,deleteState:a=async()=>{},logger:A=console}){if(!r||typeof r.start!="function"||typeof r.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.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A}async initialize(){if(this.#g)return this.status();for(let r of this.#r.list())await this.#Q(r.botId,async()=>{let o=this.#l.get(r.botId)?.status;if(this.#g||o?.ready||o?.wecomConnectionState==="connecting")return;let i=await this.#B(r.secretRef);if(!i){this.#s.set(r.botId,ri("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.#E(r,i),this.#s.delete(r.botId)}catch{this.#s.set(r.botId,ri("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002")),this.#o.warn?.(`[dsh-im:wecom] bot ${r.botId} failed to initialize`)}finally{this.#m()}});return this.status()}async startProvisioning(){if(this.#g)throw new Error("Enterprise WeChat controller is closed");this.#a&&await this.cancelProvisioning(this.#a);let r={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.#I.set(r.id,r),this.#a=r.id,this.#m();try{let o=await this.#e.start({signal:r.controller.signal});if(r.scode=qc(o.scode),r.verificationUrl=qc(o.verificationUrl),r.expiresAt=Number(o.expiresAt),r.pollIntervalMs=Math.min(1e4,Math.max(500,Number(o.pollIntervalMs)||3e3)),!r.scode||!r.verificationUrl||!Number.isFinite(r.expiresAt))throw new Error("Enterprise WeChat QR auth returned incomplete data");return this.#m(),Vc(r)}catch(o){throw r.state=r.controller.signal.aborted?"cancelled":"failed",r.error=r.controller.signal.aborted?ri("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"):ri("qr-start-failed","\u65E0\u6CD5\u751F\u6210\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"),this.#f(r),o}}async registrationStatus(r){let o=this.#I.get(r);if(!o||Hh.has(o.state))return Vc(o);if(o.state==="connecting")return await o.transition?.catch(()=>{}),Vc(o);if(Date.now()>=o.expiresAt)return o.state="expired",o.error=ri("expired","\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"),o.controller.abort(),this.#f(o),Vc(o);if(!o.polling){let i=this.#p(o).finally(()=>{o.polling===i&&(o.polling=null)});o.polling=i}return await o.polling.catch(()=>{}),Vc(o)}async bindCredentials({botId:r,secret:o}={}){if(this.#g)throw new Error("Enterprise WeChat controller is closed");let i=qc(r),e=qc(o);if(!i||!e)throw new TypeError("Enterprise WeChat Bot ID and Secret are required");if(this.#a&&await this.cancelProvisioning(this.#a),this.#g)throw new Error("Enterprise WeChat controller is closed");let a=Oy(i);return await this.#Q(a.botId,async()=>{if(this.#g)throw new Error("Enterprise WeChat controller is closed");let A=this.#r.getByRemoteBotId(i),t=await this.#A.resolve(a.secretRef).catch(()=>{});if(this.#g)throw new Error("Enterprise WeChat controller is closed");let s={botId:a.botId,remoteBotId:i,secretRef:a.secretRef,createdAt:A?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(a.secretRef,e);try{await this.#r.save(s)}catch(g){throw await this.#u(a.secretRef,t),g}try{await this.#E(s,e),this.#s.delete(a.botId)}catch{this.#s.set(a.botId,ri("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002")),this.#o.warn?.(`[dsh-im:wecom] bot ${a.botId} credential connection failed`)}this.#m()}),this.status()}async cancelProvisioning(r){let o=this.#I.get(r);return o?(Hh.has(o.state)||(o.controller.abort(),await Promise.allSettled([o.polling,o.transition].filter(Boolean)),Hh.has(o.state)||(o.state="cancelled"),o.error??=ri("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002"),this.#f(o)),Vc(o)):null}async reconnectBot(r){let o=this.#r.get(r);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(r,async()=>{let i=await this.#B(o.secretRef);if(!i)throw new Error("Enterprise WeChat bot secret is missing");try{await this.#E(o,i),this.#s.delete(r)}catch(e){throw this.#s.set(r,ri("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),e}finally{this.#m()}}),this.status()}async sendConnectionTest(r){let o=this.#r.get(r);if(!o)throw new Error("Unknown Enterprise WeChat bot");return this.#Q(r,async()=>{let i=this.#l.get(r);if(!i?.status?.ready||typeof i.sendConnectionTest!="function")throw tr("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA");return i.sendConnectionTest(ga(`\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\uFF08${JR(o.remoteBotId)}\uFF09`))})}async deleteBot(r){let o=this.#r.get(r);if(!o)throw new Error("Unknown Enterprise WeChat bot");return await this.#Q(r,async()=>{let i=await this.#A.resolve(o.secretRef).catch(()=>{});await this.#d(r);try{await this.#A.unset(o.secretRef),await this.#r.remove(r)}catch(e){throw i?.value&&(await this.#A.set(o.secretRef,i.value).catch(()=>{}),await this.#E(o,i.value).catch(()=>{})),new Error("Unable to remove the Enterprise WeChat bot safely.",{cause:e})}await this.#n({botId:r,config:o}).catch(e=>{this.#o.warn?.(`[dsh-im:wecom] bot ${r} state cleanup failed:`,e)}),this.#s.delete(r),this.#m()}),this.status()}status(){let r=this.#r.list().map(e=>{let a=this.#l.get(e.botId)?.status??null,A=a?.ready===!0&&a.wecomConnectionState==="connected"&&a.harnessReachable===!0,t=A?"connected":a?.wecomConnectionState==="connecting"?"connecting":this.#s.has(e.botId)||a?.wecomConnectionState==="failed"?"error":"offline";return{botId:e.botId,state:t,connected:A,configured:!0,bot:{name:"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA",appIdMasked:JR(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:a?.lastCheckedAt??null,lastConnectedAt:a?.lastConnectedAt??null},stats:{messagesReceived:a?.messagesReceived??0,messagesReplied:a?.messagesReplied??0},error:structuredClone(this.#s.get(e.botId)??null)}}),o=r.filter(e=>e.connected).length,i=this.#a?this.#I.get(this.#a):null;return{schemaVersion:1,revision:this.#c,state:i&&z4.has(i.state)?"provisioning":r.length===0?"disconnected":o===r.length?"connected":o>0?"degraded":"offline",bots:r,totals:{configured:r.length,connected:o},...i&&z4.has(i.state)?{provisioning:Vc(i)}:{}}}async close(){this.#g||(this.#g=!0,this.#a&&await this.cancelProvisioning(this.#a),await Promise.allSettled([...this.#i.values()]),await Promise.allSettled([...this.#l.keys()].map(r=>this.#d(r))))}async#p(r){try{let o=await this.#e.poll({scode:r.scode,signal:r.controller.signal});if(r.controller.signal.aborted||Hh.has(r.state)||o.status==="waiting")return;if(o.status==="expired"){r.state="expired",r.error=ri("expired","\u4F01\u4E1A\u5FAE\u4FE1\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"),this.#f(r);return}if(o.status!=="success"){r.state="failed",r.error=ri("qr-connect-failed","\u4F01\u4E1A\u5FAE\u4FE1\u626B\u7801\u6CA1\u6709\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u4E8C\u7EF4\u7801\u3002"),this.#f(r);return}r.state="connecting",r.verificationUrl=null,r.expiresAt=null,r.scode=null,this.#m();let i=this.#h(r,o);r.transition=i,await i}catch{if(r.controller.signal.aborted)return;r.state="failed",r.error=ri("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.#o.warn?.("[dsh-im:wecom] QR polling failed"),this.#f(r)}}async#h(r,o){try{let i=qc(o.remoteBotId),e=qc(o.secret);if(!i||!e)throw new Error("Enterprise WeChat authorization returned incomplete credentials");r.botId=await this.#C(r,{remoteBotId:i,secret:e}),r.state="connected",r.error=null}catch{r.controller.signal.aborted?(r.state="cancelled",r.error=ri("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(r.state="failed",r.error=ri("activation-failed","\u4F01\u4E1A\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u5B89\u5168\u4FDD\u5B58\u63A5\u5165\u914D\u7F6E\u3002"),this.#o.error?.("[dsh-im:wecom] provisioning failed"))}finally{this.#f(r)}}async#C(r,{remoteBotId:o,secret:i}){let e=Oy(o),a=this.#r.getByRemoteBotId(o),A=await this.#A.resolve(e.secretRef).catch(()=>{}),t={botId:e.botId,remoteBotId:o,secretRef:e.secretRef,createdAt:a?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};return this.#Q(e.botId,async()=>{await this.#A.set(e.secretRef,i);try{if(r.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#r.save(t)}catch(s){throw await this.#u(e.secretRef,A),s}try{if(r.controller.signal.aborted)throw new DOMException("Cancelled","AbortError");await this.#E(t,i),this.#s.delete(e.botId)}catch(s){if(r.controller.signal.aborted)throw await this.#d(e.botId),a?await this.#r.save(a).catch(()=>{}):await this.#r.remove(e.botId).catch(()=>null)&&await this.#n({botId:e.botId,config:t}).catch(c=>{this.#o.warn?.("[dsh-im:wecom] cancelled bot state cleanup failed:",c)}),await this.#u(e.secretRef,A),s;this.#s.set(e.botId,ri("connection-failed","\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u7ED1\u5B9A\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002")),this.#o.warn?.(`[dsh-im:wecom] bot ${e.botId} activation connection failed`)}return this.#m(),e.botId})}async#E(r,o){if(this.#g)throw new Error("Enterprise WeChat controller is closed");if(await this.#d(r.botId),this.#g)throw new Error("Enterprise WeChat controller is closed");let i=await this.#t({botId:r.botId,config:r,secret:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError("createRuntime returned an invalid Enterprise WeChat runtime");this.#l.set(r.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#l.delete(r.botId),e}}async#d(r){let o=this.#l.get(r);this.#l.delete(r),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-im:wecom] bot ${r} failed to stop cleanly:`,i)})}async#B(r){let o=await this.#A.resolve(r).catch(()=>{});return qc(o?.value)}async#u(r,o){o?.value?await this.#A.set(r,o.value).catch(()=>{}):await this.#A.unset(r).catch(()=>{})}#Q(r,o){let a=(this.#i.get(r)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#i.get(r)===a&&this.#i.delete(r)});return this.#i.set(r,a),a}#f(r){r.scode=null,r.verificationUrl=null,r.expiresAt=null,this.#a===r.id&&(this.#a=null),this.#m();let o=[...this.#I.values()].filter(i=>Hh.has(i.state));for(;o.length>16;)this.#I.delete(o.shift().id)}#m(){this.#c+=1}};import{WSAuthFailureError as Obe,WSClient as bbe,WSReconnectExhaustedError as Mbe}from"@wecom/aibot-node-sdk";import{generateReqId as ube}from"@wecom/aibot-node-sdk";var Bbe=["\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u6216\u56FE\u7247\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002","/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD","/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587","/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 \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B","/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B","\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2","/presetlist \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset","/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset","\u7EAF\u6570\u5B57 ID\uFF1A/preset id:","/preset --default \u8DDF\u968F Host \u9ED8\u8BA4","/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1","/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1","/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001","/help \u663E\u793A\u672C\u5E2E\u52A9"].join(` `),fbe=18e3,W4=5*1024*1024,X4=4,Ty="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002";function hs(n){return typeof n=="string"&&n.trim()?n.trim():null}function zc(n){return n?.body&&typeof n.body=="object"?n.body:{}}function Z4(n){let r=zc(n);return r.chattype==="group"?`group:${r.chatid}`:`direct:${r.from?.userid}`}function $4(n){let r=zc(n),o="";return r.msgtype==="text"?o=typeof r.text?.content=="string"?r.text.content.trim():"":r.msgtype==="voice"?o=typeof r.voice?.content=="string"?r.voice.content.trim():"":r.msgtype==="mixed"&&Array.isArray(r.mixed?.msg_item)&&(o=r.mixed.msg_item.filter(i=>i?.msgtype==="text"&&typeof i.text?.content=="string").map(i=>i.text.content).join(` -`).trim()),r.chattype==="group"?o.replace(/^\s*@\S+(?:\s+|$)/u,"").trim():o}function Qbe(n){let r=zc(n);return r.msgtype==="image"?[r.image]:r.msgtype!=="mixed"||!Array.isArray(r.mixed?.msg_item)?[]:r.mixed.msg_item.filter(o=>o?.msgtype==="image").map(o=>o.image)}function ybe(n,r){let o=hs(r?.url);if(!o)return null;let i=hs(r?.aeskey)??void 0;return{async load({signal:e,maxBytes:a}){if(e?.throwIfAborted(),typeof n?.downloadFile!="function")throw new Error("Enterprise WeChat image download is unavailable");let A=await n.downloadFile(o,i);e?.throwIfAborted();let t=A?.buffer;if(!Buffer.isBuffer(t)&&!(t instanceof Uint8Array))throw new Error("Enterprise WeChat image download returned no data");let s=Buffer.from(t);if(Number.isFinite(a)&&s.length>a)throw new ct("image-too-large",`Enterprise WeChat image exceeds ${a} bytes`,"\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002");return{data:s,name:A?.filename}}}}function qR(n,r){return{content:$4(n),images:Qbe(n).map(o=>ybe(r,o)).filter(Boolean)}}function mbe(n,r){return Ir(n)?{...n,images:n.images.map(o=>{let i=o.load({signal:r,maxBytes:W4});return i.catch(()=>{}),{...o,async load({signal:e,maxBytes:a=W4}={}){e?.throwIfAborted();let A=await i;e?.throwIfAborted();let t=A?.data??A?.buffer??A;if((Buffer.isBuffer(t)||t instanceof Uint8Array?t.length:0)>a)throw new ct("image-too-large",`Enterprise WeChat image exceeds ${a} bytes`,"\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002");return A}}})}:n}function Sbe(n){return{...n,images:n.images.map(r=>({...r,async load(){throw new ct("image-queue-full",`Enterprise WeChat already has ${X4} prefetched images`,"\u5F53\u524D\u5F85\u5904\u7406\u56FE\u7247\u8F83\u591A\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0\u53D1\u9001\u3002")}}))}}function VR(n){return zc(n).msgtype==="text"?$4(n):""}function Ry(n,r=fbe){let o=String(n??"").trim();if(!o)return[];let i=[],e="",a=0;for(let A of o){let t=Buffer.byteLength(A);e&&a+t>r?(i.push(e),e=A,a=t):(e+=A,a+=t)}return e&&i.push(e),i}function Dbe(n){return n?.type==="text"?n.text:n?.type==="tool"?`\u6B63\u5728\u4F7F\u7528${n.name}\u2026`:n?.text}function wbe(n,r){return r.questions[r.index]&&hs(zc(n).from?.userid)===r.actor&&hs(VR(n))}function zR(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var ky=class{#e;#A;#r;#t;#n;#o;#l;#s;#I=new Map;#a=new Map;#i=new Map;#c=new Set;#g=new Set;#p=new Set;#h;#C=0;constructor({client:r,harness:o,state:i,status:e=zR(),logger:a=console,replyTimeoutMs:A=6e5,generateStreamId:t=ube,signal:s}){if(!r||typeof r.replyStream!="function"||typeof r.sendMessage!="function")throw new TypeError("Enterprise WeChat client is required");if(!o||!i)throw new TypeError("Harness client and state store are required");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#h=new ja({label:"wecom",logger:a})}get status(){return structuredClone(this.#t)}accept(r){if(this.#s?.aborted)return Promise.resolve();let o=zc(r),i=hs(o.msgid),e=hs(o.from?.userid),a=o.chattype==="group"?hs(o.chatid):e;if(!i||!e||!a||!["single","group"].includes(o.chattype)||this.#r.hasSeen(i)||this.#c.has(i))return Promise.resolve();let A=Z4(r);this.#c.add(i),o.chattype==="single"&&Pi(this.#r,{chatId:a});let t=this.#a.get(A),s=qR(r,this.#e),g=hs(s.content)??"",c=pi(g)?Hi:Ei(g)?Yi:Ci(g)?xi:null;if(c){let E;return E=this.#d(r,i,a,A,s,c).catch(B=>{if(!(B?.code==="turn-stopped"||this.#s?.aborted))return this.#t.lastError=B?.message??String(B),this.#n.error?.("[dsh-im:wecom] failed to process a command"),this.#u(r,a,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002").catch(()=>{})}).finally(()=>{this.#c.delete(i),this.#p.delete(E)}),this.#p.add(E),E}let I=this.#h.claimReply({key:A,actor:e,messageId:i,text:VR(r),addressed:!0,hasPendingQuestion:!!t,questionCompletion:t?.submitting||t?.claimedReplyMessageId?t.queue:null,isQuestionPending:()=>this.#a.has(A),send:E=>this.#u(r,a,E)});if(I){let E;return E=I.process(async()=>this.#r.hasSeen(i)?!1:(await this.#r.markSeen(i),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#c.delete(i),this.#g.delete(E)}),this.#g.add(E),E}if(t&&t.actor!==e)return this.#E(r,i,A);if(t?.submitting||t?.claimedReplyMessageId)return this.#E(r,i,A);if(t){wbe(r,t)&&(t.claimedReplyMessageId=i);let B=(t.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#f(r,i,e,a,A,t)).finally(()=>{this.#c.delete(i),t.claimedReplyMessageId===i&&(t.claimedReplyMessageId=null),t.queue===B&&(t.queue=null)});return t.queue=B,B}return this.#E(r,i,A)}#E(r,o,i,{releaseMessageId:e=!0,alreadyRecorded:a=!1}={}){let A=qR(r,this.#e),t=A.images.length,s=0,g=A;t>0&&(this.#C+t<=X4?(s=t,this.#C+=s,g=mbe(A,this.#s)):g=Sbe(A));let I=(this.#I.get(i)??Promise.resolve()).catch(()=>{}).then(()=>this.#Q(r,{alreadyRecorded:a,preparedMessage:g})).finally(()=>{this.#C-=s,e&&this.#c.delete(o),this.#I.get(i)===I&&this.#I.delete(i)});return this.#I.set(i,I),I}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#a.values()].flatMap(r=>r.queue?[r.queue]:[]),...this.#g,...this.#p])}async#d(r,o,i,e,a,A){if(this.#s?.throwIfAborted(),this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString();let t=await A(a.content,this.#A,this.#r,e,{signal:this.#s,hasImages:Ir(a),pendingInteraction:this.#a.has(e)||this.#h.hasPending(e),control:{owner:this,key:e}});t?.stopped&&await Promise.allSettled([this.#T(e),this.#h.closeRoute(e)]);for(let s of t?.messages??[t?.message])s&&await this.#u(r,i,s);this.#t.lastError=null}async#B(r,o){for(let i of Ry(o))this.#s?.throwIfAborted(),await this.#e.sendMessage(r,{msgtype:"markdown",markdown:{content:i}})}async#u(r,o,i){this.#s?.throwIfAborted();let e=Ry(i);if(e.length!==0)try{await this.#e.replyStream(r,this.#l("stream"),e[0],!0);for(let a of e.slice(1))await this.#e.sendMessage(o,{msgtype:"markdown",markdown:{content:a}})}catch{await this.#B(o,i)}}async#Q(r,{alreadyRecorded:o=!1,preparedMessage:i}={}){if(this.#s?.aborted)return;let e=zc(r),a=typeof e.msgid=="string"?e.msgid:"",A=typeof e.from?.userid=="string"?e.from.userid:"",t=e.chattype==="group"?e.chatid:A;if(!a||!A||!t||!["single","group"].includes(e.chattype))return;if(!o){if(this.#r.hasSeen(a))return;this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString()}let s=i??qR(r,this.#e),g=s.content,c=Ir(s),I=Z4(r),E=null,B=!1;try{if(!g&&!c){await this.#u(r,t,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u8BED\u97F3\u8F6C\u5199\u6D88\u606F\u3002"),await this.#r.markSeen(a);return}let f=g.toLowerCase();if(!c&&f==="/help"){await this.#u(r,t,Bbe),await this.#r.markSeen(a);return}if(!c&&f==="/status"){await this.#A.ensureRunning({signal:this.#s}),await this.#u(r,t,"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),await this.#r.markSeen(a);return}if(!c&&f==="/new"){await this.#r.clearSession(I),await this.#u(r,t,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#r.markSeen(a);return}let Q=c?null:await Ki(g,this.#A,I);if(Q){for(let Y of Q.messages??[Q.message])await this.#u(r,t,Y);await this.#r.markSeen(a);return}let y=c?null:await Ui(g,this.#A,this.#r,I,{signal:this.#s});if(y){await this.#u(r,t,y.message),await this.#r.markSeen(a);return}E=this.#l("stream");try{await this.#e.replyStream(r,E,"\u6B63\u5728\u601D\u8003\u4E2D\u2026",!1),B=!0}catch(Y){this.#n.warn?.("[dsh-im:wecom] unable to start a stream; using an active reply:",Y)}let m=c?await Fi(s,{signal:this.#s}):void 0,{answer:R}=await qa({harness:this.#A,state:this.#r,key:I,text:g,content:m,createOptions:{signal:this.#s},existsOptions:{signal:this.#s},askOptions:{timeoutMs:this.#o,signal:this.#s,control:{owner:this,key:I},onUpdate:B&&typeof this.#e.replyStreamNonBlocking=="function"?async Y=>{let j=Ry(Dbe(Y))[0];j&&await this.#e.replyStreamNonBlocking(r,E,j,!1)}:void 0,onInteraction:Y=>this.#m(Y,{key:I,actor:A,chatId:t,requiresMention:e.chattype==="group"}),onInteractionResolved:Y=>this.#y(Y)}}),_=Ry(R||"\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u4F46\u6CA1\u6709\u751F\u6210\u53EF\u663E\u793A\u7684\u6587\u672C\u3002"),P=!1;if(B&&_.length>0)try{await this.#e.replyStream(r,E,_[0],!0);for(let Y of _.slice(1))await this.#e.sendMessage(t,{msgtype:"markdown",markdown:{content:Y}});P=!0}catch(Y){this.#n.warn?.("[dsh-im:wecom] stream finalization failed; using an active reply:",Y)}P||await this.#B(t,R),await this.#r.markSeen(a),this.#t.messagesReplied+=1,this.#t.lastReplyAt=new Date().toISOString(),this.#t.lastError=null}catch(f){if(f?.code==="turn-stopped"){B&&E&&await this.#e.replyStream(r,E,"\u5DF2\u505C\u6B62\u3002",!0).catch(()=>{}),await this.#r.markSeen(a);return}if(this.#s?.aborted)return;this.#t.lastError=f?.message??String(f),this.#n.error?.("[dsh-im:wecom] failed to process an inbound message");let Q=Li(f)??"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";try{B&&E?await this.#e.replyStream(r,E,Q,!0):await this.#u(r,t,Q),await this.#r.markSeen(a)}catch{this.#n.error?.("[dsh-im:wecom] failed to send the safe error reply")}}finally{await Promise.allSettled([this.#T(I),this.#h.closeRoute(I)])}}async#f(r,o,i,e,a,A){if(this.#s?.aborted)return;let t=this.#a.get(a),s=A.claimedReplyMessageId===o;if(!t||t!==A||t.submitting)return s&&(!t||t!==A)?this.#w(r,o,e):this.#E(r,o,a,{releaseMessageId:!1});if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString();let g=hs(VR(r));if(!g){await this.#u(r,e,"\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002").catch(()=>{});return}let c=this.#a.get(a);if(!c||c!==A||c.submitting){if(s&&(!c||c!==A)){await this.#u(r,e,Ty).catch(()=>{});return}return this.#E(r,o,a,{releaseMessageId:!1,alreadyRecorded:!0})}if(c.actor!==i)return this.#E(r,o,a,{releaseMessageId:!1,alreadyRecorded:!0});if(c.chatId=e,c.needsPresentation){try{await this.#S(c)}catch{this.#t.lastError="\u4F01\u4E1A\u5FAE\u4FE1\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002",this.#n.error?.("[dsh-im:wecom] failed to retry an interaction question"),c.interaction.reconnect?.();return}let E=this.#a.get(a);if(!E||E!==A||E.submitting){if(s&&(!E||E!==A)){await this.#u(r,e,Ty).catch(()=>{});return}return this.#E(r,o,a,{releaseMessageId:!1,alreadyRecorded:!0})}}let I=c.questions[c.index];if(I){if(c.answers.push(xa(I,g)),c.index+=1,c.index{});return}if(this.#a.get(a)!==c)return;c.submitting=!1,c.answers.pop(),c.index-=1,this.#t.lastError="\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\u3002",this.#n.error?.("[dsh-im:wecom] failed to answer a Harness interaction"),await this.#u(r,e,"\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u5F53\u524D\u95EE\u9898\u7684\u7B54\u6848\u3002").catch(()=>{})}}}async#m(r,{key:o,actor:i,chatId:e,requiresMention:a}){if(r?.kind==="approval")return this.#h.handleRequested(r,{key:o,actor:i,requiresMention:a,send:c=>this.#B(e,c)});if(r?.kind!=="question")return;let A=r?.payload?.questions,t=typeof r?.interactionId=="string"?r.interactionId:r?.rpcId;if(typeof r?.rpcId!="string"||typeof t!="string"||typeof r.sessionId!="string"||!Array.isArray(A)||A.length===0||A.some(c=>!Ka(c))){this.#n.warn?.("[dsh-im:wecom] ignored an invalid Harness question interaction");return}if(r.recovered===!0){await r.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat safely cancelled an interaction left by an earlier client.",details:{}}}),await this.#B(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.#a.get(o);if(s?.interactionId===t){s.interaction=r,s.needsPresentation&&await this.#S(s);return}if(this.#i.has(t))return;if(s){this.#n.warn?.("[dsh-im:wecom] cancelled a second pending Harness question"),await r.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat is already handling another user interaction.",details:{}}});return}let g={kind:"question",interactionId:t,sessionId:r.sessionId,interaction:r,actor:i,requiresMention:a,questions:A,answers:[],index:0,chatId:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationPromise:null};this.#a.set(o,g),this.#i.set(g.interactionId,o),await this.#S(g)}async#y(r){if(r?.kind==="approval"){await this.#h.handleResolved(r);return}let o=r?.interactionId;if(r?.kind!=="question"||typeof o!="string")return;let i=this.#i.get(o);i&&this.#M(i,o)}#S(r){if(!r.needsPresentation)return Promise.resolve();if(r.presentationPromise)return r.presentationPromise;let o=r.questions[r.index];if(!o)return Promise.resolve();let i=this.#B(r.chatId,Ya(o,r.index,r.questions.length,{requiresMention:r.requiresMention})).then(()=>{r.needsPresentation=!1}).finally(()=>{r.presentationPromise===i&&(r.presentationPromise=null)});return r.presentationPromise=i,i}async#w(r,o,i){this.#r.hasSeen(o)||(await this.#r.markSeen(o),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString(),await this.#u(r,i,Ty).catch(()=>{}))}#R(r,o){let i=this.#a.get(r);return!i||o!==void 0&&i.interactionId!==o?null:(this.#a.delete(r),this.#i.delete(i.interactionId),i)}#M(r,o){return this.#R(r,o)!==null}async#T(r){let o=this.#R(r);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.#n.warn?.("[dsh-im:wecom] failed to cancel a pending Harness interaction")}}};function _be(){let n=new Error("Enterprise WeChat WebSocket authentication timed out");return n.code="connect-timeout",n}function Nbe(){return{startedAt:null,ready:!1,wecomConnectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...zR()}}var Yh=class{#e;#A;#r;#t;#n;#o;#l;#s;#I;#a=Nbe();#i=null;#c=null;#g=null;#p=null;#h=null;constructor({config:r,secret:o,harness:i,state:e,logger:a=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,maxReconnectAttempts:s=10,createClient:g=c=>new bbe(c)}){if(!r||!o||!i||!e)throw new TypeError("WecomRuntime requires config, secret, Harness, and state");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#I=g}get status(){return structuredClone(this.#a)}async start(){if(this.#a.ready&&this.#i)return this.status;if(this.#g)return this.#g;this.#h?.abort(new DOMException("Enterprise WeChat runtime replaced","AbortError"));let r=new AbortController;return this.#p=r,this.#h=r,this.#g=this.#C(r.signal).finally(()=>{this.#p===r&&(this.#p=null),this.#g=null}),this.#g}async#C(r){await this.#E(),r.throwIfAborted(),this.#a.startedAt=new Date().toISOString(),this.#a.wecomConnectionState="connecting",this.#a.lastError=null,await this.#r.ensureRunning(),this.#a.harnessReachable=!0;let o={debug(){},info(){},warn(){},error(){}},i=this.#I({botId:this.#e.remoteBotId,secret:this.#A,logger:o,maxReconnectAttempts:this.#s});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.#c=new ky({client:i,harness:this.#r,state:this.#t,status:this.#a,logger:this.#n,replyTimeoutMs:this.#o,signal:r});let e,a,A=!1,t=new Promise((f,Q)=>{e=f,a=Q}),s=()=>{if(this.#i!==i||r.aborted)return;A=!0;let f=Date.now();this.#a.ready=!0,this.#a.wecomConnectionState="connected",this.#a.lastCheckedAt=f,this.#a.lastConnectedAt=f,this.#a.lastError=null,e()},g=()=>{this.#i===i&&(this.#a.ready=!1,this.#a.wecomConnectionState="connecting",this.#a.lastCheckedAt=Date.now())},c=()=>{this.#i===i&&(this.#a.ready=!1,this.#a.wecomConnectionState="connecting",this.#a.lastCheckedAt=Date.now())},I=f=>{if(this.#i!==i)return;let Q=f instanceof Obe||f instanceof Mbe;!A&&Q&&a(f),Q&&(this.#a.ready=!1,this.#a.wecomConnectionState="failed"),this.#a.lastError=Q?f.name:"connection-error",this.#n.warn?.(`[dsh-im:wecom] bot ${this.#e.botId} connection error`)},E=f=>this.#c?.accept(f);i.on("authenticated",s),i.on("disconnected",g),i.on("reconnecting",c),i.on("error",I),i.on("message",E);let B;try{return i.connect(),await Promise.race([t,new Promise((f,Q)=>{r.addEventListener("abort",()=>Q(r.reason),{once:!0})}),new Promise((f,Q)=>{B=setTimeout(()=>Q(_be()),this.#l)})]),this.status}catch(f){throw r.aborted?(await this.#E(),f):(this.#a.ready=!1,this.#a.wecomConnectionState="failed",this.#a.lastError=f?.message??String(f),await this.#E(),f)}finally{clearTimeout(B)}}async stop(){let r=this.#g;return this.#p?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#h?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#h=null,await this.#E(),await r?.catch(()=>{}),this.status}async sendConnectionTest(r){return Ys({state:this.#t,text:r,channelLabel:"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA",send:async({chatId:o},i)=>{if(!this.#a.ready||!this.#i)throw new Error("Enterprise WeChat runtime is not connected");await this.#i.sendMessage(o,{msgtype:"markdown",markdown:{content:i}})}})}async#E(){let r=this.#i,o=this.#c;this.#i=null,this.#c=null;try{r?.disconnect(),r?.removeAllListeners?.()}catch{this.#n.warn?.(`[dsh-im:wecom] bot ${this.#e.botId} failed to stop cleanly`)}await o?.waitForIdle(),this.#a.ready=!1,this.#a.wecomConnectionState="idle"}};var e8=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function Tbe(n){if(!Array.isArray(n)||n.length===0)return[...e8];let r=n.filter(o=>Number.isFinite(o)&&o>=0);return r.length>0?r:[...e8]}var vy=class{#e;#A;#r;#t;#n;#o;#l;#s=null;#I=null;#a=0;#i=!1;#c=!1;#g;#p;constructor({controller:r,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!r||typeof r.initialize!="function"||typeof r.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=r,this.#A=o,this.#r=i,this.#t=Tbe(e),this.#n=Number.isFinite(a)&&a>=0?a:15e3,this.#o=A,this.#l=t,this.#g=new Promise(s=>{this.#p=s})}get ready(){return this.#g}start(){return this.#c||this.#i?this:(this.#c=!0,this.#h(0),this)}async close(){this.#i||(this.#i=!0,this.#s!==null&&this.#l(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#h(r){this.#i||(this.#s=this.#o(()=>{this.#s=null,this.#C()},r),this.#s?.unref?.())}async#C(){if(this.#i||this.#I)return;let r=this.#E();this.#I=r;try{await r}finally{this.#I===r&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#i)return;let r=await this.#e.initialize();if(this.#i)return;this.#p?.(r),this.#p=null;let{configured:o,connected:i}=r.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 Pbe(n){let r=Wc(n.dshHome??process.env.DSH_HOME??xh(kbe(),".dsh")),o=Wc(n.dataDir??xh(r,"integrations","dsh-wecom"));return{config:Wc(n.configPath??xh(o,"config.json")),bots:Wc(n.botsDir??xh(o,"bots")),workspaces:Wc(n.workspacesPath??xh(o,"workspaces.json"))}}async function ZR(n,r={},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??wy,e=o.StateStore??Ny,a=o.HarnessClient??by,A=o.Controller??Kh,t=o.Runtime??Yh,s=o.QrAuth??My,g=o.createConnectionSupervisor??WR,c=typeof n.logger=="function"?n.logger("dsh-im:wecom"):n.logger??console,I=()=>pa(n),E=Pbe(r),B=await new i(E.config).load(),f=Wc(r.workspace??process.cwd()),Q=o.WorkspaceStore??Fr,y=o.workspaces??await new Q(E.workspaces,{defaultWorkspace:f}).load(),m=B.list();await y.reconcile(m.map(M=>M.botId)),await Promise.all(m.map(M=>y.ensure(M.botId,{defaultAgentPreset:r.agentPreset})));let R=typeof B.remove=="function"?Ea(B,{workspaces:y}):B,_=o.qrAuth??new s({source:r.qrSource??"deepseek-harness",platform:r.qrPlatform}),P=new Map,Y=M=>Wc(E.bots,M,"state.json"),j=async M=>{let G=P.get(M);return G||(G=await new e(Y(M)).load(),P.set(M,G)),G},K=da(n,o.commandExecutor),{controlExecutor:q,sessionMaintenanceExecutor:V}=ua(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor}),H=new a({baseUrl:vbe(n.webServer,r.harnessBaseUrl),workspace:f,autostart:!1,dshBin:r.dshBin??"dsh",...K?{commandExecutor:K}:{},...q?{controlExecutor:q}:{},...V?{sessionMaintenanceExecutor:V}:{}}),v=new A({qrAuth:_,credentials:n.credentials,configStore:R,logger:c,createRuntime:async({botId:M,config:G,secret:te})=>{let se=await j(M);await y.ensure(M,{defaultAgentPreset:r.agentPreset});let ne=Ca(H,{botId:M,workspaces:y,state:se,agentPresetCatalog:I});return new t({config:G,secret:te,harness:ne.harness,state:ne.state,replyTimeoutMs:r.replyTimeoutMs??6e5,connectTimeoutMs:r.connectTimeoutMs??2e4,maxReconnectAttempts:r.maxReconnectAttempts??10,logger:{error:(...Me)=>c.error?.(`[${M}]`,...Me),warn:(...Me)=>c.warn?.(`[${M}]`,...Me),info:(...Me)=>c.info?.(`[${M}]`,...Me),debug:(...Me)=>c.debug?.(`[${M}]`,...Me)}})},deleteState:async({botId:M})=>{let G=P.get(M);if(P.delete(M),G&&typeof G.remove=="function")await G.remove();else try{await Rbe(Y(M))}catch(te){if(te?.code!=="ENOENT")throw te}}}),Z=ha(v,{workspaces:y,stateFor:j,agentPresetCatalog:I}),U=g({controller:Z,harness:H,logger:c,retryDelaysMs:r.retryDelaysMs,healthyIntervalMs:r.healthyIntervalMs}).start();return{controller:Z,ready:U.ready,async close(){await U.close(),await Z.close(),H.stopManagedProcess()}}}import Gbe from"qrcode";var t8="/wecom",Dr=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:za,setAgentPreset:Wa}),r8=Object.freeze(Object.values(Dr)),Fbe=new Set(["secret","secretRef","scode","remoteBotId","verificationUrl","bot_info","botid"]);function ek(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function rp(n,r){return ek(n)&&Object.keys(n).every(o=>r.includes(o))}function XR(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function A8(n,r){return typeof n=="string"&&n.trim().length>0&&n.length<=r}function Lbe(n,r){return ek(r)?n===Dr.status?rp(r,[])?null:"connection.status does not accept fields.":n===Dr.beginProvisioning?rp(r,["locale"])&&(r.locale===void 0||r.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Dr.pollProvisioning,Dr.cancelProvisioning].includes(n)?rp(r,["attemptId"])&&XR(r.attemptId)?null:`${n} requires an attemptId.`:n===Dr.bindCredentials?rp(r,["botId","secret"])&&A8(r.botId,512)&&A8(r.secret,1024)?null:"bot.bind-credentials requires Bot ID and Secret.":n===Dr.reconnectBot?rp(r,["botId","sendTest"])&&XR(r.botId)&&(r.sendTest===void 0||r.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===Dr.deleteBot?rp(r,["botId","confirm"])&&XR(r.botId)&&r.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===Dr.setWorkspace?Ba(r)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Dr.setAgentPreset?Qa(r)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":"Unknown Enterprise WeChat endpoint.":"Payload must be an object."}function ip(n){if(Array.isArray(n))return n.map(ip);if(!ek(n))return n;let r={};for(let[o,i]of Object.entries(n))Fbe.has(o)||(r[o]=ip(i));return r}async function Ube(n){return Gbe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function $R(n,r){return!n||typeof n.verificationUrl!="string"?ip(n):ip({...n,qrCodeDataUrl:await r(n.verificationUrl)})}async function ap(n,r){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await $R(o.provisioning,r)),ip(o)}function a8(n,{encodeQr:r=Ube}={}){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 a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>r(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!r8.includes(e))return{ok:!1,error:{code:"bad-request",message:"Unknown Enterprise WeChat endpoint."}};let t=Lbe(e,a);if(t)return{ok:!1,error:{code:"bad-request",message:t}};try{let s;if(e===Dr.status)s=await ap(await n.status(),i);else if(e===Dr.beginProvisioning)s=await $R(await n.startProvisioning(),i);else if(e===Dr.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return{ok:!1,error:{code:"bad-request",message:"The provisioning attempt no longer exists."}};s=await $R(g,i)}else if(e===Dr.cancelProvisioning)s=ip(await n.cancelProvisioning(a.attemptId));else if(e===Dr.bindCredentials)s=await ap(await n.bindCredentials(a),i);else if(e===Dr.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};let c;if(a.sendTest===!0)if(!g?.bots?.some(E=>E?.botId===a.botId&&E?.connected===!0)||typeof n.sendConnectionTest!="function")c=qt(tr("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=qt()}catch(E){c=qt(E)}s=await ap({...g,...c?{testMessage:c}:{}},i)}else if(e===Dr.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await ap(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===Dr.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await ap(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else s=await ap(await n.deleteBot(a.botId),i);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:s}}catch(s){let g=fa(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 Py(n,r,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(t8,a8(r,o),{authority:Er(i)})}async function i8(n,r={}){if(r?.controller)return Py(n,r.controller,r.rpcOptions,r.rpcAuthority);let o=await ZR(n,r,r.internals),i=Py(n,o.controller,r.rpcOptions,r.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Enterprise WeChat bot connections"),i}import{unlink as vMe}from"node:fs/promises";import{homedir as PMe}from"node:os";import{join as zh,resolve as Zc}from"node:path";import{createHash as aMe}from"node:crypto";import{mkdir as iMe,readFile as oMe,rename as nMe,unlink as sMe,writeFile as gMe}from"node:fs/promises";import{dirname as cMe}from"node:path";import{createDecipheriv as Hbe,randomBytes as Kbe,randomUUID as Ybe}from"node:crypto";var Fy="https://ilinkai.weixin.qq.com/",xbe="2.4.6",jbe="3",Jbe="https://novac2c.cdn.weixin.qq.com/c2c",s8="novac2c.cdn.weixin.qq.com",qbe="bot",Vbe=2<<16|1024|6,zbe=15e3,o8=35e3,Wbe=new Set(["wait","scaned","confirmed","expired","scaned_but_redirect","need_verifycode","verify_code_blocked","binded_redirect"]),it=class extends Error{constructor(r,o,i={}){super(o,i),this.name="WeixinApiError",this.code=r,this.status=i.status}};function Ta(n){return typeof n=="string"&&n.trim()?n.trim():null}function Zbe(n){let r=Ta(n);return!r||r.length%4!==0||!/^[A-Za-z0-9+/]+={0,2}$/.test(r)?null:Buffer.from(r,"base64")}function Xbe(n){let r=Ta(n?.aeskey);if(r){if(!/^[0-9a-fA-F]{32}$/.test(r))throw new it("invalid-image-key","\u5FAE\u4FE1\u56FE\u7247\u7684\u52A0\u5BC6\u5BC6\u94A5\u65E0\u6548\u3002");return Buffer.from(r,"hex")}let o=Zbe(n?.media?.aes_key);if(o?.length===16)return o;if(o?.length===32&&/^[0-9a-fA-F]{32}$/.test(o.toString("ascii")))return Buffer.from(o.toString("ascii"),"hex");throw new it("invalid-image-key","\u5FAE\u4FE1\u56FE\u7247\u7684\u52A0\u5BC6\u5BC6\u94A5\u65E0\u6548\u3002")}function $be(n,r){let o=Buffer.from(n),i=Buffer.from(r);if(i.length!==16||o.length===0||o.length%16!==0)throw new it("invalid-image-ciphertext","\u5FAE\u4FE1\u56FE\u7247\u7684\u52A0\u5BC6\u6570\u636E\u65E0\u6548\u3002");try{let e=Hbe("aes-128-ecb",i,null);return Buffer.concat([e.update(o),e.final()])}catch(e){throw new it("image-decryption-failed","\u5FAE\u4FE1\u56FE\u7247\u89E3\u5BC6\u5931\u8D25\u3002",{cause:e})}}function eMe(n){let r=Ta(n?.encrypt_query_param);if(r)return`${Jbe}/download?encrypted_query_param=${encodeURIComponent(r)}`;let o=Ta(n?.full_url);if(!o)throw new it("missing-image-url","\u5FAE\u4FE1\u56FE\u7247\u6CA1\u6709\u53EF\u7528\u7684\u4E0B\u8F7D\u5730\u5740\u3002");let i;try{i=new URL(o)}catch{throw new it("invalid-image-url","\u5FAE\u4FE1\u56FE\u7247\u7684\u4E0B\u8F7D\u5730\u5740\u65E0\u6548\u3002")}if(i.protocol!=="https:"||i.hostname!==s8||i.port&&i.port!=="443"||!i.pathname.startsWith("/c2c/"))throw new it("untrusted-image-url","\u5FAE\u4FE1\u56FE\u7247\u7684\u4E0B\u8F7D\u5730\u5740\u4E0D\u53D7\u4FE1\u4EFB\u3002");return i.username="",i.password="",i.hash="",i.toString()}function Ak(n,{fetchImpl:r=fetch}={}){if(typeof r!="function")throw new TypeError("fetchImpl must be a function");let o=[];for(let i of n?.item_list??[]){let e=i?.image_item;!e||typeof e!="object"||o.push({name:o.length===0?"image":`image-${o.length+1}`,load:async({signal:a,maxBytes:A})=>{let t=Xbe(e),s=eMe(e.media),g=await Gi(s,{fetchImpl:r,signal:a,maxBytes:A+16,allowedHosts:[s8]});return $be(g,t)}})}return o}function tk(n){let r=n.toLowerCase().replace(/\.$/,"");return r==="weixin.qq.com"||r.endsWith(".weixin.qq.com")}function np(n){let r;try{r=new URL(n)}catch{throw new it("invalid-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002")}if(r.protocol!=="https:"||!tk(r.hostname)||r.port!==""&&r.port!=="443")throw new it("untrusted-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002");return r.username="",r.password="",r.search="",r.hash="",r.pathname.endsWith("/")||(r.pathname+="/"),r.toString()}function AMe(n){let r=Ta(n);if(!r)throw new it("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u5730\u5740\u3002");let o;try{o=new URL(r)}catch{throw new it("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u626B\u7801\u5730\u5740\u3002")}if(o.protocol!=="https:"||!tk(o.hostname))throw new it("untrusted-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002");return o.toString()}function g8(){return{"iLink-App-Id":qbe,"iLink-App-ClientVersion":String(Vbe)}}function tMe(n){let r={...g8(),"content-type":"application/json",AuthorizationType:"ilink_bot_token","X-WECHAT-UIN":Buffer.from(String(Kbe(4).readUInt32BE(0)),"utf8").toString("base64")};return Ta(n)&&(r.Authorization=`Bearer ${n.trim()}`),r}function Gy(){return{channel_version:xbe,bot_agent:"DeepSeekHarness/1.0.0"}}function n8(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}async function op(n,{method:r,baseUrl:o,endpoint:i,body:e,token:a,timeoutMs:A=zbe,signal:t,authenticated:s=!0}){let g=np(o),c=new URL(i,g);if(!tk(c.hostname))throw new it("untrusted-endpoint","\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002");let I=new AbortController,E=!1,B=()=>I.abort(t?.reason);if(t?.aborted)throw n8(t);t?.addEventListener("abort",B,{once:!0});let f=A>0?setTimeout(()=>{E=!0,I.abort()},A):null;try{let Q=await n(c,{method:r,headers:s?tMe(a):g8(),...e===void 0?{}:{body:JSON.stringify(e)},signal:I.signal});if(!Q.ok)throw new it("http-error",`\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${Q.status}\uFF09\u3002`,{status:Q.status});try{return await Q.json()}catch(y){throw new it("invalid-response","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002",{cause:y})}}catch(Q){throw t?.aborted?n8(t):E?new it("timeout","\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002",{cause:Q}):Q instanceof it?Q:new it("network-error","\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002",{cause:Q})}finally{f&&clearTimeout(f),t?.removeEventListener("abort",B)}}function rMe(n){if(!n||typeof n!="object"||!Wbe.has(n.status))throw new it("invalid-login-status","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002");return n}function c8({fetchImpl:n=fetch}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");return Object.freeze({inboundImages(r){return Ak(r,{fetchImpl:n})},async beginLogin({localTokens:r=[],botType:o=jbe,signal:i}={}){let e=[...new Set(r.map(Ta).filter(Boolean))].slice(-10),a=await op(n,{method:"POST",baseUrl:Fy,endpoint:`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(o)}`,body:{local_token_list:e},timeoutMs:1e4,signal:i}),A=Ta(a?.qrcode);if(!A)throw new it("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4EE4\u724C\u3002");return{qrcode:A,qrcodeUrl:AMe(a.qrcode_img_content)}},async pollLogin({qrcode:r,baseUrl:o=Fy,verifyCode:i,signal:e}){let a=Ta(r);if(!a)throw new TypeError("qrcode is required");let A=`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(a)}`;Ta(i)&&(A+=`&verify_code=${encodeURIComponent(i.trim())}`);let t=await op(n,{method:"GET",baseUrl:o,endpoint:A,timeoutMs:o8,signal:e,authenticated:!1});return rMe(t)},async getUpdates({baseUrl:r,token:o,getUpdatesBuf:i="",timeoutMs:e,signal:a}){try{return await op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/getupdates",body:{get_updates_buf:i,base_info:Gy()},token:o,timeoutMs:e??o8,signal:a})}catch(A){if(A instanceof it&&A.code==="timeout")return{ret:0,msgs:[],get_updates_buf:i};throw A}},async sendText({baseUrl:r,token:o,toUserId:i,text:e,contextToken:a,runId:A,signal:t}){let s=Ta(i),g=Ta(e);if(!s||!g)throw new TypeError("toUserId and text are required");let c=await op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/sendmessage",token:o,signal:t,body:{msg:{from_user_id:"",to_user_id:s,client_id:`dsh-weixin-${Ybe()}`,message_type:2,message_state:2,item_list:[{type:1,text_item:{text:g}}],...Ta(a)?{context_token:a.trim()}:{},...Ta(A)?{run_id:A.trim()}:{}},base_info:Gy()}});if(c?.ret!==void 0&&c.ret!==0)throw new it("send-rejected","\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async notifyStart({baseUrl:r,token:o,signal:i}){let e=await op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/msg/notifystart",token:o,signal:i,timeoutMs:1e4,body:{base_info:Gy()}});if(e?.ret!==void 0&&e.ret!==0)throw new it("start-rejected","\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002");return e},async notifyStop({baseUrl:r,token:o,signal:i}){return op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/msg/notifystop",token:o,signal:i,timeoutMs:1e4,body:{base_info:Gy()}})}})}function sp(n){for(let r of n?.item_list??[]){if(r?.type===1&&typeof r.text_item?.text=="string"){let o=r.text_item.text.trim();if(o)return o}if(r?.type===3&&typeof r.voice_item?.text=="string"){let o=r.voice_item.text.trim();if(o)return o}}return null}function rk(n){return n?.message_id!==void 0&&n.message_id!==null?String(n.message_id):Ta(n?.client_id)}function I8(n,r=4e3){if(n.length<=r)return[n];let o=[],i=n;for(;i.length>r;){let e=i.lastIndexOf(` +`).trim()),r.chattype==="group"?o.replace(/^\s*@\S+(?:\s+|$)/u,"").trim():o}function Qbe(n){let r=zc(n);return r.msgtype==="image"?[r.image]:r.msgtype!=="mixed"||!Array.isArray(r.mixed?.msg_item)?[]:r.mixed.msg_item.filter(o=>o?.msgtype==="image").map(o=>o.image)}function ybe(n,r){let o=hs(r?.url);if(!o)return null;let i=hs(r?.aeskey)??void 0;return{async load({signal:e,maxBytes:a}){if(e?.throwIfAborted(),typeof n?.downloadFile!="function")throw new Error("Enterprise WeChat image download is unavailable");let A=await n.downloadFile(o,i);e?.throwIfAborted();let t=A?.buffer;if(!Buffer.isBuffer(t)&&!(t instanceof Uint8Array))throw new Error("Enterprise WeChat image download returned no data");let s=Buffer.from(t);if(Number.isFinite(a)&&s.length>a)throw new ct("image-too-large",`Enterprise WeChat image exceeds ${a} bytes`,"\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002");return{data:s,name:A?.filename}}}}function qR(n,r){return{content:$4(n),images:Qbe(n).map(o=>ybe(r,o)).filter(Boolean)}}function mbe(n,r){return Ir(n)?{...n,images:n.images.map(o=>{let i=o.load({signal:r,maxBytes:W4});return i.catch(()=>{}),{...o,async load({signal:e,maxBytes:a=W4}={}){e?.throwIfAborted();let A=await i;e?.throwIfAborted();let t=A?.data??A?.buffer??A;if((Buffer.isBuffer(t)||t instanceof Uint8Array?t.length:0)>a)throw new ct("image-too-large",`Enterprise WeChat image exceeds ${a} bytes`,"\u56FE\u7247\u8D85\u8FC7 5 MB\uFF0C\u8BF7\u538B\u7F29\u540E\u91CD\u8BD5\u3002");return A}}})}:n}function Sbe(n){return{...n,images:n.images.map(r=>({...r,async load(){throw new ct("image-queue-full",`Enterprise WeChat already has ${X4} prefetched images`,"\u5F53\u524D\u5F85\u5904\u7406\u56FE\u7247\u8F83\u591A\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0\u53D1\u9001\u3002")}}))}}function VR(n){return zc(n).msgtype==="text"?$4(n):""}function Ry(n,r=fbe){let o=String(n??"").trim();if(!o)return[];let i=[],e="",a=0;for(let A of o){let t=Buffer.byteLength(A);e&&a+t>r?(i.push(e),e=A,a=t):(e+=A,a+=t)}return e&&i.push(e),i}function Dbe(n){return n?.type==="text"?n.text:n?.type==="tool"?`\u6B63\u5728\u4F7F\u7528${n.name}\u2026`:n?.text}function wbe(n,r){return r.questions[r.index]&&hs(zc(n).from?.userid)===r.actor&&hs(VR(n))}function zR(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null}}var ky=class{#e;#A;#r;#t;#n;#o;#l;#s;#I=new Map;#a=new Map;#i=new Map;#c=new Set;#g=new Set;#p=new Set;#h;#C=0;constructor({client:r,harness:o,state:i,status:e=zR(),logger:a=console,replyTimeoutMs:A=6e5,generateStreamId:t=ube,signal:s}){if(!r||typeof r.replyStream!="function"||typeof r.sendMessage!="function")throw new TypeError("Enterprise WeChat client is required");if(!o||!i)throw new TypeError("Harness client and state store are required");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#h=new ja({label:"wecom",logger:a})}get status(){return structuredClone(this.#t)}accept(r){if(this.#s?.aborted)return Promise.resolve();let o=zc(r),i=hs(o.msgid),e=hs(o.from?.userid),a=o.chattype==="group"?hs(o.chatid):e;if(!i||!e||!a||!["single","group"].includes(o.chattype)||this.#r.hasSeen(i)||this.#c.has(i))return Promise.resolve();let A=Z4(r);this.#c.add(i),o.chattype==="single"&&Pi(this.#r,{chatId:a});let t=this.#a.get(A),s=qR(r,this.#e),g=hs(s.content)??"",c=pi(g)?Hi:Ei(g)?Yi:Ci(g)?xi:null;if(c){let E;return E=this.#d(r,i,a,A,s,c).catch(B=>{if(!(B?.code==="turn-stopped"||this.#s?.aborted))return this.#t.lastError=B?.message??String(B),this.#n.error?.("[dsh-im:wecom] failed to process a command"),this.#u(r,a,"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002").catch(()=>{})}).finally(()=>{this.#c.delete(i),this.#p.delete(E)}),this.#p.add(E),E}let I=this.#h.claimReply({key:A,actor:e,messageId:i,text:VR(r),addressed:!0,hasPendingQuestion:!!t,questionCompletion:t?.submitting||t?.claimedReplyMessageId?t.queue:null,isQuestionPending:()=>this.#a.has(A),send:E=>this.#u(r,a,E)});if(I){let E;return E=I.process(async()=>this.#r.hasSeen(i)?!1:(await this.#r.markSeen(i),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#c.delete(i),this.#g.delete(E)}),this.#g.add(E),E}if(t&&t.actor!==e)return this.#E(r,i,A);if(t?.submitting||t?.claimedReplyMessageId)return this.#E(r,i,A);if(t){wbe(r,t)&&(t.claimedReplyMessageId=i);let B=(t.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#f(r,i,e,a,A,t)).finally(()=>{this.#c.delete(i),t.claimedReplyMessageId===i&&(t.claimedReplyMessageId=null),t.queue===B&&(t.queue=null)});return t.queue=B,B}return this.#E(r,i,A)}#E(r,o,i,{releaseMessageId:e=!0,alreadyRecorded:a=!1}={}){let A=qR(r,this.#e),t=A.images.length,s=0,g=A;t>0&&(this.#C+t<=X4?(s=t,this.#C+=s,g=mbe(A,this.#s)):g=Sbe(A));let I=(this.#I.get(i)??Promise.resolve()).catch(()=>{}).then(()=>this.#Q(r,{alreadyRecorded:a,preparedMessage:g})).finally(()=>{this.#C-=s,e&&this.#c.delete(o),this.#I.get(i)===I&&this.#I.delete(i)});return this.#I.set(i,I),I}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#a.values()].flatMap(r=>r.queue?[r.queue]:[]),...this.#g,...this.#p])}async#d(r,o,i,e,a,A){if(this.#s?.throwIfAborted(),this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString();let t=await A(a.content,this.#A,this.#r,e,{signal:this.#s,hasImages:Ir(a),pendingInteraction:this.#a.has(e)||this.#h.hasPending(e),control:{owner:this,key:e}});t?.stopped&&await Promise.allSettled([this.#T(e),this.#h.closeRoute(e)]);for(let s of t?.messages??[t?.message])s&&await this.#u(r,i,s);this.#t.lastError=null}async#B(r,o){for(let i of Ry(o))this.#s?.throwIfAborted(),await this.#e.sendMessage(r,{msgtype:"markdown",markdown:{content:i}})}async#u(r,o,i){this.#s?.throwIfAborted();let e=Ry(i);if(e.length!==0)try{await this.#e.replyStream(r,this.#l("stream"),e[0],!0);for(let a of e.slice(1))await this.#e.sendMessage(o,{msgtype:"markdown",markdown:{content:a}})}catch{await this.#B(o,i)}}async#Q(r,{alreadyRecorded:o=!1,preparedMessage:i}={}){if(this.#s?.aborted)return;let e=zc(r),a=typeof e.msgid=="string"?e.msgid:"",A=typeof e.from?.userid=="string"?e.from.userid:"",t=e.chattype==="group"?e.chatid:A;if(!a||!A||!t||!["single","group"].includes(e.chattype))return;if(!o){if(this.#r.hasSeen(a))return;this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString()}let s=i??qR(r,this.#e),g=s.content,c=Ir(s),I=Z4(r),E=null,B=!1;try{if(!g&&!c){await this.#u(r,t,"\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u8BED\u97F3\u8F6C\u5199\u6D88\u606F\u3002"),await this.#r.markSeen(a);return}let f=g.toLowerCase();if(!c&&f==="/help"){await this.#u(r,t,Bbe),await this.#r.markSeen(a);return}if(!c&&f==="/status"){await this.#A.ensureRunning({signal:this.#s}),await this.#u(r,t,"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002"),await this.#r.markSeen(a);return}if(!c&&f==="/new"){await this.#r.clearSession(I),await this.#u(r,t,"\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"),await this.#r.markSeen(a);return}let Q=c?null:await Ki(g,this.#A,I);if(Q){for(let Y of Q.messages??[Q.message])await this.#u(r,t,Y);await this.#r.markSeen(a);return}let y=c?null:await Ui(g,this.#A,this.#r,I,{signal:this.#s});if(y){await this.#u(r,t,y.message),await this.#r.markSeen(a);return}E=this.#l("stream");try{await this.#e.replyStream(r,E,"\u6B63\u5728\u601D\u8003\u4E2D\u2026",!1),B=!0}catch(Y){this.#n.warn?.("[dsh-im:wecom] unable to start a stream; using an active reply:",Y)}let m=c?await Fi(s,{signal:this.#s}):void 0,{answer:R}=await qa({harness:this.#A,state:this.#r,key:I,text:g,content:m,createOptions:{signal:this.#s},existsOptions:{signal:this.#s},askOptions:{timeoutMs:this.#o,signal:this.#s,control:{owner:this,key:I},onUpdate:B&&typeof this.#e.replyStreamNonBlocking=="function"?async Y=>{let j=Ry(Dbe(Y))[0];j&&await this.#e.replyStreamNonBlocking(r,E,j,!1)}:void 0,onInteraction:Y=>this.#m(Y,{key:I,actor:A,chatId:t,requiresMention:e.chattype==="group"}),onInteractionResolved:Y=>this.#y(Y)}}),_=Ry(R||"\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u4F46\u6CA1\u6709\u751F\u6210\u53EF\u663E\u793A\u7684\u6587\u672C\u3002"),P=!1;if(B&&_.length>0)try{await this.#e.replyStream(r,E,_[0],!0);for(let Y of _.slice(1))await this.#e.sendMessage(t,{msgtype:"markdown",markdown:{content:Y}});P=!0}catch(Y){this.#n.warn?.("[dsh-im:wecom] stream finalization failed; using an active reply:",Y)}P||await this.#B(t,R),await this.#r.markSeen(a),this.#t.messagesReplied+=1,this.#t.lastReplyAt=new Date().toISOString(),this.#t.lastError=null}catch(f){if(f?.code==="turn-stopped"){B&&E&&await this.#e.replyStream(r,E,"\u5DF2\u505C\u6B62\u3002",!0).catch(()=>{}),await this.#r.markSeen(a);return}if(this.#s?.aborted)return;this.#t.lastError=f?.message??String(f),this.#n.error?.("[dsh-im:wecom] failed to process an inbound message");let Q=Li(f)??"\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";try{B&&E?await this.#e.replyStream(r,E,Q,!0):await this.#u(r,t,Q),await this.#r.markSeen(a)}catch{this.#n.error?.("[dsh-im:wecom] failed to send the safe error reply")}}finally{await Promise.allSettled([this.#T(I),this.#h.closeRoute(I)])}}async#f(r,o,i,e,a,A){if(this.#s?.aborted)return;let t=this.#a.get(a),s=A.claimedReplyMessageId===o;if(!t||t!==A||t.submitting)return s&&(!t||t!==A)?this.#w(r,o,e):this.#E(r,o,a,{releaseMessageId:!1});if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString();let g=hs(VR(r));if(!g){await this.#u(r,e,"\u8BF7\u7528\u6587\u5B57\u56DE\u7B54\u5F53\u524D\u95EE\u9898\u3002").catch(()=>{});return}let c=this.#a.get(a);if(!c||c!==A||c.submitting){if(s&&(!c||c!==A)){await this.#u(r,e,Ty).catch(()=>{});return}return this.#E(r,o,a,{releaseMessageId:!1,alreadyRecorded:!0})}if(c.actor!==i)return this.#E(r,o,a,{releaseMessageId:!1,alreadyRecorded:!0});if(c.chatId=e,c.needsPresentation){try{await this.#S(c)}catch{this.#t.lastError="\u4F01\u4E1A\u5FAE\u4FE1\u4EA4\u4E92\u95EE\u9898\u53D1\u9001\u5931\u8D25\u3002",this.#n.error?.("[dsh-im:wecom] failed to retry an interaction question"),c.interaction.reconnect?.();return}let E=this.#a.get(a);if(!E||E!==A||E.submitting){if(s&&(!E||E!==A)){await this.#u(r,e,Ty).catch(()=>{});return}return this.#E(r,o,a,{releaseMessageId:!1,alreadyRecorded:!0})}}let I=c.questions[c.index];if(I){if(c.answers.push(xa(I,g)),c.index+=1,c.index{});return}if(this.#a.get(a)!==c)return;c.submitting=!1,c.answers.pop(),c.index-=1,this.#t.lastError="\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\u3002",this.#n.error?.("[dsh-im:wecom] failed to answer a Harness interaction"),await this.#u(r,e,"\u56DE\u7B54\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u5F53\u524D\u95EE\u9898\u7684\u7B54\u6848\u3002").catch(()=>{})}}}async#m(r,{key:o,actor:i,chatId:e,requiresMention:a}){if(r?.kind==="approval")return this.#h.handleRequested(r,{key:o,actor:i,requiresMention:a,send:c=>this.#B(e,c)});if(r?.kind!=="question")return;let A=r?.payload?.questions,t=typeof r?.interactionId=="string"?r.interactionId:r?.rpcId;if(typeof r?.rpcId!="string"||typeof t!="string"||typeof r.sessionId!="string"||!Array.isArray(A)||A.length===0||A.some(c=>!Ka(c))){this.#n.warn?.("[dsh-im:wecom] ignored an invalid Harness question interaction");return}if(r.recovered===!0){await r.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat safely cancelled an interaction left by an earlier client.",details:{}}}),await this.#B(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.#a.get(o);if(s?.interactionId===t){s.interaction=r,s.needsPresentation&&await this.#S(s);return}if(this.#i.has(t))return;if(s){this.#n.warn?.("[dsh-im:wecom] cancelled a second pending Harness question"),await r.respond({ok:!1,error:{code:"cancelled",message:"Enterprise WeChat is already handling another user interaction.",details:{}}});return}let g={kind:"question",interactionId:t,sessionId:r.sessionId,interaction:r,actor:i,requiresMention:a,questions:A,answers:[],index:0,chatId:e,queue:null,claimedReplyMessageId:null,submitting:!1,needsPresentation:!0,presentationPromise:null};this.#a.set(o,g),this.#i.set(g.interactionId,o),await this.#S(g)}async#y(r){if(r?.kind==="approval"){await this.#h.handleResolved(r);return}let o=r?.interactionId;if(r?.kind!=="question"||typeof o!="string")return;let i=this.#i.get(o);i&&this.#M(i,o)}#S(r){if(!r.needsPresentation)return Promise.resolve();if(r.presentationPromise)return r.presentationPromise;let o=r.questions[r.index];if(!o)return Promise.resolve();let i=this.#B(r.chatId,Ya(o,r.index,r.questions.length,{requiresMention:r.requiresMention})).then(()=>{r.needsPresentation=!1}).finally(()=>{r.presentationPromise===i&&(r.presentationPromise=null)});return r.presentationPromise=i,i}async#w(r,o,i){this.#r.hasSeen(o)||(await this.#r.markSeen(o),this.#t.messagesReceived+=1,this.#t.lastMessageAt=new Date().toISOString(),await this.#u(r,i,Ty).catch(()=>{}))}#R(r,o){let i=this.#a.get(r);return!i||o!==void 0&&i.interactionId!==o?null:(this.#a.delete(r),this.#i.delete(i.interactionId),i)}#M(r,o){return this.#R(r,o)!==null}async#T(r){let o=this.#R(r);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.#n.warn?.("[dsh-im:wecom] failed to cancel a pending Harness interaction")}}};function _be(){let n=new Error("Enterprise WeChat WebSocket authentication timed out");return n.code="connect-timeout",n}function Nbe(){return{startedAt:null,ready:!1,wecomConnectionState:"idle",harnessReachable:!1,lastCheckedAt:null,lastConnectedAt:null,lastError:null,...zR()}}var Yh=class{#e;#A;#r;#t;#n;#o;#l;#s;#I;#a=Nbe();#i=null;#c=null;#g=null;#p=null;#h=null;constructor({config:r,secret:o,harness:i,state:e,logger:a=console,replyTimeoutMs:A=6e5,connectTimeoutMs:t=2e4,maxReconnectAttempts:s=10,createClient:g=c=>new bbe(c)}){if(!r||!o||!i||!e)throw new TypeError("WecomRuntime requires config, secret, Harness, and state");this.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A,this.#l=t,this.#s=s,this.#I=g}get status(){return structuredClone(this.#a)}async start(){if(this.#a.ready&&this.#i)return this.status;if(this.#g)return this.#g;this.#h?.abort(new DOMException("Enterprise WeChat runtime replaced","AbortError"));let r=new AbortController;return this.#p=r,this.#h=r,this.#g=this.#C(r.signal).finally(()=>{this.#p===r&&(this.#p=null),this.#g=null}),this.#g}async#C(r){await this.#E(),r.throwIfAborted(),this.#a.startedAt=new Date().toISOString(),this.#a.wecomConnectionState="connecting",this.#a.lastError=null,await this.#r.ensureRunning(),this.#a.harnessReachable=!0;let o={debug(){},info(){},warn(){},error(){}},i=this.#I({botId:this.#e.remoteBotId,secret:this.#A,logger:o,maxReconnectAttempts:this.#s});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.#c=new ky({client:i,harness:this.#r,state:this.#t,status:this.#a,logger:this.#n,replyTimeoutMs:this.#o,signal:r});let e,a,A=!1,t=new Promise((f,Q)=>{e=f,a=Q}),s=()=>{if(this.#i!==i||r.aborted)return;A=!0;let f=Date.now();this.#a.ready=!0,this.#a.wecomConnectionState="connected",this.#a.lastCheckedAt=f,this.#a.lastConnectedAt=f,this.#a.lastError=null,e()},g=()=>{this.#i===i&&(this.#a.ready=!1,this.#a.wecomConnectionState="connecting",this.#a.lastCheckedAt=Date.now())},c=()=>{this.#i===i&&(this.#a.ready=!1,this.#a.wecomConnectionState="connecting",this.#a.lastCheckedAt=Date.now())},I=f=>{if(this.#i!==i)return;let Q=f instanceof Obe||f instanceof Mbe;!A&&Q&&a(f),Q&&(this.#a.ready=!1,this.#a.wecomConnectionState="failed"),this.#a.lastError=Q?f.name:"connection-error",this.#n.warn?.(`[dsh-im:wecom] bot ${this.#e.botId} connection error`)},E=f=>this.#c?.accept(f);i.on("authenticated",s),i.on("disconnected",g),i.on("reconnecting",c),i.on("error",I),i.on("message",E);let B;try{return i.connect(),await Promise.race([t,new Promise((f,Q)=>{r.addEventListener("abort",()=>Q(r.reason),{once:!0})}),new Promise((f,Q)=>{B=setTimeout(()=>Q(_be()),this.#l)})]),this.status}catch(f){throw r.aborted?(await this.#E(),f):(this.#a.ready=!1,this.#a.wecomConnectionState="failed",this.#a.lastError=f?.message??String(f),await this.#E(),f)}finally{clearTimeout(B)}}async stop(){let r=this.#g;return this.#p?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#h?.abort(new DOMException("Enterprise WeChat runtime stopped","AbortError")),this.#h=null,await this.#E(),await r?.catch(()=>{}),this.status}async sendConnectionTest(r){return Ys({state:this.#t,text:r,channelLabel:"\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA",send:async({chatId:o},i)=>{if(!this.#a.ready||!this.#i)throw new Error("Enterprise WeChat runtime is not connected");await this.#i.sendMessage(o,{msgtype:"markdown",markdown:{content:i}})}})}async#E(){let r=this.#i,o=this.#c;this.#i=null,this.#c=null;try{r?.disconnect(),r?.removeAllListeners?.()}catch{this.#n.warn?.(`[dsh-im:wecom] bot ${this.#e.botId} failed to stop cleanly`)}await o?.waitForIdle(),this.#a.ready=!1,this.#a.wecomConnectionState="idle"}};var e8=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function Tbe(n){if(!Array.isArray(n)||n.length===0)return[...e8];let r=n.filter(o=>Number.isFinite(o)&&o>=0);return r.length>0?r:[...e8]}var vy=class{#e;#A;#r;#t;#n;#o;#l;#s=null;#I=null;#a=0;#i=!1;#c=!1;#g;#p;constructor({controller:r,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:t=clearTimeout}){if(!r||typeof r.initialize!="function"||typeof r.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=r,this.#A=o,this.#r=i,this.#t=Tbe(e),this.#n=Number.isFinite(a)&&a>=0?a:15e3,this.#o=A,this.#l=t,this.#g=new Promise(s=>{this.#p=s})}get ready(){return this.#g}start(){return this.#c||this.#i?this:(this.#c=!0,this.#h(0),this)}async close(){this.#i||(this.#i=!0,this.#s!==null&&this.#l(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#h(r){this.#i||(this.#s=this.#o(()=>{this.#s=null,this.#C()},r),this.#s?.unref?.())}async#C(){if(this.#i||this.#I)return;let r=this.#E();this.#I=r;try{await r}finally{this.#I===r&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#i)return;let r=await this.#e.initialize();if(this.#i)return;this.#p?.(r),this.#p=null;let{configured:o,connected:i}=r.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 Pbe(n){let r=Wc(n.dshHome??process.env.DSH_HOME??xh(kbe(),".dsh")),o=Wc(n.dataDir??xh(r,"integrations","dsh-wecom"));return{config:Wc(n.configPath??xh(o,"config.json")),bots:Wc(n.botsDir??xh(o,"bots")),workspaces:Wc(n.workspacesPath??xh(o,"workspaces.json"))}}async function ZR(n,r={},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??wy,e=o.StateStore??Ny,a=o.HarnessClient??by,A=o.Controller??Kh,t=o.Runtime??Yh,s=o.QrAuth??My,g=o.createConnectionSupervisor??WR,c=typeof n.logger=="function"?n.logger("dsh-im:wecom"):n.logger??console,I=()=>pa(n),E=Pbe(r),B=await new i(E.config).load(),f=Wc(r.workspace??process.cwd()),Q=o.WorkspaceStore??Fr,y=o.workspaces??await new Q(E.workspaces,{defaultWorkspace:f}).load(),m=B.list();await y.reconcile(m.map(M=>M.botId)),await Promise.all(m.map(M=>y.ensure(M.botId,{defaultAgentPreset:r.agentPreset})));let R=typeof B.remove=="function"?Ea(B,{workspaces:y}):B,_=o.qrAuth??new s({source:r.qrSource??"deepseek-harness",platform:r.qrPlatform}),P=new Map,Y=M=>Wc(E.bots,M,"state.json"),j=async M=>{let G=P.get(M);return G||(G=await new e(Y(M)).load(),P.set(M,G)),G},K=da(n,o.commandExecutor),{controlExecutor:q,sessionMaintenanceExecutor:V}=ua(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor}),H=new a({baseUrl:vbe(n.webServer,r.harnessBaseUrl),workspace:f,autostart:!1,dshBin:r.dshBin??"dsh",...K?{commandExecutor:K}:{},...q?{controlExecutor:q}:{},...V?{sessionMaintenanceExecutor:V}:{}}),v=new A({qrAuth:_,credentials:n.credentials,configStore:R,logger:c,createRuntime:async({botId:M,config:G,secret:te})=>{let se=await j(M);await y.ensure(M,{defaultAgentPreset:r.agentPreset});let ne=Ca(H,{botId:M,workspaces:y,state:se,agentPresetCatalog:I});return new t({config:G,secret:te,harness:ne.harness,state:ne.state,replyTimeoutMs:r.replyTimeoutMs??6e5,connectTimeoutMs:r.connectTimeoutMs??2e4,maxReconnectAttempts:r.maxReconnectAttempts??10,logger:{error:(...Me)=>c.error?.(`[${M}]`,...Me),warn:(...Me)=>c.warn?.(`[${M}]`,...Me),info:(...Me)=>c.info?.(`[${M}]`,...Me),debug:(...Me)=>c.debug?.(`[${M}]`,...Me)}})},deleteState:async({botId:M})=>{let G=P.get(M);if(P.delete(M),G&&typeof G.remove=="function")await G.remove();else try{await Rbe(Y(M))}catch(te){if(te?.code!=="ENOENT")throw te}}}),Z=ha(v,{workspaces:y,stateFor:j,agentPresetCatalog:I}),U=g({controller:Z,harness:H,logger:c,retryDelaysMs:r.retryDelaysMs,healthyIntervalMs:r.healthyIntervalMs}).start();return{controller:Z,ready:U.ready,async close(){await U.close(),await Z.close(),H.stopManagedProcess()}}}import Gbe from"qrcode";var t8="/wecom",Dr=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:za,setAgentPreset:Wa}),r8=Object.freeze(Object.values(Dr)),Fbe=new Set(["secret","secretRef","scode","remoteBotId","verificationUrl","bot_info","botid"]);function ek(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function rp(n,r){return ek(n)&&Object.keys(n).every(o=>r.includes(o))}function XR(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function A8(n,r){return typeof n=="string"&&n.trim().length>0&&n.length<=r}function Lbe(n,r){return ek(r)?n===Dr.status?rp(r,[])?null:"connection.status does not accept fields.":n===Dr.beginProvisioning?rp(r,["locale"])&&(r.locale===void 0||r.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[Dr.pollProvisioning,Dr.cancelProvisioning].includes(n)?rp(r,["attemptId"])&&XR(r.attemptId)?null:`${n} requires an attemptId.`:n===Dr.bindCredentials?rp(r,["botId","secret"])&&A8(r.botId,512)&&A8(r.secret,1024)?null:"bot.bind-credentials requires Bot ID and Secret.":n===Dr.reconnectBot?rp(r,["botId","sendTest"])&&XR(r.botId)&&(r.sendTest===void 0||r.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===Dr.deleteBot?rp(r,["botId","confirm"])&&XR(r.botId)&&r.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===Dr.setWorkspace?Ba(r)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===Dr.setAgentPreset?Qa(r)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":"Unknown Enterprise WeChat endpoint.":"Payload must be an object."}function ip(n){if(Array.isArray(n))return n.map(ip);if(!ek(n))return n;let r={};for(let[o,i]of Object.entries(n))Fbe.has(o)||(r[o]=ip(i));return r}async function Ube(n){return Gbe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function $R(n,r){return!n||typeof n.verificationUrl!="string"?ip(n):ip({...n,qrCodeDataUrl:await r(n.verificationUrl)})}async function ap(n,r){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await $R(o.provisioning,r)),ip(o)}function a8(n,{encodeQr:r=Ube}={}){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 a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>r(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};if(!r8.includes(e))return{ok:!1,error:{code:"bad-request",message:"Unknown Enterprise WeChat endpoint."}};let t=Lbe(e,a);if(t)return{ok:!1,error:{code:"bad-request",message:t}};try{let s;if(e===Dr.status)s=await ap(await n.status(),i);else if(e===Dr.beginProvisioning)s=await $R(await n.startProvisioning(),i);else if(e===Dr.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return{ok:!1,error:{code:"bad-request",message:"The provisioning attempt no longer exists."}};s=await $R(g,i)}else if(e===Dr.cancelProvisioning)s=ip(await n.cancelProvisioning(a.attemptId));else if(e===Dr.bindCredentials)s=await ap(await n.bindCredentials(a),i);else if(e===Dr.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}};let c;if(a.sendTest===!0)if(!g?.bots?.some(E=>E?.botId===a.botId&&E?.connected===!0)||typeof n.sendConnectionTest!="function")c=qt(tr("\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=qt()}catch(E){c=qt(E)}s=await ap({...g,...c?{testMessage:c}:{}},i)}else if(e===Dr.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await ap(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===Dr.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await ap(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else s=await ap(await n.deleteBot(a.botId),i);return A?.aborted?{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}:{ok:!0,value:s}}catch(s){let g=fa(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 Py(n,r,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(t8,a8(r,o),{authority:Er(i)})}async function i8(n,r={}){if(r?.controller)return Py(n,r.controller,r.rpcOptions,r.rpcAuthority);let o=await ZR(n,r,r.internals),i=Py(n,o.controller,r.rpcOptions,r.rpcAuthority);return n.effect(()=>async()=>o.close(),"dsh-im: close Enterprise WeChat bot connections"),i}import{unlink as vMe}from"node:fs/promises";import{homedir as PMe}from"node:os";import{join as zh,resolve as Zc}from"node:path";import{createHash as aMe}from"node:crypto";import{mkdir as iMe,readFile as oMe,rename as nMe,unlink as sMe,writeFile as gMe}from"node:fs/promises";import{dirname as cMe}from"node:path";import{createDecipheriv as Hbe,randomBytes as Kbe,randomUUID as Ybe}from"node:crypto";var Fy="https://ilinkai.weixin.qq.com/",xbe="2.4.6",jbe="3",Jbe="https://novac2c.cdn.weixin.qq.com/c2c",s8="novac2c.cdn.weixin.qq.com",qbe="bot",Vbe=2<<16|1024|6,zbe=15e3,o8=35e3,Wbe=new Set(["wait","scaned","confirmed","expired","scaned_but_redirect","need_verifycode","verify_code_blocked","binded_redirect"]),it=class extends Error{constructor(r,o,i={}){super(o,i),this.name="WeixinApiError",this.code=r,this.status=i.status}};function Ta(n){return typeof n=="string"&&n.trim()?n.trim():null}function Zbe(n){let r=Ta(n);return!r||r.length%4!==0||!/^[A-Za-z0-9+/]+={0,2}$/.test(r)?null:Buffer.from(r,"base64")}function Xbe(n){let r=Ta(n?.aeskey);if(r){if(!/^[0-9a-fA-F]{32}$/.test(r))throw new it("invalid-image-key","\u5FAE\u4FE1\u56FE\u7247\u7684\u52A0\u5BC6\u5BC6\u94A5\u65E0\u6548\u3002");return Buffer.from(r,"hex")}let o=Zbe(n?.media?.aes_key);if(o?.length===16)return o;if(o?.length===32&&/^[0-9a-fA-F]{32}$/.test(o.toString("ascii")))return Buffer.from(o.toString("ascii"),"hex");throw new it("invalid-image-key","\u5FAE\u4FE1\u56FE\u7247\u7684\u52A0\u5BC6\u5BC6\u94A5\u65E0\u6548\u3002")}function $be(n,r){let o=Buffer.from(n),i=Buffer.from(r);if(i.length!==16||o.length===0||o.length%16!==0)throw new it("invalid-image-ciphertext","\u5FAE\u4FE1\u56FE\u7247\u7684\u52A0\u5BC6\u6570\u636E\u65E0\u6548\u3002");try{let e=Hbe("aes-128-ecb",i,null);return Buffer.concat([e.update(o),e.final()])}catch(e){throw new it("image-decryption-failed","\u5FAE\u4FE1\u56FE\u7247\u89E3\u5BC6\u5931\u8D25\u3002",{cause:e})}}function eMe(n){let r=Ta(n?.encrypt_query_param);if(r)return`${Jbe}/download?encrypted_query_param=${encodeURIComponent(r)}`;let o=Ta(n?.full_url);if(!o)throw new it("missing-image-url","\u5FAE\u4FE1\u56FE\u7247\u6CA1\u6709\u53EF\u7528\u7684\u4E0B\u8F7D\u5730\u5740\u3002");let i;try{i=new URL(o)}catch{throw new it("invalid-image-url","\u5FAE\u4FE1\u56FE\u7247\u7684\u4E0B\u8F7D\u5730\u5740\u65E0\u6548\u3002")}if(i.protocol!=="https:"||i.hostname!==s8||i.port&&i.port!=="443"||!i.pathname.startsWith("/c2c/"))throw new it("untrusted-image-url","\u5FAE\u4FE1\u56FE\u7247\u7684\u4E0B\u8F7D\u5730\u5740\u4E0D\u53D7\u4FE1\u4EFB\u3002");return i.username="",i.password="",i.hash="",i.toString()}function Ak(n,{fetchImpl:r=fetch}={}){if(typeof r!="function")throw new TypeError("fetchImpl must be a function");let o=[];for(let i of n?.item_list??[]){let e=i?.image_item;!e||typeof e!="object"||o.push({name:o.length===0?"image":`image-${o.length+1}`,load:async({signal:a,maxBytes:A})=>{let t=Xbe(e),s=eMe(e.media),g=await Gi(s,{fetchImpl:r,signal:a,maxBytes:A+16,allowedHosts:[s8]});return $be(g,t)}})}return o}function tk(n){let r=n.toLowerCase().replace(/\.$/,"");return r==="weixin.qq.com"||r.endsWith(".weixin.qq.com")}function np(n){let r;try{r=new URL(n)}catch{throw new it("invalid-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u8FDE\u63A5\u5730\u5740\u3002")}if(r.protocol!=="https:"||!tk(r.hostname)||r.port!==""&&r.port!=="443")throw new it("untrusted-base-url","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u8FDE\u63A5\u5730\u5740\u3002");return r.username="",r.password="",r.search="",r.hash="",r.pathname.endsWith("/")||(r.pathname+="/"),r.toString()}function AMe(n){let r=Ta(n);if(!r)throw new it("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u626B\u7801\u5730\u5740\u3002");let o;try{o=new URL(r)}catch{throw new it("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u7684\u626B\u7801\u5730\u5740\u3002")}if(o.protocol!=="https:"||!tk(o.hostname))throw new it("untrusted-qr","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u4E0D\u53D7\u4FE1\u4EFB\u7684\u626B\u7801\u5730\u5740\u3002");return o.toString()}function g8(){return{"iLink-App-Id":qbe,"iLink-App-ClientVersion":String(Vbe)}}function tMe(n){let r={...g8(),"content-type":"application/json",AuthorizationType:"ilink_bot_token","X-WECHAT-UIN":Buffer.from(String(Kbe(4).readUInt32BE(0)),"utf8").toString("base64")};return Ta(n)&&(r.Authorization=`Bearer ${n.trim()}`),r}function Gy(){return{channel_version:xbe,bot_agent:"DeepSeekHarness/1.0.1"}}function n8(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}async function op(n,{method:r,baseUrl:o,endpoint:i,body:e,token:a,timeoutMs:A=zbe,signal:t,authenticated:s=!0}){let g=np(o),c=new URL(i,g);if(!tk(c.hostname))throw new it("untrusted-endpoint","\u62D2\u7EDD\u8BBF\u95EE\u4E0D\u53D7\u4FE1\u4EFB\u7684\u5FAE\u4FE1\u670D\u52A1\u5730\u5740\u3002");let I=new AbortController,E=!1,B=()=>I.abort(t?.reason);if(t?.aborted)throw n8(t);t?.addEventListener("abort",B,{once:!0});let f=A>0?setTimeout(()=>{E=!0,I.abort()},A):null;try{let Q=await n(c,{method:r,headers:s?tMe(a):g8(),...e===void 0?{}:{body:JSON.stringify(e)},signal:I.signal});if(!Q.ok)throw new it("http-error",`\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u5931\u8D25\uFF08HTTP ${Q.status}\uFF09\u3002`,{status:Q.status});try{return await Q.json()}catch(y){throw new it("invalid-response","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u89E3\u6790\u7684\u54CD\u5E94\u3002",{cause:y})}}catch(Q){throw t?.aborted?n8(t):E?new it("timeout","\u5FAE\u4FE1\u670D\u52A1\u8BF7\u6C42\u8D85\u65F6\u3002",{cause:Q}):Q instanceof it?Q:new it("network-error","\u6682\u65F6\u65E0\u6CD5\u8BBF\u95EE\u5FAE\u4FE1\u670D\u52A1\u3002",{cause:Q})}finally{f&&clearTimeout(f),t?.removeEventListener("abort",B)}}function rMe(n){if(!n||typeof n!="object"||!Wbe.has(n.status))throw new it("invalid-login-status","\u5FAE\u4FE1\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u626B\u7801\u72B6\u6001\u3002");return n}function c8({fetchImpl:n=fetch}={}){if(typeof n!="function")throw new TypeError("fetchImpl must be a function");return Object.freeze({inboundImages(r){return Ak(r,{fetchImpl:n})},async beginLogin({localTokens:r=[],botType:o=jbe,signal:i}={}){let e=[...new Set(r.map(Ta).filter(Boolean))].slice(-10),a=await op(n,{method:"POST",baseUrl:Fy,endpoint:`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(o)}`,body:{local_token_list:e},timeoutMs:1e4,signal:i}),A=Ta(a?.qrcode);if(!A)throw new it("invalid-qr","\u5FAE\u4FE1\u670D\u52A1\u6CA1\u6709\u8FD4\u56DE\u4E8C\u7EF4\u7801\u4EE4\u724C\u3002");return{qrcode:A,qrcodeUrl:AMe(a.qrcode_img_content)}},async pollLogin({qrcode:r,baseUrl:o=Fy,verifyCode:i,signal:e}){let a=Ta(r);if(!a)throw new TypeError("qrcode is required");let A=`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(a)}`;Ta(i)&&(A+=`&verify_code=${encodeURIComponent(i.trim())}`);let t=await op(n,{method:"GET",baseUrl:o,endpoint:A,timeoutMs:o8,signal:e,authenticated:!1});return rMe(t)},async getUpdates({baseUrl:r,token:o,getUpdatesBuf:i="",timeoutMs:e,signal:a}){try{return await op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/getupdates",body:{get_updates_buf:i,base_info:Gy()},token:o,timeoutMs:e??o8,signal:a})}catch(A){if(A instanceof it&&A.code==="timeout")return{ret:0,msgs:[],get_updates_buf:i};throw A}},async sendText({baseUrl:r,token:o,toUserId:i,text:e,contextToken:a,runId:A,signal:t}){let s=Ta(i),g=Ta(e);if(!s||!g)throw new TypeError("toUserId and text are required");let c=await op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/sendmessage",token:o,signal:t,body:{msg:{from_user_id:"",to_user_id:s,client_id:`dsh-weixin-${Ybe()}`,message_type:2,message_state:2,item_list:[{type:1,text_item:{text:g}}],...Ta(a)?{context_token:a.trim()}:{},...Ta(A)?{run_id:A.trim()}:{}},base_info:Gy()}});if(c?.ret!==void 0&&c.ret!==0)throw new it("send-rejected","\u5FAE\u4FE1\u670D\u52A1\u62D2\u7EDD\u4E86\u56DE\u590D\u6D88\u606F\u3002");return!0},async notifyStart({baseUrl:r,token:o,signal:i}){let e=await op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/msg/notifystart",token:o,signal:i,timeoutMs:1e4,body:{base_info:Gy()}});if(e?.ret!==void 0&&e.ret!==0)throw new it("start-rejected","\u5FAE\u4FE1\u8D26\u53F7\u8FDE\u63A5\u542F\u52A8\u5931\u8D25\u3002");return e},async notifyStop({baseUrl:r,token:o,signal:i}){return op(n,{method:"POST",baseUrl:r,endpoint:"ilink/bot/msg/notifystop",token:o,signal:i,timeoutMs:1e4,body:{base_info:Gy()}})}})}function sp(n){for(let r of n?.item_list??[]){if(r?.type===1&&typeof r.text_item?.text=="string"){let o=r.text_item.text.trim();if(o)return o}if(r?.type===3&&typeof r.voice_item?.text=="string"){let o=r.voice_item.text.trim();if(o)return o}}return null}function rk(n){return n?.message_id!==void 0&&n.message_id!==null?String(n.message_id):Ta(n?.client_id)}function I8(n,r=4e3){if(n.length<=r)return[n];let o=[],i=n;for(;i.length>r;){let e=i.lastIndexOf(` `,r);ea===null))return null;let o=new Set,i=new Set,e=new Set;for(let a of r){if(o.has(a.botId)||i.has(a.accountId)||e.has(a.tokenRef))return null;o.add(a.botId),i.add(a.accountId),e.add(a.tokenRef)}return Object.freeze({version:1,accounts:Object.freeze(r)})}var Ly=class{#e;#A=ak;#r=Promise.resolve();constructor(r){this.#e=r}async load(){try{let r=lMe(JSON.parse(await oMe(this.#e,"utf8")));if(!r)throw new Error("dsh-weixin config contains invalid account data");this.#A=r}catch(r){if(r?.code!=="ENOENT")throw r;this.#A=ak}return this}list(){return structuredClone(this.#A.accounts)}get(r){let o=this.#A.accounts.find(i=>i.botId===r);return o?structuredClone(o):null}getByAccountId(r){let o=this.#A.accounts.find(i=>i.accountId===r);return o?structuredClone(o):null}async save(r){let o=p8(r);if(!o)throw new Error("Refusing to persist incomplete dsh-weixin account data");return this.#t(i=>{let e=i.find(t=>t.accountId===o.accountId&&t.botId!==o.botId),a=i.find(t=>t.tokenRef===o.tokenRef&&t.botId!==o.botId);if(e||a)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(r){if(!l8(r))throw new TypeError("Invalid Weixin bot id");return this.#t(o=>{let i=o.findIndex(a=>a.botId===r);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let r=this.#r.then(async()=>{try{await sMe(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#A=ak});this.#r=r.then(()=>{},()=>{}),await r}async#t(r){let o,i=this.#r.then(async()=>{let e=[...this.#A.accounts];o=r(e);let a=Object.freeze({version:1,accounts:Object.freeze(e)});await this.#n(a),this.#A=a});return this.#r=i.then(()=>{},()=>{}),await i,o}async#n(r){await iMe(cMe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await gMe(o,`${JSON.stringify(r,null,2)} `,{encoding:"utf8",mode:384}),await nMe(o,this.#e)}};var Uy=class extends rr{constructor(r){super({...r,rpcIdPrefix:"weixin",logPrefix:"dsh-weixin"})}};import{mkdir as pMe,readFile as EMe,rename as CMe,unlink as hMe,writeFile as dMe}from"node:fs/promises";import{dirname as uMe}from"node:path";var Hy=Object.freeze({version:1,sessions:{},seenMessageIds:[],getUpdatesBuf:""});function BMe(n){if(!n||typeof n!="object")return structuredClone(Hy);let r={};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&&(r[o]=i);return{version:1,sessions:r,seenMessageIds:Array.isArray(n.seenMessageIds)?n.seenMessageIds.filter(o=>typeof o=="string").slice(-1e3):[],getUpdatesBuf:typeof n.getUpdatesBuf=="string"?n.getUpdatesBuf:""}}var Ky=class{#e;#A=structuredClone(Hy);#r=Promise.resolve();constructor(r){this.#e=r}async load(){try{this.#A=BMe(JSON.parse(await EMe(this.#e,"utf8")))}catch(r){if(r?.code!=="ENOENT")throw r;this.#A=structuredClone(Hy),await this.#t()}return this}sessionFor(r){return this.#A.sessions[r]??null}async setSession(r,o){this.#A.sessions[r]=o,await this.#t()}async clearSession(r){delete this.#A.sessions[r],await this.#t()}async clearSessions(){this.#A.sessions={},await this.#t()}hasSeen(r){return this.#A.seenMessageIds.includes(r)}async markSeen(r){this.hasSeen(r)||(this.#A.seenMessageIds.push(r),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#t())}getUpdatesBuf(){return this.#A.getUpdatesBuf}async setGetUpdatesBuf(r){typeof r!="string"||r===this.#A.getUpdatesBuf||(this.#A.getUpdatesBuf=r,await this.#t())}snapshot(){return structuredClone(this.#A)}async remove(){try{await hMe(this.#e)}catch(r){if(r?.code!=="ENOENT")throw r}this.#A=structuredClone(Hy)}async#t(){let r=`${JSON.stringify(this.#A,null,2)} `,o=this.#r.then(async()=>{await pMe(uMe(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await dMe(i,r,{encoding:"utf8",mode:384}),await CMe(i,this.#e)});this.#r=o.then(()=>{},()=>{}),await o}};import{randomUUID as fMe}from"node:crypto";var E8=new Set(["starting","pending","scanned","needs_verification","connecting"]),Yy=new Set(["connected","expired","failed","cancelled"]),C8=5*6e4,u8=Object.freeze({"credential-read-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u8BFB\u53D6\u73B0\u6709\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u68C0\u67E5 DSH \u51ED\u636E\u5B58\u50A8\u3002","credential-save-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u767B\u5F55\u51ED\u636E\u65E0\u6CD5\u5199\u5165 DSH \u51ED\u636E\u5B58\u50A8\u3002\u8BF7\u68C0\u67E5\u51ED\u636E\u5B58\u50A8\u662F\u5426\u53EF\u5199\u3002","account-config-save-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u8D26\u53F7\u914D\u7F6E\u65E0\u6CD5\u5199\u5165\u672C\u673A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u76EE\u5F55\u6743\u9650\u3002","runtime-prepare-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u65E0\u6CD5\u521D\u59CB\u5316\u8D26\u53F7\u72B6\u6001\u6216\u5DE5\u4F5C\u533A\u3002\u8BF7\u68C0\u67E5 DSH_HOME \u548C\u5DE5\u4F5C\u533A\u76EE\u5F55\u3002","harness-connect-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u63D2\u4EF6\u65E0\u6CD5\u8FDE\u63A5\u672C\u673A Harness\u3002\u8BF7\u68C0\u67E5 dsh web \u5730\u5740\u548C\u7AEF\u53E3\u3002","harness-timeout":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u8D85\u65F6\u3002\u8BF7\u786E\u8BA4 dsh web \u672A\u963B\u585E\u3002","harness-access-denied":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u62D2\u7EDD\u4E86\u672C\u673A\u5065\u5EB7\u68C0\u67E5\u3002\u8BF7\u68C0\u67E5 Host \u4FE1\u4EFB\u914D\u7F6E\u3002","harness-api-not-found":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u627E\u4E0D\u5230 Harness \u5065\u5EB7\u68C0\u67E5\u63A5\u53E3\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002","harness-http-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u8FD4\u56DE\u670D\u52A1\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002","harness-response-invalid":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u54CD\u5E94\u3002\u8BF7\u786E\u8BA4 Harness \u4E0E\u63D2\u4EF6\u7248\u672C\u517C\u5BB9\u3002","harness-rpc-rejected":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u62D2\u7EDD\u4E86\u5065\u5EB7\u68C0\u67E5\u8BF7\u6C42\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002","harness-check-unknown-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46 Harness \u5065\u5EB7\u68C0\u67E5\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002","connection-start-failed":"\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6D88\u606F\u8FDE\u63A5\u521D\u59CB\u5316\u5931\u8D25\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u540E\u91CD\u8BD5\u3002"});function gp(n){return typeof n=="string"&&n.trim()?n.trim():null}function QMe(){return new DOMException("Provisioning was cancelled","AbortError")}function h8(n,r){let o=gp(n);return o?np(o.includes("://")?o:`https://${o}`):np(r)}function jh(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 Ra(n,r){return Object.freeze({code:n,message:r})}function yMe(n){return!n||typeof n!="object"||typeof n.code!="string"||!n.code||typeof n.reason!="string"||!n.reason||typeof n.message!="string"||!n.message||!Number.isFinite(n.at)?null:{code:n.code.slice(0,64),reason:n.reason.slice(0,128),message:n.message.slice(0,500),at:n.at}}function Jh(n,r){let o=new Error(`Weixin activation failed during ${n}`,{cause:r});return o.name="WeixinActivationStageError",o.code=n,o}function mMe(n){if(n instanceof it)return Ra(n.code,n.message);let r=u8[n?.code];return r?Ra(n.code,r):Ra("activation-unknown-failed","\u5FAE\u4FE1\u5DF2\u6388\u6743\uFF0C\u4F46\u6FC0\u6D3B\u8FC7\u7A0B\u4E2D\u53D1\u751F\u672A\u77E5\u9519\u8BEF\u3002\u8BF7\u67E5\u770B dsh web \u65E5\u5FD7\u3002")}function d8(n,r){return n instanceof it||u8[n?.code]?n:Jh(r,n)}var qh=class{#e;#A;#r;#t;#n;#o;#l=new Map;#s=new Map;#I=new Map;#a=null;#i=new Map;#c=0;#g=!1;constructor({api:r,credentials:o,configStore:i,createRuntime:e,deleteState:a=async()=>{},logger:A=console}){if(!r||typeof r.beginLogin!="function"||typeof r.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.#e=r,this.#A=o,this.#r=i,this.#t=e,this.#n=a,this.#o=A}async initialize(){if(this.#g)return this.status();for(let r of this.#r.list())this.#l.get(r.botId)?.status?.ready!==!0&&await this.#Q(r.botId,async()=>{let i=this.#r.get(r.botId);if(!(!i||this.#g))try{let e=await this.#d(i.tokenRef);if(!e){this.#s.set(i.botId,Ra("missing-token","\u767B\u5F55\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u8D26\u53F7\u540E\u91CD\u65B0\u626B\u7801\u3002"));return}await this.#C(i,e),this.#s.delete(i.botId)}catch(e){this.#s.set(i.botId,Ra("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002")),this.#o.warn?.(`[dsh-weixin] account ${i.botId} failed to initialize:`,e)}finally{this.#m()}});return this.status()}async startProvisioning(){if(this.#g)throw new Error("dsh-weixin controller is closed");this.#a&&await this.cancelProvisioning(this.#a);let r={id:fMe(),state:"starting",createdAt:Date.now(),expiresAt:Date.now()+C8,controller:new AbortController,pendingVerifyCode:null,verifyResolve:null,currentBaseUrl:Fy,error:null,botId:null,task:null};this.#I.set(r.id,r),this.#a=r.id,this.#m();try{let o=(await Promise.all(this.#r.list().slice(-10).map(async e=>this.#d(e.tokenRef)))).filter(Boolean),i=await this.#e.beginLogin({localTokens:o,signal:r.controller.signal});return this.#u(r),r.qrcode=i.qrcode,r.verificationUrl=i.qrcodeUrl,r.state="pending",r.expiresAt=Date.now()+C8,this.#m(),r.task=this.#p(r),jh(r)}catch(o){throw r.controller.signal.aborted?(r.state="cancelled",r.error=Ra("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(r.state="failed",r.error=Ra(o instanceof it?o.code:"qr-start-failed",o instanceof it?o.message:"\u65E0\u6CD5\u751F\u6210\u5FAE\u4FE1\u4E8C\u7EF4\u7801\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),this.#a===r.id&&(this.#a=null),this.#m(),o}}registrationStatus(r){return jh(this.#I.get(r))}async submitVerification(r,o){let i=this.#I.get(r);if(!i||i.state!=="needs_verification")throw new Error("The provisioning attempt is not waiting for a verification code");let e=gp(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.#m(),jh(i)}async cancelProvisioning(r){let o=this.#I.get(r);return o?(Yy.has(o.state)||(o.controller.abort(),o.verifyResolve?.(),o.verifyResolve=null,await o.task?.catch(()=>{}),Yy.has(o.state)||(o.state="cancelled"),o.error??=Ra("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")),this.#a===o.id&&(this.#a=null),this.#m(),jh(o)):null}async reconnectBot(r){let o=this.#r.get(r);if(!o)throw new Error("Unknown Weixin account");return await this.#Q(r,async()=>{let i=await this.#d(o.tokenRef);if(!i)throw new Error("The Weixin token is missing");try{await this.#C(o,i),this.#s.delete(r)}catch(e){throw this.#s.set(r,Ra("connection-failed","\u5FAE\u4FE1\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")),e}finally{this.#m()}}),this.status()}async sendConnectionTest(r){let o=this.#r.get(r);if(!o)throw new Error("Unknown Weixin account");return this.#Q(r,async()=>{let i=this.#l.get(r);if(!i?.status?.ready||typeof i.sendConnectionTest!="function")throw tr("\u5FAE\u4FE1\u673A\u5668\u4EBA");return i.sendConnectionTest(ga(`\u5FAE\u4FE1\u673A\u5668\u4EBA\uFF08${ok(o.accountId)}\uFF09`))})}async deleteBot(r){let o=this.#r.get(r);if(!o)throw new Error("Unknown Weixin account");return await this.#Q(r,async()=>{let i=await this.#A.resolve(o.tokenRef).catch(()=>{});await this.#E(r);try{await this.#A.unset(o.tokenRef),await this.#r.remove(r)}catch(e){throw i?.value&&(await this.#A.set(o.tokenRef,i.value).catch(()=>{}),await this.#C(o,i.value).catch(()=>{})),new Error("Unable to remove the Weixin account safely.",{cause:e})}try{await this.#n({botId:r,config:o})}catch(e){this.#o.warn?.(`[dsh-weixin] account ${r} state cleanup failed:`,e)}this.#s.delete(r),this.#m()}),this.status()}status(){let r=this.#r.list().map(e=>{let a=this.#l.get(e.botId)?.status??null,A=a?.ready===!0&&a.weixinConnectionState==="connected"&&a.harnessReachable===!0,t=A?"connected":a?.weixinConnectionState==="connecting"?"connecting":this.#s.has(e.botId)||a?.weixinConnectionState==="failed"?"error":"offline",s=this.#s.get(e.botId)??(t==="error"?Ra("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:ok(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:a?.lastCheckedAt??null},stats:{messagesReceived:a?.messagesReceived??0,messagesReplied:a?.messagesReplied??0},lastMessageError:yMe(a?.lastMessageError),error:s?structuredClone(s):null}}),o=r.filter(e=>e.connected).length,i=this.#a?this.#I.get(this.#a):null;return{schemaVersion:1,revision:this.#c,state:i&&E8.has(i.state)?"provisioning":r.length===0?"disconnected":o===r.length?"connected":o>0?"degraded":"offline",bots:r,totals:{configured:r.length,connected:o},...i&&E8.has(i.state)?{provisioning:jh(i)}:{}}}async close(){this.#g||(this.#g=!0,this.#a&&await this.cancelProvisioning(this.#a),await Promise.allSettled([...this.#l.keys()].map(r=>this.#E(r))))}async#p(r){try{for(;!r.controller.signal.aborted&&Date.now(){r.verifyResolve=i,r.controller.signal.aborted&&i()}),r.verifyResolve=null,this.#u(r));let o=await this.#e.pollLogin({qrcode:r.qrcode,baseUrl:r.currentBaseUrl,verifyCode:r.pendingVerifyCode,signal:r.controller.signal});if(this.#u(r),o.status==="wait")r.state="pending";else if(o.status==="scaned")r.pendingVerifyCode=null,r.state="scanned";else if(o.status==="need_verifycode")r.pendingVerifyCode=null,r.state="needs_verification";else if(o.status==="verify_code_blocked"){r.state="failed",r.error=Ra("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"){r.state="expired",r.error=Ra("expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002");break}else if(o.status==="scaned_but_redirect")r.currentBaseUrl=h8(o.redirect_host,r.currentBaseUrl),r.state="scanned";else if(o.status==="binded_redirect"){let i=this.#r.list().find(e=>this.#l.get(e.botId)?.status?.ready===!0)??this.#r.list()[0];i?(r.state="connected",r.botId=i.botId,r.alreadyConnected=!0):(r.state="failed",r.error=Ra("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=gp(o.bot_token),e=gp(o.ilink_bot_id),a=gp(o.ilink_user_id);if(!i||!e||!a)throw new it("incomplete-login","\u5FAE\u4FE1\u6388\u6743\u6210\u529F\uFF0C\u4F46\u8FD4\u56DE\u7684\u8D26\u53F7\u51ED\u636E\u4E0D\u5B8C\u6574\u3002");r.state="connecting",this.#m();let A=h8(o.baseurl,r.currentBaseUrl);r.botId=await this.#h(r,{token:i,accountId:e,ownerUserId:a,baseUrl:A}),r.state="connected",r.error=null;break}this.#m()}!r.controller.signal.aborted&&Date.now()>=r.expiresAt&&!Yy.has(r.state)&&(r.state="expired",r.error=Ra("expired","\u4E8C\u7EF4\u7801\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u751F\u6210\u3002"))}catch(o){r.controller.signal.aborted||o?.name==="AbortError"?(r.state="cancelled",r.error=Ra("cancelled","\u626B\u7801\u7ED1\u5B9A\u5DF2\u53D6\u6D88\u3002")):(r.state="failed",r.error=mMe(o),this.#o.error?.("[dsh-weixin] provisioning failed:",o))}finally{r.pendingVerifyCode=null,r.verifyResolve?.(),r.verifyResolve=null,this.#a===r.id&&(this.#a=null),this.#m(),this.#f()}}async#h(r,{token:o,accountId:i,ownerUserId:e,baseUrl:a}){let A=ik(i),t=this.#r.getByAccountId(i),s={botId:A.botId,accountId:i,tokenRef:A.tokenRef,ownerUserId:e,baseUrl:a,createdAt:t?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()},g;try{g=await this.#A.resolve(A.tokenRef)}catch(c){throw Jh("credential-read-failed",c)}return this.#Q(A.botId,async()=>{try{try{await this.#A.set(A.tokenRef,o)}catch(c){throw Jh("credential-save-failed",c)}this.#u(r);try{await this.#r.save(s)}catch(c){throw Jh("account-config-save-failed",c)}return this.#u(r),await this.#C(s,o),this.#u(r),this.#s.delete(A.botId),this.#m(),A.botId}catch(c){throw await this.#E(A.botId),t?await this.#r.save(t).catch(()=>{}):this.#r.get(A.botId)&&await this.#r.remove(A.botId).catch(()=>null)&&await this.#n({botId:A.botId,config:s}).catch(E=>{this.#o.warn?.("[dsh-weixin] failed to clean up cancelled bot state:",E)}),await this.#B(A.tokenRef,g),t&&g?.value&&await this.#C(t,g.value).catch(()=>{}),c}})}async#C(r,o){await this.#E(r.botId);let i;try{i=await this.#t({botId:r.botId,config:r,token:o})}catch(e){throw d8(e,"runtime-prepare-failed")}if(!i||typeof i.start!="function"||typeof i.stop!="function")throw Jh("runtime-prepare-failed",new TypeError("createRuntime returned an invalid Weixin runtime"));try{await i.start(),this.#l.set(r.botId,i)}catch(e){throw await i.stop().catch(()=>{}),d8(e,"connection-start-failed")}}async#E(r){let o=this.#l.get(r);this.#l.delete(r),await o?.stop().catch(i=>{this.#o.warn?.(`[dsh-weixin] account ${r} failed to stop cleanly:`,i)})}async#d(r){let o=await this.#A.resolve(r).catch(()=>{});return gp(o?.value)}async#B(r,o){try{o?.value?await this.#A.set(r,o.value):await this.#A.unset(r)}catch(i){this.#o.error?.(`[dsh-weixin] failed to restore credential ${r}:`,i)}}#u(r){if(r.controller.signal.aborted||this.#a!==r.id)throw QMe()}#Q(r,o){let a=(this.#i.get(r)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#i.get(r)===a&&this.#i.delete(r)});return this.#i.set(r,a),a}#f(){for(let[r,o]of this.#I)r!==this.#a&&Yy.has(o.state)&&this.#I.size>16&&this.#I.delete(r)}#m(){this.#c+=1}};var xy="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002",jy="\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",SMe=["\u5FAE\u4FE1\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002","","\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u3001\u56FE\u7247\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","/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587","/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 \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD","/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B","/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B","\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2","/presetlist \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset","/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset","\u7EAF\u6570\u5B57 ID\uFF1A/preset id:","/preset --default \u8DDF\u968F Host \u9ED8\u8BA4","/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1","/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1","/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 4b646ba..2c83b62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@xmanrui/dsh-im", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@xmanrui/dsh-im", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "dependencies": { "@tencent-connect/qqbot-connector": "1.2.0", diff --git a/package.json b/package.json index 056c683..1ad449c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@xmanrui/dsh-im", - "version": "1.0.0", + "version": "1.0.1", "description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.", "keywords": [ "deepseek-harness", diff --git a/src/channels/discord/discord-api.mjs b/src/channels/discord/discord-api.mjs index 440cb0a..f102e51 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, 1.0.0)', + 'user-agent': 'DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.0.1)', }, ...(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 ee9be52..72b248b 100644 --- a/src/channels/weixin/weixin-api.mjs +++ b/src/channels/weixin/weixin-api.mjs @@ -184,7 +184,7 @@ function authenticatedHeaders(token) { function baseInfo() { return { channel_version: WEIXIN_PROTOCOL_VERSION, - bot_agent: 'DeepSeekHarness/1.0.0', + bot_agent: 'DeepSeekHarness/1.0.1', }; } diff --git a/test/channels/weixin/weixin-api.test.mjs b/test/channels/weixin/weixin-api.test.mjs index fd3d873..3d423c7 100644 --- a/test/channels/weixin/weixin-api.test.mjs +++ b/test/channels/weixin/weixin-api.test.mjs @@ -167,7 +167,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/1.0.0'); + assert.equal(body.base_info.bot_agent, 'DeepSeekHarness/1.0.1'); assert.doesNotMatch(calls[0].init.body, /host-only-token/); });