From 03565e5a69bfd03dc246990c3376fbd794caea6e Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Thu, 27 Aug 2026 19:40:50 +0800 Subject: [PATCH] fix(commands): send empty images list to the commands Typert endpoint The Harness commands execute descriptor declares agentId, line, and images as required JSON wire fields (strict codec, no acceptsUndefined). The Host command executor only sent agentId and line, so the Typert gateway rejected every IM /compact call with arguments-invalid before the command could run. Send images: [] so /compact works from every IM channel. --- lib/index.js | 2 +- plugin-src/host/harness-command-executor.mjs | 6 +++++- test/compact-command.test.mjs | 5 ++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/index.js b/lib/index.js index bfae34e..c5a31b9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -211,7 +211,7 @@ ${N}`:J;y&&await Q.finish(H)||await this.#O(g,H)}catch{this.#c.error?.("[dsh-din `).trim()}function pi(n){return typeof n=="string"&&n.trim()?n.trim():null}function lpe(n){if(!n||typeof n!="object")return null;let t=pi(n.message);if(t)return t;let o=pi(n.name),i=pi(n.code);return o||i?[o??"Error",i].filter(Boolean).join(": "):null}function ppe(n,t){let o=[...t].map(i=>i?.event??i).filter(Boolean).sort((i,e)=>(i.seq??-1)-(e.seq??-1));for(let i of o){let e=i.seq??-1;if(e<=n.lastSeq)continue;if(n.lastSeq=e,i.type==="turn/start"){let A=i.data?.turn??null;n.active&&A!==n.turn&&(n.active=!1),n.turn!==null&&A!==n.turn&&(n.completed=!0),n.openTurn=A;continue}if(i.type==="user/message"&&i.data?.source?.rpcId===n.promptRpcId){n.active=!0,n.started=!0,n.completed=!1,n.turn=i.data?.turn??n.openTurn;continue}if(i.type==="turn/end"&&i.data?.turn===n.turn){n.active=!1,n.completed=!0;continue}let a=null;if(i.type==="tool/call"&&n.active&&i.data?.turn===n.turn&&typeof i.data?.callId=="string"&&i.data.callId)a={callId:i.data.callId,name:i.data?.name,arguments:i.data?.arguments};else if(i.type==="tool/code-dispatch-start"&&n.active&&typeof i.data?.subCallId=="string"&&i.data.subCallId){let A;try{A=JSON.stringify(i.data?.arguments)}catch{A=void 0}a={callId:i.data.subCallId,name:i.data?.name,arguments:A}}a&&n.toolCalls.set(a.callId,Object.freeze(a))}}var jl=class{#e;#A;#t=null;#r=null;#a=new Map;#i="";#c=!1;#s=null;#I=new Map;#o=null;constructor({promptRpcId:t,afterSeq:o=-1}){this.#e=t,this.#A=o}get finished(){return this.#c}get answer(){return this.#i.trim()}get reason(){return this.#s}get tracking(){return this.#r!==null&&!this.#c}get turn(){return this.#r}consumeAll(t){let o=[],i=a=>{if(a.type==="text"&&o.length>0&&o[o.length-1].type==="text"){o[o.length-1]=a;return}o.push(a)},e=[...t].map(a=>a?.event??a).filter(Boolean).sort((a,A)=>(a.seq??-1)-(A.seq??-1));for(let a of e){let A=a.seq??-1;if(!(A<=this.#A)){if(this.#A=A,a.type==="turn/start"&&(this.#t=a.data?.turn??null),a.type==="user/message"&&a.data?.source?.rpcId===this.#e){this.#r=this.#t;continue}if(this.#r!==null){if(a.type==="turn/end"){if(a.data?.turn!==this.#r)continue;this.#c=!0,this.#s=a.data?.reason??null,this.#t=null;continue}if(a.data?.turn===this.#r){if(a.type==="assistant/chunk"&&a.data?.chunk?.type==="text-delta"){let r=a.data?.step??0,s=a.data.chunk.index??0,g=`${r}:${s}`;this.#a.set(g,(this.#a.get(g)??"")+a.data.chunk.text);let c=`${r}:`,I=[...this.#a.entries()].filter(([d])=>d.startsWith(c)).sort(([d],[B])=>Number(d.split(":")[1])-Number(B.split(":")[1])).map(([,d])=>d).join(` `).trim();I&&I!==this.#i&&(this.#i=I,i({type:"text",text:I}));continue}if(a.type==="assistant/message"){let r=Ipe(a);r&&r!==this.#i&&(this.#i=r,i({type:"text",text:r}));continue}if(a.type==="tool/call"){let r=pi(a.data?.name)??D("\u5DE5\u5177"),s=pi(a.data?.callId)??pi(a.data?.subCallId);s&&this.#I.set(s,r),this.#o=r,i({type:"tool",name:r,...s?{callId:s}:{}})}else if(a.type==="tool/result"){let r=pi(a.data?.message?.source?.callId)??pi(a.data?.callId)??pi(a.data?.subCallId),s=(r?this.#I.get(r):null)??this.#o,g=lpe(a.data?.error);i({type:"status",text:D("\u6B63\u5728\u6574\u7406\u7ED3\u679C\u2026"),...s?{toolName:s}:{},...g?{error:g}:{}})}}}}}return o}consume(t){return this.consumeAll(t).at(-1)??null}},Xo=class extends Error{constructor(t,o){super(`${t}: ${o?.message??"unknown Harness RPC error"}`),this.name="HarnessRpcError",this.method=t,this.code=o?.code??"internal",this.details=o?.details??{}}},kg=class extends Error{constructor(t,o,{cause:i,status:e}={}){let a=Number.isInteger(e)?`, HTTP ${e}`:"";super(`Harness ${o} transport failed (${t}${a})`,{cause:i}),this.name="HarnessTransportError",this.code=t,this.method=o,Number.isInteger(e)&&(this.status=e)}},IM=class extends Error{constructor(t){super("Harness health RPC was rejected",{cause:t}),this.name="HarnessHealthError",this.code="harness-rpc-rejected",this.method="host.describe"}},Jl=class extends Error{constructor(t,o){super(o),this.name="HarnessInteractionError",this.code=t}},kn=class extends Error{constructor(t,{reason:o,providerCode:i}={}){super(`Harness turn failed (${t})`),this.name="HarnessTurnError",this.code=t,this.promptAccepted=!0,o&&typeof o=="object"&&(this.reason=o),typeof i=="string"&&i&&(this.providerCode=i)}};function Ax(n){let t=pi(n?.kind)??pi(n);if(t==="error"){let o=n?.error??n?.failure;return new kn("harness-turn-failed",{reason:n,providerCode:pi(o?.code)??void 0})}return t==="max-tokens"?new kn("model-max-tokens",{reason:n}):t==="blocked"?new kn("turn-blocked",{reason:n}):["interrupted","stopped","cancelled","canceled"].includes(t)?new kn("turn-interrupted",{reason:n}):t==="aborted"?new kn("turn-aborted",{reason:n}):t==="completed"?new kn("model-empty-response",{reason:n}):new kn("harness-turn-failed",{reason:n})}function dpe(n){return n==null?!0:(pi(n?.kind)??pi(n))==="completed"}var lr=class{#e;#A;#t;#r;#a;#i;#c;#s;#I;#o;#n;#g;#l;#p;#d=null;#h;#E;#u;#B;constructor({baseUrl:t,workspace:o,agentPreset:i,autostart:e=!1,dshBin:a="dsh",fetchImpl:A=fetch,createWebSocket:r=Q=>new WebSocket(Q),interactionReconnectDelayMs:s=500,rpcIdPrefix:g="im",logPrefix:c="dsh-im",commandExecutor:I,controlExecutor:d,sessionMaintenanceExecutor:B,fileIngressExecutor:f}){if(typeof r!="function")throw new TypeError("createWebSocket must be a function");if(!Number.isFinite(s)||s<0)throw new TypeError("interactionReconnectDelayMs must be a non-negative number");if(typeof g!="string"||!g.trim())throw new TypeError("rpcIdPrefix must be a non-empty string");if(typeof c!="string"||!c.trim())throw new TypeError("logPrefix must be a non-empty string");if(I!==void 0&&typeof I!="function")throw new TypeError("commandExecutor must be a function");if(d!==void 0&&typeof d!="function")throw new TypeError("controlExecutor must be a function");if(B!==void 0&&typeof B!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(f!==void 0&&typeof f!="function")throw new TypeError("fileIngressExecutor must be a function");this.#e=new URL(t),this.#A=o,this.#t=i??void 0,this.#r=e,this.#a=a,this.#i=A,this.#c=r,this.#s=s,this.#I=g.trim(),this.#o=c.trim(),this.#n=I,this.#g=d,this.#l=B,this.#p=f,this.#h=ape(this.#e.origin),this.#E=this.#h.ownerships,this.#u=this.#h.claims,this.#B=this.#h.controls}async rpc(t,o={},i=3e4,e={}){let a=e.rpcId??`${this.#I}-${WK()}`,A=AbortSignal.timeout(i),r=e.signal?AbortSignal.any([e.signal,A]):A,s;try{s=await this.#i(new URL(`/api/${t}`,this.#e),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-request",rpcId:a,method:t,payload:o}),signal:r})}catch(c){throw e.signal?.aborted?c:new kg(A.aborted?"harness-timeout":"harness-connect-failed",t,{cause:c})}if(!s.ok){let c=await rpe(s,this.#e.hostname);throw new kg(c,t,{status:s.status})}let g;try{g=await s.json()}catch(c){throw new kg("harness-response-invalid",t,{cause:c})}if(g?.type!=="server-response"||g?.rpcId!==a)throw new kg("harness-response-invalid",t,{cause:new Error(`Harness returned an invalid response for ${t}`)});if(!g.result||typeof g.result!="object"||typeof g.result.ok!="boolean")throw new kg("harness-response-invalid",t,{cause:new Error(`Harness returned an invalid result for ${t}`)});if(!g.result?.ok)throw new Xo(t,g.result?.error);return g.result.value}async health(t={}){try{return await this.rpc("host.describe",{},5e3,t),!0}catch(o){throw o instanceof Xo?new IM(o):o}}async ensureRunning(t={}){try{return await this.health(t)}catch(e){if(!this.#r)throw e}if(!this.#d||this.#d.exitCode!==null){let e=this.#e.port||(this.#e.protocol==="https:"?"443":"80");this.#d=Xle(this.#a,["web","--host",this.#e.hostname,"--port",e],{cwd:this.#A,env:process.env,stdio:["ignore","inherit","inherit"]}),this.#d.on("error",a=>{console.error(`[${this.#o}] failed to start Harness:`,a.message)})}let o=Date.now()+6e4,i;for(;Date.now(){let r=A&&i.signal?AbortSignal.any([A,i.signal]):A??i.signal;return this.rpc("session.selectModel",{sessionId:t,provider:o.provider,model:o.model,...o.reasoningEffort===void 0?{}:{reasoningEffort:o.reasoningEffort}},3e4,r?{...i,signal:r}:i)},a=this.#l?await this.#l({sessionId:t,operation:e}):await e();if(!a||typeof a!="object"||!cM(a.selected))throw new Error("Harness returned an invalid response for session.selectModel");return a}async isSessionRunning(t,o={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");await this.ensureRunning(o);let i=await this.rpc("session.list",{},3e4,o);if(!i||typeof i!="object"||!Array.isArray(i.items))throw new Error("Harness returned an invalid response for session.list");for(let e of i.items)if(!e||typeof e!="object"||typeof e.sessionId!="string"||!e.sessionId||typeof e.running!="boolean")throw new Error("Harness returned an invalid response for session.list");return i.items.find(e=>e.sessionId===t)?.running??!1}async adoptWorkspaceSession(t,o={}){return VK(this,t,o)}async workspaceId(t={}){let{workspace:o=this.#A,...i}=t,{items:e}=await this.rpc("workspace.list",{},3e4,i),a=e.find(r=>r.path===o);return a?a.workspaceId:(await this.rpc("workspace.create",{path:o},3e4,i)).workspace.workspaceId}async createSession(t={}){let{agentPreset:o,...i}=t;await this.ensureRunning(i);let a={workspaceId:await this.workspaceId(i)},A=o!==void 0?o:this.#t;return A!=null&&(a.agentPreset=A),(await this.rpc("session.create",a,3e4,i)).sessionId}async executeCommand(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(typeof o!="string"||!o)throw new TypeError("command line is required");if(!this.#n){let e=new Error("Harness command execution is unavailable");throw e.code="commands-unavailable",e}try{return await this.#n(t,o,i)}catch(e){throw e?.failure&&typeof e.failure=="object"?new Xo("commands.execute",e.failure):e}}async sessionExists(t,o={}){try{return await this.rpc("session.history",{sessionId:t,maxMessages:1},3e4,o),!0}catch(i){if(i instanceof Xo&&i.code==="session-not-found")return!1;throw i}}async respondInteraction(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("rpcId is required");if(!o||typeof o!="object"||typeof o.ok!="boolean")throw new TypeError("A Harness RPC result is required");let e=AbortSignal.timeout(i.timeoutMs??3e4),a=i.signal?AbortSignal.any([i.signal,e]):e,A=await this.#i(new URL("/api/respond",this.#e),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({type:"client-response",rpcId:t,result:o}),signal:a});if(!A.ok)throw new Error(`Harness transport respond failed: HTTP ${A.status}`);let r=await A.json();if(r?.accepted===!0)return r;if(r?.accepted!==!1||r.reason!=="bad-response"&&r.reason!=="not-pending")throw new Error("Harness returned an invalid interaction response receipt");let s=r.reason;throw new Jl(`interaction-${s}`,`Harness interaction response was rejected (${s})`)}async watchInteractions(t,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A}={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(!o||typeof o.addEventListener!="function")throw new TypeError("watchInteractions requires an AbortSignal");if(i!==void 0&&typeof i!="function")throw new TypeError("onInteraction must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("onResolved must be a function");if(a!==void 0&&typeof a!="function")throw new TypeError("onOpen must be a function");for(;!o.aborted;){try{await this.#R(t,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A})}catch(r){if(o.aborted)return;console.warn(`[${this.#o}] Harness interaction stream disconnected:`,r.message)}if(o.aborted)return;try{await eE(this.#s,o)}catch{if(o.aborted)return;throw new Error("Harness interaction reconnect wait failed")}}}#f(t,o){let i=this.#E.get(t)??new Set;o.order=this.#h.nextOrder,this.#h.nextOrder+=1,i.add(o),this.#E.set(t,i)}#m(t,o){let i=this.#E.get(t);i?.delete(o),i?.size===0&&this.#E.delete(t);for(let[e,a]of this.#u)a.ownership===o&&this.#u.delete(e)}#y(t){if(!t.control)return;let o=this.#B.get(t.control.owner);o||(o=new Map,this.#B.set(t.control.owner,o));let i=o.get(t.control.key)??new Set;i.add(t),o.set(t.control.key,i)}#Q(t){if(!t.control)return;let o=this.#B.get(t.control.owner),i=o?.get(t.control.key);i?.delete(t),i?.size===0&&o.delete(t.control.key),o?.size===0&&this.#B.delete(t.control.owner)}#C(t,o){let i=XK(o);return i?[...this.#B.get(i.owner)?.get(i.key)??[]].filter(a=>a.sessionId===t).sort((a,A)=>a.order-A.order):[]}#b(t,o){return this.#C(t,o).find(i=>i.started&&i.active&&!i.completed&&i.turn!==null)??null}async#M(t,o,i){let e=this.#C(t,o);if(e.length===0)return null;try{let a=await this.rpc("session.history",{sessionId:t,maxMessages:50},3e4,i);this.#w(t,a.events??[])}catch(a){if(!(a instanceof Xo)||a.code!=="session-not-found")throw a;for(let A of e)A.active=!1,A.completed=!0;return null}return this.#b(t,o)}async hasActiveTurn(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");return!!await this.#M(t,o,i)}async stopActiveTurn(t,o,i={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");let e=await this.#M(t,o,i);if(!e)return!1;if(e.stopRequested)return!0;if(this.#b(t,o)!==e)return!1;e.stopRequested=!0;try{if(this.#g){let a=this.#g({sessionId:t,expectedTurn:e.turn,promptRpcId:e.promptRpcId,action:"stop"});if(a&&typeof a.then=="function")throw new TypeError("controlExecutor must return synchronously");if(a!==void 0){if(typeof a!="boolean")throw new TypeError("controlExecutor must return a boolean or undefined");return a||(e.stopRequested=!1),a}}return await this.rpc("session.cancel",{sessionId:t,keepInbox:!0},3e4,i),!0}catch(a){if(this.#b(t,o)===e&&(e.stopRequested=!1),a instanceof Xo&&a.code==="session-not-found")return!1;throw a}}async steerActiveTurn(t,o,i,e={}){if(typeof t!="string"||!t)throw new TypeError("sessionId is required");if(typeof o!="string"||!o.trim())throw new TypeError("Steering text is required");let a=await this.#M(t,i,e);if(!a||a.stopRequested||this.#b(t,i)!==a)return!1;if(this.#g){let A=this.#g({sessionId:t,expectedTurn:a.turn,promptRpcId:a.promptRpcId,action:"steer",text:o});if(A&&typeof A.then=="function")throw new TypeError("controlExecutor must return synchronously");if(A!==void 0){if(typeof A!="boolean")throw new TypeError("controlExecutor must return a boolean or undefined");return A}}return await this.rpc("session.prompt",{sessionId:t,mode:"steer",content:[{type:"text",text:o}],clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,e),!0}#w(t,o){for(let i of this.#E.get(t)??[])ppe(i,o)}async#S(t,o){let i=await this.rpc("session.history",{sessionId:t,maxMessages:50},3e4,{signal:o});this.#w(t,i.events??[])}#_(t,o,i){let e=this.#u.get(o);if(e&&this.#E.get(t)?.has(e.ownership))return e;let a=[...this.#E.get(t)??[]],A=a.filter(s=>s.active).sort((s,g)=>s.order-g.order);if(A.length>0)return{ownership:A[0],recovered:!1};let r=a.filter(s=>!s.started&&!s.completed).sort((s,g)=>s.order-g.order)[0]??null;return r?{ownership:r,recovered:!0}:null}async ask(t,o,i={}){typeof i=="number"&&(i={timeoutMs:i});let e=i.timeoutMs??6e5,a=i.signal,A=typeof i.onUpdate=="function"?i.onUpdate:null,r=i.progressMode==="all"?"all":"latest",s=typeof i.onArtifact=="function"?i.onArtifact:null,g=typeof i.onInteraction=="function"?i.onInteraction:void 0,c=typeof i.onInteractionResolved=="function"?i.onInteractionResolved:void 0,I=XK(i.control),d=Array.isArray(i.files)?i.files.filter(Boolean):[];await this.ensureRunning({signal:a});let B=await this.rpc("session.history",{sessionId:t,maxMessages:1},3e4,{signal:a}),f=Math.max(-1,...(B.events??[]).map(({event:V})=>V.seq??-1)),Q=`${this.#I}-${WK()}`,y=new jl({promptRpcId:Q,afterSeq:f}),m=g||c?new AbortController:null,_=m?a?AbortSignal.any([a,m.signal]):m.signal:null,N=m||I?{sessionId:t,promptRpcId:Q,active:!1,started:!1,completed:!1,stopRequested:!1,turn:null,openTurn:null,lastSeq:f,reconnect:null,order:-1,toolCalls:new Map,control:I}:null,G=null,Y=!1,J=0,H=null,j=!1,q=!1,U=async()=>{if(!s||Y||y.turn===null)return J;Y=!0;let V=$c.take(t,y.turn,{signal:a});for(let L of V)try{await s(L),J+=1}catch(T){$c.release(L),console.warn(`[${this.#o}] ignored an artifact handoff failure:`,T.message)}return J};N&&(this.#f(t,N),this.#y(N));let R=$c.openConsumer(t,Q);try{if(d.length>0){if(!this.#p)throw new ho("inbound-file-ingress-unavailable","Harness file ingress is unavailable in this Host process.");let T=(await this.rpc("session.list",{},3e4,{signal:a}))?.items?.find(P=>P?.sessionId===t)?.cwd;H=await this.#p({sessionId:t,workspace:T,files:d,signal:a}),o=_K(o,H)}if(_){let L,T=new Promise(P=>{L=P});G=this.watchInteractions(t,{signal:_,onInteraction:g,onResolved:c,onOpen:L,ownership:N}),G.catch(()=>{}),await Promise.race([T,eE(3e4,_).then(()=>{throw new Error("Harness interaction stream did not open within 30 seconds")})])}let V=typeof o=="string"?[{type:"text",text:o}]:o;if(!Array.isArray(V)||V.length===0)throw new TypeError("Harness prompt content is required");await this.rpc("session.prompt",{sessionId:t,mode:"queue",content:V,clientTimeZone:Intl.DateTimeFormat().resolvedOptions().timeZone},3e4,{rpcId:Q,signal:a}),j=!0;try{let L=Date.now()+e;for(;Date.now()0)return"";throw N?.stopRequested?ex():Ax(y.reason)}throw new kn("harness-reply-timeout")}catch(L){if(!N?.stopRequested)throw L;if(y.answer)return y.answer;throw L?.code==="turn-stopped"?L:ex()}}finally{H&&(!j||q)&&await H.cleanup().catch(V=>{console.warn(`[${this.#o}] unable to clean inbound files:`,V.message)}),R(),N&&(this.#Q(N),this.#m(t,N)),y.turn!==null&&$c.discard(t,y.turn),m?.abort(new DOMException("Harness turn finished","AbortError")),G&&await G.catch(()=>{})}}#R(t,{signal:o,onInteraction:i,onResolved:e,onOpen:a,ownership:A}){let r=new URL("/api/events.mux",this.#e);return r.protocol=r.protocol==="https:"?"wss:":"ws:",new Promise((s,g)=>{let c;try{c=this.#c(r.toString())}catch(U){g(U);return}let I=!1,d=!1,B=null,f=Promise.resolve(),Q=A==null,y=[],m=U=>{if(!d){if(d=!0,c.removeEventListener("open",N),c.removeEventListener("message",J),c.removeEventListener("close",H),c.removeEventListener("error",j),o.removeEventListener("abort",q),A?.reconnect===_&&(A.reconnect=null),o.aborted){s();return}f.then(()=>{let R=U??B;R?g(R):s()},g)}},_=()=>{try{(c.readyState===0||c.readyState===1)&&c.close()}catch{}},N=()=>{I=!0,A&&(A.reconnect=_);try{a?.()}catch(U){console.warn(`[${this.#o}] ignored an interaction open callback failure:`,U.message)}A&&this.#S(t,o).then(()=>{if(!d){Q=!0;for(let U of y.splice(0))Y(U)}}).catch(U=>{B??=U,_(),m(U)})},G=(U,R)=>{U&&(f=f.then(()=>U(R)).catch(V=>{B??=V,_(),m(B)}))},Y=U=>{let R=U.payload;if(A&&R.type==="session/event"){this.#w(t,[R.event]);return}if(R.type==="question/requested"||R.type==="approval/requested"){let V=R.type==="question/requested"?"question":"approval",L=V==="question"?U.rpcId:R.approvalId,T=`${V}:${L}`;if(A){let W=this.#_(t,T,V);if(W?.ownership!==A)return;this.#u.set(T,W)}let P=V==="approval"&&A&&typeof R.callId=="string"?this.#u.get(T)?.ownership.toolCalls.get(R.callId):void 0;G(i,Object.freeze({kind:V,interactionId:L,rpcId:U.rpcId,sessionId:t,payload:R,recovered:A?this.#u.get(T)?.recovered===!0:!1,...P?{toolCall:P}:{},reconnect:_,respond:(W,ae={})=>this.respondInteraction(U.rpcId,W,{...ae,signal:ae.signal??o})}));return}if(R.type==="question/resolved"||R.type==="approval/resolved"){let V=R.type==="question/resolved"?"question":"approval",L=V==="question"?R.questionRpcId:R.approvalId,T=`${V}:${L}`;if(A){if(this.#u.get(T)?.ownership!==A)return;this.#u.delete(T)}G(e,Object.freeze({kind:V,interactionId:L,sessionId:t,outcome:R.outcome,payload:R}))}},J=U=>{try{if(typeof U.data!="string")throw new Error("binary WebSocket frame");let R=JSON.parse(U.data),V=R?.payload;if(R?.type!=="server-request"||typeof R.rpcId!="string"||!V||typeof V!="object"||R.method!==V.type)throw new Error("invalid server-request envelope");if(V.sessionId!==t)return;Q?Y(R):y.push(R)}catch(R){console.warn(`[${this.#o}] ignored a malformed Harness interaction frame:`,R.message)}},H=()=>m(I?null:new Error("Harness interaction WebSocket closed before opening")),j=()=>{m(new Error(I?"Harness interaction WebSocket failed":"Harness interaction WebSocket failed before opening")),_()},q=()=>{_(),m()};c.addEventListener("open",N),c.addEventListener("message",J),c.addEventListener("close",H,{once:!0}),c.addEventListener("error",j,{once:!0}),o.addEventListener("abort",q,{once:!0}),o.aborted&&q()})}async watchHarnessEvents({signal:t,onSessionEvent:o,onReconnect:i}={}){if(typeof o!="function")throw new TypeError("watchHarnessEvents requires onSessionEvent");if(!t||typeof t.addEventListener!="function")throw new TypeError("watchHarnessEvents requires an AbortSignal");if(i!==void 0&&typeof i!="function")throw new TypeError("onReconnect must be a function");let e=new URL("/api/events.mux",this.#e);for(e.protocol=e.protocol==="https:"?"wss:":"ws:";!t.aborted;){try{await this.#k(e.toString(),{signal:t,onSessionEvent:o,onReconnect:i})}catch(a){if(t.aborted)return;console.warn(`[${this.#o}] Harness event mux disconnected:`,a.message)}if(t.aborted)return;try{await eE(this.#s,t)}catch{if(t.aborted)return;throw new Error("Harness event mux reconnect wait failed")}}}#k(t,{signal:o,onSessionEvent:i,onReconnect:e}){return new Promise((a,A)=>{let r;try{r=this.#c(t)}catch(m){A(m);return}let s=!1,g=!1,c=()=>{try{r.close()}catch{}},I=m=>{g||(g=!0,r.removeEventListener("open",d),r.removeEventListener("message",B),r.removeEventListener("close",f),r.removeEventListener("error",Q),o.removeEventListener("abort",y),m?A(m):a())},d=()=>{s=!0;try{e?.()}catch(m){console.warn(`[${this.#o}] mux reconnect hook failed:`,m.message)}},B=m=>{try{if(typeof m.data!="string")return;let _=JSON.parse(m.data),N=_?.payload;if(_?.type!=="server-request"||!N||typeof N!="object"||_.method!==N.type||N.type!=="session/event"||typeof N.sessionId!="string"||!N.event||typeof N.event!="object")return;i({sessionId:N.sessionId,event:N.event})}catch(_){console.warn(`[${this.#o}] ignored a malformed global mux frame:`,_.message)}},f=()=>I(s?null:new Error("Harness event mux WebSocket closed before opening")),Q=()=>{I(new Error(s?"Harness event mux WebSocket failed":"Harness event mux WebSocket failed before opening")),c()},y=()=>{c(),I()};r.addEventListener("open",d),r.addEventListener("message",B),r.addEventListener("close",f,{once:!0}),r.addEventListener("error",Q,{once:!0}),o.addEventListener("abort",y,{once:!0}),o.aborted&&y()})}stopManagedProcess(){this.#d?.exitCode===null&&this.#d.kill("SIGTERM")}};var wf=class extends lr{constructor(t){super({...t,rpcIdPrefix:"dingtalk",logPrefix:"dsh-dingtalk"})}};import{randomUUID as hpe}from"node:crypto";import{mkdir as Epe,readFile as Cpe,rename as upe,unlink as Bpe,writeFile as fpe}from"node:fs/promises";import{dirname as Qpe}from"node:path";var Of=Object.freeze({version:1,sessions:{},seenMessageIds:[],pendingSenders:{}});function pr(n){return typeof n=="string"&&n.trim()?n.trim():null}function tx(n){return(pr(n)??D("\u9489\u9489\u7528\u6237")).slice(0,100)}function ype(n,t){if(!n||typeof n!="object")return null;let o=pr(n.requestId)??pr(t),i=pr(n.staffId),e=pr(n.requestedAt)??pr(n.lastSeenAt),a=pr(n.lastSeenAt)??e;return!o||!i||!e||!a?null:{requestId:o,staffId:i,displayName:tx(n.displayName??n.nick),requestedAt:e,lastSeenAt:a}}function mpe(n){if(!n||typeof n!="object")return structuredClone(Of);let t={};if(n.sessions&&typeof n.sessions=="object"&&!Array.isArray(n.sessions))for(let[e,a]of Object.entries(n.sessions)){let A=pr(e),r=pr(a);A&&r&&(t[A]=r)}let o={},i=Array.isArray(n.pendingSenders)?n.pendingSenders.map(e=>[e?.requestId,e]):Object.entries(n.pendingSenders&&typeof n.pendingSenders=="object"?n.pendingSenders:{});for(let[e,a]of i){let A=ype(a,e);if(!A)continue;let r=Object.values(o).find(s=>s.staffId===A.staffId);(!r||r.lastSeenAtnew Date().toISOString()}={}){if(!pr(t))throw new TypeError("state path is required");if(typeof o!="function"||typeof i!="function")throw new TypeError("idFactory and now must be functions");this.#e=t,this.#r=o,this.#a=i}async load(){try{this.#A=mpe(JSON.parse(await Cpe(this.#e,"utf8")))}catch(t){if(t?.code!=="ENOENT")throw t;this.#A=structuredClone(Of),await this.#i()}return this}sessionFor(t){return this.#A.sessions[t]??null}async setSession(t,o){let i=pr(t),e=pr(o);if(!i||!e)throw new TypeError("key and sessionId are required");this.#A.sessions[i]=e,await this.#i()}async clearSession(t){let o=pr(t);!o||!(o in this.#A.sessions)||(delete this.#A.sessions[o],await this.#i())}async clearSessions(){this.#A.sessions={},await this.#i()}hasSeen(t){let o=pr(t);return!!(o&&this.#A.seenMessageIds.includes(o))}async markSeen(t){let o=pr(t);if(!o)throw new TypeError("messageId is required");this.hasSeen(o)||(this.#A.seenMessageIds.push(o),this.#A.seenMessageIds.length>1e3&&this.#A.seenMessageIds.splice(0,this.#A.seenMessageIds.length-1e3),await this.#i())}pendingSenders(){return Object.values(this.#A.pendingSenders).sort((t,o)=>t.requestedAt.localeCompare(o.requestedAt)).map(t=>structuredClone(t))}pendingSender(t){let o=pr(t),i=o?this.#A.pendingSenders[o]:null;return i?structuredClone(i):null}async recordPendingSender(t,o,i){let e=t&&typeof t=="object"?t:{staffId:t,displayName:o,lastSeenAt:i},a=pr(e.staffId);if(!a)throw new TypeError("staffId is required");let A=pr(e.lastSeenAt)??pr(e.requestedAt)??this.#a(),r=Object.values(this.#A.pendingSenders).find(g=>g.staffId===a),s={requestId:r?.requestId??`ding_sender_${this.#r()}`,staffId:a,displayName:tx(e.displayName??e.nick??o),requestedAt:r?.requestedAt??A,lastSeenAt:A};return this.#A.pendingSenders[s.requestId]=s,await this.#i(),structuredClone(s)}async removePendingSender(t){let o=pr(t);return!o||!this.#A.pendingSenders[o]?!1:(delete this.#A.pendingSenders[o],await this.#i(),!0)}async removePendingSenderByStaffId(t){let o=pr(t),i=o?Object.values(this.#A.pendingSenders).find(e=>e.staffId===o):null;return i?this.removePendingSender(i.requestId):!1}snapshot(){return structuredClone(this.#A)}async remove(){await this.#t;try{await Bpe(this.#e)}catch(t){if(t?.code!=="ENOENT")throw t}this.#A=structuredClone(Of)}async#i(){let t=`${JSON.stringify(this.#A,null,2)} `,o=this.#t.then(async()=>{await Epe(Qpe(this.#e),{recursive:!0,mode:448});let i=`${this.#e}.tmp`;await fpe(i,t,{encoding:"utf8",mode:384}),await upe(i,this.#e)});this.#t=o.then(()=>{},()=>{}),await o}};import{mkdir as Spe,readFile as Dpe,realpath as wpe,rename as Ope,stat as bpe,unlink as Mpe,writeFile as _pe}from"node:fs/promises";import{dirname as Tpe,isAbsolute as ix,resolve as AE}from"node:path";var b5e=Object.freeze({version:1,workspaces:Object.freeze({})});function eI(n){let t=new Error(n);return t.code=oi,t}async function lM(n){return AE(await wpe(n))}async function Npe(n,t){if(n===t)return!0;try{return await lM(n)===await lM(t)}catch{return!1}}function di(n){if(typeof n!="string"||!/^[A-Za-z0-9_-]{1,128}$/.test(n))throw new TypeError("Invalid bot id");return n}function Rpe(n){if(!n||n.version!==1||!n.workspaces||typeof n.workspaces!="object"||Array.isArray(n.workspaces))return null;let t={};for(let[i,e]of Object.entries(n.workspaces)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(i)||typeof e!="string"||!ix(e))return null;t[i]=AE(e)}let o={};if(n.agentPresets!==void 0){if(!n.agentPresets||typeof n.agentPresets!="object"||Array.isArray(n.agentPresets))return null;for(let[i,e]of Object.entries(n.agentPresets)){if(!/^[A-Za-z0-9_-]{1,128}$/.test(i))return null;try{let a=Kl(e);if(!a)return null;o[i]=a}catch{return null}}}return{version:1,workspaces:t,agentPresets:o}}async function rx(n){if(typeof n!="string"||!n.trim()||!ix(n.trim())){let i=new Error("\u5DE5\u4F5C\u533A\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");throw i.code="workspace-not-absolute",i}let t=AE(n.trim()),o;try{o=await bpe(t)}catch(i){let e=new Error("\u5DE5\u4F5C\u533A\u8DEF\u5F84\u4E0D\u5B58\u5728\u3002",{cause:i});throw e.code="workspace-not-found",e}if(!o.isDirectory()){let i=new Error("\u5DE5\u4F5C\u533A\u8DEF\u5F84\u5FC5\u987B\u6307\u5411\u4E00\u4E2A\u76EE\u5F55\u3002");throw i.code="workspace-not-directory",i}return t}var Zr=class{#e;#A;#t={};#r={};#a=new Map;#i=1;#c=new Map;#s=1;#I=new Map;#o=new WeakMap;#n=new Set;#g=Promise.resolve();#l=new Map;constructor(t,{defaultWorkspace:o=process.cwd()}={}){if(typeof t!="string"||!t)throw new TypeError("workspace store path is required");this.#e=t,this.#A=AE(o)}async load(){try{let t=Rpe(JSON.parse(await Dpe(this.#e,"utf8")));if(!t)throw new Error("dsh-im workspace config is invalid");this.#t=t.workspaces,this.#r=t.agentPresets}catch(t){if(t?.code!=="ENOENT")throw t;this.#t={},this.#r={}}this.#a.clear(),this.#i=1,this.#c.clear(),this.#s=1,this.#I.clear(),this.#n.clear();for(let t of Object.keys(this.#t))this.#a.set(t,this.#p()),this.#c.set(t,this.#d());return this}has(t){let o=di(t);return Object.hasOwn(this.#t,o)&&!this.#I.has(o)}incarnationFor(t){return this.#c.get(di(t))??null}workspaceFor(t){return this.#t[di(t)]??this.#A}agentPresetFor(t){return this.#r[di(t)]??null}generationFor(t){return this.#a.get(di(t))??null}async whenIdle(){await this.#g}async whenBotIdle(t){let o=di(t);for(;;){let i=this.#l.get(o);if(!i||(await i,this.#l.get(o)===i))return}}async ensure(t,{workspace:o=this.#A,defaultAgentPreset:i}={}){let e=di(t),a=AE(o);return this.#u(e,async()=>{if(this.#t[e])this.#a.has(e)||this.#a.set(e,this.#p());else{let A=Kl(i),r=Object.hasOwn(this.#r,e),s=this.#r[e];this.#t[e]=a,A&&(this.#r[e]=A),this.#a.set(e,this.#p()),this.#c.set(e,this.#d());try{await this.#B()}catch(g){throw delete this.#t[e],r?this.#r[e]=s:delete this.#r[e],this.#a.delete(e),this.#c.delete(e),g}}return this.#t[e]})}async setWorkspace(t,o,{clearSessions:i,incarnation:e}={}){let a=di(t);if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}let A=await rx(o);return this.#u(a,async()=>{if(!this.has(a)||e!==void 0&&e!==this.incarnationFor(a)){let s=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw s.code="workspace-bot-not-found",s}if(A===this.workspaceFor(a))return A;let r=this.#t[a];this.#a.set(a,this.#p()),await i?.(),this.#t[a]=A;try{await this.#B()}catch(s){throw this.#t[a]=r,s}return A})}async setAgentPreset(t,o,{incarnation:i}={}){let e=di(t);if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let A=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw A.code="workspace-bot-not-found",A}let a=Kl(o);return this.#u(e,async()=>{if(!this.has(e)||i!==void 0&&i!==this.incarnationFor(e)){let r=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw r.code="workspace-bot-not-found",r}let A=this.#r[e]??null;if(A===a)return a;a?this.#r[e]=a:delete this.#r[e];try{await this.#B()}catch(r){throw A?this.#r[e]=A:delete this.#r[e],r}return a})}async bindWorkspaceSession(t,o,{conversationKey:i,sessionId:e,clearSessions:a,setSession:A,incarnation:r,expectedGeneration:s}={}){let g=di(t);if(typeof i!="string"||!i||typeof e!="string"||!e)throw new TypeError("conversationKey and sessionId are required");if(typeof a!="function"||typeof A!="function")throw new TypeError("session state callbacks are required");if(!this.has(g)||r!==void 0&&r!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}let c=await lM(await rx(o));return this.#u(g,async()=>{if(!this.has(g)||r!==void 0&&r!==this.incarnationFor(g)){let I=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw I.code="workspace-bot-not-found",I}if(s!==void 0&&s!==this.generationFor(g))throw eI("The bot workspace changed before the session binding could be committed.");if(!await Npe(c,this.workspaceFor(g))){let I=this.#t[g];this.#a.set(g,this.#p()),await a(),this.#t[g]=c;try{await this.#B()}catch(d){throw this.#t[g]=I,d}}return await A(i,e),{workspace:c,sessionId:e,generation:this.#a.get(g)}})}async invalidateSessions(t,{clearSessions:o}={}){let i=di(t);return this.#u(i,async()=>{this.#a.set(i,this.#p()),await o?.()})}async beginRemoval(t,{clearSessions:o}={}){let i=di(t);return this.#u(i,async()=>{let e=this.#I.get(i);if(e)return e;let a=Object.freeze({});this.#I.set(i,a),this.#o.set(a,{botId:i,incarnation:this.incarnationFor(i)}),this.#a.set(i,this.#p());try{await o?.()}catch(A){throw this.#I.get(i)===a&&this.#I.delete(i),A}return a})}async abortRemoval(t){let{botId:o}=this.#h(t);return this.#u(o,async()=>this.#I.get(o)!==t?!1:(this.#I.delete(o),Object.hasOwn(this.#t,o)&&(this.#a.set(o,this.#p()),this.#c.has(o)||this.#c.set(o,this.#d())),!0))}async finishRemoval(t){let{botId:o,incarnation:i}=this.#h(t);return this.#u(o,async()=>this.#I.get(o)!==t?{removed:!1,persisted:!0,error:null,stale:!0}:this.incarnationFor(o)!==i?(this.#I.delete(o),{removed:!1,persisted:!0,error:null,stale:!0}):(this.#I.delete(o),this.#E(o)))}async retireAfterConfigCommit(t){let o=di(t);return this.#u(o,async()=>(this.#I.delete(o),this.#E(o)))}async remove(t){let o=await this.retireAfterConfigCommit(t);if(o.error)throw o.error;return o.removed}async reconcile(t){let o=new Set([...t].map(di)),i=new Set([...Object.keys(this.#t),...Object.keys(this.#r),...this.#n]);for(let e of i)o.has(e)||await this.remove(e)}decorateStatus(t){return!t||typeof t!="object"||!Array.isArray(t.bots)?t:{...t,bots:t.bots.map(o=>o?.botId?{...o,workspace:this.workspaceFor(o.botId),agentPreset:this.agentPresetFor(o.botId)}:o)}}#p(){let t=this.#i;return this.#i+=1,t}#d(){let t=this.#s;return this.#s+=1,t}#h(t){if(!t||typeof t!="object")throw new TypeError("Invalid workspace removal transaction");let o=this.#o.get(t);if(!o)throw new TypeError("Invalid workspace removal transaction");return o}async#E(t){let o=Object.hasOwn(this.#t,t),i=Object.hasOwn(this.#r,t),e=o||i||this.#n.has(t);if(delete this.#t[t],delete this.#r[t],this.#a.delete(t),this.#c.delete(t),!e)return{removed:!1,persisted:!0,error:null,stale:!1};try{return await this.#f(),{removed:o,persisted:!0,error:null,stale:!1}}catch(a){return this.#n.add(t),{removed:o,persisted:!1,error:a,stale:!1}}}async#u(t,o){let i=this.#g.then(o,o),e=i.then(()=>{},()=>{});return this.#g=e,this.#l.set(t,e),e.finally(()=>{this.#l.get(t)===e&&this.#l.delete(t)}),i}async#B(){let t={version:1,workspaces:this.#t};Object.keys(this.#r).length>0&&(t.agentPresets=this.#r),await Spe(Tpe(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await _pe(o,`${JSON.stringify(t,null,2)} -`,{encoding:"utf8",mode:384}),await Ope(o,this.#e),this.#n.clear()}async#f(){if(Object.keys(this.#t).length>0||Object.keys(this.#r).length>0){await this.#B();return}try{await Mpe(this.#e),this.#n.clear()}catch(t){if(t?.code!=="ENOENT")throw t;this.#n.clear()}}};function pM(n){if(!n)return null;let t=typeof n=="function"?n():n;return t&&typeof t.then=="function"?t.then(_n):_n(t)}function ox(){let n=new Error("Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002");return n.code="agent-preset-unavailable",n}function ql(n){if(n())return;let t=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw t.code="workspace-bot-not-found",t}function ax(n,t,o){let i=e=>{let a=n.decorateStatus(e);if(!o||!a||typeof a!="object")return a;let A=s=>s?{...a,agentPresetCatalog:s}:a,r=pM(o);return r&&typeof r.then=="function"?r.then(A):A(r)};return t&&typeof t.then=="function"?t.then(i):i(t)}function kpe(n){return Promise.resolve(n.status())}function Ma(n,{workspaces:t,method:o="remove",botIdFromRemoved:i=e=>e?.botId}){if(!n||!t||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(e,a){let A=Reflect.get(e,a,e);return a===o?async(...r)=>{let s=await A.apply(e,r),g=s?i(s,r):null;return g&&await t.retireAfterConfigCommit(g),s}:typeof A=="function"?A.bind(e):A}})}function _a(n,{botId:t,workspaces:o,state:i,agentPresetCatalog:e}={}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let a=o.incarnationFor(t),A=()=>o.has(t)&&o.incarnationFor(t)===a,r=async(I=e)=>{let d;try{d=await pM(I)??_n(null)}catch(B){throw ql(A),B}return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:d}},s=new Map,g=new Proxy(n,{get(I,d){if(d==="agentPresetSettings")return async(f={})=>{f?.signal?.throwIfAborted(),ql(A);let Q=await r();return f?.signal?.throwIfAborted(),Q};if(d==="updateAgentPreset")return async(f,Q={})=>{Q?.signal?.throwIfAborted(),ql(A);let y=f==="--default"?null:Kl(f),m=null;if(y&&({agentPresetCatalog:m}=await r(),Q?.signal?.throwIfAborted(),!m.items.some(_=>_.id===y)))throw ox();if(await o.setAgentPreset(t,y,{incarnation:a}),ql(A),m)return{agentPreset:o.agentPresetFor(t),agentPresetCatalog:m};try{return await r()}catch(_){if(_?.code==="workspace-bot-not-found")throw _;return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:_n(null)}}};if(d==="currentWorkspace")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}return o.workspaceFor(t)};if(d==="assertWorkspaceScope")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}};if((d==="listWorkspaces"||d==="listWorkspaceSessions"||d==="listModels")&&typeof I[d]=="function")return async(...f)=>{if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=await I[d](...f);if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}return Q};if(d==="switchWorkspace")return f=>{if(!A()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return Q.code="workspace-bot-not-found",Promise.reject(Q)}return o.setWorkspace(t,f,{clearSessions:()=>i.clearSessions(),incarnation:a})};if(d==="bindWorkspaceSession")return async(f,Q)=>{if(typeof f!="string"||!f||typeof Q!="string"||!Q)throw new TypeError("conversationKey and sessionId are required");if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(typeof I.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let y=o.generationFor(t),m=await I.adoptWorkspaceSession(Q);if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(y!==o.generationFor(t))throw eI("The bot workspace changed while the session was being adopted.");if(!m||typeof m!="object"||m.sessionId!==Q||typeof m.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let _=await o.bindWorkspaceSession(t,m.workspace,{conversationKey:f,sessionId:Q,clearSessions:()=>i.clearSessions(),setSession:(N,G)=>i.setSession(N,G),incarnation:a,expectedGeneration:y});if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(_.generation!==o.generationFor(t))throw eI("The bot workspace changed before the session binding completed.");return s.set(Q,_.generation),{...m,workspace:_.workspace,sessionId:_.sessionId}};if(d==="createSession")return async(f={})=>{if(await o.whenBotIdle(t),!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}let Q=o.generationFor(t),y=o.agentPresetFor(t),m=await I.createSession({...f,workspace:o.workspaceFor(t),...y==null?{}:{agentPreset:y}});return s.set(m,Q),m};if(d==="workspaceSession")return f=>{if(typeof f!="string"||!f)throw new TypeError("sessionId is required");let Q=s.get(f)??o.generationFor(t);s.delete(f);let y=()=>A()&&Q===o.generationFor(t),m=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);let J=await I[N](f,...G);if(!y())throw eI(`The bot workspace changed while this ${Y} was running.`);return J},_=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);return I[N](f,...G)};return Object.freeze({sessionId:f,async sessionExists(...N){if(!y())return!1;let G=await I.sessionExists(f,...N);return y()&&G},models(...N){return m("getSessionModels",N,"model listing")},selectModel(...N){return m("selectSessionModel",N,"model selection")},isRunning(...N){return m("isSessionRunning",N,"run-state check")},hasActiveTurn(...N){return m("hasActiveTurn",N,"turn ownership check")},stopActiveTurn(...N){return _("stopActiveTurn",N,"turn stop")},steerActiveTurn(...N){return _("steerActiveTurn",N,"turn steering")},ask(...N){if(!y())throw eI("The bot workspace changed before this prompt started.");return I.ask(f,...N)}})};if(d==="sessionExists")return(f,...Q)=>{if(!A())return!1;let y=s.get(f);return y!==void 0&&y!==o.generationFor(t)?(s.delete(f),!1):I.sessionExists(f,...Q)};if(d==="ask")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this prompt started.");throw m.code=oi,m}return I.ask(f,...Q)};if(d==="executeCommand"&&typeof I.executeCommand=="function")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this command started.");throw m.code=oi,m}return I.executeCommand(f,...Q)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}}),c=new Proxy(i,{get(I,d){if(d===Ob)return I;if(d==="sessionFor")return(f,...Q)=>{if(!A())return null;let y=I.sessionFor(f,...Q);return y&&!s.has(y)&&s.set(y,o.generationFor(t)),y};if(d==="setSession")return(f,Q,...y)=>{let m=s.get(Q);return!A()||m!==void 0&&m!==o.generationFor(t)?(s.delete(Q),!1):I.setSession(f,Q,...y)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}});return Object.freeze({harness:g,state:c})}function Ta(n,{workspaces:t,stateFor:o,agentPresetCatalog:i}={}){if(!n||!t||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let e=new Map,a=(c,I)=>{let B=(e.get(c)??Promise.resolve()).catch(()=>{}).then(I);return e.set(c,B),B.finally(()=>{e.get(c)===B&&e.delete(c)})},A=c=>ax(t,c,i),r=(c,I)=>{let d=t.incarnationFor(c);return a(c,async()=>{if(!(await n.status())?.bots?.some(Q=>Q?.botId===c)){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}let f=await o(c);return await t.setWorkspace(c,I,{clearSessions:()=>f.clearSessions(),incarnation:d}),A(await n.status())})},s=(c,I)=>{let d=t.incarnationFor(c),B=Kl(I);return a(c,async()=>{if(!(await n.status())?.bots?.some(y=>y?.botId===c)){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=B&&i?await pM(i):null;if(B&&i&&!Q?.items.some(y=>y.id===B))throw ox();return await t.setAgentPreset(c,B,{incarnation:d}),ax(t,await n.status(),Q??i)})},g=(c,I)=>a(c,async()=>{let d=await t.beginRemoval(c,{clearSessions:async()=>{try{let B=await o(c);if(!B||typeof B.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await B.clearSessions()}catch(B){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${c}:`,B?.message??B)}}});try{let B=await I();return await t.finishRemoval(d),A(B)}catch(B){let f=await kpe(n).catch(()=>null);throw Array.isArray(f?.bots)&&!f.bots.some(y=>y?.botId===c)?await t.finishRemoval(d):await t.abortRemoval(d),B}});return new Proxy(n,{get(c,I){if(I==="updateWorkspace")return r;if(I==="updateAgentPreset")return s;let d=Reflect.get(c,I,c);return typeof d!="function"?d:I==="deleteBot"?(B,...f)=>g(B,()=>d.call(c,B,...f)):I==="disconnect"?async(...B)=>{let Q=(await c.status())?.bots?.[0]?.botId;return Q?g(Q,()=>d.apply(c,B)):A(d.apply(c,B))}:(...B)=>A(d.apply(c,B))}})}var nx=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function vpe(n){if(!Array.isArray(n)||n.length===0)return[...nx];let t=n.filter(o=>Number.isFinite(o)&&o>=0);return t.length>0?t:[...nx]}var Mf=class{#e;#A;#t;#r;#a;#i;#c;#s=null;#I=null;#o=0;#n=!1;#g=!1;#l;#p;constructor({controller:t,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:r=clearTimeout}){if(!t||typeof t.initialize!="function"||typeof t.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=t,this.#A=o,this.#t=i,this.#r=vpe(e),this.#a=Number.isFinite(a)&&a>=0?a:15e3,this.#i=A,this.#c=r,this.#l=new Promise(s=>{this.#p=s})}get ready(){return this.#l}start(){return this.#g||this.#n?this:(this.#g=!0,this.#d(0),this)}async close(){this.#n||(this.#n=!0,this.#s!==null&&this.#c(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#d(t){this.#n||(this.#s=this.#i(()=>{this.#s=null,this.#h()},t),this.#s?.unref?.())}async#h(){if(this.#n||this.#I)return;let t=this.#E();this.#I=t;try{await t}finally{this.#I===t&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#n)return;let t=await this.#e.initialize();if(this.#n)return;this.#p?.(t),this.#p=null;let{configured:o,connected:i}=t.totals;if(io.invoke({namespace:"commands",method:"execute",args:{agentId:i,line:e},signal:a.signal})}}import{randomUUID as Ppe}from"node:crypto";function Gpe(n){if(typeof n?.get!="function")return;let t;try{t=n.get("agents")}catch{return}if(t!=null){if(typeof t.get!="function")throw new TypeError('dsh-im requires a callable AgentRegistry when ctx.get("agents") is present');return t}}function Fpe(n,t,o){if(n?.status!=="running")return!1;let i=n?.session?.events;if(!Array.isArray(i))return!1;let e=null,a=!1;for(let A of i){if(A?.type==="turn/start"){e=A.data?.turn??null,a=!1;continue}if(A?.type==="turn/end"&&A.data?.turn===e){e=null,a=!1;continue}e===t&&A?.type==="user/message"&&A.data?.source?.rpcId===o&&(a=!0)}return e===t&&a}function sx(n){if(!n||typeof n!="object"||Object.isFrozen(n))return n;for(let t of Object.values(n))sx(t);return Object.freeze(n)}function Lpe(n){return sx({id:Ppe(),role:"user",content:[{type:"text",text:n}],source:{kind:"user"}})}function Upe(n){let t=new Error("Session is busy with an active turn or maintenance task",{cause:n});return t.code="agent-busy",t}function Hpe(n){return({sessionId:t,expectedTurn:o,promptRpcId:i,action:e,text:a})=>{let A=n.get(t);if(A){if(!Fpe(A,o,i))return!1;if(e==="stop")return A.cancel({kind:"user"},{keepInbox:!0}),!0;if(e==="steer")return typeof a!="string"||!a.trim()?!1:(A.inject(Lpe(a)),!0);throw new TypeError(`Unsupported Harness control action: ${String(e)}`)}}}function Kpe(n){return({sessionId:t,operation:o})=>{if(typeof o!="function")throw new TypeError("maintenance operation is required");let i=n.get(t);if(!i)return o();try{return i.runMaintenance(e=>{if(n.get(t)!==i){let a=new Error("Session agent changed before maintenance started");throw a.code="agent-unavailable",a}return o(e)})}catch(e){throw Upe(e)}}}function xpe(n){return({sessionId:t,workspace:o,files:i,signal:e})=>{let A=n.get(t)?.session?.header?.cwd,r=typeof A=="string"&&A?A:o;if(typeof r!="string"||!r)throw new ho("inbound-file-workspace-unavailable","The Harness Session workspace is unavailable for inbound files.");return MK({files:i},{workspace:r,signal:e})}}function Ra(n,t={}){let{controlExecutor:o,sessionMaintenanceExecutor:i,fileIngressExecutor:e}=t;if(o!==void 0&&typeof o!="function")throw new TypeError("controlExecutor must be a function");if(i!==void 0&&typeof i!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("fileIngressExecutor must be a function");let a=o&&i&&e?void 0:Gpe(n);return{controlExecutor:o??(a?Hpe(a):void 0),sessionMaintenanceExecutor:i??(a?Kpe(a):void 0),fileIngressExecutor:e??xpe(a??{get:()=>{}})}}function Jpe(n,t){if(t!==void 0)return new URL(t);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-dingtalk requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function qpe(n){let t=AI(n.dshHome??process.env.DSH_HOME??tE(jpe(),".dsh")),o=AI(n.dataDir??tE(t,"integrations","dsh-dingtalk"));return{root:o,config:AI(n.configPath??tE(o,"config.json")),bots:AI(n.botsDir??tE(o,"bots")),workspaces:AI(n.workspacesPath??tE(o,"workspaces.json"))}}async function hM(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-dingtalk requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-dingtalk requires ctx.webServer");let i=o.ConfigStore??cf,e=o.DeviceAuth??lf,a=o.StateStore??bf,A=o.HarnessClient??wf,r=o.Controller??xh,s=o.Runtime??Xh,g=o.createConnectionSupervisor??dM,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,I=()=>Oa(n),d=qpe(t),B=await new i(d.config).load(),f=AI(t.workspace??process.cwd()),Q=o.WorkspaceStore??Zr,y=o.workspaces??await new Q(d.workspaces,{defaultWorkspace:f}).load(),m=typeof B.list=="function",_=m?B.list():[];m&&await y.reconcile(_.map(W=>W.botId)),await Promise.all(_.map(W=>y.ensure(W.botId,{defaultAgentPreset:t.agentPreset})));let N=typeof B.remove=="function"?Ma(B,{workspaces:y}):B,G=o.deviceAuth??new e({baseUrl:t.registrationBaseUrl}),Y=new Map,J=W=>AI(d.bots,W,"state.json"),H=async W=>{let ae=Y.get(W);return ae||(ae=await new a(J(W)).load(),Y.set(W,ae)),ae},j=Na(n,o.commandExecutor),{controlExecutor:q,sessionMaintenanceExecutor:U,fileIngressExecutor:R}=Ra(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),V=new A({baseUrl:Jpe(n.webServer,t.harnessBaseUrl),workspace:f,autostart:!1,dshBin:t.dshBin??"dsh",...j?{commandExecutor:j}:{},...q?{controlExecutor:q}:{},...U?{sessionMaintenanceExecutor:U}:{},...R?{fileIngressExecutor:R}:{}}),L=new r({deviceAuth:G,credentials:n.credentials,configStore:N,logger:c,createRuntime:async({botId:W,config:ae,clientSecret:ge})=>{let Se=await H(W);await y.ensure(W,{defaultAgentPreset:t.agentPreset});let de=_a(V,{botId:W,workspaces:y,state:Se,agentPresetCatalog:I});return new s({config:ae,clientSecret:ge,harness:de.harness,state:de.state,replyTimeoutMs:t.replyTimeoutMs??6e5,maxMessageChars:t.maxMessageChars??4e3,connectTimeoutMs:t.connectTimeoutMs??15e3,logger:{error:(...De)=>c.error?.(`[${W}]`,...De),warn:(...De)=>c.warn?.(`[${W}]`,...De),info:(...De)=>c.info?.(`[${W}]`,...De),debug:(...De)=>c.debug?.(`[${W}]`,...De)}})},deleteState:async({botId:W})=>{let ae=Y.get(W);if(Y.delete(W),ae&&typeof ae.remove=="function")await ae.remove();else try{await Ype(J(W))}catch(ge){if(ge?.code!=="ENOENT")throw ge}}}),T=Ta(L,{workspaces:y,stateFor:H,agentPresetCatalog:I}),P=g({controller:T,harness:V,logger:c,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:T,ready:P.ready,async close(){await P.close(),await T.close(),V.stopManagedProcess()}}}import Zpe from"qrcode";var zpe=new Set(["loopback","trusted-host"]);function yr(n){if(n===void 0)return"loopback";if(zpe.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as Vpe}from"node:path";var hi="bot.workspace.set";function ka(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(t=>["botId","workspace"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&Vpe(n.workspace.trim())}function va(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found","agent-preset-invalid","agent-preset-unavailable"].includes(n?.code)?{code:n.code,message:n.message}:null}var Ei="bot.preset.set";function Wpe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Pa(n){return Wpe(n)&&Object.keys(n).every(t=>["botId","agentPreset"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&(n.agentPreset===null||typeof n.agentPreset=="string"&&zb.test(n.agentPreset))}var cx="/dingtalk",ar=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:hi,setAgentPreset:Ei,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),Ix=Object.freeze(Object.values(ar)),Xpe=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function CM(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function vg(n,t){return CM(n)&&Object.keys(n).every(o=>t.includes(o))}function tI(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function gx(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function $pe(n,t){return CM(t)?n===ar.status?vg(t,[])?null:"connection.status does not accept fields.":n===ar.beginProvisioning?vg(t,["locale"])&&(t.locale===void 0||t.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[ar.pollProvisioning,ar.cancelProvisioning].includes(n)?vg(t,["attemptId"])&&tI(t.attemptId)?null:`${n} requires an attemptId.`:n===ar.bindCredentials?vg(t,["clientId","clientSecret"])&&gx(t.clientId,256)&&gx(t.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===ar.reconnectBot?vg(t,["botId","sendTest"])&&tI(t.botId)&&(t.sendTest===void 0||t.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===ar.deleteBot?vg(t,["botId","confirm"])&&tI(t.botId)&&t.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===ar.setWorkspace?ka(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===ar.setAgentPreset?Pa(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===ar.approveSender?vg(t,["botId","requestId","confirm"])&&tI(t.botId)&&tI(t.requestId)&&t.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===ar.revokeSender?vg(t,["botId","senderKey","confirm"])&&tI(t.botId)&&tI(t.senderKey)&&t.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function _f(n){return{ok:!1,error:{code:"bad-request",message:n}}}function rE(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function ede(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function zl(n){if(Array.isArray(n))return n.map(zl);if(!CM(n))return n;let t={};for(let[o,i]of Object.entries(n))Xpe.has(o)||(t[o]=zl(i));return t}async function Ade(n){return Zpe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function EM(n,t){return!n||typeof n.verificationUrl!="string"?zl(n):zl({...n,qrCodeDataUrl:await t(n.verificationUrl)})}async function Pg(n,t){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await EM(o.provisioning,t)),zl(o)}function tde(n){for(let t of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[t]!="function")throw new TypeError(`A complete DingTalk controller is required (${t})`)}function lx(n,{encodeQr:t=Ade}={}){tde(n);let o=new Map,i=e=>{let a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>t(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return rE();if(!Ix.includes(e))return _f("Unknown DingTalk endpoint.");let r=$pe(e,a);if(r)return _f(r);try{let s;if(e===ar.status)s=await Pg(await n.status(),i);else if(e===ar.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),rE();s=await EM(g,i)}else if(e===ar.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return _f("The provisioning attempt no longer exists.");s=await EM(g,i)}else if(e===ar.cancelProvisioning){if(s=await n.cancelProvisioning(a.attemptId),!s)return _f("The provisioning attempt no longer exists.");s=zl(s)}else if(e===ar.bindCredentials)s=await Pg(await n.bindCredentials(a),i);else if(e===ar.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return rE();let c;if(a.sendTest===!0)if(!g?.bots?.some(d=>d?.botId===a.botId&&d?.connected===!0)||typeof n.sendConnectionTest!="function")c=rr(Ir("\u9489\u9489\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=rr()}catch(d){c=rr(d)}s=await Pg({...g,...c?{testMessage:c}:{}},i)}else if(e===ar.deleteBot)s=await Pg(await n.deleteBot(a.botId),i);else if(e===ar.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await Pg(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===ar.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await Pg(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else e===ar.approveSender?s=await Pg(await n.approveSender(a.botId,a.requestId),i):s=await Pg(await n.revokeSender(a.botId,a.senderKey),i);return A?.aborted?rE():{ok:!0,value:s}}catch(s){let g=va(s);return A?.aborted?rE():g?{ok:!1,error:g}:ede()}}}function Tf(n,t,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(cx,lx(t,o),{authority:yr(i)})}async function px(n,t={}){if(t?.controller)return Tf(n,t.controller,t.rpcOptions,t.rpcAuthority);let o=await hM(n,t,t.internals),i=Tf(n,o.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as rde}from"node:crypto";import{mkdir as ade,readFile as ide,rename as ode,unlink as nde,writeFile as sde}from"node:fs/promises";import{dirname as gde}from"node:path";var uM=Object.freeze({version:1,bots:Object.freeze([])});function Gs(n){return typeof n=="string"&&n.trim()?n.trim():null}function dx(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function aE(n,{botPrefix:t,tokenRefPrefix:o}){let i=Gs(n);if(!i)throw new TypeError("platformId is required");let e=rde("sha256").update(i).digest("hex").slice(0,24);return{botId:`${t}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function Nf(n,t){let o=Gs(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:t:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var Vl=class{#e;#A;#t;#r;#a;#i;#c;#s=uM;#I=Promise.resolve();constructor(t,{channel:o,botPrefix:i,tokenRefPrefix:e,normalizeBotExtension:a=()=>({})}){if(typeof a!="function")throw new TypeError("normalizeBotExtension must be a function");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=new RegExp(`^${dx(i)}_[a-f0-9]{24}$`),this.#c=new RegExp(`^${dx(e)}_[A-F0-9]{24}$`)}async load(){try{let t=this.#n(JSON.parse(await ide(this.#e,"utf8")));if(!t)throw new Error(`dsh-im ${this.#A} config contains invalid bot data`);this.#s=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#s=uM}return this}list(){return structuredClone(this.#s.bots)}get(t){let o=this.#s.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByPlatformId(t){let o=this.#s.bots.find(i=>i.platformId===t);return o?structuredClone(o):null}async save(t){let o=this.#o(t);if(!o)throw new Error(`Refusing to persist incomplete ${this.#A} bot data`);return this.#g(i=>{let e=i.find(r=>r.platformId===o.platformId&&r.botId!==o.botId),a=i.find(r=>r.tokenRef===o.tokenRef&&r.botId!==o.botId);if(e||a)throw new Error(`Duplicate ${this.#A} bot identity`);let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!this.#i.test(t))throw new TypeError(`Invalid ${this.#A} bot id`);return this.#g(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#I.then(async()=>{try{await nde(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#s=uM});this.#I=t.then(()=>{},()=>{}),await t}#o(t){if(!t||typeof t!="object")return null;let o=Gs(t.platformId),i=Gs(t.botId),e=Gs(t.tokenRef),a=Gs(t.name);if(!o||!i||!e||!a||!this.#i.test(i)||!this.#c.test(e))return null;let A=aE(o,{botPrefix:this.#t,tokenRefPrefix:this.#r});if(A.botId!==i||A.tokenRef!==e)return null;let r=this.#a(t);return!r||typeof r!="object"||Array.isArray(r)?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:a,username:Gs(t.username),createdAt:Gs(t.createdAt)??new Date().toISOString(),connectedAt:Gs(t.connectedAt),...r})}#n(t){if(!t||t.version!==1||!Array.isArray(t.bots))return null;let o=t.bots.map(A=>this.#o(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||a.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),a.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#g(t){let o,i=this.#I.then(async()=>{let e=[...this.#s.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#s=a});return this.#I=i.then(()=>{},()=>{}),await i,o}async#l(t){await ade(gde(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await sde(o,`${JSON.stringify(t,null,2)} +`,{encoding:"utf8",mode:384}),await Ope(o,this.#e),this.#n.clear()}async#f(){if(Object.keys(this.#t).length>0||Object.keys(this.#r).length>0){await this.#B();return}try{await Mpe(this.#e),this.#n.clear()}catch(t){if(t?.code!=="ENOENT")throw t;this.#n.clear()}}};function pM(n){if(!n)return null;let t=typeof n=="function"?n():n;return t&&typeof t.then=="function"?t.then(_n):_n(t)}function ox(){let n=new Error("Agent Preset \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528\u3002");return n.code="agent-preset-unavailable",n}function ql(n){if(n())return;let t=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw t.code="workspace-bot-not-found",t}function ax(n,t,o){let i=e=>{let a=n.decorateStatus(e);if(!o||!a||typeof a!="object")return a;let A=s=>s?{...a,agentPresetCatalog:s}:a,r=pM(o);return r&&typeof r.then=="function"?r.then(A):A(r)};return t&&typeof t.then=="function"?t.then(i):i(t)}function kpe(n){return Promise.resolve(n.status())}function Ma(n,{workspaces:t,method:o="remove",botIdFromRemoved:i=e=>e?.botId}){if(!n||!t||typeof n[o]!="function")throw new TypeError("configStore removal observer dependencies are required");return new Proxy(n,{get(e,a){let A=Reflect.get(e,a,e);return a===o?async(...r)=>{let s=await A.apply(e,r),g=s?i(s,r):null;return g&&await t.retireAfterConfigCommit(g),s}:typeof A=="function"?A.bind(e):A}})}function _a(n,{botId:t,workspaces:o,state:i,agentPresetCatalog:e}={}){if(!n||!o||!i)throw new TypeError("harness, workspaces, and state are required");let a=o.incarnationFor(t),A=()=>o.has(t)&&o.incarnationFor(t)===a,r=async(I=e)=>{let d;try{d=await pM(I)??_n(null)}catch(B){throw ql(A),B}return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:d}},s=new Map,g=new Proxy(n,{get(I,d){if(d==="agentPresetSettings")return async(f={})=>{f?.signal?.throwIfAborted(),ql(A);let Q=await r();return f?.signal?.throwIfAborted(),Q};if(d==="updateAgentPreset")return async(f,Q={})=>{Q?.signal?.throwIfAborted(),ql(A);let y=f==="--default"?null:Kl(f),m=null;if(y&&({agentPresetCatalog:m}=await r(),Q?.signal?.throwIfAborted(),!m.items.some(_=>_.id===y)))throw ox();if(await o.setAgentPreset(t,y,{incarnation:a}),ql(A),m)return{agentPreset:o.agentPresetFor(t),agentPresetCatalog:m};try{return await r()}catch(_){if(_?.code==="workspace-bot-not-found")throw _;return ql(A),{agentPreset:o.agentPresetFor(t),agentPresetCatalog:_n(null)}}};if(d==="currentWorkspace")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}return o.workspaceFor(t)};if(d==="assertWorkspaceScope")return()=>{if(!A()){let f=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw f.code="workspace-bot-not-found",f}};if((d==="listWorkspaces"||d==="listWorkspaceSessions"||d==="listModels")&&typeof I[d]=="function")return async(...f)=>{if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=await I[d](...f);if(!A()){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}return Q};if(d==="switchWorkspace")return f=>{if(!A()){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");return Q.code="workspace-bot-not-found",Promise.reject(Q)}return o.setWorkspace(t,f,{clearSessions:()=>i.clearSessions(),incarnation:a})};if(d==="bindWorkspaceSession")return async(f,Q)=>{if(typeof f!="string"||!f||typeof Q!="string"||!Q)throw new TypeError("conversationKey and sessionId are required");if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(typeof I.adoptWorkspaceSession!="function")throw new TypeError("Harness does not support adopting workspace sessions");let y=o.generationFor(t),m=await I.adoptWorkspaceSession(Q);if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(y!==o.generationFor(t))throw eI("The bot workspace changed while the session was being adopted.");if(!m||typeof m!="object"||m.sessionId!==Q||typeof m.workspace!="string")throw new TypeError("Harness returned an invalid adopted workspace session");let _=await o.bindWorkspaceSession(t,m.workspace,{conversationKey:f,sessionId:Q,clearSessions:()=>i.clearSessions(),setSession:(N,G)=>i.setSession(N,G),incarnation:a,expectedGeneration:y});if(!A()){let N=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw N.code="workspace-bot-not-found",N}if(_.generation!==o.generationFor(t))throw eI("The bot workspace changed before the session binding completed.");return s.set(Q,_.generation),{...m,workspace:_.workspace,sessionId:_.sessionId}};if(d==="createSession")return async(f={})=>{if(await o.whenBotIdle(t),!A()){let _=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw _.code="workspace-bot-not-found",_}let Q=o.generationFor(t),y=o.agentPresetFor(t),m=await I.createSession({...f,workspace:o.workspaceFor(t),...y==null?{}:{agentPreset:y}});return s.set(m,Q),m};if(d==="workspaceSession")return f=>{if(typeof f!="string"||!f)throw new TypeError("sessionId is required");let Q=s.get(f)??o.generationFor(t);s.delete(f);let y=()=>A()&&Q===o.generationFor(t),m=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);let J=await I[N](f,...G);if(!y())throw eI(`The bot workspace changed while this ${Y} was running.`);return J},_=async(N,G,Y)=>{if(!y())throw eI(`The bot workspace changed before this ${Y} started.`);return I[N](f,...G)};return Object.freeze({sessionId:f,async sessionExists(...N){if(!y())return!1;let G=await I.sessionExists(f,...N);return y()&&G},models(...N){return m("getSessionModels",N,"model listing")},selectModel(...N){return m("selectSessionModel",N,"model selection")},isRunning(...N){return m("isSessionRunning",N,"run-state check")},hasActiveTurn(...N){return m("hasActiveTurn",N,"turn ownership check")},stopActiveTurn(...N){return _("stopActiveTurn",N,"turn stop")},steerActiveTurn(...N){return _("steerActiveTurn",N,"turn steering")},ask(...N){if(!y())throw eI("The bot workspace changed before this prompt started.");return I.ask(f,...N)}})};if(d==="sessionExists")return(f,...Q)=>{if(!A())return!1;let y=s.get(f);return y!==void 0&&y!==o.generationFor(t)?(s.delete(f),!1):I.sessionExists(f,...Q)};if(d==="ask")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this prompt started.");throw m.code=oi,m}return I.ask(f,...Q)};if(d==="executeCommand"&&typeof I.executeCommand=="function")return(f,...Q)=>{let y=s.get(f);if(s.delete(f),!A()||y!==void 0&&y!==o.generationFor(t)){let m=new Error("The bot workspace changed before this command started.");throw m.code=oi,m}return I.executeCommand(f,...Q)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}}),c=new Proxy(i,{get(I,d){if(d===Ob)return I;if(d==="sessionFor")return(f,...Q)=>{if(!A())return null;let y=I.sessionFor(f,...Q);return y&&!s.has(y)&&s.set(y,o.generationFor(t)),y};if(d==="setSession")return(f,Q,...y)=>{let m=s.get(Q);return!A()||m!==void 0&&m!==o.generationFor(t)?(s.delete(Q),!1):I.setSession(f,Q,...y)};let B=Reflect.get(I,d,I);return typeof B=="function"?B.bind(I):B}});return Object.freeze({harness:g,state:c})}function Ta(n,{workspaces:t,stateFor:o,agentPresetCatalog:i}={}){if(!n||!t||typeof o!="function")throw new TypeError("controller, workspaces, and stateFor are required");let e=new Map,a=(c,I)=>{let B=(e.get(c)??Promise.resolve()).catch(()=>{}).then(I);return e.set(c,B),B.finally(()=>{e.get(c)===B&&e.delete(c)})},A=c=>ax(t,c,i),r=(c,I)=>{let d=t.incarnationFor(c);return a(c,async()=>{if(!(await n.status())?.bots?.some(Q=>Q?.botId===c)){let Q=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw Q.code="workspace-bot-not-found",Q}let f=await o(c);return await t.setWorkspace(c,I,{clearSessions:()=>f.clearSessions(),incarnation:d}),A(await n.status())})},s=(c,I)=>{let d=t.incarnationFor(c),B=Kl(I);return a(c,async()=>{if(!(await n.status())?.bots?.some(y=>y?.botId===c)){let y=new Error("\u627E\u4E0D\u5230\u8981\u4FEE\u6539\u7684\u673A\u5668\u4EBA\u3002");throw y.code="workspace-bot-not-found",y}let Q=B&&i?await pM(i):null;if(B&&i&&!Q?.items.some(y=>y.id===B))throw ox();return await t.setAgentPreset(c,B,{incarnation:d}),ax(t,await n.status(),Q??i)})},g=(c,I)=>a(c,async()=>{let d=await t.beginRemoval(c,{clearSessions:async()=>{try{let B=await o(c);if(!B||typeof B.clearSessions!="function")throw new TypeError("bot state does not support session cleanup");await B.clearSessions()}catch(B){console.warn(`[dsh-im] ignored session cleanup failure while deleting bot ${c}:`,B?.message??B)}}});try{let B=await I();return await t.finishRemoval(d),A(B)}catch(B){let f=await kpe(n).catch(()=>null);throw Array.isArray(f?.bots)&&!f.bots.some(y=>y?.botId===c)?await t.finishRemoval(d):await t.abortRemoval(d),B}});return new Proxy(n,{get(c,I){if(I==="updateWorkspace")return r;if(I==="updateAgentPreset")return s;let d=Reflect.get(c,I,c);return typeof d!="function"?d:I==="deleteBot"?(B,...f)=>g(B,()=>d.call(c,B,...f)):I==="disconnect"?async(...B)=>{let Q=(await c.status())?.bots?.[0]?.botId;return Q?g(Q,()=>d.apply(c,B)):A(d.apply(c,B))}:(...B)=>A(d.apply(c,B))}})}var nx=Object.freeze([250,1e3,3e3,5e3,1e4,3e4]);function vpe(n){if(!Array.isArray(n)||n.length===0)return[...nx];let t=n.filter(o=>Number.isFinite(o)&&o>=0);return t.length>0?t:[...nx]}var Mf=class{#e;#A;#t;#r;#a;#i;#c;#s=null;#I=null;#o=0;#n=!1;#g=!1;#l;#p;constructor({controller:t,harness:o,logger:i=console,retryDelaysMs:e,healthyIntervalMs:a=15e3,setTimeoutImpl:A=setTimeout,clearTimeoutImpl:r=clearTimeout}){if(!t||typeof t.initialize!="function"||typeof t.status!="function")throw new TypeError("ConnectionSupervisor requires a controller");if(!o||typeof o.ensureRunning!="function")throw new TypeError("ConnectionSupervisor requires a Harness client");this.#e=t,this.#A=o,this.#t=i,this.#r=vpe(e),this.#a=Number.isFinite(a)&&a>=0?a:15e3,this.#i=A,this.#c=r,this.#l=new Promise(s=>{this.#p=s})}get ready(){return this.#l}start(){return this.#g||this.#n?this:(this.#g=!0,this.#d(0),this)}async close(){this.#n||(this.#n=!0,this.#s!==null&&this.#c(this.#s),this.#s=null,await this.#I?.catch(()=>{}),this.#p?.(null),this.#p=null)}#d(t){this.#n||(this.#s=this.#i(()=>{this.#s=null,this.#h()},t),this.#s?.unref?.())}async#h(){if(this.#n||this.#I)return;let t=this.#E();this.#I=t;try{await t}finally{this.#I===t&&(this.#I=null)}}async#E(){try{if(await this.#A.ensureRunning(),this.#n)return;let t=await this.#e.initialize();if(this.#n)return;this.#p?.(t),this.#p=null;let{configured:o,connected:i}=t.totals;if(io.invoke({namespace:"commands",method:"execute",args:{agentId:i,line:e,images:[]},signal:a.signal})}}import{randomUUID as Ppe}from"node:crypto";function Gpe(n){if(typeof n?.get!="function")return;let t;try{t=n.get("agents")}catch{return}if(t!=null){if(typeof t.get!="function")throw new TypeError('dsh-im requires a callable AgentRegistry when ctx.get("agents") is present');return t}}function Fpe(n,t,o){if(n?.status!=="running")return!1;let i=n?.session?.events;if(!Array.isArray(i))return!1;let e=null,a=!1;for(let A of i){if(A?.type==="turn/start"){e=A.data?.turn??null,a=!1;continue}if(A?.type==="turn/end"&&A.data?.turn===e){e=null,a=!1;continue}e===t&&A?.type==="user/message"&&A.data?.source?.rpcId===o&&(a=!0)}return e===t&&a}function sx(n){if(!n||typeof n!="object"||Object.isFrozen(n))return n;for(let t of Object.values(n))sx(t);return Object.freeze(n)}function Lpe(n){return sx({id:Ppe(),role:"user",content:[{type:"text",text:n}],source:{kind:"user"}})}function Upe(n){let t=new Error("Session is busy with an active turn or maintenance task",{cause:n});return t.code="agent-busy",t}function Hpe(n){return({sessionId:t,expectedTurn:o,promptRpcId:i,action:e,text:a})=>{let A=n.get(t);if(A){if(!Fpe(A,o,i))return!1;if(e==="stop")return A.cancel({kind:"user"},{keepInbox:!0}),!0;if(e==="steer")return typeof a!="string"||!a.trim()?!1:(A.inject(Lpe(a)),!0);throw new TypeError(`Unsupported Harness control action: ${String(e)}`)}}}function Kpe(n){return({sessionId:t,operation:o})=>{if(typeof o!="function")throw new TypeError("maintenance operation is required");let i=n.get(t);if(!i)return o();try{return i.runMaintenance(e=>{if(n.get(t)!==i){let a=new Error("Session agent changed before maintenance started");throw a.code="agent-unavailable",a}return o(e)})}catch(e){throw Upe(e)}}}function xpe(n){return({sessionId:t,workspace:o,files:i,signal:e})=>{let A=n.get(t)?.session?.header?.cwd,r=typeof A=="string"&&A?A:o;if(typeof r!="string"||!r)throw new ho("inbound-file-workspace-unavailable","The Harness Session workspace is unavailable for inbound files.");return MK({files:i},{workspace:r,signal:e})}}function Ra(n,t={}){let{controlExecutor:o,sessionMaintenanceExecutor:i,fileIngressExecutor:e}=t;if(o!==void 0&&typeof o!="function")throw new TypeError("controlExecutor must be a function");if(i!==void 0&&typeof i!="function")throw new TypeError("sessionMaintenanceExecutor must be a function");if(e!==void 0&&typeof e!="function")throw new TypeError("fileIngressExecutor must be a function");let a=o&&i&&e?void 0:Gpe(n);return{controlExecutor:o??(a?Hpe(a):void 0),sessionMaintenanceExecutor:i??(a?Kpe(a):void 0),fileIngressExecutor:e??xpe(a??{get:()=>{}})}}function Jpe(n,t){if(t!==void 0)return new URL(t);let o=n?.port;if(!Number.isInteger(o)||o<1||o>65535)throw new Error("dsh-dingtalk requires an initialized DSH webServer port");return new URL(`http://127.0.0.1:${o}`)}function qpe(n){let t=AI(n.dshHome??process.env.DSH_HOME??tE(jpe(),".dsh")),o=AI(n.dataDir??tE(t,"integrations","dsh-dingtalk"));return{root:o,config:AI(n.configPath??tE(o,"config.json")),bots:AI(n.botsDir??tE(o,"bots")),workspaces:AI(n.workspacesPath??tE(o,"workspaces.json"))}}async function hM(n,t={},o={}){if(!n?.credentials)throw new TypeError("dsh-dingtalk requires ctx.credentials");if(!n?.webServer)throw new TypeError("dsh-dingtalk requires ctx.webServer");let i=o.ConfigStore??cf,e=o.DeviceAuth??lf,a=o.StateStore??bf,A=o.HarnessClient??wf,r=o.Controller??xh,s=o.Runtime??Xh,g=o.createConnectionSupervisor??dM,c=typeof n.logger=="function"?n.logger("dsh-dingtalk"):n.logger??console,I=()=>Oa(n),d=qpe(t),B=await new i(d.config).load(),f=AI(t.workspace??process.cwd()),Q=o.WorkspaceStore??Zr,y=o.workspaces??await new Q(d.workspaces,{defaultWorkspace:f}).load(),m=typeof B.list=="function",_=m?B.list():[];m&&await y.reconcile(_.map(W=>W.botId)),await Promise.all(_.map(W=>y.ensure(W.botId,{defaultAgentPreset:t.agentPreset})));let N=typeof B.remove=="function"?Ma(B,{workspaces:y}):B,G=o.deviceAuth??new e({baseUrl:t.registrationBaseUrl}),Y=new Map,J=W=>AI(d.bots,W,"state.json"),H=async W=>{let ae=Y.get(W);return ae||(ae=await new a(J(W)).load(),Y.set(W,ae)),ae},j=Na(n,o.commandExecutor),{controlExecutor:q,sessionMaintenanceExecutor:U,fileIngressExecutor:R}=Ra(n,{controlExecutor:o.controlExecutor,sessionMaintenanceExecutor:o.sessionMaintenanceExecutor,fileIngressExecutor:o.fileIngressExecutor}),V=new A({baseUrl:Jpe(n.webServer,t.harnessBaseUrl),workspace:f,autostart:!1,dshBin:t.dshBin??"dsh",...j?{commandExecutor:j}:{},...q?{controlExecutor:q}:{},...U?{sessionMaintenanceExecutor:U}:{},...R?{fileIngressExecutor:R}:{}}),L=new r({deviceAuth:G,credentials:n.credentials,configStore:N,logger:c,createRuntime:async({botId:W,config:ae,clientSecret:ge})=>{let Se=await H(W);await y.ensure(W,{defaultAgentPreset:t.agentPreset});let de=_a(V,{botId:W,workspaces:y,state:Se,agentPresetCatalog:I});return new s({config:ae,clientSecret:ge,harness:de.harness,state:de.state,replyTimeoutMs:t.replyTimeoutMs??6e5,maxMessageChars:t.maxMessageChars??4e3,connectTimeoutMs:t.connectTimeoutMs??15e3,logger:{error:(...De)=>c.error?.(`[${W}]`,...De),warn:(...De)=>c.warn?.(`[${W}]`,...De),info:(...De)=>c.info?.(`[${W}]`,...De),debug:(...De)=>c.debug?.(`[${W}]`,...De)}})},deleteState:async({botId:W})=>{let ae=Y.get(W);if(Y.delete(W),ae&&typeof ae.remove=="function")await ae.remove();else try{await Ype(J(W))}catch(ge){if(ge?.code!=="ENOENT")throw ge}}}),T=Ta(L,{workspaces:y,stateFor:H,agentPresetCatalog:I}),P=g({controller:T,harness:V,logger:c,retryDelaysMs:t.retryDelaysMs,healthyIntervalMs:t.healthyIntervalMs}).start();return{controller:T,ready:P.ready,async close(){await P.close(),await T.close(),V.stopManagedProcess()}}}import Zpe from"qrcode";var zpe=new Set(["loopback","trusted-host"]);function yr(n){if(n===void 0)return"loopback";if(zpe.has(n))return n;throw new TypeError('dsh-im rpcAuthority must be "loopback" or "trusted-host"')}import{isAbsolute as Vpe}from"node:path";var hi="bot.workspace.set";function ka(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)&&Object.keys(n).every(t=>["botId","workspace"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&typeof n.workspace=="string"&&n.workspace.length<=4096&&Vpe(n.workspace.trim())}function va(n){return["workspace-not-absolute","workspace-not-found","workspace-not-directory","workspace-bot-not-found","agent-preset-invalid","agent-preset-unavailable"].includes(n?.code)?{code:n.code,message:n.message}:null}var Ei="bot.preset.set";function Wpe(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function Pa(n){return Wpe(n)&&Object.keys(n).every(t=>["botId","agentPreset"].includes(t))&&typeof n.botId=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n.botId)&&(n.agentPreset===null||typeof n.agentPreset=="string"&&zb.test(n.agentPreset))}var cx="/dingtalk",ar=Object.freeze({status:"connection.status",beginProvisioning:"provision.begin",pollProvisioning:"provision.poll",cancelProvisioning:"provision.cancel",bindCredentials:"bot.bind-credentials",reconnectBot:"bot.reconnect",deleteBot:"bot.delete",setWorkspace:hi,setAgentPreset:Ei,approveSender:"bot.sender.approve",revokeSender:"bot.sender.revoke"}),Ix=Object.freeze(Object.values(ar)),Xpe=new Set(["clientSecret","client_secret","deviceCode","device_code","secretRef","staffId","senderStaffId","verificationUrl","verificationUri","userCode"]);function CM(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function vg(n,t){return CM(n)&&Object.keys(n).every(o=>t.includes(o))}function tI(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{1,128}$/.test(n)}function gx(n,t){return typeof n=="string"&&n.trim().length>0&&n.length<=t}function $pe(n,t){return CM(t)?n===ar.status?vg(t,[])?null:"connection.status does not accept fields.":n===ar.beginProvisioning?vg(t,["locale"])&&(t.locale===void 0||t.locale==="zh-CN")?null:"provision.begin received unsupported fields.":[ar.pollProvisioning,ar.cancelProvisioning].includes(n)?vg(t,["attemptId"])&&tI(t.attemptId)?null:`${n} requires an attemptId.`:n===ar.bindCredentials?vg(t,["clientId","clientSecret"])&&gx(t.clientId,256)&&gx(t.clientSecret,1024)?null:"bot.bind-credentials requires Client ID and Client Secret.":n===ar.reconnectBot?vg(t,["botId","sendTest"])&&tI(t.botId)&&(t.sendTest===void 0||t.sendTest===!0)?null:"bot.reconnect requires a botId and optional sendTest=true.":n===ar.deleteBot?vg(t,["botId","confirm"])&&tI(t.botId)&&t.confirm===!0?null:"bot.delete requires a botId and confirm=true.":n===ar.setWorkspace?ka(t)?null:"\u8BF7\u8F93\u5165\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84\u3002":n===ar.setAgentPreset?Pa(t)?null:"\u8BF7\u9009\u62E9 Agent Preset\u3002":n===ar.approveSender?vg(t,["botId","requestId","confirm"])&&tI(t.botId)&&tI(t.requestId)&&t.confirm===!0?null:"bot.sender.approve requires botId, requestId, and confirm=true.":n===ar.revokeSender?vg(t,["botId","senderKey","confirm"])&&tI(t.botId)&&tI(t.senderKey)&&t.confirm===!0?null:"bot.sender.revoke requires botId, senderKey, and confirm=true.":"Unknown DingTalk endpoint.":"Payload must be an object."}function _f(n){return{ok:!1,error:{code:"bad-request",message:n}}}function rE(){return{ok:!1,error:{code:"cancelled",message:"The request was cancelled."}}}function ede(){return{ok:!1,error:{code:"dingtalk-operation-failed",message:"\u9489\u9489\u64CD\u4F5C\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"}}}function zl(n){if(Array.isArray(n))return n.map(zl);if(!CM(n))return n;let t={};for(let[o,i]of Object.entries(n))Xpe.has(o)||(t[o]=zl(i));return t}async function Ade(n){return Zpe.toDataURL(n,{type:"image/png",errorCorrectionLevel:"M",margin:2,width:320})}async function EM(n,t){return!n||typeof n.verificationUrl!="string"?zl(n):zl({...n,qrCodeDataUrl:await t(n.verificationUrl)})}async function Pg(n,t){let o=structuredClone(n);return o?.provisioning&&(o.provisioning=await EM(o.provisioning,t)),zl(o)}function tde(n){for(let t of["status","startProvisioning","registrationStatus","cancelProvisioning","bindCredentials","reconnectBot","deleteBot","approveSender","revokeSender"])if(typeof n?.[t]!="function")throw new TypeError(`A complete DingTalk controller is required (${t})`)}function lx(n,{encodeQr:t=Ade}={}){tde(n);let o=new Map,i=e=>{let a=o.get(e);return a||(o.size>=16&&o.delete(o.keys().next().value),a=Promise.resolve().then(()=>t(e)),o.set(e,a)),a};return async(e,a,A)=>{if(A?.aborted)return rE();if(!Ix.includes(e))return _f("Unknown DingTalk endpoint.");let r=$pe(e,a);if(r)return _f(r);try{let s;if(e===ar.status)s=await Pg(await n.status(),i);else if(e===ar.beginProvisioning){let g=await n.startProvisioning({signal:A});if(A?.aborted)return await n.cancelProvisioning(g.attemptId),rE();s=await EM(g,i)}else if(e===ar.pollProvisioning){let g=await n.registrationStatus(a.attemptId);if(!g)return _f("The provisioning attempt no longer exists.");s=await EM(g,i)}else if(e===ar.cancelProvisioning){if(s=await n.cancelProvisioning(a.attemptId),!s)return _f("The provisioning attempt no longer exists.");s=zl(s)}else if(e===ar.bindCredentials)s=await Pg(await n.bindCredentials(a),i);else if(e===ar.reconnectBot){let g=await n.reconnectBot(a.botId);if(A?.aborted)return rE();let c;if(a.sendTest===!0)if(!g?.bots?.some(d=>d?.botId===a.botId&&d?.connected===!0)||typeof n.sendConnectionTest!="function")c=rr(Ir("\u9489\u9489\u673A\u5668\u4EBA"));else try{await n.sendConnectionTest(a.botId),c=rr()}catch(d){c=rr(d)}s=await Pg({...g,...c?{testMessage:c}:{}},i)}else if(e===ar.deleteBot)s=await Pg(await n.deleteBot(a.botId),i);else if(e===ar.setWorkspace){if(typeof n.updateWorkspace!="function")throw new Error("Workspace update is unavailable");s=await Pg(await n.updateWorkspace(a.botId,a.workspace),i)}else if(e===ar.setAgentPreset){if(typeof n.updateAgentPreset!="function")throw new Error("Agent preset update is unavailable");s=await Pg(await n.updateAgentPreset(a.botId,a.agentPreset),i)}else e===ar.approveSender?s=await Pg(await n.approveSender(a.botId,a.requestId),i):s=await Pg(await n.revokeSender(a.botId,a.senderKey),i);return A?.aborted?rE():{ok:!0,value:s}}catch(s){let g=va(s);return A?.aborted?rE():g?{ok:!1,error:g}:ede()}}}function Tf(n,t,o,i){if(!n?.connection?.rpc||typeof n.connection.rpc.handle!="function")throw new TypeError("DSH Host Connection RPC is required");return n.connection.rpc.handle(cx,lx(t,o),{authority:yr(i)})}async function px(n,t={}){if(t?.controller)return Tf(n,t.controller,t.rpcOptions,t.rpcAuthority);let o=await hM(n,t,t.internals),i=Tf(n,o.controller,t.rpcOptions,t.rpcAuthority);return n.effect(()=>async()=>{await o.close()},"dsh-dingtalk: close bot connections"),i}import{createHash as rde}from"node:crypto";import{mkdir as ade,readFile as ide,rename as ode,unlink as nde,writeFile as sde}from"node:fs/promises";import{dirname as gde}from"node:path";var uM=Object.freeze({version:1,bots:Object.freeze([])});function Gs(n){return typeof n=="string"&&n.trim()?n.trim():null}function dx(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function aE(n,{botPrefix:t,tokenRefPrefix:o}){let i=Gs(n);if(!i)throw new TypeError("platformId is required");let e=rde("sha256").update(i).digest("hex").slice(0,24);return{botId:`${t}_${e}`,tokenRef:`${o}_${e.toUpperCase()}`}}function Nf(n,t){let o=Gs(n)??"";return o.length<=10?o?`${o.slice(0,3)}\u2022\u2022\u2022`:t:`${o.slice(0,6)}\u2022\u2022\u2022\u2022${o.slice(-4)}`}var Vl=class{#e;#A;#t;#r;#a;#i;#c;#s=uM;#I=Promise.resolve();constructor(t,{channel:o,botPrefix:i,tokenRefPrefix:e,normalizeBotExtension:a=()=>({})}){if(typeof a!="function")throw new TypeError("normalizeBotExtension must be a function");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=new RegExp(`^${dx(i)}_[a-f0-9]{24}$`),this.#c=new RegExp(`^${dx(e)}_[A-F0-9]{24}$`)}async load(){try{let t=this.#n(JSON.parse(await ide(this.#e,"utf8")));if(!t)throw new Error(`dsh-im ${this.#A} config contains invalid bot data`);this.#s=t}catch(t){if(t?.code!=="ENOENT")throw t;this.#s=uM}return this}list(){return structuredClone(this.#s.bots)}get(t){let o=this.#s.bots.find(i=>i.botId===t);return o?structuredClone(o):null}getByPlatformId(t){let o=this.#s.bots.find(i=>i.platformId===t);return o?structuredClone(o):null}async save(t){let o=this.#o(t);if(!o)throw new Error(`Refusing to persist incomplete ${this.#A} bot data`);return this.#g(i=>{let e=i.find(r=>r.platformId===o.platformId&&r.botId!==o.botId),a=i.find(r=>r.tokenRef===o.tokenRef&&r.botId!==o.botId);if(e||a)throw new Error(`Duplicate ${this.#A} bot identity`);let A=i.findIndex(r=>r.botId===o.botId);return A===-1?i.push(o):i[A]=o,structuredClone(o)})}async remove(t){if(!this.#i.test(t))throw new TypeError(`Invalid ${this.#A} bot id`);return this.#g(o=>{let i=o.findIndex(a=>a.botId===t);if(i===-1)return null;let[e]=o.splice(i,1);return structuredClone(e)})}async clear(){let t=this.#I.then(async()=>{try{await nde(this.#e)}catch(o){if(o?.code!=="ENOENT")throw o}this.#s=uM});this.#I=t.then(()=>{},()=>{}),await t}#o(t){if(!t||typeof t!="object")return null;let o=Gs(t.platformId),i=Gs(t.botId),e=Gs(t.tokenRef),a=Gs(t.name);if(!o||!i||!e||!a||!this.#i.test(i)||!this.#c.test(e))return null;let A=aE(o,{botPrefix:this.#t,tokenRefPrefix:this.#r});if(A.botId!==i||A.tokenRef!==e)return null;let r=this.#a(t);return!r||typeof r!="object"||Array.isArray(r)?null:Object.freeze({botId:i,platformId:o,tokenRef:e,name:a,username:Gs(t.username),createdAt:Gs(t.createdAt)??new Date().toISOString(),connectedAt:Gs(t.connectedAt),...r})}#n(t){if(!t||t.version!==1||!Array.isArray(t.bots))return null;let o=t.bots.map(A=>this.#o(A));if(o.some(A=>A===null))return null;let i=new Set,e=new Set,a=new Set;for(let A of o){if(i.has(A.botId)||e.has(A.platformId)||a.has(A.tokenRef))return null;i.add(A.botId),e.add(A.platformId),a.add(A.tokenRef)}return Object.freeze({version:1,bots:Object.freeze(o)})}async#g(t){let o,i=this.#I.then(async()=>{let e=[...this.#s.bots];o=t(e);let a=Object.freeze({version:1,bots:Object.freeze(e)});await this.#l(a),this.#s=a});return this.#I=i.then(()=>{},()=>{}),await i,o}async#l(t){await ade(gde(this.#e),{recursive:!0,mode:448});let o=`${this.#e}.tmp`;await sde(o,`${JSON.stringify(t,null,2)} `,{encoding:"utf8",mode:384}),await ode(o,this.#e)}};var hx=Object.freeze({botPrefix:"discord",tokenRefPrefix:"DSH_DISCORD_BOT_TOKEN"});function Ex(n){return aE(n,hx)}function Cx(n){return Nf(n,D("Discord\u673A\u5668\u4EBA"))}var Rf=class extends Vl{constructor(t){super(t,{channel:"Discord",...hx})}};function iE(n){return typeof n=="string"&&n.trim()?n.trim():null}function oE(n,t){return Object.freeze({code:n,message:t})}var Wl=class{#e;#A;#t;#r;#a;#i;#c;#s;#I;#o=new Map;#n=new Map;#g=new Map;#l=0;#p=!1;constructor({descriptor:t,credentials:o,configStore:i,inspectToken:e,deriveIdentity:a,maskPlatformId:A,createRuntime:r,deleteState:s=async()=>{},logger:g=console}){if(!t?.key||!t?.label||!t?.connectionLabel)throw new TypeError("TokenBotController requires a channel descriptor");if(!o||typeof o.resolve!="function"||typeof o.set!="function"||typeof o.unset!="function")throw new TypeError(`${t.label} requires the DSH credential provider`);if(!i||typeof i.list!="function"||typeof i.save!="function"||typeof i.remove!="function")throw new TypeError(`${t.label} requires a config store`);if(typeof e!="function"||typeof a!="function"||typeof A!="function"||typeof r!="function")throw new TypeError(`${t.label} controller dependencies are incomplete`);this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=A,this.#c=r,this.#s=s,this.#I=g}async initialize(){if(this.#p)return this.status();for(let t of this.#t.list())await this.#B(t.botId,async()=>{if(this.#p||this.#o.get(t.botId)?.status?.ready)return;let o=await this.#E(t.tokenRef);if(!o){this.#n.set(t.botId,oE("missing-token",D("{label}\u673A\u5668\u4EBA\u51ED\u636E\u7F3A\u5931\uFF0C\u8BF7\u79FB\u9664\u540E\u91CD\u65B0\u63A5\u5165\u3002",{label:this.#e.label})));return}try{await this.#d(t,o),this.#n.delete(t.botId)}catch(i){this.#n.set(t.botId,oE("connection-failed",D("{label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5\u3002",{label:this.#e.label}))),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${t.botId} failed to initialize:`,i)}finally{this.#f()}});return this.status()}async bindCredentials({token:t}={}){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let o=iE(t);if(!o)throw new TypeError(`${this.#e.label} Bot Token is required`);let i=await this.#r(o),e=iE(i?.platformId),a=iE(i?.name);if(!e||!a)throw new Error(`${this.#e.label} returned an invalid bot identity`);let A=this.#a(e);return await this.#B(A.botId,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let r=this.#t.getByPlatformId(e),s=await this.#A.resolve(A.tokenRef).catch(()=>{}),g={botId:A.botId,platformId:e,tokenRef:A.tokenRef,name:a,username:iE(i.username),createdAt:r?.createdAt??new Date().toISOString(),connectedAt:new Date().toISOString()};await this.#A.set(A.tokenRef,o);try{await this.#t.save(g)}catch(c){throw await this.#u(A.tokenRef,s),c}try{await this.#d(g,o),this.#n.delete(A.botId)}catch(c){this.#n.set(A.botId,oE("connection-failed",D("{label}\u673A\u5668\u4EBA\u5DF2\u63A5\u5165\uFF0C\u6D88\u606F\u8FDE\u63A5\u6682\u672A\u5C31\u7EEA\u3002",{label:this.#e.label}))),this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${A.botId} credential connection failed:`,c)}this.#f()}),this.status()}async reconnectBot(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(t,async()=>{let i=await this.#E(o.tokenRef);if(!i)throw new Error(`${this.#e.label} bot token is missing`);try{await this.#d(o,i),this.#n.delete(t)}catch(e){throw this.#n.set(t,oE("connection-failed",D("{label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{label:this.#e.label}))),e}finally{this.#f()}}),this.status()}async updateBotConfig(t,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(typeof o!="function")throw new TypeError("Bot config update must be a function");return await this.#B(t,async()=>{if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=this.#t.get(t);if(!i)throw new Error(`Unknown ${this.#e.label} bot`);let e=await this.#E(i.tokenRef);if(!e)throw new Error(`${this.#e.label} bot token is missing`);if(this.#p)throw new Error(`${this.#e.label} controller is closed`);let a=o(i),A=await this.#t.save(a);try{await this.#d(A,e),this.#n.delete(t)}catch(r){throw this.#n.set(t,oE("connection-failed",D("{label}\u8FDE\u63A5\u4ECD\u672A\u5C31\u7EEA\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{label:this.#e.label}))),r}finally{this.#f()}}),this.status()}async sendConnectionTest(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return this.#B(t,async()=>{let i=this.#o.get(t);if(!i?.status?.ready||typeof i.sendConnectionTest!="function"){let a=new Error(D("{label}\u673A\u5668\u4EBA\u5C1A\u672A\u8FDE\u63A5",{label:this.#e.label}));throw a.code="test-target-unavailable",a}let e=D("{name}\uFF08{id}\uFF09",{name:o.name,id:this.#i(o.platformId)});return await i.sendConnectionTest(ma(e,D("{label}\u673A\u5668\u4EBA",{label:this.#e.label}))),{sent:!0}})}async deleteBot(t){let o=this.#t.get(t);if(!o)throw new Error(`Unknown ${this.#e.label} bot`);return await this.#B(t,async()=>{let i=await this.#A.resolve(o.tokenRef).catch(()=>{});await this.#h(t);try{await this.#A.unset(o.tokenRef),await this.#t.remove(t)}catch(e){throw i?.value&&(await this.#A.set(o.tokenRef,i.value).catch(()=>{}),await this.#d(o,i.value).catch(()=>{})),new Error(`Unable to remove the ${this.#e.label} bot safely.`,{cause:e})}await this.#s({botId:t,config:o}).catch(e=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${t} state cleanup failed:`,e)}),this.#n.delete(t),this.#f()}),this.status()}status(){let t=this.#t.list().map(i=>{let e=this.#o.get(i.botId)?.status??null,a=e?.ready===!0&&e.connectionState==="connected"&&e.harnessReachable===!0,A=a?"connected":e?.connectionState==="connecting"?"connecting":this.#n.has(i.botId)||e?.connectionState==="failed"?"error":"offline";return{botId:i.botId,state:A,connected:a,configured:!0,bot:{name:i.name,username:i.username,idMasked:this.#i(i.platformId)},health:{status:a?"healthy":A==="error"?"error":"offline",summary:a?D("{label}{connectionLabel}\u8FD0\u884C\u6B63\u5E38",{label:this.#e.label,connectionLabel:D(this.#e.connectionLabel)}):A==="error"?D("{label}\u8FDE\u63A5\u672A\u5C31\u7EEA\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u91CD\u8BD5",{label:this.#e.label}):D("{label}\u8FDE\u63A5\u5F53\u524D\u79BB\u7EBF",{label:this.#e.label}),lastCheckedAt:e?.lastCheckedAt??null,lastConnectedAt:e?.lastConnectedAt??null},stats:{messagesReceived:e?.messagesReceived??0,messagesReplied:e?.messagesReplied??0},lastMessageError:qr(e?.lastMessageError),error:structuredClone(this.#n.get(i.botId)??null)}}),o=t.filter(i=>i.connected).length;return{schemaVersion:1,revision:this.#l,state:t.length===0?"disconnected":o===t.length?"connected":o>0?"degraded":"offline",bots:t,totals:{configured:t.length,connected:o}}}async close(){this.#p||(this.#p=!0,await Promise.allSettled([...this.#g.values()]),await Promise.allSettled([...this.#o.keys()].map(t=>this.#h(t))))}async#d(t,o){if(this.#p)throw new Error(`${this.#e.label} controller is closed`);if(await this.#h(t.botId),this.#p)throw new Error(`${this.#e.label} controller is closed`);let i=await this.#c({botId:t.botId,config:t,token:o});if(!i||typeof i.start!="function"||typeof i.stop!="function")throw new TypeError(`createRuntime returned an invalid ${this.#e.label} runtime`);this.#o.set(t.botId,i);try{await i.start()}catch(e){throw await i.stop().catch(()=>{}),this.#o.delete(t.botId),e}}async#h(t){let o=this.#o.get(t);this.#o.delete(t),await o?.stop().catch(i=>{this.#I.warn?.(`[dsh-im:${this.#e.key}] bot ${t} failed to stop cleanly:`,i)})}async#E(t){let o=await this.#A.resolve(t).catch(()=>{});return iE(o?.value)}async#u(t,o){o?.value?await this.#A.set(t,o.value).catch(()=>{}):await this.#A.unset(t).catch(()=>{})}#B(t,o){let a=(this.#g.get(t)??Promise.resolve()).catch(()=>{}).then(o).finally(()=>{this.#g.get(t)===a&&this.#g.delete(t)});return this.#g.set(t,a),a}#f(){this.#l+=1}};import{createHash as cde}from"node:crypto";var Ide="https://discord.com/api/v10/",lde=12e4,pde=new Set([50001,50013]),dde=new Set([40005]);function vn(n){return typeof n=="string"&&n.trim()?n.trim():null}function ux(n,t){let o=AbortSignal.timeout(t);return n?AbortSignal.any([n,o]):o}function BM(n){return n?.reason instanceof Error?n.reason:new DOMException("The operation was aborted","AbortError")}function hde(n,t){if(!Number.isInteger(n)||n<1)throw new TypeError(`${t} must be a positive integer`);return n}function fx(n,t){return t?.providerCode!==void 0&&(n.providerCode=t.providerCode),t?.retry_after!==void 0&&(n.retry_after=t.retry_after,n.retryAfter=t.retry_after),Number.isInteger(t?.status)&&(n.status=t.status),n}function Ede(n){let t=Number(n?.providerCode),o=Number(n?.status),i=vn(n?.message)??"",e="artifact-provider-rejected",a="Discord rejected the attachment.";o===401||o===403||pde.has(t)?(e="artifact-permission-required",a="Discord denied permission to send the attachment."):o===413||dde.has(t)||/(?:request|attachment|file).{0,24}too large/i.test(i)?(e="artifact-too-large",a="The attachment exceeds Discord's size limit."):o===429?(e="artifact-rate-limited",a="Discord rate-limited attachment delivery."):o>=500&&(e="artifact-delivery-uncertain",a="Discord attachment delivery result is uncertain.");let A=new Error(a,{cause:n});return A.code=e,fx(A,n)}function Cde(n){let t=new Error("Discord attachment delivery result is uncertain",{cause:n});return t.code="artifact-delivery-uncertain",fx(t,n)}function ude(n,t){return new Promise((o,i)=>{if(t?.aborted){i(t.reason??new DOMException("Aborted","AbortError"));return}let e=setTimeout(o,n);e?.unref?.(),t?.addEventListener("abort",()=>{clearTimeout(e),i(t.reason??new DOMException("Aborted","AbortError"))},{once:!0})})}function Ga(n,t){let o=vn(n);if(!o||!/^\d{5,30}$/.test(o))throw new TypeError(`Invalid Discord ${t}`);return o}function Bx(n){let t=vn(n);if(!t)throw new TypeError("A Discord reaction emoji is required");return t}function Bde(n){return typeof n=="string"&&/^[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{20,}$/.test(n.trim())}var nE=class{#e;#A;#t;#r;constructor({token:t,fetchImpl:o=fetch,baseUrl:i=Ide,fileUploadTimeoutMs:e=lde}){if(!Bde(t))throw new TypeError("Discord Bot Token is invalid");if(typeof o!="function")throw new TypeError("DiscordApi requires fetch");this.#e=t.trim(),this.#A=o,this.#t=new URL(i),this.#r=hde(e,"fileUploadTimeoutMs")}getCurrentUser(t={}){return this.#a("users/@me",{...t,method:"GET"})}getGatewayBot(t={}){return this.#a("gateway/bot",{...t,method:"GET"})}getChannel({channelId:t,signal:o}={}){return this.#a(`channels/${Ga(t,"channel id")}`,{method:"GET",signal:o})}startThreadFromMessage({channelId:t,messageId:o,name:i,signal:e}={}){let a=vn(i);if(!a||[...a].length>100)throw new TypeError("Discord thread name must contain 1-100 characters");if(e?.aborted)throw BM(e);return this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}/threads`,{method:"POST",signal:e,body:{name:a}})}createMessage({channelId:t,content:o,replyToMessageId:i,signal:e}){return this.#a(`channels/${Ga(t,"channel id")}/messages`,{method:"POST",signal:e,body:{content:o,allowed_mentions:{parse:[],replied_user:!1},...i?{message_reference:{message_id:Ga(i,"message id"),channel_id:Ga(t,"channel id"),fail_if_not_exists:!1}}:{}}})}async createFileMessage({channelId:t,file:o,replyToMessageId:i,signal:e}){if(!o||typeof o!="object"||typeof o.fileName!="string"||!o.fileName||!Buffer.isBuffer(o.bytes))throw new TypeError("A Discord attachment is required");let a=vn(o.deliveryKey)??vn(o.artifactId),A=a?cde("sha256").update(a).digest("hex").slice(0,25):void 0,r=new FormData;r.append("payload_json",JSON.stringify({allowed_mentions:{parse:[],replied_user:!1},attachments:[{id:0,filename:o.fileName}],...A?{nonce:A,enforce_nonce:!0}:{},...i?{message_reference:{message_id:Ga(i,"message id"),channel_id:Ga(t,"channel id"),fail_if_not_exists:!1}}:{}})),r.append("files[0]",new Blob([o.bytes],{type:o.mediaType??"application/octet-stream"}),o.fileName);let s=Ga(t,"channel id");if(e?.aborted)throw BM(e);let g=ux(e,this.#r);try{return await this.#a(`channels/${s}/messages`,{method:"POST",signal:g,timeoutMs:this.#r,body:r,multipart:!0})}catch(c){throw e?.aborted?BM(e):c?.code?.startsWith?.("discord-")?Ede(c):Cde(c)}}editMessage({channelId:t,messageId:o,content:i,signal:e}){return this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}`,{method:"PATCH",signal:e,body:{content:i,allowed_mentions:{parse:[],replied_user:!1}}})}sendTyping({channelId:t,signal:o}){return this.#a(`channels/${Ga(t,"channel id")}/typing`,{method:"POST",signal:o,expectBody:!1})}async addOwnReaction({channelId:t,messageId:o,emoji:i,signal:e}={}){let a=Bx(i);return await this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}/reactions/${encodeURIComponent(a)}/@me`,{method:"PUT",signal:e,expectBody:!1,retry:!1}),a}removeOwnReaction({channelId:t,messageId:o,emoji:i,signal:e}={}){let a=Bx(i);return this.#a(`channels/${Ga(t,"channel id")}/messages/${Ga(o,"message id")}/reactions/${encodeURIComponent(a)}/@me`,{method:"DELETE",signal:e,expectBody:!1,retry:!1})}async#a(t,{method:o,body:i,signal:e,timeoutMs:a=15e3,expectBody:A=!0,retry:r=!0,multipart:s=!1}){let g;try{g=await this.#A(new URL(t,this.#t),{method:o,headers:{authorization:`Bot ${this.#e}`,...s?{}:{"content-type":"application/json"},"user-agent":"DeepSeek-Harness-dsh-im (https://github.com/xmanrui/dsh-im, 1.1.0)"},...i===void 0?{}:{body:s?i:JSON.stringify(i)},signal:ux(e,a),redirect:"error"})}catch(I){throw I?.name==="AbortError"||I?.name==="TimeoutError"?I:new Error(`Discord ${o} transport failed`)}let c=null;if(A||g.status===429||!g.ok)try{c=await g.json()}catch{if(A){let I=new Error(`Discord ${o} returned invalid JSON`);throw I.status=g?.status,I}}if(g.status===429&&r){let I=Math.min(1e4,Math.max(50,Number(c?.retry_after)*1e3||1e3));return await ude(I,e),this.#a(t,{method:o,body:i,signal:e,timeoutMs:a,expectBody:A,retry:!1,multipart:s})}if(!g.ok){let I=new Error(vn(c?.message)??`Discord API failed with HTTP ${g.status}`);I.code=`discord-${g.status}`,I.status=g.status,(Number.isInteger(c?.code)||typeof c?.code=="string")&&(I.providerCode=c.code);let d=Number(c?.retry_after);throw Number.isFinite(d)&&d>=0&&(I.retry_after=d,I.retryAfter=d),I}return A?c:null}};async function Qx(n,t={}){let i=await new nE({token:n,...t}).getCurrentUser();if(!i?.id||i?.bot!==!0)throw new Error("Discord token does not belong to a bot");return{platformId:String(i.id),name:vn(i.global_name)??vn(i.username)??D("Discord\u673A\u5668\u4EBA"),username:vn(i.username)}}var fde=Object.freeze({success(){},error(){},clear(){},settled:()=>Promise.resolve()});function yx(n,t){!n||typeof n!="object"||(n[t]=(n[t]??0)+1)}async function Qde(n,t){let o=AbortSignal.timeout(t),i,e=new Promise((a,A)=>{i=()=>A(o.reason??new DOMException("Timed out","TimeoutError")),o.addEventListener("abort",i,{once:!0})});try{return await Promise.race([n(o),e])}finally{o.removeEventListener("abort",i)}}function kf({adapter:n,target:t,reactions:o,status:i,logger:e=console,label:a="channel",timeoutMs:A=2e3}={}){if(!t||typeof n?.addReaction!="function"||typeof n?.removeReaction!="function"||typeof o?.processing!="string"||!o.processing||!Number.isSafeInteger(A)||A<=0)return fde;let r=null,s=!1,g=async(B,f)=>{try{let Q=await Qde(f,A);return yx(i,B==="add"?"reactionsAdded":"reactionsRemoved"),{ok:!0,value:Q}}catch(Q){return yx(i,"reactionErrors"),e.warn?.(`[dsh-im:${a}] status reaction ${B} failed:`,Q?.message??Q?.name??String(Q)),{ok:!1,value:null}}},c=async B=>{if(r!==null){let Q=r;r=null,await g("remove",y=>n.removeReaction(t,Q,{signal:y}))}if(typeof B!="string"||!B)return;let f=await g("add",Q=>n.addReaction(t,B,{signal:Q}));f.ok&&f.value!==void 0&&f.value!==null&&(r=f.value)},I=c(o.processing),d=B=>{s||(s=!0,I=I.then(()=>c(B),()=>c(B)),I.catch(()=>{}))};return Object.freeze({success:()=>d(o.success),error:()=>d(o.error),clear:()=>d(null),settled:()=>I})}var mx="\u8FD9\u4E2A\u95EE\u9898\u5DF2\u5728\u5176\u4ED6\u5BA2\u6237\u7AEF\u5904\u7406\uFF0C\u65E0\u9700\u518D\u6B21\u56DE\u7B54\u3002",yde="\u4EFB\u52A1\u5DF2\u5B8C\u6210\u3002";function Ci(n){return typeof n=="string"?n.trim():""}function mde(n,t,o){return t.actor===o&&(n.kind!=="group"||n.addressed===!0)&&!qt(n)&&!Gt(n)&&!!Ci(n.content)}function Sde(n,t,o){let i=String(n??D("\u7ED3\u679C\u6587\u4EF6")).replace(/[\r\n]+/g," ").trim().slice(0,255)||D("\u7ED3\u679C\u6587\u4EF6");switch(t?.code){case"artifact-delivery-uncertain":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u7684\u53D1\u9001\u7ED3\u679C\u672A\u80FD\u786E\u8BA4\uFF0C\u8BF7\u5148\u68C0\u67E5\u804A\u5929\u5185\u662F\u5426\u5DF2\u6536\u5230\uFF0C\u4E0D\u8981\u7ACB\u5373\u91CD\u8BD5\u3002",{name:i});case"artifact-permission-required":return o?.key==="slack"?D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46 Slack \u5E94\u7528\u7F3A\u5C11 files:write \u6743\u9650\u3002\u8BF7\u66F4\u65B0 Manifest\u3001\u91CD\u65B0\u5B89\u88C5\u5E94\u7528\u5E76\u91CD\u65B0\u8FDE\u63A5\u673A\u5668\u4EBA\u540E\u91CD\u8BD5\u3002",{name:i}):o?.key==="discord"?D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u673A\u5668\u4EBA\u7F3A\u5C11 Discord \u7684 Send Messages\u3001Attach Files \u6216 Read Message History \u6743\u9650\u3002",{name:i}):o?.key==="telegram"?D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46 Telegram \u4E0D\u5141\u8BB8\u673A\u5668\u4EBA\u5728\u5F53\u524D\u804A\u5929\u53D1\u9001\u6587\u6863\uFF0C\u8BF7\u68C0\u67E5\u804A\u5929\u6743\u9650\u3002",{name:i}):D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u673A\u5668\u4EBA\u6CA1\u6709\u6587\u4EF6\u53D1\u9001\u6743\u9650\uFF0C\u8BF7\u68C0\u67E5\u6E20\u9053\u6743\u9650\u3002",{name:i});case"artifact-too-large":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u8D85\u8FC7\u5F53\u524D\u6E20\u9053\u5927\u5C0F\u4E0A\u9650\uFF0C\u672A\u53D1\u9001\u3002",{name:i});case"artifact-empty":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u4E3A\u7A7A\uFF0C\u672A\u53D1\u9001\u3002",{name:i});case"artifact-invalid":case"artifact-changed":case"artifact-unavailable":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u6216\u51C6\u5907\u53D1\u9001\uFF0C\u8BF7\u786E\u8BA4\u6587\u4EF6\u4ECD\u53EF\u8BBF\u95EE\u540E\u91CD\u8BD5\u3002",{name:i});case"artifact-rate-limited":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u6682\u65F6\u88AB\u5F53\u524D\u6E20\u9053\u9650\u6D41\uFF0C\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:i});case"artifact-provider-rejected":return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6E20\u9053\u62D2\u7EDD\u4E86\u8BE5\u6587\u4EF6\u6216\u6587\u4EF6\u6D88\u606F\u3002",{name:i});default:return D("\u7ED3\u679C\u6587\u4EF6\u300C{name}\u300D\u5DF2\u751F\u6210\uFF0C\u4F46\u5F53\u524D\u6E20\u9053\u6682\u65F6\u672A\u80FD\u53D1\u9001\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",{name:i})}}function Ui(){return{messagesReceived:0,messagesReplied:0,messagesRejected:0,lastMessageAt:null,lastReplyAt:null,lastRejectedAt:null,lastError:null,lastMessageError:null,reactionsAdded:0,reactionsRemoved:0,reactionErrors:0}}var Pn=class{#e;#A;#t;#r;#a;#i;#c;#s;#I=new Map;#o=new Map;#n=new Map;#g=new Set;#l=new Set;#p=new Set;#d;#h=new Ii;constructor({descriptor:t,bot:o,harness:i,state:e,status:a=Ui(),logger:A=console,replyTimeoutMs:r=6e5,signal:s}){if(!t?.key||!t?.label)throw new TypeError("A channel descriptor is required");if(!o||typeof o.sendText!="function")throw new TypeError("A bot client is required");if(!i||!e)throw new TypeError("Harness client and state store are required");this.#e=t,this.#A=o,this.#t=i,this.#r=e,this.#a=a,this.#i=A,this.#c=r,this.#s=s,this.#d=new ii({label:t.key,logger:A})}get status(){return structuredClone(this.#a)}accept(t){if(this.#s?.aborted)return Promise.resolve();let o=Ci(t?.conversationId),i=t?.kind==="group"?"group":"direct",e={...t,kind:i,conversationId:o},a=Ci(e.messageId),A=Ci(e.senderId);if(!a||!A||!o||e.senderIsBot===!0||this.#r.hasSeen(a)||this.#g.has(a))return Promise.resolve();this.#g.add(a);let r=kf({adapter:this.#A,target:e.kind==="direct"||e.addressed===!0?e.reactionTarget:null,reactions:this.#e.reactions,status:this.#a,logger:this.#i,label:this.#e.key});e.statusReaction=r;let s=this.#E(e,a,A);return s.then(()=>r.success(),()=>r.error()),s}#E(t,o,i){t.kind==="direct"&&io(this.#r,t.connectionTestTarget??t.replyTarget);let e=`${t.kind}:${t.conversationId}`,a=this.#o.get(e),A=Ci(t.content),r=lo(A);if(r&&t.kind==="group"&&t.addressed===!0)return this.#u(t,o,Tn());if(r&&t.kind==="direct"){if(/^\/batch$/iu.test(A)&&(this.#I.has(e)||a||this.#d.hasPending(e)))return this.#u(t,o,po());let d=this.#h.handle(e,A,{plainText:!!A&&t.plainText!==!1&&!qt(t)&&!Gt(t)});if(d.handled)return d.kind==="submit"?this.#B({...t,content:d.prompt,batchSubmission:{token:d.token}},o,i,e):this.#u(t,o,d.message)}else if(t.kind==="direct"&&this.#h.status(e).phase==="collecting"){let I=this.#h.handle(e,A,{plainText:!!A&&t.plainText!==!1&&!qt(t)&&!Gt(t)});if(I.handled)return this.#u(t,o,I.message)}let g=t.kind==="direct"&&this.#h.status(e).phase==="collecting"||Gt(t)?null:Pi(A)?gi:Gi(A)?Fi:Li(A)?ci:null;if(g&&(t.kind!=="group"||t.addressed===!0)){let I;return I=this.#f(t,o,e,g).finally(()=>{this.#g.delete(o),this.#p.delete(I)}),this.#p.add(I),I}let c=this.#d.claimReply({key:e,actor:i,messageId:o,text:qt(t)||Gt(t)?"":t.content,addressed:t.kind!=="group"||t.addressed===!0,hasPendingQuestion:!!a,questionCompletion:a?.submitting||a?.claimedReplyMessageId?a.queue:null,isQuestionPending:()=>this.#o.has(e),send:I=>this.#A.sendText(t.replyTarget,I)});if(c){let I;return I=c.process(async()=>this.#r.hasSeen(o)?!1:(await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),!0)).finally(()=>{this.#g.delete(o),this.#l.delete(I)}),this.#l.add(I),I}if(a&&a.actor!==i)return this.#B(t,o,i,e);if(a?.submitting||a?.claimedReplyMessageId)return this.#B(t,o,i,e);if(a){mde(t,a,i)&&(a.claimedReplyMessageId=o);let d=(a.queue??Promise.resolve()).catch(()=>{}).then(()=>this.#Q(t,o,i,e,a)).finally(()=>{this.#g.delete(o),a.claimedReplyMessageId===o&&(a.claimedReplyMessageId=null),a.queue===d&&(a.queue=null)});return a.queue=d,d}return this.#B(t,o,i,e)}#u(t,o,i){let e;return e=(async()=>{this.#r.hasSeen(o)||(await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString(),i&&await this.#A.sendText(t.replyTarget,i),this.#a.lastError=null)})().catch(async a=>{if(this.#s?.aborted){t.statusReaction?.clear();return}t.statusReaction?.error(),this.#a.lastError=a?.message??String(a);let A=At(this.#a,a);this.#i.error?.(`[dsh-im:${this.#e.key}] failed to process a batch input message [${A.referenceId}]:`,a)}).finally(()=>{this.#g.delete(o),this.#p.delete(e)}),this.#p.add(e),e}#B(t,o,i,e,{releaseMessageId:a=!0,alreadyRecorded:A=!1}={}){let s=(this.#I.get(e)??Promise.resolve()).catch(()=>{}).then(()=>this.#y(t,o,i,e,{alreadyRecorded:A})).finally(()=>{a&&this.#g.delete(o),this.#I.get(e)===s&&this.#I.delete(e)});return this.#I.set(e,s),s}async waitForIdle(){await Promise.allSettled([...this.#I.values(),...[...this.#o.values()].flatMap(t=>t.queue?[t.queue]:[]),...this.#l,...this.#p])}async#f(t,o,i,e){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString();let a=t.replyTarget;try{let A=await e(Ci(t.content),this.#t,this.#r,i,{signal:this.#s,hasImages:qt(t),hasFiles:Gt(t),pendingInteraction:this.#o.has(i)||this.#d.hasPending(i),control:{owner:this,key:i}});A?.stopped&&await Promise.allSettled([this.#k(i),this.#d.closeRoute(i)]);for(let r of A?.messages??[A?.message])r&&await this.#A.sendText(a,r);this.#a.lastError=null}catch(A){if(A?.code==="turn-stopped"||this.#s?.aborted){t.statusReaction?.clear();return}t.statusReaction?.error(),this.#a.lastError=A?.message??String(A);let r=At(this.#a,A);this.#i.error?.(`[dsh-im:${this.#e.key}] failed to process a command [${r.referenceId}]:`,A),await this.#A.sendText(a,dt(r)).catch(()=>{})}}sendConnectionTest(t){return Tg({state:this.#r,text:t,channelLabel:D("{label}\u673A\u5668\u4EBA",{label:this.#e.label}),send:(o,i)=>this.#A.sendText(o,i)})}async#m(t,o,i=[],e){let a=await Co({artifacts:i,baseReceipt:e,deliveryId:o,channelKey:this.#e.key,signal:this.#s,sendImage:typeof this.#A.sendImage=="function"?A=>this.#A.sendImage(t,A):void 0,sendFile:typeof this.#A.sendFile=="function"?A=>this.#A.sendFile(t,A):void 0,onFailure:(A,r)=>At(this.#a,r,{userMessage:Sde(A?.fileName,r,this.#e),reason:r?.code}),sendFailureNotice:(A,r,s)=>this.#A.sendText(t,dt(s)),logger:this.#i});return this.#a.artifactsSent=(this.#a.artifactsSent??0)+a.artifactsSent,this.#a.artifactSendErrors=(this.#a.artifactSendErrors??0)+a.artifactSendErrors,{receipt:a.receipt,userVisible:a.userVisible,artifactSendErrors:a.artifactSendErrors}}async#y(t,o,i,e,{alreadyRecorded:a=!1}={}){if(!a){if(this.#r.hasSeen(o))return;await this.#r.markSeen(o),this.#a.messagesReceived+=1,this.#a.lastMessageAt=new Date().toISOString()}let A=t.replyTarget,r=Ci(t.content),s=t.batchSubmission,g=null,c=!1;try{if(this.#s?.throwIfAborted(),t.kind==="group"&&t.addressed!==!0){this.#a.messagesRejected+=1,this.#a.lastRejectedAt=new Date().toISOString();return}let I=qt(t),d=Gt(t);if(!r&&!I&&!d){await this.#A.sendText(A,D("\u76EE\u524D\u652F\u6301\u6587\u5B57\u3001\u56FE\u7247\u548C\u6587\u4EF6\u6D88\u606F\u3002"));return}let B=r.toLowerCase();if(!I&&!d&&B==="/help"){await this.#A.sendText(A,[D("{label}\u673A\u5668\u4EBA\u5DF2\u8FDE\u63A5 DeepSeek Harness\u3002",{label:this.#e.label}),"",D("\u76F4\u63A5\u53D1\u9001\u6587\u5B57\u3001\u56FE\u7247\u6216\u6587\u4EF6\u5373\u53EF\u7EE7\u7EED\u5F53\u524D\u4F1A\u8BDD\u3002"),D("/new \u5F00\u542F\u4E00\u4E2A\u5168\u65B0\u4F1A\u8BDD"),D("/compact \u538B\u7F29\u5F53\u524D\u4F1A\u8BDD\u7684\u8F83\u65E9\u4E0A\u4E0B\u6587"),D("/workspace \u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84 \u5207\u6362\u5DE5\u4F5C\u533A"),D("/workspacelist \u5217\u51FA\u5DE5\u4F5C\u533A\u7EDD\u5BF9\u8DEF\u5F84"),D("/sessionlist [\u5DE5\u4F5C\u533A\u5E8F\u53F7\u6216\u7EDD\u5BF9\u8DEF\u5F84] \u5217\u51FA\u4F1A\u8BDD ID \u548C\u6807\u9898"),D("/session Session ID \u6216\u5F53\u524D\u5DE5\u4F5C\u533A\u5E8F\u53F7 \u5C06\u5F53\u524D\u804A\u5929\u7ED1\u5B9A\u5230\u6307\u5B9A\u4F1A\u8BDD"),D("/models \u6309\u5E8F\u53F7\u5217\u51FA\u6240\u6709\u53EF\u7528\u6A21\u578B"),D("/reasoninglist \u6216 /reasonings \u6309\u5E8F\u53F7\u5217\u51FA\u5F53\u524D\u6A21\u578B\u53EF\u7528\u63A8\u7406\u7B49\u7EA7"),D("/reasoning [\u5E8F\u53F7\u3001\u7B49\u7EA7ID\u6216 --default] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u63A8\u7406\u7B49\u7EA7"),D("/model [\u5E8F\u53F7\u6216\u5B8C\u6574\u6A21\u578BID] [\u63A8\u7406\u7B49\u7EA7ID] \u67E5\u770B\u6216\u5207\u6362\u5F53\u524D\u4F1A\u8BDD\u6A21\u578B"),D("\u793A\u4F8B\uFF1A\u5148\u53D1 /models\uFF0C\u518D\u53D1 /model 2 [\u63A8\u7406\u7B49\u7EA7ID]"),D("/presetlist \u6309\u5E8F\u53F7\u5217\u51FA\u53EF\u7528 Agent Preset"),D("/preset [\u5E8F\u53F7\u6216\u5B8C\u6574ID] \u67E5\u770B\u6216\u8BBE\u7F6E\u5F53\u524D\u673A\u5668\u4EBA Agent Preset"),D("\u7EAF\u6570\u5B57 ID\uFF1A/preset id:"),D("/preset --default \u8DDF\u968F Host \u9ED8\u8BA4"),D("/stop \u505C\u6B62\u5F53\u524D\u4EFB\u52A1"),D("/steer \u8865\u5145\u6307\u4EE4 \u7EA0\u504F\u5F53\u524D\u4EFB\u52A1"),D("/batch \u5F00\u59CB\u6279\u91CF\u8F93\u5165\uFF08\u4EC5\u79C1\u804A\uFF0C\u6700\u591A 10 \u6761\u6587\u5B57\uFF09"),D("/send \u63D0\u4EA4\u5F53\u524D\u6279\u6B21"),D("/cancel \u53D6\u6D88\u5F53\u524D\u6279\u6B21"),D("/status \u68C0\u67E5\u8FDE\u63A5\u72B6\u6001"),D("/version \u67E5\u770B\u63D2\u4EF6\u7248\u672C"),D("/help \u663E\u793A\u672C\u5E2E\u52A9")].join(` `));return}if(!I&&!d&&B==="/status"){await this.#t.ensureRunning({signal:this.#s}),await this.#A.sendText(A,D("{label}\u673A\u5668\u4EBA\u4E0E DeepSeek Harness \u8FDE\u63A5\u6B63\u5E38\u3002",{label:this.#e.label}));return}let f=!I&&!d?await Io(r,this.#t,e):null;if(f){for(let R of f.messages??[f.message])await this.#A.sendText(A,R);return}if(!I&&!d&&B==="/new"){await this.#r.clearSession(e),await this.#A.sendText(A,D("\u5DF2\u5F00\u542F\u65B0\u4F1A\u8BDD\u3002\u8BF7\u53D1\u9001\u4F60\u7684\u95EE\u9898\u3002"));return}let Q=!I&&!d?await si(r,this.#t,this.#r,e,{signal:this.#s}):null;if(Q){await this.#A.sendText(A,Q.message);return}await this.#A.sendTyping?.(A).catch(R=>{this.#i.warn?.(`[dsh-im:${this.#e.key}] typing indicator failed:`,R)});let y=!1;if(typeof this.#A.openDeliveryStream=="function")try{g=await this.#A.openDeliveryStream(A),c=!0}catch(R){this.#i.warn?.(`[dsh-im:${this.#e.key}] unable to start a semantic reply stream; using final delivery:`,R)}else if(typeof this.#A.openStream=="function")try{g=await this.#A.openStream(A)}catch(R){this.#i.warn?.(`[dsh-im:${this.#e.key}] unable to start a streamed reply; using text:`,R)}let m=I?await so(t,{signal:this.#s}):void 0,{answer:_,artifacts:N=[]}=await ni({harness:this.#t,state:this.#r,key:e,text:r,content:m,createOptions:this.#s?{signal:this.#s}:void 0,existsOptions:this.#s?{signal:this.#s}:void 0,askOptions:{timeoutMs:this.#c,signal:this.#s,control:{owner:this,key:e},onUpdate:g?async R=>{let V=R.type==="text"?R.text:R.type==="tool"?D("\u6B63\u5728\u4F7F\u7528{name}\u2026",{name:R.name}):R.text;if(V){let L=R.type==="text"?"markdown":"plain";await g.update(c?Rn(V,L):V)}}:void 0,onInteraction:R=>this.#C(R,{key:e,actor:i,target:A,requiresMention:t.kind==="group"&&t.requiresMention!==!1}),onInteractionResolved:R=>this.#b(R),files:t.files}});s&&this.#h.complete(e,s.token);let G=!Ci(_)&&N.length>0,Y=G?D(yde):_,J=G?"plain":"markdown",H=null,j=null;if(g)try{let R=await g.finish(c?Rn(Y,J):Y);y=!0,j=zt({deliveryId:o,presentation:R?.presentation??g.presentation??`${this.#e.key}-stream`,providerMessageIds:[...li(g),...li(R)],deliveryOutcome:R?.deliveryOutcome,reason:R?.reason})}catch(R){g.cancel?.(),this.#i.warn?.(`[dsh-im:${this.#e.key}] streamed reply finalization failed; using text:`,R)}if(!y)try{let R=typeof this.#A.sendDelivery=="function"?await this.#A.sendDelivery(A,Rn(Y,J)):await this.#A.sendText(A,Y);j=zt({deliveryId:o,presentation:R?.presentation??`${this.#e.key}-text`,providerMessageIds:li(R),deliveryOutcome:R?.deliveryOutcome,reason:R?.reason})}catch(R){H=Sa(R)}let q=j?.deliveryOutcome==="unknown";j?.deliveryOutcome==="failed"?H=Sa(new Error(`Final text delivery failed (${j.reason??"unknown"})`),{uncertain:!1}):q&&(H=Sa(new Error(`Final text delivery outcome is unknown (${j.reason??"unknown"})`)));let U=await this.#m(A,o,N,j);if(H&&(!U.userVisible||q))throw H.deliveryReceipt=U.receipt,H;return H&&U.artifactSendErrors===0&&At(this.#a,H),U.userVisible&&(this.#a.messagesReplied+=1,this.#a.lastReplyAt=new Date().toISOString(),this.#a.lastError=null,!H&&U.artifactSendErrors===0&&oo(this.#a)),U.receipt}catch(I){let d=I?.code==="turn-stopped";s&&d&&this.#h.complete(e,s.token);let B=s&&!d?this.#h.fail(e,s.token):null;if(d){if(t.statusReaction?.clear(),g)try{await g.finish(D("\u5DF2\u505C\u6B62\u3002"))}catch{g.cancel?.()}return}if(this.#s?.aborted){t.statusReaction?.clear(),g?.cancel?.();return}t.statusReaction?.error(),this.#a.lastError=I?.message??String(I);let f=async N=>{let G=typeof g?.fail=="function"?"fail":typeof g?.finish=="function"?"finish":null;if(!G)return!1;try{let Y=await g[G](N);return G==="fail"?!!Y&&Y.deliveryOutcome!=="failed":Y!==!1&&Y?.deliveryOutcome!=="failed"}catch(Y){return this.#i.warn?.(`[dsh-im:${this.#e.key}] unable to finalize the failed stream:`,Y),!1}},Q=go(I),y=Eo(I),m=At(this.#a,I,{userMessage:y??Q,reason:vi(I)?.reason}),_=B?.retained?`${dt(m)} diff --git a/plugin-src/host/harness-command-executor.mjs b/plugin-src/host/harness-command-executor.mjs index ebf8d72..2f2d543 100644 --- a/plugin-src/host/harness-command-executor.mjs +++ b/plugin-src/host/harness-command-executor.mjs @@ -15,7 +15,11 @@ export function createHarnessCommandExecutor(ctx, provided) { return (sessionId, line, options = {}) => gateway.invoke({ namespace: 'commands', method: 'execute', - args: { agentId: sessionId, line }, + // The Harness commands execute descriptor declares agentId, line, and + // images as required JSON wire fields; omitting images makes the Typert + // gateway reject the call with arguments-invalid, so IM /compact always + // carried an empty image list. + args: { agentId: sessionId, line, images: [] }, signal: options.signal, }); } diff --git a/test/compact-command.test.mjs b/test/compact-command.test.mjs index 7bedb17..861bdfd 100644 --- a/test/compact-command.test.mjs +++ b/test/compact-command.test.mjs @@ -145,7 +145,10 @@ test('Host command executor invokes the commands Typert endpoint with the Sessio assert.deepEqual(requests, [{ namespace: 'commands', method: 'execute', - args: { agentId: 'session-one', line: '/compact' }, + // images must ride the wire as an empty array: the Harness commands + // execute descriptor declares it a required JSON field, and omitting it + // makes the Typert gateway reject the call with arguments-invalid. + args: { agentId: 'session-one', line: '/compact', images: [] }, signal, }]); assert.equal(createHarnessCommandExecutor({}), undefined);