@dcrays/mbh-chat 0.1.5-beta.3 → 0.1.5-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bridge/index.js +1 -1
  2. package/package.json +1 -1
package/bridge/index.js CHANGED
@@ -575,7 +575,7 @@ ${Wj}`}async function wne(e){let t=Tt.join(e,"AGENTS.md"),r="";try{r=await Dt.re
575
575
  WHERE status = 'awaiting_ack' AND sent_at <= ?`).all(t),n=this.db.prepare(`SELECT delivery_id, logical_key, attempt_count, sent_at, content_json
576
576
  FROM event_outbox
577
577
  WHERE status = 'awaiting_ack' AND sent_at <= ?`).all(t),o=i.map(c=>{let u=JSON.parse(c.context_json),l=JSON.parse(c.payload_json),d={kind:"chat",deliveryId:c.delivery_id,logicalKey:c.logical_key,requestId:c.request_id,attemptCount:c.attempt_count,sentAt:c.sent_at,messageId:u.messageId,sessionId:u.sessionId};return typeof l.state=="string"&&(d.payloadKind=l.state),d}),s=n.map(c=>{let u=JSON.parse(c.content_json),l={kind:"event",deliveryId:c.delivery_id,logicalKey:c.logical_key,attemptCount:c.attempt_count,sentAt:c.sent_at};return typeof u.event_type=="string"&&(l.payloadKind=u.event_type),l}),a=[...o,...s];return{deadCandidates:a.filter(c=>c.attemptCount>=r),requeueCandidates:a.filter(c=>c.attemptCount<r)}}requeueAwaitingDeliveries(t=Number.MAX_SAFE_INTEGER,r=Number.MAX_SAFE_INTEGER){let i=0,n=0;for(let o of["delivery_outbox","event_outbox"]){let s=this.db.prepare(`UPDATE ${o} SET status = 'dead', last_error = 'delivery acknowledgement timed out', updated_at = ? WHERE status = 'awaiting_ack' AND sent_at <= ? AND attempt_count >= ?`).run(Date.now(),t,r),a=this.db.prepare(`UPDATE ${o} SET status = 'pending', last_error = 'delivery acknowledgement timed out', updated_at = ? WHERE status = 'awaiting_ack' AND sent_at <= ? AND attempt_count < ?`).run(Date.now(),t,r);n+=Number(s.changes),i+=Number(a.changes)}return{requeued:i,dead:n}}listProcessingRequests(){return this.listRunningRequests()}parseDelivery(t){return{deliveryId:t.delivery_id,requestId:t.request_id,accountId:t.account_id,logicalKey:t.logical_key,context:JSON.parse(t.context_json),payload:JSON.parse(t.payload_json),attemptCount:t.attempt_count}}parseEventDelivery(t){return{deliveryId:t.delivery_id,logicalKey:t.logical_key,content:JSON.parse(t.content_json),attemptCount:t.attempt_count}}};import{createHash as poe,randomUUID as hoe}from"node:crypto";var soe=Br(tL(),1),aoe=Br(yh(),1),coe=Br(Oa(),1),uoe=Br(gE(),1),loe=Br(bE(),1),foe=Br(kE(),1),lL=Br(wh(),1),doe=Br(uL(),1);var rr=lL.default;var moe=3e4,Sh=15e3,goe=512*1024,yoe=50,IE=1e3,il=10,Eh=15e3,voe=4*1024*1024,ol="openclaw_bot_event with content.event_type=delivery, content.operation_type=ack, content.delivery_id=<id>";function boe(e,t,r){let i=Math.min(r,t*2**Math.min(e,8));return i+Math.floor(Math.random()*Math.max(1,Math.min(1e3,i/5)))}var kh=class{config;store;logger;onChat;onSkill;onState;onEvent;socket;reconnectTimer;heartbeatTimer;flushRetryTimer;ackRetryTimer;flushPromise;flushRequested=!1;stopped=!0;reconnectAttempt=0;pongPending=!1;constructor(t,r,i,n,o=async()=>{},s=()=>{},a=async()=>{}){this.config=t,this.store=r,this.logger=i,this.onChat=n,this.onSkill=o,this.onState=s,this.onEvent=a}start(){if(!this.stopped)throw new Error("mbh-chat socket already started");this.stopped=!1,this.connect()}async stop(){this.stopped=!0,this.onState("stopped"),this.reconnectTimer&&clearTimeout(this.reconnectTimer),this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.flushRetryTimer&&clearTimeout(this.flushRetryTimer),this.ackRetryTimer&&clearTimeout(this.ackRetryTimer),this.reconnectTimer=void 0,this.heartbeatTimer=void 0,this.flushRetryTimer=void 0,this.ackRetryTimer=void 0,this.flushRequested=!1;let t=this.socket;this.socket=void 0,t&&(t.readyState===rr.OPEN||t.readyState===rr.CONNECTING)&&await new Promise(r=>{let i=()=>r();t.once("close",i),t.close(1e3,"bridge stopped"),setTimeout(i,2e3).unref()})}enqueue(t,r,i){let n=this.store.enqueueDelivery(t,r,i);return this.triggerFlush(),n}enqueueTerminal(t,r,i,n,o){let s=r.message_tags&&typeof r.message_tags=="object"&&!Array.isArray(r.message_tags)?r.message_tags:{},a=r.state==="final"?{...r,message_tags:{...s,isFinal:1}}:r,c=this.store.completeRequestWithDelivery(t,a,i,n,o);return this.triggerFlush(),c}enqueueEvent(t,r){try{return this.enqueueManagementEvent({...r,domain_id:t.domainId??this.config.domainId,app_id:t.appId??this.config.appId,bot_id:t.botId,agent_id:t.agentId,session_id:t.sessionId,user_id:t.userId}),!0}catch(i){return this.logger.warn("mbh-chat event could not be persisted",{error:ne(i),sessionId:t.sessionId}),!1}}flush(){return this.flushPromise?(this.flushRequested=!0,this.flushPromise):(this.flushRequested=!1,this.flushPromise=this.flushPending().finally(()=>{this.flushPromise=void 0,this.flushRequested&&!this.stopped&&this.socket?.readyState===rr.OPEN&&(this.flushRequested=!1,queueMicrotask(()=>this.triggerFlush()))}),this.flushPromise)}async sendEvent(t){try{return this.enqueueManagementEvent(t),await this.flush(),!0}catch(r){return this.logger.error("mbh-chat management feedback could not be persisted",{error:ne(r)}),!1}}connect(){if(this.stopped)return;this.onState("connecting"),this.logger.info("connecting to mbh-chat",{endpoint:this.config.wsUrl});let t=new rr(this.config.wsUrl,{maxPayload:voe});this.socket=t,t.on("open",()=>{if(!(this.socket!==t||this.stopped)){if(this.reconnectAttempt=0,this.logger.info("connected to mbh-chat"),this.config.deliveryAckMode==="business"){let r=this.store.requeueAwaitingDeliveries();(r.requeued>0||r.dead>0)&&this.logger.info("restored unacknowledged mbh-chat deliveries",r)}else{let r=this.store.finalizeAwaitingDeliveries();r>0&&this.logger.info("finalized legacy awaiting-ack mbh-chat deliveries in transport mode",{count:r})}this.onState("awaiting-heartbeat"),this.startHeartbeat(),this.sendHeartbeat({first:!0}),this.triggerFlush()}}),t.on("pong",()=>{this.socket===t&&(this.pongPending=!1)}),t.on("message",(r,i)=>{if(i){this.logger.warn("ignoring binary mbh-chat frame");return}try{let n=nM(r.toString());if("kind"in n){if(n.kind==="heartbeat"){this.onState("connected");return}if(n.kind==="skill"){let o=n.content.operation_type;if(!["install","enable","update","remove","disable"].includes(o)){this.logger.error("unsupported mbh-chat skill operation",{operationType:o,bytes:Buffer.byteLength(r.toString())}),this.sendEvent({...n.content,status:"fail",error:`unsupported skill operation: ${o}`});return}this.onSkill(n).catch(s=>{this.logger.error("inbound mbh-chat skill handler failed",{error:ne(s)})});return}if(n.kind==="event"){let o=tM(n);if(o){for(let s of o)this.store.acknowledgeDelivery(s)||this.logger.warn("ignored unknown mbh-chat delivery acknowledgement",{deliveryId:s,expectedAck:ol});return}this.onEvent(n).catch(s=>{this.logger.error("inbound mbh-chat event handler failed",{error:ne(s)})});return}n.kind==="ignored"&&this.logger.warn("ignoring unsupported mbh-chat event",{messageType:n.messageType});return}this.onChat(n).catch(o=>{this.logger.error("inbound mbh-chat handler failed",{error:ne(o)}),this.replyToFailedChat(n,"bridge_error","\u6D88\u606F\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002")})}catch(n){if(n instanceof Xu&&n.reply){this.logger.warn("invalid mbh-chat chat frame; returning terminal feedback",{error:n.message,messageId:n.reply.content.message_id}),this.replyToFailedChat(n.reply,"invalid_input",n.userMessage);return}this.logger.warn("invalid mbh-chat frame",{error:ne(n)})}}),t.on("error",r=>{this.onState("error"),this.logger.warn("mbh-chat WebSocket error",{error:r.message})}),t.on("close",(r,i)=>{if(this.socket===t&&(this.socket=void 0,this.config.deliveryAckMode==="business"&&this.store.requeueAwaitingDeliveries(),this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0,this.onState("disconnected"),this.logger.warn("mbh-chat disconnected",{code:r,reason:i.toString()}),!this.stopped)){let n=boe(this.reconnectAttempt++,this.config.reconnectMinMs,this.config.reconnectMaxMs);this.logger.info("reconnecting to mbh-chat",{delayMs:n,attempt:this.reconnectAttempt}),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=void 0,this.connect()},n)}})}startHeartbeat(){this.heartbeatTimer&&clearInterval(this.heartbeatTimer),this.pongPending=!1,this.heartbeatTimer=setInterval(()=>{let t=this.socket;if(t?.readyState===rr.OPEN){if(this.pongPending){this.logger.warn("mbh-chat heartbeat pong timeout; terminating stale connection"),t.terminate();return}this.pongPending=!0;try{t.ping()}catch(r){this.pongPending=!1,this.logger.warn("mbh-chat heartbeat ping threw",{error:ne(r)})}this.sendHeartbeat()}},moe)}sendHeartbeat(t){let r=this.socket;if(r?.readyState===rr.OPEN)try{r.send(JSON.stringify({messageType:"openclaw_bot_heartbeat",_userId:Number(this.config.userId)||0,source:"client",content:{bot_token:this.config.botToken,status:"1"}}),i=>{i?this.logger.warn("mbh-chat heartbeat send failed",{error:i.message}):t?.first&&this.logger.info("mbh-chat first heartbeat sent")})}catch(i){this.logger.warn("mbh-chat heartbeat send threw",{error:ne(i)})}}replyToFailedChat(t,r,i){let n=Yn(this.config.accountId,t.content.message_id.trim());try{let o=sh(t,this.config.accountId,n);this.enqueueTerminal(o,{response:i,state:"final",final_tag:r,is_finish:1},"final","failed",r)}catch(o){this.logger.error("could not persist mbh-chat failure feedback",{requestId:n,tag:r,error:ne(o)})}}async flushPending(){let t=0;for(;;){let r=this.socket;if(r?.readyState!==rr.OPEN)return t;if(r.bufferedAmount>goe)return this.scheduleFlush(yoe),t;let i=this.store.listPendingDeliveries(200),n=this.store.listPendingEventDeliveries(200);if(i.length===0&&n.length===0)return t;let o=0;for(let s of i){if(this.socket!==r||r.readyState!==rr.OPEN)return t;s.attemptCount>=1&&this.config.deliveryAckMode==="business"&&this.logger.warn("mbh-chat resending chat delivery without business acknowledgement",{attempt:s.attemptCount+1,expectedAck:ol}),this.store.markDeliveryAttempt(s.deliveryId);try{await this.sendDelivery(r,s),this.config.deliveryAckMode==="business"?(this.store.markDeliverySent(s.deliveryId),this.scheduleAcknowledgementRetry()):this.store.markDeliveryDelivered(s.deliveryId),t+=1,o+=1}catch(a){let c=this.store.markDeliveryFailed(s.deliveryId,ne(a),il);if(this.logger.warn(c?"mbh-chat delivery moved to dead letter":"mbh-chat delivery remains pending",{deliveryId:s.deliveryId,attemptCount:s.attemptCount+1,error:ne(a)}),c)continue;return this.scheduleFlush(IE),t}}for(let s of n){if(this.socket!==r||r.readyState!==rr.OPEN)return t;s.attemptCount>=1&&this.config.deliveryAckMode==="business"&&this.logger.warn("mbh-chat resending event delivery without business acknowledgement",{...this.deliveryDiagnosticFields(s),attempt:s.attemptCount+1,expectedAck:ol}),this.store.markDeliveryAttempt(s.deliveryId,!0);try{await this.sendEventDelivery(r,s),this.config.deliveryAckMode==="business"?(this.store.markDeliverySent(s.deliveryId,!0),this.scheduleAcknowledgementRetry()):this.store.markDeliveryDelivered(s.deliveryId,!0),t+=1,o+=1}catch(a){let c=this.store.markDeliveryFailed(s.deliveryId,ne(a),il,!0);if(this.logger.warn(c?"mbh-chat event delivery moved to dead letter":"mbh-chat event delivery remains pending",{deliveryId:s.deliveryId,attemptCount:s.attemptCount+1,error:ne(a)}),c)continue;return this.scheduleFlush(IE),t}}if(o===0)return t}}scheduleFlush(t){this.stopped||this.flushRetryTimer||(this.flushRetryTimer=setTimeout(()=>{this.flushRetryTimer=void 0,this.triggerFlush()},t),this.flushRetryTimer.unref())}triggerFlush(){if(!this.stopped){if(this.flushPromise){this.flushRequested=!0;return}this.flush().catch(t=>{this.logger.error("mbh-chat Outbox flush failed",{error:ne(t)}),this.scheduleFlush(IE)})}}scheduleAcknowledgementRetry(){this.config.deliveryAckMode!=="business"||this.stopped||this.ackRetryTimer||(this.ackRetryTimer=setTimeout(()=>{this.ackRetryTimer=void 0;let t=Date.now()-Eh,r=this.store.listExpiredAwaitingDeliveries(t,il),i=this.store.requeueAwaitingDeliveries(t,il);i.dead>0&&this.logger.error("mbh-chat deliveries exhausted acknowledgement retries",{count:i.dead,ackTimeoutMs:Eh,maxAttempts:il,expectedAck:ol,deliveries:this.deliveryDiagnosticFieldsList(r.deadCandidates)}),i.requeued>0?(this.logger.warn("mbh-chat delivery acknowledgement timed out; will resend",{count:i.requeued,ackTimeoutMs:Eh,expectedAck:ol,deliveries:this.deliveryDiagnosticFieldsList(r.requeueCandidates)}),this.triggerFlush()):this.store.countAwaitingDeliveries()>0&&this.scheduleAcknowledgementRetry()},Eh),this.ackRetryTimer.unref())}deliveryDiagnosticFields(t){return"requestId"in t?{kind:"chat",deliveryId:t.deliveryId,logicalKey:t.logicalKey,requestId:t.requestId,attemptCount:t.attemptCount,payloadState:t.payload.state,messageId:t.context.messageId,sessionId:t.context.sessionId}:{kind:"event",deliveryId:t.deliveryId,logicalKey:t.logicalKey,attemptCount:t.attemptCount,eventType:typeof t.content.event_type=="string"?t.content.event_type:void 0}}deliveryDiagnosticFieldsList(t,r=20){return t.slice(0,r).map(i=>({kind:i.kind,deliveryId:i.deliveryId,logicalKey:i.logicalKey,requestId:i.requestId,attemptCount:i.attemptCount,payloadKind:i.payloadKind,messageId:i.messageId,sessionId:i.sessionId,sentAt:i.sentAt}))}enqueueManagementEvent(t){let r={...t};for(let s of["bot_token","token","authorization"])delete r[s];let i=typeof r.websocket_trace_id=="string"?r.websocket_trace_id.trim():"",n=i?`event:${poe("sha256").update(`${String(r.event_type??"")}\0${String(r.operation_type??"")}\0${i}\0${String(r.status??"")}`).digest("hex")}`:`event:${hoe()}`,o=this.store.enqueueEventDelivery(r,n);return this.triggerFlush(),o}sendDelivery(t,r){let i=r.context,n={...r.payload,bot_token:this.config.botToken,domain_id:i.domainId??this.config.domainId,app_id:i.appId??this.config.appId,bot_id:i.botId,agent_id:i.agentId,session_id:i.sessionId,message_id:i.messageId,delivery_id:r.deliveryId,idempotency_key:r.deliveryId,request_id:r.requestId},o=JSON.stringify({messageType:"openclaw_bot_chat",_userId:i.userId,source:"client",content:JSON.stringify(n)});return new Promise((s,a)=>{let c=!1,u=d=>{c||(c=!0,clearTimeout(l),d?a(d):s())},l=setTimeout(()=>u(new Error(`send callback timed out after ${Sh}ms`)),Sh);try{t.send(o,d=>u(d))}catch(d){u(d instanceof Error?d:new Error(String(d)))}})}sendEventDelivery(t,r){let i=JSON.stringify({messageType:"openclaw_bot_event",_userId:Number(r.content.user_id)||Number(this.config.userId)||0,source:"client",content:{bot_token:this.config.botToken,...r.content,delivery_id:r.deliveryId,idempotency_key:r.deliveryId}});return new Promise((n,o)=>{let s=!1,a=u=>{s||(s=!0,clearTimeout(c),u?o(u):n())},c=setTimeout(()=>a(new Error(`send callback timed out after ${Sh}ms`)),Sh);try{t.send(i,u=>a(u))}catch(u){a(u instanceof Error?u:new Error(String(u)))}})}};var fL="MBHCHAT_DSH_SESSION_COOKIE",_oe=/^dsh-auth-[A-Za-z0-9_-]+=[A-Za-z0-9._-]+$/u;function Th(e=process.env){let t=e[fL]?.trim();if(t){if(!_oe.test(t))throw new Error(`${fL} is not a valid DSH authentication cookie`);return t}}function vn(e,t={}){return e?{...t,cookie:e}:{...t}}var Na="dsh/cron.list",Fi="/api/cron-automations",dL="mbh-chat";function sl(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0}function woe(e){if(!Dr(e)||e.status==="deleted")return;let t=e;return{id:t.id,name:t.name,description:t.prompt,enabled:t.status==="active"||t.status==="dispatching",createdAtMs:Date.parse(t.createdAt),updatedAtMs:Date.parse(t.updatedAt),schedule:{kind:"cron",expr:t.cron,tz:t.timezone},payload:{kind:"agentTurn",message:t.prompt,timeoutSeconds:600},agentId:t.agentId,sessionTarget:"isolated",wakeMode:"now",delivery:{mode:"announce",bestEffort:!0},state:{nextRunAtMs:Date.parse(t.nextRunAt),...t.lastRunAt?{lastRunAtMs:Date.parse(t.lastRunAt)}:{}}}}function xoe(e){return Dr(e)&&typeof e.id=="string"&&typeof e.name=="string"&&typeof e.agentId=="string"&&typeof e.enabled=="boolean"&&sl(e.createdAtMs)&&sl(e.updatedAtMs)&&Dr(e.schedule)&&typeof e.schedule.kind=="string"&&Dr(e.payload)&&typeof e.payload.kind=="string"&&Dr(e.state)&&(e.state.nextRunAtMs===void 0||sl(e.state.nextRunAtMs))&&(e.state.runningAtMs===void 0||sl(e.state.runningAtMs))&&(e.state.lastRunAtMs===void 0||sl(e.state.lastRunAtMs))}function al(e){if(!Dr(e)||e.type!==Na||e.version!==1)throw new Error("cron list snapshot must be a dsh/cron.list document");let t=Array.isArray(e.jobs)?e.jobs:Array.isArray(e.crons)?e.crons.map(woe).filter(i=>i!==void 0):void 0;if(!t)throw new Error("cron list snapshot must contain jobs");let r=t.filter(xoe);return{type:Na,version:1,sequence:typeof e.sequence=="number"?e.sequence:0,generatedAt:typeof e.generatedAt=="string"?e.generatedAt:new Date().toISOString(),reason:typeof e.reason=="string"?e.reason:"unknown",jobs:r,invalidJobCount:t.length-r.length}}function zi(e){let t=e.split(":").filter(i=>i.length>0),r=t.map(i=>i.toLowerCase());return t.length>=6&&r[0]==="agent"&&r[2]==="mobook"&&r[3]==="direct"?{agentId:t[4]??"",sessionId:t[5]??""}:{agentId:t.at(-2)??"",sessionId:t.at(-1)??""}}function bn(e){let t=e.split(":").filter(i=>i.length>0),r=t.map(i=>i.toLowerCase());return t.length>=6&&r[0]==="agent"&&r[2]==="mobook"&&r[3]==="direct"}function OE(e,t){return{version:1,jobs:e.flatMap(r=>{let i=(r.sessionKey??t(r))?.trim();if(!i||!bn(i))return[];let n=zi(i),{dshSessionId:o,...s}=r;return[{...s,description:r.description??(typeof r.payload.message=="string"?r.payload.message:""),sessionKey:i,sessionTarget:r.payload.kind==="systemEvent"?"main":"isolated",wakeMode:"now",delivery:{...r.delivery,mode:"announce",to:`dcg-cron:${i}`,channel:dL,bestEffort:!0,...n.agentId?{accountId:n.agentId}:{}}}]})}}function Soe(e){let t=[],r=e;for(;;){let i=/\r?\n\r?\n/.exec(r);if(!i||i.index<0)return{events:t,rest:r};let n=r.slice(0,i.index);r=r.slice(i.index+i[0].length);let o="message",s=[];for(let a of n.split(/\r?\n/))a.startsWith("event:")?o=a.slice(6).trim():a.startsWith("data:")&&s.push(a.slice(5).trimStart());s.length>0&&t.push({event:o,data:s.join(`
578
- `)})}}var cl=class{baseUrl;fetchImpl;sessionCookie;constructor(t,r=fetch,i=Th()){this.baseUrl=t,this.fetchImpl=r,this.sessionCookie=i}url(t){return new URL(t,this.baseUrl.endsWith("/")?this.baseUrl:`${this.baseUrl}/`)}async patch(t,r){return(await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}`),{method:"PATCH",headers:vn(this.sessionCookie,{"content-type":"application/json"}),body:JSON.stringify(r),signal:AbortSignal.timeout(15e3)})).ok}async patchJob(t,r){let i=await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}`),{method:"PATCH",headers:vn(this.sessionCookie,{"content-type":"application/json"}),body:JSON.stringify(r),signal:AbortSignal.timeout(15e3)});if(!i.ok)return;let n=await i.json().catch(()=>{});return al({type:Na,version:1,jobs:[n]}).jobs.find(o=>o.id===t)}setEnabled(t,r){return this.patch(t,{enabled:r})}async delete(t){let r=await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}`),{method:"DELETE",headers:vn(this.sessionCookie),signal:AbortSignal.timeout(15e3)});return r.ok?"deleted":r.status===404?"not_found":"failed"}async runOnce(t){let r=await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}/run`),{method:"POST",headers:vn(this.sessionCookie),signal:AbortSignal.timeout(15e3)}),i=await r.json().catch(()=>{}),n=Dr(i)&&typeof i.status=="string"?i.status:void 0;return n==="dispatched"||n==="not_found"||n==="already_running"||n==="delivery_unavailable"?n:r.status===404?"not_found":r.status===202?"already_running":r.ok&&Dr(i)&&i.delivered===!0?"dispatched":"delivery_unavailable"}async list(){let t=await this.fetchImpl(this.url(`${Fi}`),{method:"GET",headers:vn(this.sessionCookie),signal:AbortSignal.timeout(15e3)});if(!t.ok)return;let r=await t.json().catch(()=>{});if(!(!Dr(r)||!Array.isArray(r.jobs)))return al({type:Na,version:1,sequence:0,generatedAt:new Date().toISOString(),reason:"fetch",jobs:r.jobs})}async subscribe(t,r,i=()=>{}){let n=await this.fetchImpl(this.url(`${Fi}/events`),{method:"GET",headers:vn(this.sessionCookie,{accept:"text/event-stream"}),signal:r});if(!n.ok||!n.body)throw new Error(`cron SSE failed with HTTP ${n.status}`);let o=n.body.getReader(),s=new TextDecoder,a="";for(;;){let{value:c,done:u}=await o.read();if(u){if(!r.aborted)throw new Error("cron SSE stream ended");return}a+=s.decode(c,{stream:!0});let{events:l,rest:d}=Soe(a);a=d;for(let p of l)if(p.event==="cron-list")try{t(al(JSON.parse(p.data)))}catch(f){i(f)}}}};var Eoe=100,koe=1e3,Toe=3e4;function $E(e){let{updatedAtMs:t,state:r,...i}=e;return JSON.stringify(i,(n,o)=>o&&typeof o=="object"&&!Array.isArray(o)?Object.fromEntries(Object.entries(o).sort(([s],[a])=>s.localeCompare(a))):o)}function Ioe(e,t){return new Promise(r=>{if(e.aborted){r();return}let i=()=>{clearTimeout(n),e.removeEventListener("abort",i),r()},n=setTimeout(i,t);n.unref(),e.addEventListener("abort",i,{once:!0})})}var Ih=class{options;client;abort;loop;debounce;publishTail=Promise.resolve();lastFingerprint;lastContext;lastSnapshot;lastJobs=new Map;lastContexts=new Map;constructor(t){this.options=t,this.client=new cl(t.dshBaseUrl,t.fetchImpl)}start(){if(this.loop)return;let t=this.options.store.getLatestContext();t&&(this.lastContext=t),this.abort=new AbortController,this.loop=this.run(this.abort.signal)}async stop(){this.abort?.abort(),this.debounce&&clearTimeout(this.debounce),this.debounce=void 0,await this.loop?.catch(()=>{}),await this.publishTail,this.loop=void 0,this.abort=void 0}async applyControl(t,r){if(t==="remove"){let n=await this.client.delete(r);return{applied:n!=="failed",...n==="not_found"?{reconciled:!0}:{}}}if(t==="enable")return{applied:await this.client.setEnabled(r,!0)};if(t==="disable")return{applied:await this.client.setEnabled(r,!1)};await this.ensureSessionForCron(r),await this.ensureSessionFollowed(r);let i=await this.client.runOnce(r);return i==="delivery_unavailable"&&(i=await this.rebindAndRetryRun(r,i)),{applied:i==="dispatched"||i==="already_running",runStatus:i}}notifySessionAvailable(){this.lastSnapshot&&this.schedulePublish(this.lastSnapshot)}businessKeyForCronId(t){let r=this.lastSnapshot?.jobs.find(i=>i.id===t);if(r)return this.sessionKeyFor(r)}async bindDshSessionId(t,r){if(!bn(t))return;let i=this.lastSnapshot??await this.client.list();if(!i)return;let n=i.jobs.filter(o=>o.sessionKey===t&&(!o.dshSessionId||o.dshSessionId!==r));n.length!==0&&await Promise.all(n.map(async o=>{await this.client.patch(o.id,{dshSessionId:r})?(this.options.logger.info("bound cron job to mbh-chat session",{cronId:o.id,sessionKey:t,dshSessionId:r}),this.followCronSession(r)):this.options.logger.warn("failed to patch cron dshSessionId binding",{cronId:o.id,sessionKey:t,dshSessionId:r})}))}async bindAllKnownDshSessions(){let t=this.lastSnapshot??await this.client.list();if(!t)return;let r=new Map;for(let i of t.jobs){if(!i.sessionKey||!bn(i.sessionKey))continue;let n=this.options.store.getSession(i.sessionKey);!n||i.dshSessionId===n||r.set(i.id,n)}r.size!==0&&await Promise.all([...r.entries()].map(async([i,n])=>{await this.client.patch(i,{dshSessionId:n})?(this.options.logger.info("bound cron job to pre-existing mbh-chat session",{cronId:i,dshSessionId:n}),this.followCronSession(n)):this.options.logger.warn("failed to patch cron dshSessionId binding",{cronId:i,dshSessionId:n})}))}async run(t){let r=0;for(;!t.aborted;)try{await this.client.subscribe(i=>this.schedulePublish(i),t,i=>this.options.logger.warn("ignored invalid cron catalog SSE event",{error:ne(i)})),r=0}catch(i){if(t.aborted)return;r+=1;let n=Math.min(Toe,koe*2**Math.min(r-1,8));this.options.logger.warn("cron catalog SSE disconnected; retrying",{delayMs:n,error:ne(i)}),await Ioe(t,n)}}schedulePublish(t){this.lastSnapshot=t,this.debounce&&clearTimeout(this.debounce),this.debounce=setTimeout(()=>{this.debounce=void 0,this.publishTail=this.publishTail.then(()=>this.publish(t)).catch(r=>this.options.logger.warn("failed to publish cron catalog to Mobook",{error:ne(r)}))},this.options.debounceMs??Eoe),this.debounce.unref()}async rebindAndRetryRun(t,r){let n=(await this.client.list().catch(()=>{}))?.jobs.find(s=>s.id===t);if(!n?.sessionKey||!bn(n.sessionKey))return r;let o=this.options.store.getSession(n.sessionKey);return!o||o===n.dshSessionId||!await this.client.patch(t,{dshSessionId:o})?r:(this.options.logger.info("rebound stale cron DSH session before manual run",{cronId:t,dshSessionId:o}),await this.followCronSession(o),this.client.runOnce(t))}async ensureSessionForCron(t){let i=(await this.client.list().catch(()=>{}))?.jobs.find(o=>o.id===t);if(!i?.sessionKey||!bn(i.sessionKey))return;let n=this.options.store.getSession(i.sessionKey);n||(n=await this.options.provisionSession?.(i)),n&&i.dshSessionId!==n&&await this.client.patch(t,{dshSessionId:n})&&this.options.logger.info("provisioned cron DSH session before dispatch",{cronId:t,dshSessionId:n})}contextFor(t){if(t.sessionKey){let i=this.options.store.getLatestContextForBusinessKey(t.sessionKey);if(i)return i}let r=this.options.store.getBusinessKeyByDshSessionId(t.dshSessionId??t.agentId);return r?this.options.store.getLatestContextForBusinessKey(r):void 0}sessionKeyFor(t){return t.sessionKey?t.sessionKey:this.options.store.getBusinessKeyByDshSessionId(t.dshSessionId??t.agentId)}adoptionOwner(){let t=this.lastContext??this.options.store.getLatestContext?.();if(!t||!bn(t.businessKey))return;let r=zi(t.businessKey).agentId;return r?{businessKey:t.businessKey,agentId:r}:void 0}isForeignOwner(t,r){return!t||!bn(t)?!0:zi(t).agentId!==r}send(t,r){return this.options.dcg.enqueueEvent(t,r)!==!1}async publish(t){let r=this.adoptionOwner(),i=[];for(let l of t.jobs){let d=this.sessionKeyFor(l);if(r&&this.isForeignOwner(d,r.agentId)&&(d=r.businessKey),!d){i.push(l);continue}let p=zi(d),f=this.options.store.getSession(d),h={...l.sessionKey===d?{}:{sessionKey:d},...f&&l.dshSessionId!==f?{dshSessionId:f}:{},...p.agentId&&l.agentId!==p.agentId?{agentId:p.agentId}:{}};if(Object.keys(h).length>0){let m=await this.client.patchJob(l.id,h);if(!m){this.options.logger.warn("failed to persist cron sessionKey binding",{cronId:l.id});return}i.push(m)}else i.push(l)}let n=OE(i,l=>this.sessionKeyFor(l)),o=JSON.stringify(n.jobs.map(l=>[l.id,$E(l)]).sort());if(o===this.lastFingerprint)return;if(t.jobs.length>0&&n.jobs.length===0){this.options.logger.warn("skipping Mobook cron catalog publish; no mbh-chat session mapping is available yet");return}let s=new Set(n.jobs.map(l=>l.id)),a=new Set,c=new Set;for(let l of n.jobs){let d=$E(l);if(this.lastJobs.get(l.id)===d)continue;let p=i.find(h=>h.id===l.id),f=p?this.contextFor(p):void 0;if(!f&&p?.sessionKey&&bn(p.sessionKey)&&(await this.ensureSessionForCron(p.id),f=this.contextFor(p)),!f){this.options.logger.warn("skipping cron install; no mapped mbh-chat session is available",{cronId:l.id}),a.add(l.id);continue}if(!this.send(f,{event_type:"cron",operation_type:"install",data:l})){this.options.logger.warn("cron install event was not sent; will retry",{cronId:l.id});return}this.lastJobs.set(l.id,d),this.lastContexts.set(l.id,f),this.lastContext=f,this.lastFingerprint=void 0,this.options.logger.info("enqueued cron install to Mobook",{cronId:l.id,sequence:t.sequence})}if(t.invalidJobCount===0)for(let l of this.lastJobs.keys()){if(s.has(l))continue;let d=this.lastContexts.get(l);if(!d){this.options.logger.warn("skipping cron remove; no mapped mbh-chat session is available",{cronId:l}),c.add(l);continue}if(!this.send(d,{event_type:"cron",operation_type:"remove",data:{id:l,jobId:l,action:"removed"}})){this.options.logger.warn("cron remove event was not sent; will retry",{cronId:l});return}this.lastJobs.delete(l),this.lastContexts.delete(l),this.lastFingerprint=void 0}else this.options.logger.warn("cron snapshot contained invalid jobs; preserving previously published jobs",{invalidJobCount:t.invalidJobCount});let u=new Map([...this.lastJobs].filter(([l])=>s.has(l)||c.has(l)));for(let l of n.jobs)a.has(l.id)||u.set(l.id,$E(l));if(t.invalidJobCount>0)for(let[l,d]of this.lastJobs)u.has(l)||u.set(l,d);this.lastJobs=u,this.lastFingerprint=t.invalidJobCount===0&&a.size===0&&c.size===0?o:void 0,this.followBoundJobs(i),this.options.logger.info("published cron catalog to Mobook",{jobs:n.jobs.length,sequence:t.sequence})}async ensureSessionFollowed(t){let i=(this.lastSnapshot??await this.client.list().catch(()=>{}))?.jobs.find(s=>s.id===t);if(!i)return;let n=this.sessionKeyFor(i),o=(n?this.options.store.getSession(n):void 0)||i.dshSessionId;o&&await this.followCronSession(o)}followBoundJobs(t){let r=new Set;for(let i of t){let n=this.sessionKeyFor(i),o=(n?this.options.store.getSession(n):void 0)||i.dshSessionId;!o||r.has(o)||(r.add(o),this.followCronSession(o))}}async followCronSession(t){this.options.followSession&&await this.options.followSession(t)}};import{timingSafeEqual as Ooe}from"node:crypto";import Pa from"node:fs";import $oe from"node:http";import Coe from"node:path";var pL=1024*1024,qke=64*1024;function Aoe(e,t){if(!e?.startsWith("Bearer "))return!1;let r=Buffer.from(e.slice(7)),i=Buffer.from(t);return r.length===i.length&&Ooe(r,i)}async function Roe(e){let t=[],r=0;for await(let i of e){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(r+=n.length,r>pL)throw new Error(`request body exceeds ${pL} bytes`);t.push(n)}return JSON.parse(Buffer.concat(t).toString("utf8"))}function qa(e,t,r){let i=JSON.stringify(r);e.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(i)}),e.end(i)}var Oh=class{socketPath;token;handler;statusProvider;server;constructor(t,r,i,n){this.socketPath=t,this.token=r,this.handler=i,this.statusProvider=n}async start(){if(this.server)throw new Error("message control server already started");if(process.platform!=="win32"){Pa.mkdirSync(Coe.dirname(this.socketPath),{recursive:!0});try{if(!Pa.lstatSync(this.socketPath).isSocket())throw new Error(`refusing to replace non-socket control path: ${this.socketPath}`);Pa.unlinkSync(this.socketPath)}catch(r){if(r.code!=="ENOENT")throw r}}let t=$oe.createServer((r,i)=>{this.handle(r,i)});this.server=t,await new Promise((r,i)=>{let n=s=>{t.off("listening",o),i(s)},o=()=>{t.off("error",n),r()};t.once("error",n),t.once("listening",o),t.listen(this.socketPath)}),process.platform!=="win32"&&Pa.chmodSync(this.socketPath,384)}async stop(){let t=this.server;if(this.server=void 0,t&&await new Promise(r=>t.close(()=>r())),process.platform!=="win32")try{Pa.lstatSync(this.socketPath).isSocket()&&Pa.unlinkSync(this.socketPath)}catch(r){if(r.code!=="ENOENT")throw r}}async handle(t,r){let i=t.method==="POST"&&t.url==="/v1/message",n=t.method==="GET"&&t.url==="/v1/status";if(!i&&!n){qa(r,404,{error:"not found"});return}if(!Aoe(t.headers.authorization,this.token)){qa(r,401,{error:"unauthorized"});return}if(n){if(!this.statusProvider){qa(r,404,{error:"not found"});return}qa(r,200,this.statusProvider());return}let o=new AbortController,s=()=>o.abort(new Error("control client disconnected"));t.once("aborted",s);try{let a=await Roe(t),c=await this.handler(a,o.signal);qa(r,c.success?200:422,c)}catch(a){qa(r,400,{success:!1,sentMediaCount:0,queued:!1,error:a instanceof Error?a.message:String(a)})}finally{t.off("aborted",s)}}};import{createHash as Doe}from"node:crypto";var jo=class extends Error{status;constructor(t,r){super(t),this.status=r,this.name="DcgApiRequestError"}};function Noe(e){return e!==null&&typeof e=="object"?JSON.stringify(e):String(e)}function Poe(e,t,r,i,n="1.0.0"){let o={timestamp:t,path:r,version:n,...e},s=Object.keys(o).sort().map(a=>o[a]===void 0?"":`${a}${Noe(o[a])}`).join("")+i;return Doe("md5").update(s).digest("hex").toUpperCase()}function qoe(e,t){try{let r=new URL(t,e);return`POST ${r.origin}${r.pathname}`}catch{return`POST ${t.split("?",1)[0]??""}`}}var $h=class{config;logger;fetchImpl;timeoutMs;constructor(t,r,i=fetch,n=6e4){this.config=t,this.logger=r,this.fetchImpl=i,this.timeoutMs=n}async post(t,r,i={}){if(!t.startsWith("/")||t.startsWith("//"))throw new Error("mbh-chat API request path must be an origin-relative path");let n=new URL(this.config.apiBaseUrl),o=new URL(t,n);if(o.origin!==n.origin)throw new Error("mbh-chat API request path must stay on the configured origin");let s=typeof i.appId=="number"&&Number.isFinite(i.appId)?Math.trunc(i.appId):typeof i.appId=="string"&&i.appId.trim()?i.appId.trim():this.config.appId,a={...r,_appId:s},c=Date.now(),u=AbortSignal.timeout(this.timeoutMs),l=i.signal?AbortSignal.any([i.signal,u]):u,d=qoe(this.config.apiBaseUrl,t);try{let p=await this.fetchImpl(o,{method:"POST",signal:l,headers:{"content-type":"application/json",appKey:this.config.apiAppKey,sign:Poe(a,c,t,this.config.apiSignKey,this.config.apiVersion),timestamp:String(c),version:this.config.apiVersion,...i.userToken?{authorization:i.userToken}:{}},body:JSON.stringify(a)});if(!p.ok)throw await p.body?.cancel(),new jo(`mbh-chat API request failed with HTTP ${p.status}`,p.status);let f=await p.json();if(!f||typeof f!="object"||Array.isArray(f))throw new jo("mbh-chat API returned a non-object JSON response",p.status);return f}catch(p){let f=p instanceof jo?p.status:void 0;throw this.logger.warn("mbh-chat API request failed",{request:d,...f!==void 0?{status:f}:{},error:p instanceof Error?p.message:String(p)}),p}}};var Ch=class{ttlMs;tokens=new Map;pending=new Map;constructor(t=3600*1e3){if(this.ttlMs=t,!Number.isFinite(t)||t<=0)throw new Error("user-token cache ttlMs must be positive")}key(t,r){return`${t}\0${r.userId}\0${r.appId}`}get(t,r){let i=this.key(t,r),n=this.tokens.get(i);if(n){if(Date.now()>=n.expiresAt){this.tokens.delete(i);return}return n.token}}set(t,r,i){this.tokens.set(this.key(t,r),{token:i,expiresAt:Date.now()+this.ttlMs})}delete(t,r){this.tokens.delete(this.key(t,r))}async getOrLoad(t,r,i){let n=this.get(t,r);if(n)return n;let o=this.key(t,r),s=this.pending.get(o);if(s)return s;let a=i().then(c=>{if(!c)throw new Error("mbh-chat user-token lookup returned an empty token");return this.set(t,r,c),c}).finally(()=>this.pending.delete(o));return this.pending.set(o,a),a}clear(){this.tokens.clear(),this.pending.clear()}};var joe=1001;function Ah(e,t){let r=t.code===void 0?"unknown":String(t.code),i=typeof t.message=="string"?t.message.replace(/[\u0000-\u001f\u007f]+/g," ").slice(0,300):"";return new Error(`${e} failed (code=${r})${i?`: ${i}`:""}`)}function CE(e,t,r){let i=e==null||e===""?t:e,n=typeof i=="number"?i:Number(String(i).trim());if(!Number.isSafeInteger(n)||n<0)throw new Error(`${r} must be a non-negative safe integer`);return n}function Moe(e){let t=e.match(/^(.*?)-(\d+(?:-\d+)*)$/);return t?t[1]??"":""}function Loe(e){if(e==null||e==="")return;let t=typeof e=="number"?e:Number(String(e).trim());return Number.isSafeInteger(t)&&t>=0?t:void 0}var Rh=class{config;client;tokenCache;constructor(t,r,i){this.config=t,this.client=new $h(t,r,i?.fetchImpl,i?.timeoutMs),this.tokenCache=i?.tokenCache??new Ch}context(t){return{appId:typeof t?.appId=="number"&&Number.isFinite(t.appId)?String(Math.trunc(t.appId)):typeof t?.appId=="string"&&t.appId.trim()?t.appId.trim():this.config.appId,userId:Number.isFinite(t?.userId)?t?.userId??0:Number(this.config.userId)||0}}async queryUserTokenByBotToken(t,r){let i=this.context(r),n=await this.client.post("/organization/queryUserTokenByBotTokenV2",{botToken:t,_userId:i.userId},{appId:i.appId,...r?.signal?{signal:r.signal}:{}});if(!n.data?.token)throw Ah("mbh-chat user-token lookup",n);return n.data.token}async getUserToken(t,r){let i=t.trim();if(!i)throw new Error("botToken is required for mbh-chat API authentication");let n=this.context(r);return this.tokenCache.getOrLoad(i,n,()=>this.queryUserTokenByBotToken(i,r))}async withUserToken(t,r,i){let n=t.trim(),o=this.context(r),s=await this.getUserToken(n,r);try{return await i(s)}catch(a){if(!(a instanceof jo)||a.status!==401)throw a;return this.tokenCache.delete(n,o),s=await this.getUserToken(n,r),i(s)}}async generateSignUrl(t,r,i){if(!t.trim())throw new Error("fileUrl is required for mbh-chat generateSignUrl");let n=this.context(i),o=await this.withUserToken(r,i,s=>this.client.post("/user/generateSignUrl",{loudPlatform:0,fileName:t},{appId:n.appId,userToken:s,...i?.signal?{signal:i.signal}:{}}));if(Number(o.code)!==0||!o.data?.filePath)throw Ah("mbh-chat generateSignUrl",o);return o.data.filePath}async getMyExpertDownloadUrl(t,r,i={}){let n=t.trim(),o=r.trim();if(!n)throw new Error("cloneCode is required for Agent package lookup");if(!o)throw new Error("botToken is required for mbh-chat Agent package lookup");let s=this.context(i),a=CE(i.userId,s.userId,"_userId"),c=Loe(i.businessUserId)??a,u=CE(i.domainId,this.config.domainId,"_domainId"),l=CE(i.appId,this.config.appId,"_appId"),d=await this.withUserToken(o,i,h=>this.client.post("/skill-market/v1/user_expert/get_my_expert_list",{_orgId:joe,_domainId:u,user_id:c,bot_token:o,page_no:1,key_word:Moe(n),page_size:200,with_download:!0,_userId:a},{appId:l,userToken:h,...i.signal?{signal:i.signal}:{}}));if(Number(d.code)!==0)throw Ah("mbh-chat Agent package lookup",d);let p=ye(d.data)?.list;if(!Array.isArray(p))throw new Error("mbh-chat Agent package lookup returned an invalid list");let f=p.map(h=>ye(h)).map(h=>nt(h?Ae(h,"downloadUrl","download_url"):void 0)).find(Boolean);if(!f)throw new Error(`Agent ${n} has no downloadable package`);return f}async getStsToken(t,r,i,n){if(!t.trim())throw new Error("sourceFileName is required for mbh-chat STS credentials");let o=this.context(n),s=await this.withUserToken(r,n,a=>this.client.post("/user/getStsTokenByAsync",{sourceFileName:t,isPrivate:i},{appId:o.appId,userToken:a,...n?.signal?{signal:n.signal}:{}}));if(!s.data?.bucket)throw Ah("mbh-chat STS credential lookup",s);return s.data}};var yV=Br(gV(),1);import{extname as Mye}from"node:path";import{fileURLToPath as Lye}from"node:url";var Fye=yV.default,zye=1024*1024,Uye=900*1e3;function Bye(e){if(typeof e=="string"){let t=e.trim();if(t.startsWith("file:"))try{return Lye(t)}catch{return e}return e}if(Buffer.isBuffer(e))return e;if(e&&typeof e=="object"){if(ArrayBuffer.isView(e)&&!(e instanceof DataView)&&!Buffer.isBuffer(e)){let i=e;return Buffer.from(i.buffer,i.byteOffset,i.byteLength)}let t=e,r=t.path??t.filePath;if(typeof r=="string"&&r.trim())return r.trim()}return e}var Wye={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".svg":"image/svg+xml",".ico":"image/x-icon",".avif":"image/avif",".heic":"image/heic",".heif":"image/heif",".pdf":"application/pdf",".mp4":"video/mp4",".webm":"video/webm",".mov":"video/quicktime",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".opus":"audio/opus",".m4a":"audio/mp4",".aac":"audio/aac",".flac":"audio/flac",".txt":"text/plain; charset=utf-8",".log":"text/plain; charset=utf-8",".csv":"text/csv; charset=utf-8",".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".xml":"application/xml; charset=utf-8",".md":"text/markdown; charset=utf-8",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation"};function JT(e){let t=e.split(/[/\\]/).pop()??e,r=Mye(t).toLowerCase();return r?Wye[r]:void 0}function Vye(e,t){if(typeof e=="string")return JT(e)??"application/octet-stream";if(Buffer.isBuffer(e)){if(t){let n=JT(t);if(n)return n}return"application/octet-stream"}let r=e.type?.trim();if(r&&r!=="application/octet-stream")return r;let i=typeof e.name=="string"&&e.name?e.name:"";if(i){let n=JT(i);if(n)return n}return r||"application/octet-stream"}function Zye(e){let t=e.split(";",1)[0]?.trim().toLowerCase()??"";return t==="image/svg+xml"||t==="text/html"||t==="application/xml"||t==="text/javascript"||t==="application/javascript"?"attachment":"inline"}async function Hye(e){if(Buffer.isBuffer(e))return{content:e,fileName:"file"};if(typeof e=="string")return{content:e,fileName:e.split(/[/\\]/).pop()??"file"};let t=Buffer.from(await e.arrayBuffer()),r=e.name;return{content:t,fileName:typeof r=="string"&&r?r:"file"}}var YT=class{api;logger;constructor(t,r){this.api=t,this.logger=r}async upload(t,r,i=1,n,o){let s=Bye(t),{content:a,fileName:c}=await Hye(s),u=await this.api.getStsToken(c,r,i,o),l=Vye(s,c),d=n?.onProgress,p={accessKeyId:u.tempAccessKeyId,accessKeySecret:u.tempAccessKeySecret,stsToken:u.tempSecurityToken,bucket:u.bucket,endpoint:u.endPoint,region:u.region,secure:!0,cname:!0,authorizationV4:!0,timeout:n?.timeoutMs??Uye},f=new Fye(p),h=`${u.uploadDir}${u.ossFileKey}`;try{let m,_={progress:g=>{d?.(g)},parallel:4,partSize:zye,mime:l,headers:{"Content-Disposition":Zye(l)}};if(m=await f.multipartUpload(h,a,_),m?.res?.status!==200)throw new Error(`OSS upload failed with status ${m?.res?.status??"unknown"}`);let x=(m?.res?.requestUrls||[])[0]||"",v=i===1&&m.name||x;if(!v)throw new Error("OSS upload succeeded but returned no object name or URL");return this.logger.info("OSS upload succeeded",{private:i===1}),v}catch(m){throw this.logger.error("OSS upload failed",{error:m instanceof Error?m.message:String(m)}),m}}};function vV(e,t){let r=new YT(e,t);return r.upload.bind(r)}var Jg=class{tails=new Map;generations=new Map;enqueue(t,r){let i=this.tails.get(t)??Promise.resolve(),n=this.generations.get(t)??0,o=i.catch(()=>{}).then(async()=>{(this.generations.get(t)??0)===n&&await r()});return this.tails.set(t,o),o.finally(()=>{this.tails.get(t)===o&&(this.tails.delete(t),this.generations.delete(t))}).catch(()=>{}),o}cancelPending(t){this.tails.has(t)&&this.generations.set(t,(this.generations.get(t)??0)+1)}cancelAllPending(){for(let t of this.tails.keys())this.cancelPending(t)}};import{randomUUID as eI}from"node:crypto";import tve from"node:fs";import Tr from"node:fs/promises";import rve from"node:os";import li from"node:path";import{resolveDshHome as nve,dshHomePath as ive,dshHomeDisplay as ove}from"@deepseek-ai/dsh-home-paths";var wV=Br(J0(),1);import Gye from"node:fs";import bV from"node:fs/promises";import Vl from"node:path";import{Transform as Kye}from"node:stream";import{pipeline as Xye}from"node:stream/promises";var xV=500*1024*1024,QT=1024*1024*1024,_V=2e4;function Jye(e){if((e.flags&2048)!==0)return new TextDecoder("utf-8").decode(e.pathBuffer);try{return new TextDecoder("utf-8",{fatal:!0}).decode(e.pathBuffer)}catch{return new TextDecoder("gbk").decode(e.pathBuffer)}}function Yye(e){let t=e.replaceAll("\\","/"),r=t.split("/").filter(Boolean);if(t.startsWith("/")||/^[a-z]:\//i.test(t)||r.some(i=>i==="."||i===".."))throw new Error(`skill archive contains an unsafe path: ${e}`);return t}function Qye(e){let t=e.map(n=>n.replaceAll("\\","/").replace(/\/+$/,"")).filter(Boolean);if(t.length===0)return;let r=new Set(t.map(n=>n.split("/").filter(Boolean)[0]).filter(Boolean));if(r.size!==1)return;let i=[...r][0];return i&&t.some(n=>n.startsWith(`${i}/`))&&t.every(n=>n===i||n.startsWith(`${i}/`))?i:void 0}function eve(e,t){let r=Vl.resolve(e,t),i=Vl.relative(Vl.resolve(e),r);if(!i||i.startsWith("..")||Vl.isAbsolute(i))throw new Error(`skill archive contains an unsafe path: ${t}`);return r}var Yg=class extends Kye{limitBytes;budget;constructor(t,r){super(),this.limitBytes=t,this.budget=r}_transform(t,r,i){if(this.budget.used+=t.length,this.budget.used>this.limitBytes){i(new Error(`skill archive expands beyond ${this.limitBytes} bytes`));return}i(null,t)}};async function SV(e,t){let r=await wV.default.Open.buffer(e);if(r.files.length>_V)throw new Error(`skill archive exceeds ${_V} entries`);let i=r.files.reduce((a,c)=>a+c.uncompressedSize,0);if(!Number.isSafeInteger(i)||i>QT)throw new Error(`skill archive expands beyond ${QT} bytes`);let n=r.files.map(a=>Yye(Jye(a))),o=Qye(n),s={used:0};for(let a=0;a<r.files.length;a+=1){let c=r.files[a],u=n[a];if(!c||!u)continue;let l=u.replaceAll("\\","/");if(o&&(l===o||l===`${o}/`)||(o&&l.startsWith(`${o}/`)&&(l=l.slice(o.length+1)),l=l.replace(/\/+$/,""),!l))continue;let d=eve(t,l);if(c.type==="Directory"){await bV.mkdir(d,{recursive:!0});continue}if(c.type!=="File")throw new Error(`skill archive contains an unsupported entry: ${u}`);await bV.mkdir(Vl.dirname(d),{recursive:!0}),await Xye(c.stream(),new Yg(QT,s),Gye.createWriteStream(d,{mode:384}))}}var sve=/^[a-z0-9]+(?:-[a-z0-9]+)*$/;function ey(e){let t=Array.isArray(e.skills_scope)?ye(e.skills_scope[0]):void 0,r=Array.isArray(e.intent_recognition)?e.intent_recognition.map(ye).filter(c=>!!c).find(c=>nt(Ae(c,"biz_type","bizType")).toLowerCase()==="skill"):void 0,i=t??r;if(!i)return;let n=nt(Ae(i,"skill_code","skillCode"))||(i===r?nt(i.name):"");if(!n)return;let o=nt(Ae(i,"short_name","shortName","name"))||n,s=nt(Ae(i,"url","download_url","downloadUrl","skill_url","skillUrl")),a=Ae(i,"skill_id","skillId","id");return{code:n,url:s,name:o,...typeof a=="string"||typeof a=="number"?{id:a}:{}}}var Qg=class{logger;options;dshHome;skillsRoot;skillsDisplayRoot;operations=new Map;constructor(t,r={}){this.logger=t,this.options=r,this.dshHome=nve(),this.skillsRoot=ive("skills"),this.skillsDisplayRoot=li.join(ove(this.dshHome),"skills")}normalizeCode(t){let r=t.trim();if(!sve.test(r))throw new Error(`invalid mbh-chat skill code: ${r||"<empty>"}`);return r}skillPath(t){return li.join(this.skillsRoot,this.normalizeCode(t))}skillDisplayPath(t){return li.join(this.skillsDisplayRoot,this.normalizeCode(t))}exists(t){try{return tve.existsSync(li.join(this.skillPath(t),"SKILL.md"))}catch{return!1}}install(t,r){return this.serialized(r,async()=>{let i,n;try{if(i=this.normalizeCode(r),n=this.skillPath(i),!t.trim())throw new Error("skill url is empty")}catch(c){return{success:!1,status:"fail",error:ne(c)}}let o=li.dirname(n),s=li.join(o,`.${i}.${eI()}.tmp`),a=li.join(o,`.${i}.${eI()}.bak`);try{await Tr.mkdir(o,{recursive:!0,mode:448}),await Hu(async()=>{await Tr.rm(s,{recursive:!0,force:!0}),await Tr.mkdir(s,{recursive:!0,mode:448});let u=await this.download(t);await SV(u,s);let l=li.join(s,"SKILL.md");if(!(await Tr.stat(l).catch(()=>{}))?.isFile())throw new Error("skill archive does not contain a root SKILL.md")});let c=await Tr.stat(n).then(()=>!0,()=>!1);c&&await Tr.rename(n,a);try{await Tr.rename(s,n)}catch(u){throw c&&await Tr.rename(a,n).catch(()=>{}),u}return await Tr.rm(a,{recursive:!0,force:!0}).catch(u=>{this.logger.warn("could not remove the previous mbh-chat skill backup",{code:i,error:ne(u)})}),this.logger.info("installed mbh-chat skill",{code:i,path:this.skillDisplayPath(i)}),{success:!0,status:"ok"}}catch(c){return await Tr.rm(s,{recursive:!0,force:!0}).catch(()=>{}),this.logger.error("mbh-chat skill installation failed",{code:i,error:ne(c)}),{success:!1,status:"fail",error:ne(c)}}})}uninstall(t){return this.serialized(t,async()=>{try{let r=this.normalizeCode(t),i=this.skillPath(r);return await Tr.rm(i,{recursive:!0,force:!0}),this.logger.info("uninstalled mbh-chat skill",{code:r,path:this.skillDisplayPath(r)}),{success:!0,status:"ok"}}catch(r){return this.logger.error("mbh-chat skill removal failed",{code:t,error:ne(r)}),{success:!1,status:"fail",error:ne(r)}}})}eventContent(t,r){return{event_type:"skill",operation_type:"install",skill_url:t.url,skill_code:t.code,...t.id!==void 0?{skill_id:t.id}:{},...r?{bot_token:r}:{}}}serialized(t,r){let i=t.trim(),o=(this.operations.get(i)??Promise.resolve({success:!0,status:"ok"})).catch(()=>{}).then(r);return this.operations.set(i,o),o.finally(()=>{this.operations.get(i)===o&&this.operations.delete(i)}),o}async download(t){let r=await Tr.mkdtemp(li.join(rve.tmpdir(),"mbh-chat-skill-"));try{let i=await Vs([{url:t,name:"skill.zip"}],{storageRoot:r,requestId:eI(),maxBytes:xV,maxFiles:1,maxInlineImageBytes:1,fetchTimeoutMs:18e4,concurrency:1,allowPrivateNetwork:this.options.allowPrivateNetwork??!1,...this.options.fetchImpl?{fetchImpl:this.options.fetchImpl}:{}}),n=i.media[0];if(!n)throw new Error(i.failures[0]?.reason||"skill download failed");return await Tr.readFile(n.localPath)}finally{await Tr.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}};import{randomUUID as EV}from"node:crypto";var tI=class{baseUrl;logger;sessionCookie;socket;streams=new Map;opening;closed;constructor(t,r,i){this.baseUrl=t,this.logger=r,this.sessionCookie=i}async*open(t,r,i,n){let o=EV(),s=[],a,c=l=>{s.push(l),a?.(),a=void 0};this.streams.set(o,c);let u=()=>{this.send({type:"cancel",streamId:o}),c({kind:"end"})};i.addEventListener("abort",u,{once:!0});try{if(await this.ensureOpen(),this.closed)throw this.closed;for(this.send({type:"open",streamId:o,endpoint:t,payload:r}),n?.(),i.aborted&&u();;){for(;s.length>0;){let l=s.shift();if(!l||l.kind==="end")return;if(l.kind==="error")throw l.error;yield l.value}await new Promise(l=>{a=l})}}finally{i.removeEventListener("abort",u),this.streams.delete(o),i.aborted||this.send({type:"cancel",streamId:o})}}close(t){this.closed=t??new Error("mbh-chat Remote mux closed");for(let i of this.streams.values())i({kind:"end"});this.streams.clear();let r=this.socket;this.socket=void 0,this.opening=void 0,r&&(r.readyState===rr.CONNECTING?r.terminate():r.readyState===rr.OPEN&&r.close(1e3,"bridge stream stopped"))}async ensureOpen(){if(this.socket?.readyState===rr.OPEN)return;if(this.opening)return this.opening;let t=new URL("/api/remote.mux",this.baseUrl);t.protocol=t.protocol==="https:"?"wss:":"ws:";let r=new rr(t,{headers:vn(this.sessionCookie)});this.socket=r,this.opening=new Promise((i,n)=>{let o=s=>{this.close(s),n(s)};r.once("open",()=>{r.once("close",()=>this.close(new Error("mbh-chat Remote mux closed"))),i()}),r.once("error",s=>o(s instanceof Error?s:new Error(String(s))))}),r.on("message",(i,n)=>{if(n){this.logger.warn("dropping binary mbh-chat WebSocket frame",{path:"/api/remote.mux"});return}let o;try{o=JSON.parse(i.toString())}catch(a){this.logger.warn("dropping malformed mbh-chat Remote mux frame",{error:a instanceof Error?a.message:String(a)});return}let s=this.streams.get(o.streamId);s&&(o.type==="item"?s({kind:"frame",value:o.value}):o.type==="error"?s({kind:"error",error:new Error(`mbh-chat ${o.error.code}: ${o.error.message}`)}):s({kind:"end"}))}),await this.opening}send(t){this.socket?.readyState===rr.OPEN&&this.socket.send(JSON.stringify(t))}},ty=class{baseUrl;logger;timeoutMs;sessionCookie;mux;eventClientId;constructor(t,r,i=3e4,n=Th()){this.baseUrl=t,this.logger=r,this.timeoutMs=i,this.sessionCookie=n}sessions={create:(t,r)=>this.invoke("session/create",{request:t},r),prompt:(t,r)=>this.invoke("session/prompt",{request:t},r),cancel:(t,r)=>this.invoke("session/cancel",{request:t},r),selectModel:(t,r)=>this.invoke("session/selectModel",{request:t},r),modelCatalog:t=>this.invoke("session/modelCatalog",{},t),follow:(t,r,i)=>this.openStream("session/follow",{request:t},r,i)};openEvents(t,r){return this.openStream("$events",{},t,r)}respondEvent(t,r){let i=t.clientId??this.eventClientId;if(!i)throw new Error("mbh-chat event stream is not ready");return this.invoke("$events/result",{clientId:i,eventId:t.eventId,outcome:t.outcome},r)}disconnect(){this.eventClientId=void 0,this.mux?.close(),this.mux=void 0}async invoke(t,r,i){let n=EV(),o=await fetch(new URL(`/api/${t}`,this.baseUrl),{method:"POST",headers:vn(this.sessionCookie,{"Content-Type":"application/json"}),body:JSON.stringify({type:"client-request",rpcId:n,method:t,payload:{args:r}}),signal:i?AbortSignal.any([i,AbortSignal.timeout(this.timeoutMs)]):AbortSignal.timeout(this.timeoutMs)});if(!o.ok)throw Object.assign(new Error(`mbh-chat ${t} returned HTTP ${o.status}`),{code:"http-error"});return await o.json()}openStream(t,r,i,n){return this.mux??=new tI(this.baseUrl,this.logger,this.sessionCookie),this.mux.open(t,{args:r},i,n)}};function An(e){if(e.result.ok)return e.result.value;let t=new Error(`mbh-chat ${e.result.error.code}: ${e.result.error.message}`);throw Object.assign(t,{code:e.result.error.code}),t}function ave(e){if(!(typeof e!="object"||e===null||!("code"in e)))return typeof e.code=="string"?e.code:void 0}var cve=new Set(["session/not-found","session-not-found"]);function rI(e){return e!==void 0&&cve.has(e)}function nI(e){return rI(ave(e))}function kV(){let e,t;return{promise:new Promise((i,n)=>{e=i,t=n}),resolve:e,reject:t}}var uve=3e3;function lve(e,t,r){let i=Math.min(r,t*2**Math.min(e,8));return i+Math.floor(Math.random()*Math.max(1,Math.min(1e3,i/5)))}function TV(e,t){return new Promise(r=>{if(t.aborted)return r();let i=setTimeout(n,e);function n(){clearTimeout(i),t.removeEventListener("abort",n),r()}t.addEventListener("abort",n,{once:!0})})}var ry=class{reconnectMinMs;reconnectMaxMs;logger;api;rootAbort;generationAbort;handlers;loopPromise;connected=!1;followedSessions=new Set;followAborts=new Map;followReadiness=new Map;liveFollows=new Set;connectionWaiters=new Set;constructor(t,r,i,n){this.reconnectMinMs=r,this.reconnectMaxMs=i,this.logger=n,this.api=new ty(t,n)}start(t){if(this.loopPromise)throw new Error("mbh-chat connection already started");this.handlers=t,this.rootAbort=new AbortController,this.loopPromise=this.run(t,this.rootAbort.signal)}async stop(){this.rootAbort?.abort();let t=new Error("mbh-chat connection stopped before becoming ready");for(let r of this.connectionWaiters)r.reject(t);this.connectionWaiters.clear();for(let r of this.followReadiness.values())r.reject(t);this.followReadiness.clear(),this.liveFollows.clear(),await this.loopPromise,this.loopPromise=void 0,this.rootAbort=void 0,this.handlers=void 0,this.api.disconnect()}isConnected(){return this.connected}followSession(t){if(this.followedSessions.add(t),this.liveFollows.has(t))return Promise.resolve();let r=this.followReadiness.get(t);r||(r=kV(),this.followReadiness.set(t,r)),this.connected&&this.generationAbort&&!this.followAborts.has(t)&&this.startFollow(t,this.generationAbort.signal);let i=r.promise;return i.catch(()=>{}),Promise.race([i,TV(uve,this.generationAbort?.signal??new AbortController().signal).then(()=>{this.liveFollows.has(t)||this.logger.warn("mbh-chat session follow was not ready before timeout",{sessionId:t})})])}unfollowSession(t){this.followedSessions.delete(t),this.liveFollows.delete(t),this.followAborts.get(t)?.abort(),this.followAborts.delete(t),this.followReadiness.get(t)?.reject(new Error(`mbh-chat stopped following session ${t}`)),this.followReadiness.delete(t)}whenConnected(t){return this.connected?Promise.resolve():new Promise((r,i)=>{let n=()=>{a(),r()},o=u=>{a(),i(u)},s=()=>o(t?.reason??new Error("waiting for mbh-chat connection was aborted")),a=()=>{this.connectionWaiters.delete(c),t?.removeEventListener("abort",s)},c={resolve:n,reject:o};this.connectionWaiters.add(c),t?.addEventListener("abort",s,{once:!0}),t?.aborted&&s()})}async setConnected(t,r){if(t||(this.connected=!1),await r.onConnection?.(t),t){this.connected=!0;for(let i of this.connectionWaiters)i.resolve();this.connectionWaiters.clear()}}async run(t,r){let i=0;for(;!r.aborted;){let n=new AbortController;this.generationAbort=n;let o=()=>n.abort();r.addEventListener("abort",o,{once:!0});let s=kV(),a=!1,c;try{c=this.pumpEvents(t,n.signal,s.resolve);let u=c.then(()=>{throw new Error("a mbh-chat event stream closed")});await Promise.race([s.promise,u]),a=!0,i=0,await this.setConnected(!0,t);for(let l of this.followedSessions)this.startFollow(l,n.signal);await u}catch(u){r.aborted||this.logger.warn("mbh-chat connection lost",{error:ne(u)})}finally{if(this.generationAbort=void 0,n.abort(),this.stopFollows(),this.api.disconnect(),await Promise.allSettled(c?[c]:[]),r.removeEventListener("abort",o),a)try{await this.setConnected(!1,t)}catch(u){this.logger.error("mbh-chat connection-state handler failed during disconnect",{error:ne(u)})}}if(!r.aborted){let u=lve(i++,this.reconnectMinMs,this.reconnectMaxMs);this.logger.info("reconnecting to mbh-chat Host",{delayMs:u,attempt:i}),await TV(u,r)}}}async pumpEvents(t,r,i){let n=!1;for await(let o of this.api.openEvents(r)){if(o.type==="ready"){this.api.eventClientId=o.clientId,n||(n=!0,i());continue}try{await t.onRemoteEvent(o)}catch(s){this.logger.error("mbh-chat event handler failed",{error:ne(s)})}}}markFollowReady(t){this.liveFollows.add(t),this.followReadiness.get(t)?.resolve()}async startFollow(t,r){if(this.followAborts.has(t))return;let i=new AbortController;this.followAborts.set(t,i);let n=AbortSignal.any([r,i.signal]),o=!1;try{for await(let s of this.api.sessions.follow({address:{kind:"session",sessionId:t}},n)){if(s.type==="snapshot"){o=!0,this.markFollowReady(t);continue}if(s.type==="event")try{this.handlers?.onSessionEvent(t,s.event)}catch(a){this.logger.error("mbh-chat session event handler failed",{sessionId:t,error:ne(a)})}}if(!n.aborted&&!o)throw new Error(`mbh-chat session follow ended before receiving a snapshot for ${t}`)}catch(s){!r.aborted&&!i.signal.aborted&&(this.followReadiness.get(t)?.reject(s),this.logger.warn("mbh-chat session follow ended",{sessionId:t,error:ne(s)}))}finally{this.followAborts.get(t)===i&&this.followAborts.delete(t),this.liveFollows.delete(t)}}stopFollows(){for(let t of this.followAborts.values())t.abort();this.followAborts.clear(),this.liveFollows.clear()}};async function IV(e,t,r,i){let n=new Map;for(let u of e.store.listActiveSubagentsForRoot(t))(!r||u.requestId===r)&&n.set(u.childSessionId,u.parentSessionId);for(let[u,l]of i??[])n.set(u,l);let o=!1,s=!1,a,c=u=>{e.store.settleSubagent(u,"cancelled"),n.delete(u)};for(let u=1;u<=e.config.task.maxAttempts;u+=1){let l=p=>{let f=0,h=p,m=new Set;for(;!m.has(h);){m.add(h);let _=n.get(h);if(!_)break;f+=1,h=_}return f},d=[...n].sort(([p],[f])=>l(f)-l(p));for(let[p,f]of d)try{An(await e.dsh.api.sessions.cancel({sessionId:p})),c(p)}catch(h){if(nI(h)){c(p);continue}a=h,e.logger.warn("subagent interrupt failed",{parentSessionId:f,childSessionId:p,attempt:u,error:ne(h)})}if(!o)try{An(await e.dsh.api.sessions.cancel({sessionId:t})),o=!0}catch(p){nI(p)?(o=!0,s=!0):(a=p,e.logger.warn("model/tool cancellation failed",{dshSessionId:t,attempt:u,error:ne(p)}))}if(o&&n.size===0)return s?"absent":"cancelled";if(u<e.config.task.maxAttempts){let p=Math.min(e.config.task.retryMaxMs,e.config.task.retryBaseMs*2**(u-1));await new Promise(f=>setTimeout(f,p))}}throw a instanceof Error?a:new Error("execution cancellation could not be confirmed")}var fve=/request id\s*:\s*([a-z0-9_-]{1,128})/iu,dve=new RegExp("\\p{Script=Han}","u");function pve(e){let t=fve.exec(e)?.[1];return t?`\uFF08\u8BF7\u6C42 ID\uFF1A${t}\uFF09`:""}function hve(e,t){let r=e?.trim();return r?r.slice(0,120):t}function mve(e){let t=ne(e).trim(),r=pve(t),i=/range of max_tokens should be \[\s*(\d+)\s*,\s*(\d+)\s*\]/iu.exec(t);if(i)return`\u6A21\u578B\u751F\u6210\u957F\u5EA6\u53C2\u6570\uFF08max_tokens\uFF09\u8D85\u51FA\u5141\u8BB8\u8303\u56F4\uFF0C\u6709\u6548\u8303\u56F4\u4E3A ${i[1]}\u2013${i[2]}\u3002${r}`;let n=/no available channel for model\s+(.+?)\s+under group\b/iu.exec(t);return n?`\u6A21\u578B ${hve(n[1],"\u5F53\u524D\u6A21\u578B")} \u5F53\u524D\u6682\u65E0\u53EF\u7528\u670D\u52A1\u901A\u9053\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/no available channel/iu.test(t)?`\u5F53\u524D\u6A21\u578B\u6682\u65E0\u53EF\u7528\u670D\u52A1\u901A\u9053\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/tokenization failed/iu.test(t)?`\u6A21\u578B\u65E0\u6CD5\u5904\u7406\u5F53\u524D\u8F93\u5165\uFF0C\u8BF7\u7F29\u77ED\u5185\u5BB9\u6216\u5207\u6362\u6A21\u578B\u540E\u91CD\u8BD5\u3002${r}`:/completed response with no content|empty response|no content returned/iu.test(t)?`\u6A21\u578B\u672A\u8FD4\u56DE\u6709\u6548\u5185\u5BB9\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/context length|maximum context|context window|too many tokens/iu.test(t)?`\u5BF9\u8BDD\u5185\u5BB9\u8D85\u8FC7\u6A21\u578B\u53EF\u5904\u7406\u7684\u957F\u5EA6\uFF0C\u8BF7\u7F29\u77ED\u5185\u5BB9\u6216\u65B0\u5EFA\u4F1A\u8BDD\u3002${r}`:/\b(401|unauthorized|invalid api.?key|authentication)\b/iu.test(t)?`\u6A21\u578B\u670D\u52A1\u8BA4\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u670D\u52A1\u914D\u7F6E\u3002${r}`:/\b(403|forbidden|permission denied)\b/iu.test(t)?`\u5F53\u524D\u8D26\u53F7\u65E0\u6743\u8BBF\u95EE\u8BE5\u6A21\u578B\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u6743\u9650\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/\b(429|rate.?limit|too many requests|overload|busy)\b/iu.test(t)?`\u6A21\u578B\u670D\u52A1\u5F53\u524D\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`:/timeout|timed out/iu.test(t)?`\u6A21\u578B\u670D\u52A1\u54CD\u5E94\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`:/\b5\d\d\b|bad gateway|service unavailable|upstream.*(?:error|failed)/iu.test(t)?`\u4E0A\u6E38\u6A21\u578B\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`:/invalidparameter|invalid parameter|\b400\b|bad request/iu.test(t)?`\u6A21\u578B\u8BF7\u6C42\u53C2\u6570\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u914D\u7F6E\u3002${r}`:dve.test(t)?t.replace(/^\[错误\]\s*/u,""):`\u6A21\u578B\u670D\u52A1\u8C03\u7528\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`}function bc(e){return`[\u9519\u8BEF] ${mve(e)}`}var OV=2e3;function Qi(e){return e.time/1e3+e.seq/1e9}function ny(e,t){return Array.isArray(e)?e.map(r=>{let i=ye(r);return i?.type===t&&typeof i.text=="string"?i.text:""}).join(""):""}function iI(e,t){let r=e.trim()||t;return r.length<=OV?r:`${r.slice(0,OV)}\u2026\u2026\uFF08\u5185\u5BB9\u5DF2\u622A\u65AD\uFF09`}function oI(e){return Array.isArray(e)?e.map(t=>{let r=ye(t);if(!r)return"";if((r.type==="text"||r.type==="reasoning")&&typeof r.text=="string")return r.text;if(r.type==="image")return"[\u56FE\u7247]";try{return JSON.stringify(r)}catch{return"[\u65E0\u6CD5\u5C55\u793A\u7684\u5DE5\u5177\u7ED3\u679C]"}}).filter(Boolean).join(`
578
+ `)})}}var cl=class{baseUrl;fetchImpl;sessionCookie;constructor(t,r=fetch,i=Th()){this.baseUrl=t,this.fetchImpl=r,this.sessionCookie=i}url(t){return new URL(t,this.baseUrl.endsWith("/")?this.baseUrl:`${this.baseUrl}/`)}async patch(t,r){return(await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}`),{method:"PATCH",headers:vn(this.sessionCookie,{"content-type":"application/json"}),body:JSON.stringify(r),signal:AbortSignal.timeout(15e3)})).ok}async patchJob(t,r){let i=await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}`),{method:"PATCH",headers:vn(this.sessionCookie,{"content-type":"application/json"}),body:JSON.stringify(r),signal:AbortSignal.timeout(15e3)});if(!i.ok)return;let n=await i.json().catch(()=>{});return al({type:Na,version:1,jobs:[n]}).jobs.find(o=>o.id===t)}setEnabled(t,r){return this.patch(t,{enabled:r})}async delete(t){let r=await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}`),{method:"DELETE",headers:vn(this.sessionCookie),signal:AbortSignal.timeout(15e3)});return r.ok?"deleted":r.status===404?"not_found":"failed"}async runOnce(t){let r=await this.fetchImpl(this.url(`${Fi}/${encodeURIComponent(t)}/run`),{method:"POST",headers:vn(this.sessionCookie),signal:AbortSignal.timeout(15e3)}),i=await r.json().catch(()=>{}),n=Dr(i)&&typeof i.status=="string"?i.status:void 0;return n==="dispatched"||n==="not_found"||n==="already_running"||n==="delivery_unavailable"?n:r.status===404?"not_found":r.status===202?"already_running":r.ok&&Dr(i)&&i.delivered===!0?"dispatched":"delivery_unavailable"}async list(){let t=await this.fetchImpl(this.url(`${Fi}`),{method:"GET",headers:vn(this.sessionCookie),signal:AbortSignal.timeout(15e3)});if(!t.ok)return;let r=await t.json().catch(()=>{});if(!(!Dr(r)||!Array.isArray(r.jobs)))return al({type:Na,version:1,sequence:0,generatedAt:new Date().toISOString(),reason:"fetch",jobs:r.jobs})}async subscribe(t,r,i=()=>{}){let n=await this.fetchImpl(this.url(`${Fi}/events`),{method:"GET",headers:vn(this.sessionCookie,{accept:"text/event-stream"}),signal:r});if(!n.ok||!n.body)throw new Error(`cron SSE failed with HTTP ${n.status}`);let o=n.body.getReader(),s=new TextDecoder,a="";for(;;){let{value:c,done:u}=await o.read();if(u){if(!r.aborted)throw new Error("cron SSE stream ended");return}a+=s.decode(c,{stream:!0});let{events:l,rest:d}=Soe(a);a=d;for(let p of l)if(p.event==="cron-list")try{t(al(JSON.parse(p.data)))}catch(f){i(f)}}}};var Eoe=100,koe=1e3,Toe=3e4;function $E(e){let{updatedAtMs:t,state:r,...i}=e;return JSON.stringify(i,(n,o)=>o&&typeof o=="object"&&!Array.isArray(o)?Object.fromEntries(Object.entries(o).sort(([s],[a])=>s.localeCompare(a))):o)}function Ioe(e,t){return new Promise(r=>{if(e.aborted){r();return}let i=()=>{clearTimeout(n),e.removeEventListener("abort",i),r()},n=setTimeout(i,t);n.unref(),e.addEventListener("abort",i,{once:!0})})}var Ih=class{options;client;abort;loop;debounce;publishTail=Promise.resolve();lastFingerprint;lastContext;lastSnapshot;lastJobs=new Map;lastContexts=new Map;constructor(t){this.options=t,this.client=new cl(t.dshBaseUrl,t.fetchImpl)}start(){if(this.loop)return;let t=this.options.store.getLatestContext();t&&(this.lastContext=t),this.abort=new AbortController,this.loop=this.run(this.abort.signal)}async stop(){this.abort?.abort(),this.debounce&&clearTimeout(this.debounce),this.debounce=void 0,await this.loop?.catch(()=>{}),await this.publishTail,this.loop=void 0,this.abort=void 0}async applyControl(t,r){if(t==="remove"){let n=await this.client.delete(r);return{applied:n!=="failed",...n==="not_found"?{reconciled:!0}:{}}}if(t==="enable")return{applied:await this.client.setEnabled(r,!0)};if(t==="disable")return{applied:await this.client.setEnabled(r,!1)};await this.ensureSessionForCron(r),await this.ensureSessionFollowed(r);let i=await this.client.runOnce(r);return i==="delivery_unavailable"&&(i=await this.rebindAndRetryRun(r,i)),{applied:i==="dispatched"||i==="already_running",runStatus:i}}notifySessionAvailable(){this.lastSnapshot&&this.schedulePublish(this.lastSnapshot)}businessKeyForCronId(t){let r=this.lastSnapshot?.jobs.find(i=>i.id===t);if(r)return this.sessionKeyFor(r)}async bindDshSessionId(t,r){if(!bn(t))return;let i=this.lastSnapshot??await this.client.list();if(!i)return;let n=i.jobs.filter(o=>o.sessionKey===t&&(!o.dshSessionId||o.dshSessionId!==r));n.length!==0&&await Promise.all(n.map(async o=>{await this.client.patch(o.id,{dshSessionId:r})?(this.options.logger.info("bound cron job to mbh-chat session",{cronId:o.id,sessionKey:t,dshSessionId:r}),this.followCronSession(r)):this.options.logger.warn("failed to patch cron dshSessionId binding",{cronId:o.id,sessionKey:t,dshSessionId:r})}))}async bindAllKnownDshSessions(){let t=this.lastSnapshot??await this.client.list();if(!t)return;let r=new Map;for(let i of t.jobs){if(!i.sessionKey||!bn(i.sessionKey))continue;let n=this.options.store.getSession(i.sessionKey);!n||i.dshSessionId===n||r.set(i.id,n)}r.size!==0&&await Promise.all([...r.entries()].map(async([i,n])=>{await this.client.patch(i,{dshSessionId:n})?(this.options.logger.info("bound cron job to pre-existing mbh-chat session",{cronId:i,dshSessionId:n}),this.followCronSession(n)):this.options.logger.warn("failed to patch cron dshSessionId binding",{cronId:i,dshSessionId:n})}))}async run(t){let r=0;for(;!t.aborted;)try{await this.client.subscribe(i=>this.schedulePublish(i),t,i=>this.options.logger.warn("ignored invalid cron catalog SSE event",{error:ne(i)})),r=0}catch(i){if(t.aborted)return;r+=1;let n=Math.min(Toe,koe*2**Math.min(r-1,8));this.options.logger.warn("cron catalog SSE disconnected; retrying",{delayMs:n,error:ne(i)}),await Ioe(t,n)}}schedulePublish(t){this.lastSnapshot=t,this.debounce&&clearTimeout(this.debounce),this.debounce=setTimeout(()=>{this.debounce=void 0,this.publishTail=this.publishTail.then(()=>this.publish(t)).catch(r=>this.options.logger.warn("failed to publish cron catalog to Mobook",{error:ne(r)}))},this.options.debounceMs??Eoe),this.debounce.unref()}async rebindAndRetryRun(t,r){let n=(await this.client.list().catch(()=>{}))?.jobs.find(s=>s.id===t);if(!n?.sessionKey||!bn(n.sessionKey))return r;let o=this.options.store.getSession(n.sessionKey);return!o||o===n.dshSessionId||!await this.client.patch(t,{dshSessionId:o})?r:(this.options.logger.info("rebound stale cron DSH session before manual run",{cronId:t,dshSessionId:o}),await this.followCronSession(o),this.client.runOnce(t))}async ensureSessionForCron(t){let i=(await this.client.list().catch(()=>{}))?.jobs.find(o=>o.id===t);if(!i?.sessionKey||!bn(i.sessionKey))return;let n=this.options.store.getSession(i.sessionKey);n||(n=await this.options.provisionSession?.(i)),n&&i.dshSessionId!==n&&await this.client.patch(t,{dshSessionId:n})&&this.options.logger.info("provisioned cron DSH session before dispatch",{cronId:t,dshSessionId:n})}contextFor(t){if(t.sessionKey){let i=this.options.store.getLatestContextForBusinessKey(t.sessionKey);if(i)return i}let r=this.options.store.getBusinessKeyByDshSessionId(t.dshSessionId??t.agentId);return r?this.options.store.getLatestContextForBusinessKey(r):void 0}sessionKeyFor(t){return t.sessionKey?t.sessionKey:this.options.store.getBusinessKeyByDshSessionId(t.dshSessionId??t.agentId)}adoptionOwner(){let t=this.lastContext??this.options.store.getLatestContext?.();if(!t||!bn(t.businessKey))return;let r=zi(t.businessKey).agentId;return r?{businessKey:t.businessKey,agentId:r}:void 0}isForeignOwner(t,r){return!t||!bn(t)?!0:zi(t).agentId!==r}send(t,r){return this.options.dcg.enqueueEvent(t,r)!==!1}async publish(t){let r=this.adoptionOwner(),i=[];for(let l of t.jobs){let d=this.sessionKeyFor(l);if(r&&this.isForeignOwner(d,r.agentId)&&(d=r.businessKey),!d){i.push(l);continue}let p=zi(d),f=this.options.store.getSession(d),h={...l.sessionKey===d?{}:{sessionKey:d},...f&&l.dshSessionId!==f?{dshSessionId:f}:{},...p.agentId&&l.agentId!==p.agentId?{agentId:p.agentId}:{}};if(Object.keys(h).length>0){let m=await this.client.patchJob(l.id,h);if(!m){this.options.logger.warn("failed to persist cron sessionKey binding",{cronId:l.id});return}i.push(m)}else i.push(l)}let n=OE(i,l=>this.sessionKeyFor(l)),o=JSON.stringify(n.jobs.map(l=>[l.id,$E(l)]).sort());if(o===this.lastFingerprint)return;if(t.jobs.length>0&&n.jobs.length===0){this.options.logger.warn("skipping Mobook cron catalog publish; no mbh-chat session mapping is available yet");return}let s=new Set(n.jobs.map(l=>l.id)),a=new Set,c=new Set;for(let l of n.jobs){let d=$E(l);if(this.lastJobs.get(l.id)===d)continue;let p=i.find(h=>h.id===l.id),f=p?this.contextFor(p):void 0;if(!f&&p?.sessionKey&&bn(p.sessionKey)&&(await this.ensureSessionForCron(p.id),f=this.contextFor(p)),!f){this.options.logger.warn("skipping cron install; no mapped mbh-chat session is available",{cronId:l.id}),a.add(l.id);continue}if(!this.send(f,{event_type:"cron",operation_type:"install",data:l})){this.options.logger.warn("cron install event was not sent; will retry",{cronId:l.id});return}this.lastJobs.set(l.id,d),this.lastContexts.set(l.id,f),this.lastContext=f,this.lastFingerprint=void 0,this.options.logger.info("enqueued cron install to Mobook",{cronId:l.id,sequence:t.sequence})}if(t.invalidJobCount===0)for(let l of this.lastJobs.keys()){if(s.has(l))continue;let d=this.lastContexts.get(l);if(!d){this.options.logger.warn("skipping cron remove; no mapped mbh-chat session is available",{cronId:l}),c.add(l);continue}if(!this.send(d,{event_type:"cron",operation_type:"remove",data:{id:l,jobId:l,action:"removed"}})){this.options.logger.warn("cron remove event was not sent; will retry",{cronId:l});return}this.lastJobs.delete(l),this.lastContexts.delete(l),this.lastFingerprint=void 0}else this.options.logger.warn("cron snapshot contained invalid jobs; preserving previously published jobs",{invalidJobCount:t.invalidJobCount});let u=new Map([...this.lastJobs].filter(([l])=>s.has(l)||c.has(l)));for(let l of n.jobs)a.has(l.id)||u.set(l.id,$E(l));if(t.invalidJobCount>0)for(let[l,d]of this.lastJobs)u.has(l)||u.set(l,d);this.lastJobs=u,this.lastFingerprint=t.invalidJobCount===0&&a.size===0&&c.size===0?o:void 0,this.followBoundJobs(i),this.options.logger.info("published cron catalog to Mobook",{jobs:n.jobs.length,sequence:t.sequence})}async ensureSessionFollowed(t){let i=(this.lastSnapshot??await this.client.list().catch(()=>{}))?.jobs.find(s=>s.id===t);if(!i)return;let n=this.sessionKeyFor(i),o=(n?this.options.store.getSession(n):void 0)||i.dshSessionId;o&&await this.followCronSession(o)}followBoundJobs(t){let r=new Set;for(let i of t){let n=this.sessionKeyFor(i),o=(n?this.options.store.getSession(n):void 0)||i.dshSessionId;!o||r.has(o)||(r.add(o),this.followCronSession(o))}}async followCronSession(t){this.options.followSession&&await this.options.followSession(t)}};import{timingSafeEqual as Ooe}from"node:crypto";import Pa from"node:fs";import $oe from"node:http";import Coe from"node:path";var pL=1024*1024,qke=64*1024;function Aoe(e,t){if(!e?.startsWith("Bearer "))return!1;let r=Buffer.from(e.slice(7)),i=Buffer.from(t);return r.length===i.length&&Ooe(r,i)}async function Roe(e){let t=[],r=0;for await(let i of e){let n=Buffer.isBuffer(i)?i:Buffer.from(i);if(r+=n.length,r>pL)throw new Error(`request body exceeds ${pL} bytes`);t.push(n)}return JSON.parse(Buffer.concat(t).toString("utf8"))}function qa(e,t,r){let i=JSON.stringify(r);e.writeHead(t,{"content-type":"application/json; charset=utf-8","content-length":Buffer.byteLength(i)}),e.end(i)}var Oh=class{socketPath;token;handler;statusProvider;server;constructor(t,r,i,n){this.socketPath=t,this.token=r,this.handler=i,this.statusProvider=n}async start(){if(this.server)throw new Error("message control server already started");if(process.platform!=="win32"){Pa.mkdirSync(Coe.dirname(this.socketPath),{recursive:!0});try{if(!Pa.lstatSync(this.socketPath).isSocket())throw new Error(`refusing to replace non-socket control path: ${this.socketPath}`);Pa.unlinkSync(this.socketPath)}catch(r){if(r.code!=="ENOENT")throw r}}let t=$oe.createServer((r,i)=>{this.handle(r,i)});this.server=t,await new Promise((r,i)=>{let n=s=>{t.off("listening",o),i(s)},o=()=>{t.off("error",n),r()};t.once("error",n),t.once("listening",o),t.listen(this.socketPath)}),process.platform!=="win32"&&Pa.chmodSync(this.socketPath,384)}async stop(){let t=this.server;if(this.server=void 0,t&&await new Promise(r=>t.close(()=>r())),process.platform!=="win32")try{Pa.lstatSync(this.socketPath).isSocket()&&Pa.unlinkSync(this.socketPath)}catch(r){if(r.code!=="ENOENT")throw r}}async handle(t,r){let i=t.method==="POST"&&t.url==="/v1/message",n=t.method==="GET"&&t.url==="/v1/status";if(!i&&!n){qa(r,404,{error:"not found"});return}if(!Aoe(t.headers.authorization,this.token)){qa(r,401,{error:"unauthorized"});return}if(n){if(!this.statusProvider){qa(r,404,{error:"not found"});return}qa(r,200,this.statusProvider());return}let o=new AbortController,s=()=>o.abort(new Error("control client disconnected"));t.once("aborted",s);try{let a=await Roe(t),c=await this.handler(a,o.signal);qa(r,c.success?200:422,c)}catch(a){qa(r,400,{success:!1,sentMediaCount:0,queued:!1,error:a instanceof Error?a.message:String(a)})}finally{t.off("aborted",s)}}};import{createHash as Doe}from"node:crypto";var jo=class extends Error{status;constructor(t,r){super(t),this.status=r,this.name="DcgApiRequestError"}};function Noe(e){return e!==null&&typeof e=="object"?JSON.stringify(e):String(e)}function Poe(e,t,r,i,n="1.0.0"){let o={timestamp:t,path:r,version:n,...e},s=Object.keys(o).sort().map(a=>o[a]===void 0?"":`${a}${Noe(o[a])}`).join("")+i;return Doe("md5").update(s).digest("hex").toUpperCase()}function qoe(e,t){try{let r=new URL(t,e);return`POST ${r.origin}${r.pathname}`}catch{return`POST ${t.split("?",1)[0]??""}`}}var $h=class{config;logger;fetchImpl;timeoutMs;constructor(t,r,i=fetch,n=6e4){this.config=t,this.logger=r,this.fetchImpl=i,this.timeoutMs=n}async post(t,r,i={}){if(!t.startsWith("/")||t.startsWith("//"))throw new Error("mbh-chat API request path must be an origin-relative path");let n=new URL(this.config.apiBaseUrl),o=new URL(t,n);if(o.origin!==n.origin)throw new Error("mbh-chat API request path must stay on the configured origin");let s=typeof i.appId=="number"&&Number.isFinite(i.appId)?Math.trunc(i.appId):typeof i.appId=="string"&&i.appId.trim()?i.appId.trim():this.config.appId,a={...r,_appId:s},c=Date.now(),u=AbortSignal.timeout(this.timeoutMs),l=i.signal?AbortSignal.any([i.signal,u]):u,d=qoe(this.config.apiBaseUrl,t);try{let p=await this.fetchImpl(o,{method:"POST",signal:l,headers:{"content-type":"application/json",appKey:this.config.apiAppKey,sign:Poe(a,c,t,this.config.apiSignKey,this.config.apiVersion),timestamp:String(c),version:this.config.apiVersion,...i.userToken?{authorization:i.userToken}:{}},body:JSON.stringify(a)});if(!p.ok)throw await p.body?.cancel(),new jo(`mbh-chat API request failed with HTTP ${p.status}`,p.status);let f=await p.json();if(!f||typeof f!="object"||Array.isArray(f))throw new jo("mbh-chat API returned a non-object JSON response",p.status);return f}catch(p){let f=p instanceof jo?p.status:void 0;throw this.logger.warn("mbh-chat API request failed",{request:d,...f!==void 0?{status:f}:{},error:p instanceof Error?p.message:String(p)}),p}}};var Ch=class{ttlMs;tokens=new Map;pending=new Map;constructor(t=3600*1e3){if(this.ttlMs=t,!Number.isFinite(t)||t<=0)throw new Error("user-token cache ttlMs must be positive")}key(t,r){return`${t}\0${r.userId}\0${r.appId}`}get(t,r){let i=this.key(t,r),n=this.tokens.get(i);if(n){if(Date.now()>=n.expiresAt){this.tokens.delete(i);return}return n.token}}set(t,r,i){this.tokens.set(this.key(t,r),{token:i,expiresAt:Date.now()+this.ttlMs})}delete(t,r){this.tokens.delete(this.key(t,r))}async getOrLoad(t,r,i){let n=this.get(t,r);if(n)return n;let o=this.key(t,r),s=this.pending.get(o);if(s)return s;let a=i().then(c=>{if(!c)throw new Error("mbh-chat user-token lookup returned an empty token");return this.set(t,r,c),c}).finally(()=>this.pending.delete(o));return this.pending.set(o,a),a}clear(){this.tokens.clear(),this.pending.clear()}};var joe=1001;function Ah(e,t){let r=t.code===void 0?"unknown":String(t.code),i=typeof t.message=="string"?t.message.replace(/[\u0000-\u001f\u007f]+/g," ").slice(0,300):"";return new Error(`${e} failed (code=${r})${i?`: ${i}`:""}`)}function CE(e,t,r){let i=e==null||e===""?t:e,n=typeof i=="number"?i:Number(String(i).trim());if(!Number.isSafeInteger(n)||n<0)throw new Error(`${r} must be a non-negative safe integer`);return n}function Moe(e){let t=e.match(/^(.*?)-(\d+(?:-\d+)*)$/);return t?t[1]??"":""}function Loe(e){if(e==null||e==="")return;let t=typeof e=="number"?e:Number(String(e).trim());return Number.isSafeInteger(t)&&t>=0?t:void 0}var Rh=class{config;client;tokenCache;constructor(t,r,i){this.config=t,this.client=new $h(t,r,i?.fetchImpl,i?.timeoutMs),this.tokenCache=i?.tokenCache??new Ch}context(t){return{appId:typeof t?.appId=="number"&&Number.isFinite(t.appId)?String(Math.trunc(t.appId)):typeof t?.appId=="string"&&t.appId.trim()?t.appId.trim():this.config.appId,userId:Number.isFinite(t?.userId)?t?.userId??0:Number(this.config.userId)||0}}async queryUserTokenByBotToken(t,r){let i=this.context(r),n=await this.client.post("/organization/queryUserTokenByBotTokenV2",{botToken:t,_userId:i.userId},{appId:i.appId,...r?.signal?{signal:r.signal}:{}});if(!n.data?.token)throw Ah("mbh-chat user-token lookup",n);return n.data.token}async getUserToken(t,r){let i=t.trim();if(!i)throw new Error("botToken is required for mbh-chat API authentication");let n=this.context(r);return this.tokenCache.getOrLoad(i,n,()=>this.queryUserTokenByBotToken(i,r))}async withUserToken(t,r,i){let n=t.trim(),o=this.context(r),s=await this.getUserToken(n,r);try{return await i(s)}catch(a){if(!(a instanceof jo)||a.status!==401)throw a;return this.tokenCache.delete(n,o),s=await this.getUserToken(n,r),i(s)}}async generateSignUrl(t,r,i){if(!t.trim())throw new Error("fileUrl is required for mbh-chat generateSignUrl");let n=this.context(i),o=await this.withUserToken(r,i,s=>this.client.post("/user/generateSignUrl",{loudPlatform:0,fileName:t},{appId:n.appId,userToken:s,...i?.signal?{signal:i.signal}:{}}));if(Number(o.code)!==0||!o.data?.filePath)throw Ah("mbh-chat generateSignUrl",o);return o.data.filePath}async getMyExpertDownloadUrl(t,r,i={}){let n=t.trim(),o=r.trim();if(!n)throw new Error("cloneCode is required for Agent package lookup");if(!o)throw new Error("botToken is required for mbh-chat Agent package lookup");let s=this.context(i),a=CE(i.userId,s.userId,"_userId"),c=Loe(i.businessUserId)??a,u=CE(i.domainId,this.config.domainId,"_domainId"),l=CE(i.appId,this.config.appId,"_appId"),d=await this.withUserToken(o,i,h=>this.client.post("/skill-market/v1/user_expert/get_my_expert_list",{_orgId:joe,_domainId:u,user_id:c,bot_token:o,page_no:1,key_word:Moe(n),page_size:200,with_download:!0,_userId:a},{appId:l,userToken:h,...i.signal?{signal:i.signal}:{}}));if(Number(d.code)!==0)throw Ah("mbh-chat Agent package lookup",d);let p=ye(d.data)?.list;if(!Array.isArray(p))throw new Error("mbh-chat Agent package lookup returned an invalid list");let f=p.map(h=>ye(h)).map(h=>nt(h?Ae(h,"downloadUrl","download_url"):void 0)).find(Boolean);if(!f)throw new Error(`Agent ${n} has no downloadable package`);return f}async getStsToken(t,r,i,n){if(!t.trim())throw new Error("sourceFileName is required for mbh-chat STS credentials");let o=this.context(n),s=await this.withUserToken(r,n,a=>this.client.post("/user/getStsTokenByAsync",{sourceFileName:t,isPrivate:i},{appId:o.appId,userToken:a,...n?.signal?{signal:n.signal}:{}}));if(!s.data?.bucket)throw Ah("mbh-chat STS credential lookup",s);return s.data}};var yV=Br(gV(),1);import{extname as Mye}from"node:path";import{fileURLToPath as Lye}from"node:url";var Fye=yV.default,zye=1024*1024,Uye=900*1e3;function Bye(e){if(typeof e=="string"){let t=e.trim();if(t.startsWith("file:"))try{return Lye(t)}catch{return e}return e}if(Buffer.isBuffer(e))return e;if(e&&typeof e=="object"){if(ArrayBuffer.isView(e)&&!(e instanceof DataView)&&!Buffer.isBuffer(e)){let i=e;return Buffer.from(i.buffer,i.byteOffset,i.byteLength)}let t=e,r=t.path??t.filePath;if(typeof r=="string"&&r.trim())return r.trim()}return e}var Wye={".jpg":"image/jpeg",".jpeg":"image/jpeg",".png":"image/png",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp",".svg":"image/svg+xml",".ico":"image/x-icon",".avif":"image/avif",".heic":"image/heic",".heif":"image/heif",".pdf":"application/pdf",".mp4":"video/mp4",".webm":"video/webm",".mov":"video/quicktime",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".opus":"audio/opus",".m4a":"audio/mp4",".aac":"audio/aac",".flac":"audio/flac",".txt":"text/plain; charset=utf-8",".log":"text/plain; charset=utf-8",".csv":"text/csv; charset=utf-8",".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".js":"text/javascript; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".xml":"application/xml; charset=utf-8",".md":"text/markdown; charset=utf-8",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation"};function JT(e){let t=e.split(/[/\\]/).pop()??e,r=Mye(t).toLowerCase();return r?Wye[r]:void 0}function Vye(e,t){if(typeof e=="string")return JT(e)??"application/octet-stream";if(Buffer.isBuffer(e)){if(t){let n=JT(t);if(n)return n}return"application/octet-stream"}let r=e.type?.trim();if(r&&r!=="application/octet-stream")return r;let i=typeof e.name=="string"&&e.name?e.name:"";if(i){let n=JT(i);if(n)return n}return r||"application/octet-stream"}function Zye(e){let t=e.split(";",1)[0]?.trim().toLowerCase()??"";return t==="image/svg+xml"||t==="application/xml"||t==="text/javascript"||t==="application/javascript"?"attachment":"inline"}async function Hye(e){if(Buffer.isBuffer(e))return{content:e,fileName:"file"};if(typeof e=="string")return{content:e,fileName:e.split(/[/\\]/).pop()??"file"};let t=Buffer.from(await e.arrayBuffer()),r=e.name;return{content:t,fileName:typeof r=="string"&&r?r:"file"}}var YT=class{api;logger;constructor(t,r){this.api=t,this.logger=r}async upload(t,r,i=1,n,o){let s=Bye(t),{content:a,fileName:c}=await Hye(s),u=await this.api.getStsToken(c,r,i,o),l=Vye(s,c),d=n?.onProgress,p={accessKeyId:u.tempAccessKeyId,accessKeySecret:u.tempAccessKeySecret,stsToken:u.tempSecurityToken,bucket:u.bucket,endpoint:u.endPoint,region:u.region,secure:!0,cname:!0,authorizationV4:!0,timeout:n?.timeoutMs??Uye},f=new Fye(p),h=`${u.uploadDir}${u.ossFileKey}`;try{let m,_={progress:y=>{d?.(y)},parallel:4,partSize:zye,mime:l,headers:{"Content-Disposition":Zye(l)}};if(m=await f.multipartUpload(h,a,_),m?.res?.status!==200)throw new Error(`OSS upload failed with status ${m?.res?.status??"unknown"}`);let x=(m?.res?.requestUrls||[])[0]||"",v=i===1&&m.name||x;if(!v)throw new Error("OSS upload succeeded but returned no object name or URL");let g=i===1?await this.api.generateSignUrl(v,r,o):v;if(!g)throw new Error("OSS upload succeeded but returned no signed URL");return this.logger.info("OSS upload succeeded",{private:i===1}),g}catch(m){throw this.logger.error("OSS upload failed",{error:m instanceof Error?m.message:String(m)}),m}}};function vV(e,t){let r=new YT(e,t);return r.upload.bind(r)}var Jg=class{tails=new Map;generations=new Map;enqueue(t,r){let i=this.tails.get(t)??Promise.resolve(),n=this.generations.get(t)??0,o=i.catch(()=>{}).then(async()=>{(this.generations.get(t)??0)===n&&await r()});return this.tails.set(t,o),o.finally(()=>{this.tails.get(t)===o&&(this.tails.delete(t),this.generations.delete(t))}).catch(()=>{}),o}cancelPending(t){this.tails.has(t)&&this.generations.set(t,(this.generations.get(t)??0)+1)}cancelAllPending(){for(let t of this.tails.keys())this.cancelPending(t)}};import{randomUUID as eI}from"node:crypto";import tve from"node:fs";import Tr from"node:fs/promises";import rve from"node:os";import li from"node:path";import{resolveDshHome as nve,dshHomePath as ive,dshHomeDisplay as ove}from"@deepseek-ai/dsh-home-paths";var wV=Br(J0(),1);import Gye from"node:fs";import bV from"node:fs/promises";import Vl from"node:path";import{Transform as Kye}from"node:stream";import{pipeline as Xye}from"node:stream/promises";var xV=500*1024*1024,QT=1024*1024*1024,_V=2e4;function Jye(e){if((e.flags&2048)!==0)return new TextDecoder("utf-8").decode(e.pathBuffer);try{return new TextDecoder("utf-8",{fatal:!0}).decode(e.pathBuffer)}catch{return new TextDecoder("gbk").decode(e.pathBuffer)}}function Yye(e){let t=e.replaceAll("\\","/"),r=t.split("/").filter(Boolean);if(t.startsWith("/")||/^[a-z]:\//i.test(t)||r.some(i=>i==="."||i===".."))throw new Error(`skill archive contains an unsafe path: ${e}`);return t}function Qye(e){let t=e.map(n=>n.replaceAll("\\","/").replace(/\/+$/,"")).filter(Boolean);if(t.length===0)return;let r=new Set(t.map(n=>n.split("/").filter(Boolean)[0]).filter(Boolean));if(r.size!==1)return;let i=[...r][0];return i&&t.some(n=>n.startsWith(`${i}/`))&&t.every(n=>n===i||n.startsWith(`${i}/`))?i:void 0}function eve(e,t){let r=Vl.resolve(e,t),i=Vl.relative(Vl.resolve(e),r);if(!i||i.startsWith("..")||Vl.isAbsolute(i))throw new Error(`skill archive contains an unsafe path: ${t}`);return r}var Yg=class extends Kye{limitBytes;budget;constructor(t,r){super(),this.limitBytes=t,this.budget=r}_transform(t,r,i){if(this.budget.used+=t.length,this.budget.used>this.limitBytes){i(new Error(`skill archive expands beyond ${this.limitBytes} bytes`));return}i(null,t)}};async function SV(e,t){let r=await wV.default.Open.buffer(e);if(r.files.length>_V)throw new Error(`skill archive exceeds ${_V} entries`);let i=r.files.reduce((a,c)=>a+c.uncompressedSize,0);if(!Number.isSafeInteger(i)||i>QT)throw new Error(`skill archive expands beyond ${QT} bytes`);let n=r.files.map(a=>Yye(Jye(a))),o=Qye(n),s={used:0};for(let a=0;a<r.files.length;a+=1){let c=r.files[a],u=n[a];if(!c||!u)continue;let l=u.replaceAll("\\","/");if(o&&(l===o||l===`${o}/`)||(o&&l.startsWith(`${o}/`)&&(l=l.slice(o.length+1)),l=l.replace(/\/+$/,""),!l))continue;let d=eve(t,l);if(c.type==="Directory"){await bV.mkdir(d,{recursive:!0});continue}if(c.type!=="File")throw new Error(`skill archive contains an unsupported entry: ${u}`);await bV.mkdir(Vl.dirname(d),{recursive:!0}),await Xye(c.stream(),new Yg(QT,s),Gye.createWriteStream(d,{mode:384}))}}var sve=/^[a-z0-9]+(?:-[a-z0-9]+)*$/;function ey(e){let t=Array.isArray(e.skills_scope)?ye(e.skills_scope[0]):void 0,r=Array.isArray(e.intent_recognition)?e.intent_recognition.map(ye).filter(c=>!!c).find(c=>nt(Ae(c,"biz_type","bizType")).toLowerCase()==="skill"):void 0,i=t??r;if(!i)return;let n=nt(Ae(i,"skill_code","skillCode"))||(i===r?nt(i.name):"");if(!n)return;let o=nt(Ae(i,"short_name","shortName","name"))||n,s=nt(Ae(i,"url","download_url","downloadUrl","skill_url","skillUrl")),a=Ae(i,"skill_id","skillId","id");return{code:n,url:s,name:o,...typeof a=="string"||typeof a=="number"?{id:a}:{}}}var Qg=class{logger;options;dshHome;skillsRoot;skillsDisplayRoot;operations=new Map;constructor(t,r={}){this.logger=t,this.options=r,this.dshHome=nve(),this.skillsRoot=ive("skills"),this.skillsDisplayRoot=li.join(ove(this.dshHome),"skills")}normalizeCode(t){let r=t.trim();if(!sve.test(r))throw new Error(`invalid mbh-chat skill code: ${r||"<empty>"}`);return r}skillPath(t){return li.join(this.skillsRoot,this.normalizeCode(t))}skillDisplayPath(t){return li.join(this.skillsDisplayRoot,this.normalizeCode(t))}exists(t){try{return tve.existsSync(li.join(this.skillPath(t),"SKILL.md"))}catch{return!1}}install(t,r){return this.serialized(r,async()=>{let i,n;try{if(i=this.normalizeCode(r),n=this.skillPath(i),!t.trim())throw new Error("skill url is empty")}catch(c){return{success:!1,status:"fail",error:ne(c)}}let o=li.dirname(n),s=li.join(o,`.${i}.${eI()}.tmp`),a=li.join(o,`.${i}.${eI()}.bak`);try{await Tr.mkdir(o,{recursive:!0,mode:448}),await Hu(async()=>{await Tr.rm(s,{recursive:!0,force:!0}),await Tr.mkdir(s,{recursive:!0,mode:448});let u=await this.download(t);await SV(u,s);let l=li.join(s,"SKILL.md");if(!(await Tr.stat(l).catch(()=>{}))?.isFile())throw new Error("skill archive does not contain a root SKILL.md")});let c=await Tr.stat(n).then(()=>!0,()=>!1);c&&await Tr.rename(n,a);try{await Tr.rename(s,n)}catch(u){throw c&&await Tr.rename(a,n).catch(()=>{}),u}return await Tr.rm(a,{recursive:!0,force:!0}).catch(u=>{this.logger.warn("could not remove the previous mbh-chat skill backup",{code:i,error:ne(u)})}),this.logger.info("installed mbh-chat skill",{code:i,path:this.skillDisplayPath(i)}),{success:!0,status:"ok"}}catch(c){return await Tr.rm(s,{recursive:!0,force:!0}).catch(()=>{}),this.logger.error("mbh-chat skill installation failed",{code:i,error:ne(c)}),{success:!1,status:"fail",error:ne(c)}}})}uninstall(t){return this.serialized(t,async()=>{try{let r=this.normalizeCode(t),i=this.skillPath(r);return await Tr.rm(i,{recursive:!0,force:!0}),this.logger.info("uninstalled mbh-chat skill",{code:r,path:this.skillDisplayPath(r)}),{success:!0,status:"ok"}}catch(r){return this.logger.error("mbh-chat skill removal failed",{code:t,error:ne(r)}),{success:!1,status:"fail",error:ne(r)}}})}eventContent(t,r){return{event_type:"skill",operation_type:"install",skill_url:t.url,skill_code:t.code,...t.id!==void 0?{skill_id:t.id}:{},...r?{bot_token:r}:{}}}serialized(t,r){let i=t.trim(),o=(this.operations.get(i)??Promise.resolve({success:!0,status:"ok"})).catch(()=>{}).then(r);return this.operations.set(i,o),o.finally(()=>{this.operations.get(i)===o&&this.operations.delete(i)}),o}async download(t){let r=await Tr.mkdtemp(li.join(rve.tmpdir(),"mbh-chat-skill-"));try{let i=await Vs([{url:t,name:"skill.zip"}],{storageRoot:r,requestId:eI(),maxBytes:xV,maxFiles:1,maxInlineImageBytes:1,fetchTimeoutMs:18e4,concurrency:1,allowPrivateNetwork:this.options.allowPrivateNetwork??!1,...this.options.fetchImpl?{fetchImpl:this.options.fetchImpl}:{}}),n=i.media[0];if(!n)throw new Error(i.failures[0]?.reason||"skill download failed");return await Tr.readFile(n.localPath)}finally{await Tr.rm(r,{recursive:!0,force:!0}).catch(()=>{})}}};import{randomUUID as EV}from"node:crypto";var tI=class{baseUrl;logger;sessionCookie;socket;streams=new Map;opening;closed;constructor(t,r,i){this.baseUrl=t,this.logger=r,this.sessionCookie=i}async*open(t,r,i,n){let o=EV(),s=[],a,c=l=>{s.push(l),a?.(),a=void 0};this.streams.set(o,c);let u=()=>{this.send({type:"cancel",streamId:o}),c({kind:"end"})};i.addEventListener("abort",u,{once:!0});try{if(await this.ensureOpen(),this.closed)throw this.closed;for(this.send({type:"open",streamId:o,endpoint:t,payload:r}),n?.(),i.aborted&&u();;){for(;s.length>0;){let l=s.shift();if(!l||l.kind==="end")return;if(l.kind==="error")throw l.error;yield l.value}await new Promise(l=>{a=l})}}finally{i.removeEventListener("abort",u),this.streams.delete(o),i.aborted||this.send({type:"cancel",streamId:o})}}close(t){this.closed=t??new Error("mbh-chat Remote mux closed");for(let i of this.streams.values())i({kind:"end"});this.streams.clear();let r=this.socket;this.socket=void 0,this.opening=void 0,r&&(r.readyState===rr.CONNECTING?r.terminate():r.readyState===rr.OPEN&&r.close(1e3,"bridge stream stopped"))}async ensureOpen(){if(this.socket?.readyState===rr.OPEN)return;if(this.opening)return this.opening;let t=new URL("/api/remote.mux",this.baseUrl);t.protocol=t.protocol==="https:"?"wss:":"ws:";let r=new rr(t,{headers:vn(this.sessionCookie)});this.socket=r,this.opening=new Promise((i,n)=>{let o=s=>{this.close(s),n(s)};r.once("open",()=>{r.once("close",()=>this.close(new Error("mbh-chat Remote mux closed"))),i()}),r.once("error",s=>o(s instanceof Error?s:new Error(String(s))))}),r.on("message",(i,n)=>{if(n){this.logger.warn("dropping binary mbh-chat WebSocket frame",{path:"/api/remote.mux"});return}let o;try{o=JSON.parse(i.toString())}catch(a){this.logger.warn("dropping malformed mbh-chat Remote mux frame",{error:a instanceof Error?a.message:String(a)});return}let s=this.streams.get(o.streamId);s&&(o.type==="item"?s({kind:"frame",value:o.value}):o.type==="error"?s({kind:"error",error:new Error(`mbh-chat ${o.error.code}: ${o.error.message}`)}):s({kind:"end"}))}),await this.opening}send(t){this.socket?.readyState===rr.OPEN&&this.socket.send(JSON.stringify(t))}},ty=class{baseUrl;logger;timeoutMs;sessionCookie;mux;eventClientId;constructor(t,r,i=3e4,n=Th()){this.baseUrl=t,this.logger=r,this.timeoutMs=i,this.sessionCookie=n}sessions={create:(t,r)=>this.invoke("session/create",{request:t},r),prompt:(t,r)=>this.invoke("session/prompt",{request:t},r),cancel:(t,r)=>this.invoke("session/cancel",{request:t},r),selectModel:(t,r)=>this.invoke("session/selectModel",{request:t},r),modelCatalog:t=>this.invoke("session/modelCatalog",{},t),follow:(t,r,i)=>this.openStream("session/follow",{request:t},r,i)};openEvents(t,r){return this.openStream("$events",{},t,r)}respondEvent(t,r){let i=t.clientId??this.eventClientId;if(!i)throw new Error("mbh-chat event stream is not ready");return this.invoke("$events/result",{clientId:i,eventId:t.eventId,outcome:t.outcome},r)}disconnect(){this.eventClientId=void 0,this.mux?.close(),this.mux=void 0}async invoke(t,r,i){let n=EV(),o=await fetch(new URL(`/api/${t}`,this.baseUrl),{method:"POST",headers:vn(this.sessionCookie,{"Content-Type":"application/json"}),body:JSON.stringify({type:"client-request",rpcId:n,method:t,payload:{args:r}}),signal:i?AbortSignal.any([i,AbortSignal.timeout(this.timeoutMs)]):AbortSignal.timeout(this.timeoutMs)});if(!o.ok)throw Object.assign(new Error(`mbh-chat ${t} returned HTTP ${o.status}`),{code:"http-error"});return await o.json()}openStream(t,r,i,n){return this.mux??=new tI(this.baseUrl,this.logger,this.sessionCookie),this.mux.open(t,{args:r},i,n)}};function An(e){if(e.result.ok)return e.result.value;let t=new Error(`mbh-chat ${e.result.error.code}: ${e.result.error.message}`);throw Object.assign(t,{code:e.result.error.code}),t}function ave(e){if(!(typeof e!="object"||e===null||!("code"in e)))return typeof e.code=="string"?e.code:void 0}var cve=new Set(["session/not-found","session-not-found"]);function rI(e){return e!==void 0&&cve.has(e)}function nI(e){return rI(ave(e))}function kV(){let e,t;return{promise:new Promise((i,n)=>{e=i,t=n}),resolve:e,reject:t}}var uve=3e3;function lve(e,t,r){let i=Math.min(r,t*2**Math.min(e,8));return i+Math.floor(Math.random()*Math.max(1,Math.min(1e3,i/5)))}function TV(e,t){return new Promise(r=>{if(t.aborted)return r();let i=setTimeout(n,e);function n(){clearTimeout(i),t.removeEventListener("abort",n),r()}t.addEventListener("abort",n,{once:!0})})}var ry=class{reconnectMinMs;reconnectMaxMs;logger;api;rootAbort;generationAbort;handlers;loopPromise;connected=!1;followedSessions=new Set;followAborts=new Map;followReadiness=new Map;liveFollows=new Set;connectionWaiters=new Set;constructor(t,r,i,n){this.reconnectMinMs=r,this.reconnectMaxMs=i,this.logger=n,this.api=new ty(t,n)}start(t){if(this.loopPromise)throw new Error("mbh-chat connection already started");this.handlers=t,this.rootAbort=new AbortController,this.loopPromise=this.run(t,this.rootAbort.signal)}async stop(){this.rootAbort?.abort();let t=new Error("mbh-chat connection stopped before becoming ready");for(let r of this.connectionWaiters)r.reject(t);this.connectionWaiters.clear();for(let r of this.followReadiness.values())r.reject(t);this.followReadiness.clear(),this.liveFollows.clear(),await this.loopPromise,this.loopPromise=void 0,this.rootAbort=void 0,this.handlers=void 0,this.api.disconnect()}isConnected(){return this.connected}followSession(t){if(this.followedSessions.add(t),this.liveFollows.has(t))return Promise.resolve();let r=this.followReadiness.get(t);r||(r=kV(),this.followReadiness.set(t,r)),this.connected&&this.generationAbort&&!this.followAborts.has(t)&&this.startFollow(t,this.generationAbort.signal);let i=r.promise;return i.catch(()=>{}),Promise.race([i,TV(uve,this.generationAbort?.signal??new AbortController().signal).then(()=>{this.liveFollows.has(t)||this.logger.warn("mbh-chat session follow was not ready before timeout",{sessionId:t})})])}unfollowSession(t){this.followedSessions.delete(t),this.liveFollows.delete(t),this.followAborts.get(t)?.abort(),this.followAborts.delete(t),this.followReadiness.get(t)?.reject(new Error(`mbh-chat stopped following session ${t}`)),this.followReadiness.delete(t)}whenConnected(t){return this.connected?Promise.resolve():new Promise((r,i)=>{let n=()=>{a(),r()},o=u=>{a(),i(u)},s=()=>o(t?.reason??new Error("waiting for mbh-chat connection was aborted")),a=()=>{this.connectionWaiters.delete(c),t?.removeEventListener("abort",s)},c={resolve:n,reject:o};this.connectionWaiters.add(c),t?.addEventListener("abort",s,{once:!0}),t?.aborted&&s()})}async setConnected(t,r){if(t||(this.connected=!1),await r.onConnection?.(t),t){this.connected=!0;for(let i of this.connectionWaiters)i.resolve();this.connectionWaiters.clear()}}async run(t,r){let i=0;for(;!r.aborted;){let n=new AbortController;this.generationAbort=n;let o=()=>n.abort();r.addEventListener("abort",o,{once:!0});let s=kV(),a=!1,c;try{c=this.pumpEvents(t,n.signal,s.resolve);let u=c.then(()=>{throw new Error("a mbh-chat event stream closed")});await Promise.race([s.promise,u]),a=!0,i=0,await this.setConnected(!0,t);for(let l of this.followedSessions)this.startFollow(l,n.signal);await u}catch(u){r.aborted||this.logger.warn("mbh-chat connection lost",{error:ne(u)})}finally{if(this.generationAbort=void 0,n.abort(),this.stopFollows(),this.api.disconnect(),await Promise.allSettled(c?[c]:[]),r.removeEventListener("abort",o),a)try{await this.setConnected(!1,t)}catch(u){this.logger.error("mbh-chat connection-state handler failed during disconnect",{error:ne(u)})}}if(!r.aborted){let u=lve(i++,this.reconnectMinMs,this.reconnectMaxMs);this.logger.info("reconnecting to mbh-chat Host",{delayMs:u,attempt:i}),await TV(u,r)}}}async pumpEvents(t,r,i){let n=!1;for await(let o of this.api.openEvents(r)){if(o.type==="ready"){this.api.eventClientId=o.clientId,n||(n=!0,i());continue}try{await t.onRemoteEvent(o)}catch(s){this.logger.error("mbh-chat event handler failed",{error:ne(s)})}}}markFollowReady(t){this.liveFollows.add(t),this.followReadiness.get(t)?.resolve()}async startFollow(t,r){if(this.followAborts.has(t))return;let i=new AbortController;this.followAborts.set(t,i);let n=AbortSignal.any([r,i.signal]),o=!1;try{for await(let s of this.api.sessions.follow({address:{kind:"session",sessionId:t}},n)){if(s.type==="snapshot"){o=!0,this.markFollowReady(t);continue}if(s.type==="event")try{this.handlers?.onSessionEvent(t,s.event)}catch(a){this.logger.error("mbh-chat session event handler failed",{sessionId:t,error:ne(a)})}}if(!n.aborted&&!o)throw new Error(`mbh-chat session follow ended before receiving a snapshot for ${t}`)}catch(s){!r.aborted&&!i.signal.aborted&&(this.followReadiness.get(t)?.reject(s),this.logger.warn("mbh-chat session follow ended",{sessionId:t,error:ne(s)}))}finally{this.followAborts.get(t)===i&&this.followAborts.delete(t),this.liveFollows.delete(t)}}stopFollows(){for(let t of this.followAborts.values())t.abort();this.followAborts.clear(),this.liveFollows.clear()}};async function IV(e,t,r,i){let n=new Map;for(let u of e.store.listActiveSubagentsForRoot(t))(!r||u.requestId===r)&&n.set(u.childSessionId,u.parentSessionId);for(let[u,l]of i??[])n.set(u,l);let o=!1,s=!1,a,c=u=>{e.store.settleSubagent(u,"cancelled"),n.delete(u)};for(let u=1;u<=e.config.task.maxAttempts;u+=1){let l=p=>{let f=0,h=p,m=new Set;for(;!m.has(h);){m.add(h);let _=n.get(h);if(!_)break;f+=1,h=_}return f},d=[...n].sort(([p],[f])=>l(f)-l(p));for(let[p,f]of d)try{An(await e.dsh.api.sessions.cancel({sessionId:p})),c(p)}catch(h){if(nI(h)){c(p);continue}a=h,e.logger.warn("subagent interrupt failed",{parentSessionId:f,childSessionId:p,attempt:u,error:ne(h)})}if(!o)try{An(await e.dsh.api.sessions.cancel({sessionId:t})),o=!0}catch(p){nI(p)?(o=!0,s=!0):(a=p,e.logger.warn("model/tool cancellation failed",{dshSessionId:t,attempt:u,error:ne(p)}))}if(o&&n.size===0)return s?"absent":"cancelled";if(u<e.config.task.maxAttempts){let p=Math.min(e.config.task.retryMaxMs,e.config.task.retryBaseMs*2**(u-1));await new Promise(f=>setTimeout(f,p))}}throw a instanceof Error?a:new Error("execution cancellation could not be confirmed")}var fve=/request id\s*:\s*([a-z0-9_-]{1,128})/iu,dve=new RegExp("\\p{Script=Han}","u");function pve(e){let t=fve.exec(e)?.[1];return t?`\uFF08\u8BF7\u6C42 ID\uFF1A${t}\uFF09`:""}function hve(e,t){let r=e?.trim();return r?r.slice(0,120):t}function mve(e){let t=ne(e).trim(),r=pve(t),i=/range of max_tokens should be \[\s*(\d+)\s*,\s*(\d+)\s*\]/iu.exec(t);if(i)return`\u6A21\u578B\u751F\u6210\u957F\u5EA6\u53C2\u6570\uFF08max_tokens\uFF09\u8D85\u51FA\u5141\u8BB8\u8303\u56F4\uFF0C\u6709\u6548\u8303\u56F4\u4E3A ${i[1]}\u2013${i[2]}\u3002${r}`;let n=/no available channel for model\s+(.+?)\s+under group\b/iu.exec(t);return n?`\u6A21\u578B ${hve(n[1],"\u5F53\u524D\u6A21\u578B")} \u5F53\u524D\u6682\u65E0\u53EF\u7528\u670D\u52A1\u901A\u9053\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/no available channel/iu.test(t)?`\u5F53\u524D\u6A21\u578B\u6682\u65E0\u53EF\u7528\u670D\u52A1\u901A\u9053\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/tokenization failed/iu.test(t)?`\u6A21\u578B\u65E0\u6CD5\u5904\u7406\u5F53\u524D\u8F93\u5165\uFF0C\u8BF7\u7F29\u77ED\u5185\u5BB9\u6216\u5207\u6362\u6A21\u578B\u540E\u91CD\u8BD5\u3002${r}`:/completed response with no content|empty response|no content returned/iu.test(t)?`\u6A21\u578B\u672A\u8FD4\u56DE\u6709\u6548\u5185\u5BB9\uFF0C\u8BF7\u91CD\u65B0\u53D1\u9001\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/context length|maximum context|context window|too many tokens/iu.test(t)?`\u5BF9\u8BDD\u5185\u5BB9\u8D85\u8FC7\u6A21\u578B\u53EF\u5904\u7406\u7684\u957F\u5EA6\uFF0C\u8BF7\u7F29\u77ED\u5185\u5BB9\u6216\u65B0\u5EFA\u4F1A\u8BDD\u3002${r}`:/\b(401|unauthorized|invalid api.?key|authentication)\b/iu.test(t)?`\u6A21\u578B\u670D\u52A1\u8BA4\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u670D\u52A1\u914D\u7F6E\u3002${r}`:/\b(403|forbidden|permission denied)\b/iu.test(t)?`\u5F53\u524D\u8D26\u53F7\u65E0\u6743\u8BBF\u95EE\u8BE5\u6A21\u578B\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u6743\u9650\u6216\u5207\u6362\u6A21\u578B\u3002${r}`:/\b(429|rate.?limit|too many requests|overload|busy)\b/iu.test(t)?`\u6A21\u578B\u670D\u52A1\u5F53\u524D\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`:/timeout|timed out/iu.test(t)?`\u6A21\u578B\u670D\u52A1\u54CD\u5E94\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`:/\b5\d\d\b|bad gateway|service unavailable|upstream.*(?:error|failed)/iu.test(t)?`\u4E0A\u6E38\u6A21\u578B\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`:/invalidparameter|invalid parameter|\b400\b|bad request/iu.test(t)?`\u6A21\u578B\u8BF7\u6C42\u53C2\u6570\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5\u6A21\u578B\u914D\u7F6E\u3002${r}`:dve.test(t)?t.replace(/^\[错误\]\s*/u,""):`\u6A21\u578B\u670D\u52A1\u8C03\u7528\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002${r}`}function bc(e){return`[\u9519\u8BEF] ${mve(e)}`}var OV=2e3;function Qi(e){return e.time/1e3+e.seq/1e9}function ny(e,t){return Array.isArray(e)?e.map(r=>{let i=ye(r);return i?.type===t&&typeof i.text=="string"?i.text:""}).join(""):""}function iI(e,t){let r=e.trim()||t;return r.length<=OV?r:`${r.slice(0,OV)}\u2026\u2026\uFF08\u5185\u5BB9\u5DF2\u622A\u65AD\uFF09`}function oI(e){return Array.isArray(e)?e.map(t=>{let r=ye(t);if(!r)return"";if((r.type==="text"||r.type==="reasoning")&&typeof r.text=="string")return r.text;if(r.type==="image")return"[\u56FE\u7247]";try{return JSON.stringify(r)}catch{return"[\u65E0\u6CD5\u5C55\u793A\u7684\u5DE5\u5177\u7ED3\u679C]"}}).filter(Boolean).join(`
579
579
  `):""}function $V(e){return/^started subagent\s+(\S+)\s*$/u.exec(oI(e))?.[1]}function iy(e){if(e.type!=="user/message")return;let t=ye(ye(e.data)?.source);return t?.kind==="subagent-settled"&&typeof t.senderSessionId=="string"?t.senderSessionId:void 0}function CV(e){let t=ye(e),r=typeof t?.kind=="string"?t.kind:"unknown";if(r==="completed")return{tag:"end",status:"succeeded"};if(r==="aborted")return{tag:"abort",status:"cancelled"};if(r==="interrupted")return{tag:"interrupted",status:"cancelled"};if(r==="max-tokens")return{tag:"max_tokens",status:"failed",response:"[\u9519\u8BEF] \u6A21\u578B\u8F93\u51FA\u8FBE\u5230\u957F\u5EA6\u4E0A\u9650"};if(r==="blocked")return{tag:"blocked",status:"failed",response:"[\u9519\u8BEF] \u672C\u8F6E\u88AB\u5BBF\u4E3B\u7B56\u7565\u963B\u6B62"};if(r==="error"){let i=ye(t?.error),n=typeof i?.message=="string"?i.message:"mbh-chat agent turn failed";return{tag:"error",status:"failed",response:bc(n)}}return{tag:"error",status:"failed",response:`[\u9519\u8BEF] \u672A\u8BC6\u522B\u7684 mbh-chat \u7ED3\u675F\u72B6\u6001\uFF1A${r}`}}function AV(e){if(e.type!=="turn/end")return;let t=ye(ye(e.data)?.reason);if(t?.kind!=="error")return;let r=ye(t.error);return typeof r?.message=="string"&&r.message.trim()?r.message:void 0}function RV(e){let t=ye(e.data);if(e.type==="assistant/message"){let n=ye(t?.message);return Array.isArray(n?.content)?n.content.some(o=>{let s=ye(o);return s?.type==="tool-call"&&(!_c(s.id)||!_c(s.name))}):!1}if(e.type==="tool/call")return!_c(t?.callId)||!_c(t?.name);if(e.type!=="tool/result")return!1;let r=ye(t?.message),i=ye(r?.source);return _c(i?.callId)?Array.isArray(r?.content)?r.content.some(n=>{let o=ye(n);return o?.type==="tool-result"&&!_c(o.toolCallId)}):!1:!0}function _c(e){return typeof e=="string"&&e.trim().length>0}function DV(e){return e.type==="user/message"?ny(ye(e.data)?.content,"text"):JSON.stringify(e.data??"")}function oy(e,t){let r=`${t}:`,i=DV(e).split(`
580
580
  `).find(n=>n.startsWith(r));if(i)try{let n=JSON.parse(i.slice(r.length).trim());return typeof n=="string"&&n.trim()?n.trim():void 0}catch{return}}function sy(e){let t=DV(e);return t.includes("SCHEDULED TASK DUE")||t.includes("CRON AUTOMATION DUE")}function sI(e,t){return e==="allow-once"||t?"allowed-once":"rejected"}import NV from"node:path";function Zl(e){let t=e.toLowerCase();return/cannot read properties of undefined \(reading ['"]prepare['"]\)/u.test(t)||/session event ['"]turn\/end['"] carries non-json-serializable data/u.test(t)||/messages\[\d+\]/u.test(t)&&t.includes("missing field")&&t.includes("tool_call_id")||t.includes("stored session")&&t.includes("is corrupt")&&t.includes("failed validation")||t.includes("insufficient tool messages")||t.includes("tool_calls")&&t.includes("followed by tool")}var ay=class{config;store;getDsh;logger;getCronSync;activeBySession;finish;cancelExecution;quarantineUnconfirmedExecution;hostDefaultProvider;constructor(t,r,i,n,o,s,a,c,u){this.config=t,this.store=r,this.getDsh=i,this.logger=n,this.getCronSync=o,this.activeBySession=s,this.finish=a,this.cancelExecution=c,this.quarantineUnconfirmedExecution=u}clearHostDefaultProvider(){this.hostDefaultProvider=void 0}async ensureSession(t,r,i,n){let o=this.store.getSessionBinding(t);if(o){let s=!!o.workspaceDir&&!!i.workspaceDir&&NV.resolve(o.workspaceDir)!==NV.resolve(i.workspaceDir),a=i.managed&&!o.workspaceDir,c=!!o.agentPreset&&o.agentPreset!==i.agentPreset;if(s||a||c)this.store.removeSession(t),this.logger.info("discarded stale mbh-chat session route",{businessKey:t,dshSessionId:o.dshSessionId,workspaceMismatch:s||a,presetMismatch:c});else{this.store.bindSession(t,o.dshSessionId,n,{...i.workspaceDir?{workspaceDir:i.workspaceDir}:{},...i.agentPreset?{agentPreset:i.agentPreset}:{}});try{await this.getDsh().followSession?.(o.dshSessionId)}catch(u){let l=ne(u);if(!Zl(l))throw this.getDsh().unfollowSession?.(o.dshSessionId),u;return this.store.removeSession(t),this.getDsh().unfollowSession?.(o.dshSessionId),this.logger.info("discarded stored corrupt mbh-chat session before prompt",{businessKey:t,dshSessionId:o.dshSessionId,error:l}),this.createSession(t,r,i,n)}return r?.trim()&&await this.selectModel(o.dshSessionId,r.trim()),o.dshSessionId}}return this.createSession(t,r,i,n)}async createSession(t,r,i,n){let o={...i.workspaceDir?{cwd:i.workspaceDir}:{},...i.agentPreset?{agentPreset:i.agentPreset}:{}},a=An(await this.getDsh().api.sessions.create(o)).sessionId;this.store.bindSession(t,a,n,{...i.workspaceDir?{workspaceDir:i.workspaceDir}:{},...i.agentPreset?{agentPreset:i.agentPreset}:{}});try{await this.getDsh().followSession?.(a)}catch(u){throw this.store.removeSession(t),this.getDsh().unfollowSession?.(a),u}this.getCronSync()?.notifySessionAvailable(),this.getCronSync()?.bindDshSessionId(t,a).catch(u=>{this.logger.warn("failed to bind cron jobs to new mbh-chat session",{businessKey:t,dshSessionId:a,error:ne(u)})});let c=r?.trim()||this.config.dsh.model;return c&&await this.selectModel(a,c),this.logger.info("created mbh-chat session mapping",{businessKey:t,dshSessionId:a,workspaceDir:i.workspaceDir,agentPreset:i.agentPreset,managedAgent:i.agent?.cloneCode}),a}async invalidateAgentSessions(t,r){let i=new Set;for(let n of t)for(let o of this.store.listSessionBindingsForAgent(n)){let s=this.activeBySession.get(o.dshSessionId);try{s&&!s.finalized?await this.cancelExecution(s):An(await this.getDsh().api.sessions.cancel({sessionId:o.dshSessionId}))}catch(a){i.add(n),this.quarantineUnconfirmedExecution?.(o.businessKey,o.dshSessionId,`${r}_cancel_unconfirmed`,!1),this.logger.warn("could not cancel invalidated Agent session",{cloneCode:n,dshSessionId:o.dshSessionId,error:ne(a)})}s&&!s.finalized&&this.finish(s,r,"cancelled","[\u9519\u8BEF] \u4E13\u5BB6\u914D\u7F6E\u5DF2\u53D8\u66F4\uFF0C\u672C\u8F6E\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u8BD5"),this.store.removeSession(o.businessKey),this.getDsh().unfollowSession?.(o.dshSessionId)}return[...i]}async selectModel(t,r){let i=r.indexOf("/"),n=i>0?r.slice(0,i):this.config.dsh.modelProvider,o=i>0?r.slice(i+1):r;if(!n){if(!this.hostDefaultProvider){let s=An(await this.getDsh().api.sessions.modelCatalog());this.hostDefaultProvider=s.default.provider}n=this.hostDefaultProvider}if(!n)throw new Error(`model ${r} has no provider and mbh-chat Host reports no default provider`);An(await this.getDsh().api.sessions.selectModel({sessionId:t,provider:n,model:o,...this.config.dsh.reasoningEffort?{reasoningEffort:this.config.dsh.reasoningEffort}:{}})),this.logger.info("selected mbh-chat model",{dshSessionId:t,provider:n,model:o})}};var aI=10,cI=100,uI=128,lI=256,Hl=4e3,cy=2e3;function gve(e,t){if(typeof e!="string"||!e.trim())throw new Error(`user question ${t} must be a non-empty string`);return e.trim()}function uy(e,t,r){let i=gve(e,t);if(i.length>r)throw new Error(`user question ${t} exceeds ${r} characters`);return i}function yve(e,t,r){return typeof e=="number"&&Number.isFinite(e)?String(Math.trunc(e)):uy(e,t,r)}function vve(e){if(e.eventType!=="user_question")return;let t=yve(e.content.session_id,"session_id",lI),r=uy(e.content.tool_call_id,"tool_call_id",uI);if(e.operationType==="cancel")return{action:"cancel",sessionId:t,toolCallId:r};if(e.operationType!=="answer")throw new Error("user question operation_type must be answer or cancel");if(!Array.isArray(e.content.answers)||e.content.answers.length===0)throw new Error("user question answers must be a non-empty array");if(e.content.answers.length>aI)throw new Error(`user question answers must contain at most ${aI} items`);return{action:"answer",sessionId:t,toolCallId:r,answers:e.content.answers.map(i=>{if(!i||typeof i!="object"||Array.isArray(i))throw new Error("user question answer must be an object");let n=i;if(!Array.isArray(n.selected)||n.selected.length>cI||!n.selected.every(a=>typeof a=="string"))throw new Error(`user question answer selected must be a string array of at most ${cI} items`);let o=n.custom;if(o!==void 0&&typeof o!="string")throw new Error("user question answer.custom must be a string");let s=o?.trim();if(s&&s.length>Hl)throw new Error(`user question answer.custom exceeds ${Hl} characters`);return{id:uy(n.id,"answer.id",uI),selected:n.selected.map(a=>uy(a,"answer.selected",cy)),...s===void 0?{}:{custom:s}}})}}function bve(e,t){if(t.length!==e.length)throw new Error("user question answer count does not match the request");return t.map((r,i)=>{let n=e[i];if(r.id!==n.id)throw new Error(`user question answer id does not match ${n.id}`);let o=new Set((n.options??[]).map(l=>l.label)),s=r.selected.map(l=>l.trim());if(s.some(l=>!l))throw new Error(`user question ${n.id} contains an empty selection`);if(new Set(s).size!==s.length)throw new Error(`user question ${n.id} contains duplicate selections`);let a=s.filter(l=>o.has(l)),c=s.filter(l=>!o.has(l)),u=r.custom?.trim()||c.join(`
581
581
  `);if(u.length>Hl)throw new Error(`user question ${n.id} custom answer exceeds ${Hl} characters`);if(n.multiSelect!==!0&&u)return{id:r.id,selected:[],custom:u};if(n.multiSelect!==!0&&a.length>1)throw new Error(`user question ${n.id} accepts only one selection`);return{id:r.id,selected:a,...u?{custom:u}:{}}})}function Gl(e,t,r){return{version:1,type:"ask_user_question",interaction_id:e.rpcId,session_id:e.context.sessionId,...e.toolCallId?{tool_call_id:e.toolCallId}:{},status:t,questions:e.frame.questions.map(i=>({id:i.id,question:i.question,...i.header===void 0?{}:{header:i.header},...i.options===void 0?{}:{options:i.options},...i.multiSelect===void 0?{}:{multi_select:i.multiSelect}})),...r===void 0?{}:{answers:r}}}async function qV(e,t){let r=vve(t);if(!r)return!1;let i=[...e.pendingUserQuestions.values()].filter(l=>l.context.sessionId!==r.sessionId||l.context.userId!==t._userId?!1:l.toolCallId===void 0||l.toolCallId===r.toolCallId);if(i.length>1)return e.logger.warn("rejected ambiguous user question response",{toolCallId:r.toolCallId,sessionId:r.sessionId,matches:i.length}),!1;let n=i[0];if(!n)return e.logger.info("ignored stale user question response",{toolCallId:r.toolCallId,sessionId:r.sessionId}),!1;let o=r.action==="answer"?bve(n.frame.questions,r.answers):void 0,s=o?{ok:!0,value:{answers:o}}:{ok:!1,error:{code:"cancelled",message:"the user cancelled this question request",details:{}}},a=r.action==="answer"?"answered":"cancelled";n.submitted={status:a,...o?{answers:o}:{}};let c;try{c=await e.dsh.api.respondEvent({eventId:n.rpcId,outcome:s.ok?{kind:"result",value:s.value}:{kind:"rejected",error:{name:"Error",message:s.error.message,code:s.error.code,details:s.error.details}}})}catch(l){throw e.pendingUserQuestions.get(n.rpcId)===n&&delete n.submitted,l}if(!c.result.ok)return e.pendingUserQuestions.get(n.rpcId)===n&&delete n.submitted,e.logger.warn("DSH rejected user question response",{interactionId:n.rpcId}),!1;e.pendingUserQuestions.delete(n.rpcId);let u=fI(e,n.frame.sessionId);return u&&e.turns.resumeAfterUserInput(u),e.dcg.enqueue(n.context,{response:"",state:"chunk",is_finish:0,interaction:Gl(n,a,o)},`question:${n.rpcId}:${a}`),!0}function jV(e,t){for(let[r,i]of e.pendingUserQuestions)if(!(t&&i.frame.sessionId!==t)){e.pendingUserQuestions.delete(r);try{e.dcg.enqueue(i.context,{response:"",state:"chunk",is_finish:0,interaction:Gl(i,"cancelled")},`question:${r}:cancelled`)}catch(n){e.logger.warn("could not persist user-question cancellation",{interactionId:r,error:n instanceof Error?n.message:String(n)})}}}async function MV(e,t){let r=_ve(t.request,t.agentId),i=r?fI(e,r.sessionId):void 0;if(!r||!i||i.followup){e.logger.warn("rejected user question without an interactive user",{eventId:t.eventId,agentId:t.agentId,sessionId:r?.sessionId,reason:r?i?"followup":"no_live_run":"invalid_request"});let s=e.pendingUserQuestions.get(t.eventId);if(s){e.pendingUserQuestions.delete(t.eventId);try{e.dcg.enqueue(s.context,{response:"",state:"chunk",is_finish:0,interaction:Gl(s,"cancelled")},`question:${t.eventId}:cancelled`)}catch(a){e.logger.warn("could not persist stale user-question cancellation",{eventId:t.eventId,error:a instanceof Error?a.message:String(a)})}}await PV(e,t.eventId,"\u5F53\u524D\u8FD0\u884C\u6CA1\u6709\u53EF\u4EA4\u4E92\u7684\u7528\u6237","cancelled");return}let n=[...i.toolCalls].reverse().find(([,s])=>s.name==="ask_user_question"&&!s.settled)?.[0],o={rpcId:t.eventId,frame:r,context:i.context,...n?{toolCallId:n}:{}};e.pendingUserQuestions.set(t.eventId,o);try{e.store.markRequestToolWaiting(i.context.requestId),e.turns.pauseForUserInput(i),e.dcg.enqueue(i.context,{response:"",state:"waiting_input",is_finish:0,interaction:Gl(o,"pending")},`question:${t.eventId}:requested`)}catch(s){e.pendingUserQuestions.delete(t.eventId),e.logger.warn("could not persist user question for MBHChat",{eventId:t.eventId,error:s instanceof Error?s.message:String(s)});try{e.store.markRequestRunningAfterTool(i.context.requestId)}catch(a){e.logger.warn("could not restore task state after user-question delivery failure",{eventId:t.eventId,error:a instanceof Error?a.message:String(a)})}try{e.turns.resumeAfterUserInput(i)}catch(a){e.logger.warn("could not resume turn timeout after user-question delivery failure",{eventId:t.eventId,error:a instanceof Error?a.message:String(a)})}await PV(e,t.eventId,"\u65E0\u6CD5\u5C06\u95EE\u9898\u53D1\u9001\u7ED9\u5F53\u524D\u7528\u6237","delivery_failed");return}e.logger.info("forwarded user question to MBHChat",{sessionId:r.sessionId,rpcId:t.eventId})}function LV(e,t){let r=e.pendingUserQuestions.get(t);if(!r)return;e.pendingUserQuestions.delete(t);let i=fI(e,r.frame.sessionId);i&&e.turns.resumeAfterUserInput(i),e.dcg.enqueue(r.context,{response:"",state:"chunk",is_finish:0,interaction:Gl(r,"cancelled",r.submitted?.answers)},`question:${t}:cancelled`)}function fI(e,t){let r=e.turns.liveRun(t);return r||e.turns.liveRuns().find(i=>!i.finalized&&i.dshSessionId===t)}function _ve(e,t){let r=cs(e.sessionId,lI)??cs(t,lI),i=e.questions;if(!r||!Array.isArray(i)||i.length===0||i.length>aI)return;let n=[];for(let o of i){let s=ye(o);if(!s)return;let a=cs(s.id,uI),c=cs(s.question,Hl);if(!a||!c)return;let u;if(s.options!==void 0){if(!Array.isArray(s.options)||s.options.length>cI)return;u=[];for(let d of s.options){let p=ye(d),f=cs(p?.label,cy);if(!f)return;let h=cs(p?.description,cy);if(p?.description!==void 0&&!h)return;u.push({label:f,...h?{description:h}:{}})}}let l=cs(s.header,cy);if(s.header!==void 0&&!l||s.multiSelect!==void 0&&typeof s.multiSelect!="boolean")return;n.push({id:a,question:c,...l?{header:l}:{},...u?{options:u}:{},...typeof s.multiSelect=="boolean"?{multiSelect:s.multiSelect}:{}})}return{sessionId:r,questions:n}}function cs(e,t){if(typeof e!="string")return;let r=e.trim();return r&&r.length<=t?r:void 0}async function PV(e,t,r,i){try{(await e.dsh.api.respondEvent({eventId:t,outcome:{kind:"rejected",error:{name:"Error",message:r,code:i}}})).result.ok||e.logger.warn("DSH rejected user-question rejection",{eventId:t,code:i})}catch(n){e.logger.warn("could not reject user question through DSH",{eventId:t,code:i,error:n instanceof Error?n.message:String(n)})}}async function FV(e,t){if(t.type==="waterfall"&&t.event==="approval/request"){let r=dI(t.request,"sessionId"),i=dI(t.request,"approvalId"),n=dI(t.request,"toolName"),o=r?e.turns.liveRun(r):void 0,s=sI(e.config.dsh.approvalPolicy,o?.followup===!0);await e.dsh.api.respondEvent({eventId:t.eventId,outcome:{kind:"result",value:{sessionId:r,approvalId:i,outcome:s}}}),e.logger.info("answered headless approval",{sessionId:r,toolName:n,outcome:s});return}if(t.type==="waterfall"&&t.event==="user-questions/request"){await MV(e,t);return}if(t.type==="cancel"){LV(e,t.eventId);return}if(t.type==="emit"){if(t.event==="api-session/removed"){let r=String(t.args[0]??"");if(!r)return;e.unfollowSession?.(r),e.store.removeSessionByDshId(r);for(let i of e.turns.liveRuns())i.dshSessionId===r&&e.turns.finish(i,"session_removed","failed","[\u9519\u8BEF] mbh-chat \u4F1A\u8BDD\u5DF2\u88AB\u79FB\u9664");return}t.event==="api-session/error"&&wve(e,String(t.args[0]??""),String(t.args[1]??""))}}function dI(e,t){let r=e[t];return typeof r=="string"&&r?r:void 0}function wve(e,t,r){if(t){if(!Zl(r)){e.logger.error("mbh-chat agent error",{sessionId:t,message:r});return}pI(e,t,r)}}function pI(e,t,r){if(e.handledCorruptSessions.has(t))return;e.handledCorruptSessions.add(t);let i=e.stopRequestedSessions.delete(t);if(i?e.logger.info("ignored late mbh-chat agent error after stop",{dshSessionId:t,error:r}):e.logger.error("mbh-chat agent error",{sessionId:t,message:r}),e.unfollowSession?.(t),e.store.removeSessionByDshId(t),e.logger.info("discarded mbh-chat session with corrupt history",{dshSessionId:t,error:r,followsStop:i}),i){for(let o of e.turns.liveRuns())o.dshSessionId===t&&e.turns.finish(o,"stop","cancelled","");return}let n=e.corruptSessionRecoveries.get(t);n&&!n.active.finalized&&n.recover(r);for(let o of e.turns.liveRuns())o.dshSessionId===t&&o!==n?.active&&e.turns.finish(o,"session_invalidated","cancelled","")}var zV=["\u5982\u679C\u4EFB\u52A1\u751F\u6210\u4E86\u4E00\u4E2A\u6216\u591A\u4E2A\u6587\u4EF6\uFF0C\u5FC5\u987B\u5728\u6700\u7EC8\u56DE\u590D\u524D\u8C03\u7528 mbhchat_message \u5DE5\u5177\uFF0C\u5E76\u5728\u540C\u4E00\u4E2A media \u6570\u7EC4\u4E2D\u5217\u51FA\u6240\u6709\u6587\u4EF6\u7684\u7EDD\u5BF9\u8DEF\u5F84\u3002","\u4E0D\u8981\u5728\u6B63\u6587\u4E2D\u66B4\u9732\u672C\u5730\u6587\u4EF6\u8DEF\u5F84\uFF1B\u7B49\u5F85\u5DE5\u5177\u8FD4\u56DE success=true \u540E\u518D\u544A\u77E5\u7528\u6237\u6587\u4EF6\u5DF2\u53D1\u9001\u3002","\u666E\u901A\u6B63\u6587\u76F4\u63A5\u4F5C\u4E3A\u52A9\u624B\u56DE\u590D\uFF1Bmbhchat_message \u5DE5\u5177\u4E3B\u8981\u7528\u4E8E\u9644\u4EF6\u4EA4\u4ED8\uFF0C\u907F\u514D\u6B63\u6587\u53CC\u5199\u3002","\u5B9A\u65F6\u4EFB\u52A1\u81EA\u52A8\u6267\u884C\u65F6\uFF0C\u9644\u4EF6\u53CA\u5176\u4EA4\u4ED8\u8BF4\u660E\u4F1A\u4E0E\u6700\u7EC8\u6B63\u6587\u5408\u5E76\u4E3A\u540C\u4E00\u6761\u63A8\u9001\uFF1B\u4ECD\u5E94\u5148\u8C03\u7528\u5DE5\u5177\uFF0C\u5E76\u5728\u6210\u529F\u540E\u518D\u5B8C\u6210\u6B63\u6587\u3002"],UV=`[\u7CFB\u7EDF: ${zV.join("")}]`,pAe=["\u5411\u5F53\u524D\u4E66\u7075\u58A8\u5B9D\u7528\u6237\u53D1\u9001\u6587\u672C\u6216\u9644\u4EF6\u3002",...zV].join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcrays/mbh-chat",
3
- "version": "0.1.5-beta.3",
3
+ "version": "0.1.5-beta.4",
4
4
  "description": "DeepSeek Harness host plugin and headless sidecar bridge for MBHChat/Mobook",
5
5
  "type": "module",
6
6
  "main": "plugin/index.js",