shennian 0.2.110 → 0.2.111
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.
|
@@ -156,8 +156,8 @@
|
|
|
156
156
|
},
|
|
157
157
|
{
|
|
158
158
|
"file": "src/channels/runtime.js",
|
|
159
|
-
"beforeBytes":
|
|
160
|
-
"afterBytes":
|
|
159
|
+
"beforeBytes": 30070,
|
|
160
|
+
"afterBytes": 16457
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
"file": "src/channels/secret-registry.js",
|
|
@@ -266,8 +266,8 @@
|
|
|
266
266
|
},
|
|
267
267
|
{
|
|
268
268
|
"file": "src/channels/wechat-channel/outbound-ledger.js",
|
|
269
|
-
"beforeBytes":
|
|
270
|
-
"afterBytes":
|
|
269
|
+
"beforeBytes": 9833,
|
|
270
|
+
"afterBytes": 5572
|
|
271
271
|
},
|
|
272
272
|
{
|
|
273
273
|
"file": "src/channels/wechat-channel/outbound-sender.js",
|
|
@@ -63,6 +63,7 @@ export declare class ChannelRuntime {
|
|
|
63
63
|
syncManagerWeChatRpaChannel(managerSessionId: string): Promise<{
|
|
64
64
|
channel: ExternalChannelView;
|
|
65
65
|
messages: ExternalMessageEvent[];
|
|
66
|
+
recentMessages: ExternalMessageEvent[];
|
|
66
67
|
}>;
|
|
67
68
|
cancelManagerWeChatRpaOutbound(input: {
|
|
68
69
|
managerSessionId: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import v from"node:crypto";import g from"node:fs";import u from"node:path";import{ChannelConfigRegistry as M}from"./registry.js";import{ChannelSecretRegistry as N}from"./secret-registry.js";import{WeComChannelAdapter as D}from"./wecom.js";import{WeChatRpaChannelAdapter as B}from"./wechat-rpa.js";import{ExternalWebSocketChannelAdapter as x}from"./websocket.js";import{splitExternalReplyText as F}from"./reply-split.js";class J{onExternalMessage;createReplyTarget;configs=new M;secrets=new N;adapters=new Map;completedReplyKeys=new Map;recentMessages=new Map;constructor(e,t,s={}){this.onExternalMessage=e,this.createReplyTarget=t;const o=new D(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(o.type,o);const r=new x(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(r.type,r);const i=new B(a=>this.ingest(a),{createProductRunner:s.createWeChatRpaProductRunner,automationLane:s.weChatAutomationLane});this.adapters.set(i.type,i)}async start(){for(const e of this.configs.list().filter(t=>t.enabled))await this.adapters.get(e.type)?.connect(e).catch(()=>{})}async stop(){for(const e of this.configs.list())await this.adapters.get(e.type)?.disconnect(e).catch(()=>{})}ingest(e){const t=this.findRecentMessageDuplicate(e);if(t)return t;const s=this.configs.get(e.channelId),o=e.managerSessionId??s?.sessionId??s?.managerSessionId;if(!o)throw new Error(`No session bound for channel ${e.channelId}`);const r=e.replyTarget||this.createReplyTarget({managerSessionId:o,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId}),i={...e,replyTarget:r};return this.onExternalMessage(o,i),this.recordRecentMessage(i),i}async reply(e){const t=this.configs.get(e.channelId);if(!t)return{ok:!1,error:`Unknown channel: ${e.channelId}`};if((t.sessionId??t.managerSessionId)!==e.managerSessionId)return{ok:!1,error:"Channel is not bound to this session"};const s=this.adapters.get(t.type);if(!s)return{ok:!1,error:`Unsupported channel type: ${t.type}`};try{const o=W(t.type,e);if(!o.length)return{ok:!1,error:"Reply text or attachment is required"};let r=!1;for(const i of o){const a=i.idempotencyKey;if(a&&this.isReplyCompleted(t,e.conversationId,a))continue;const c=await s.send(t,{...e,...i});if(c?.status==="queued"){r=!0;continue}if(c?.status==="manual-review")return{ok:!1,error:c.reason||"Reply requires manual review before retry"};a&&this.markReplyCompleted(t,e.conversationId,a)}return r?{ok:!0,pending:!0}:{ok:!0}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}}isReplyCompleted(e,t,s){return this.loadReplyCompletionSet(e).has(A(e.id,t,s))}markReplyCompleted(e,t,s){const o=this.loadReplyCompletionSet(e);o.add(A(e.id,t,s));try{$(e.workDir,o)}catch{}}loadReplyCompletionSet(e){const t=u.resolve(e.workDir),s=this.completedReplyKeys.get(t);if(s)return s;const o=T(e.workDir);return this.completedReplyKeys.set(t,o),o}async getDefaultReplyTarget(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)throw new Error("No enabled external channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.defaultConversation)throw new Error(`External channel ${t.type} has no default conversation`);const o=await s.defaultConversation(t);return{channelId:t.id,conversationId:o.conversationId}}getManagerChannel(e,t,s={}){const o=this.configs.list().filter(c=>(c.sessionId??c.managerSessionId)===e&&c.type===t),r=o.find(c=>c.enabled)??o.at(-1);if(!r)return null;const i=this.secrets.get(r.secretRef),a=this.adapters.get(r.type)?.runtimeStatus?.(r)??{};return{id:r.id,type:r.type,name:r.name,sessionId:r.sessionId??r.managerSessionId,managerSessionId:r.managerSessionId,workDir:r.workDir,agentType:r.agentType,agentSessionId:r.agentSessionId,modelId:r.modelId,enabled:r.enabled,wsUrl:i?.wsUrl??"",token:s.includeSecret?i?.token??"":"",tokenConfigured:!!i?.token,canReply:!!i?.canReply,systemPrompt:typeof i?.systemPrompt=="string"?i.systemPrompt:"",...k(i),...a}}getChannelById(e,t={}){const s=this.configs.get(e);if(!s)return null;const o=this.secrets.get(s.secretRef),r=this.adapters.get(s.type)?.runtimeStatus?.(s)??{};return{id:s.id,type:s.type,name:s.name,sessionId:s.sessionId??s.managerSessionId,managerSessionId:s.managerSessionId,workDir:s.workDir,agentType:s.agentType,agentSessionId:s.agentSessionId,modelId:s.modelId,enabled:s.enabled,wsUrl:o?.wsUrl??"",token:t.includeSecret?o?.token??"":"",tokenConfigured:!!o?.token,canReply:!!o?.canReply,systemPrompt:typeof o?.systemPrompt=="string"?o.systemPrompt:"",...k(o),...r}}getChannelStatusById(e){const t=this.configs.get(e);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}getManagerChannelStatus(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}listManagerChannelStatuses(){return this.configs.list().filter(e=>e.enabled).map(e=>({managerSessionId:e.sessionId??e.managerSessionId,status:this.getManagerChannelStatus(e.sessionId??e.managerSessionId)})).filter(e=>!!e.status)}listManagerExternalChannels(e){return this.configs.list().filter(t=>t.enabled&&(t.sessionId??t.managerSessionId)===e).map(t=>{const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}})}async syncManagerWeChatRpaChannel(e){const t=this.configs.list().find(i=>i.enabled&&i.type==="wechat-rpa"&&(i.sessionId??i.managerSessionId)===e);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.syncNow)throw new Error("WeChat RPA channel does not support manual sync");const o=Date.now()-120*1e3,r=K(await s.syncNow(t)??[],this.getRecentMessages(t.id,o));return{channel:this.getManagerChannel(e,"wechat-rpa",{includeSecret:!0}),messages:r}}async cancelManagerWeChatRpaOutbound(e){const t=this.configs.list().find(r=>r.enabled&&r.type==="wechat-rpa"&&(r.sessionId??r.managerSessionId)===e.managerSessionId);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.cancelOutbound)throw new Error("WeChat RPA channel does not support outbound cancellation");const o=await s.cancelOutbound(t,{idempotencyKey:e.idempotencyKey,replyId:e.replyId,reason:e.reason});return{cancelled:o.cancelled,status:o.status,channel:this.getManagerChannel(e.managerSessionId,"wechat-rpa",{includeSecret:!0})}}recordRecentMessage(e){const t=this.recentMessages.get(e.channelId)??[];this.findRecentMessageDuplicate(e)||(t.push(e),this.recentMessages.set(e.channelId,t.slice(-50)))}findRecentMessageDuplicate(e){const t=I(e);return t?(this.recentMessages.get(e.channelId)??[]).find(o=>I(o)===t)??null:null}getRecentMessages(e,t){return(this.recentMessages.get(e)??[]).filter(o=>{const r=Date.parse(o.receivedAt);return!Number.isFinite(r)||r>=t})}async upsertManagerChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r={id:e.id,type:e.type,name:e.name?.trim()||t?.name||"\u5916\u90E8\u6D88\u606F\u901A\u9053",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},i=this.secrets.get(r.secretRef),a=e.wsUrl?.trim()||i?.wsUrl||"",c=e.token?.trim()||i?.token||"",p=e.canReply??i?.canReply??!1,m=e.systemPrompt??(typeof i?.systemPrompt=="string"?i.systemPrompt:"");if(r.enabled&&(!a||!c))throw new Error("WebSocket \u5730\u5740\u548C Token \u5FC5\u586B");const f=s.filter(l=>l.id!==r.id).map(l=>(l.sessionId??l.managerSessionId)===o&&l.type===e.type?{...l,enabled:!1}:l);f.push(r),this.configs.replaceAll(f),(a||c)&&this.secrets.upsert(r.secretRef,{type:"websocket",wsUrl:a,token:c,canReply:p,systemPrompt:m});const d=this.adapters.get(r.type);for(const l of s)(l.sessionId??l.managerSessionId)===o&&l.type===e.type&&l.enabled&&await this.adapters.get(l.type)?.disconnect(l).catch(()=>{});return r.enabled&&d?.connect(r).catch(()=>{}),this.getManagerChannel(o,e.type,{includeSecret:!0})}async upsertManagerWeChatRpaChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r=w(e.groups);if(e.enabled&&!r.length)throw new Error("WeChat RPA \u81F3\u5C11\u9700\u8981\u914D\u7F6E\u4E00\u4E2A\u7FA4");if(e.enabled&&r.length>1)throw new Error("WeChat RPA \u6BCF\u4E2A\u5BF9\u8BDD\u53EA\u80FD\u7ED1\u5B9A\u4E00\u4E2A\u7FA4");const i={id:e.id,type:"wechat-rpa",name:e.name?.trim()||t?.name||"\u672C\u673A\u5FAE\u4FE1 RPA",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},a=this.secrets.get(i.secretRef),c=e.source||(a?.source==="wechat-channel"||a?.source==="macos-probe"||a?.source==="fixture-jsonl"||a?.source==="macos-flow"||a?.source==="windows-visual-flow"||a?.source==="wechat-rpa-lab"?a.source:E());if(e.enabled&&c==="windows-visual-flow")throw new Error("\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF1BmacOS \u548C Windows \u6B63\u5F0F\u901A\u9053\u90FD\u4F7F\u7528 wechat-channel");const p=e.privacyConsentAccepted??!!a?.privacyConsentAccepted;if(e.enabled&&!p)throw new Error("\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743");const m=s.filter(d=>d.id!==i.id).map(d=>(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"?{...d,enabled:!1}:d);m.push(i),this.configs.replaceAll(m),this.secrets.upsert(i.secretRef,{type:"wechat-rpa",source:c,groups:r,pollIntervalMs:R(e.pollIntervalMs,a?.pollIntervalMs),recentLimit:R(e.recentLimit,a?.recentLimit),idleSeconds:R(e.idleSeconds,a?.idleSeconds),forceForeground:e.forceForeground??(a?.forceForeground===void 0?!0:!!a.forceForeground),noRestore:e.noRestore??(a?.noRestore===void 0?!0:!!a.noRestore),downloadAttachments:e.downloadAttachments??(a?.downloadAttachments===void 0?!0:!!a.downloadAttachments),downloadAttachmentsDir:e.downloadAttachmentsDir?.trim()||b(a?.downloadAttachmentsDir),selfNickname:e.selfNickname?.trim()||b(a?.selfNickname),selfTriggerMarker:e.selfTriggerMarker?.trim()||void 0,deferInitialPoll:e.deferInitialPoll===!0?!0:void 0,privacyConsentAccepted:p,flowScriptPath:e.flowScriptPath?.trim()||b(a?.flowScriptPath),canReply:e.canReply??a?.canReply??!1,systemPrompt:e.systemPrompt??(typeof a?.systemPrompt=="string"?a.systemPrompt:"")});const f=this.adapters.get(i.type);for(const d of s)(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"&&d.enabled&&await this.adapters.get(d.type)?.disconnect(d).catch(()=>{});return i.enabled&&f?.connect(i).catch(()=>{}),this.getManagerChannel(o,"wechat-rpa",{includeSecret:!0})}}function y(n,e){return!e||e.type!==n.type?!1:n.type==="wechat-rpa"?!0:n.type==="websocket"?!!(e.wsUrl&&e.token):n.type==="wecom"?!!(e.token||e.botId||e.secret):!!e.token}function k(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:"",wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):void 0,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):void 0,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):void 0,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?void 0:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:"",selfNickname:typeof n.selfNickname=="string"?n.selfNickname:"",wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:C(n)}}function h(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:null,wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):null,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):null,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):null,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?null:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:null,selfNickname:typeof n.selfNickname=="string"?n.selfNickname:null,wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:C(n)}}function w(n){const e=new Set,t=[];for(const s of n){const o=String(s?.name||"").replace(/\s+/g," ").trim();!o||e.has(o)||(e.add(o),t.push({name:o}))}return t}function E(){return"wechat-channel"}function C(n){const e=[];if(n.lastHelperPermissions&&typeof n.lastHelperPermissions=="object"){const t=n.lastHelperPermissions;e.push({code:"wechat_window_unavailable",ok:t.wechatWindowAvailable!==!1,severity:"blocking",message:t.wechatWindowAvailable===!1?"\u5FAE\u4FE1\u7A97\u53E3\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6253\u5F00\u5E76\u767B\u5F55\u5FAE\u4FE1\u540E\u518D\u8BD5\u3002":"\u5FAE\u4FE1\u7A97\u53E3\u53EF\u7528\u3002"})}return e.push({code:"platform_unsupported",ok:n.source!=="windows-visual-flow",severity:"blocking",message:n.source==="windows-visual-flow"?"\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF0C\u8BF7\u6539\u7528 wechat-channel\u3002":"\u5F53\u524D\u914D\u7F6E\u4F7F\u7528\u8DE8\u5E73\u53F0\u5FAE\u4FE1\u901A\u9053\u3002"}),e.push({code:"privacy_consent_required",ok:!!n.privacyConsentAccepted,severity:"blocking",message:n.privacyConsentAccepted?"\u5DF2\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002":"\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002"}),e.push({code:"server_decision_unavailable",ok:!0,severity:"blocking",message:"\u670D\u52A1\u7AEF\u5224\u65AD\u80FD\u529B\u53EF\u7528\u3002"}),e}function W(n,e){const t=F(e.text);if(!t.length&&!e.attachment)return[];if(n==="wechat-rpa"&&e.attachment&&t.length<=1)return[{text:t[0]??"",attachment:e.attachment,idempotencyKey:e.idempotencyKey}];const s=t.map((o,r)=>({text:o,attachment:void 0,idempotencyKey:t.length>1&&e.idempotencyKey?`${e.idempotencyKey}:${r+1}`:e.idempotencyKey}));return e.attachment&&s.push({text:"",attachment:e.attachment,idempotencyKey:t.length&&e.idempotencyKey?`${e.idempotencyKey}:attachment`:e.idempotencyKey}),s}function K(...n){const e=new Set,t=[];for(const s of n.flat()){const o=I(s);if(!o){t.push(s);continue}e.has(o)||(e.add(o),t.push(s))}return t}function I(n){const e=S(n.channelId),t=S(n.conversationId),s=S(n.messageId);return!e||!t||!s?null:`${e}
|
|
1
|
+
import M from"node:crypto";import g from"node:fs";import u from"node:path";import{ChannelConfigRegistry as v}from"./registry.js";import{ChannelSecretRegistry as N}from"./secret-registry.js";import{WeComChannelAdapter as D}from"./wecom.js";import{WeChatRpaChannelAdapter as B}from"./wechat-rpa.js";import{ExternalWebSocketChannelAdapter as x}from"./websocket.js";import{splitExternalReplyText as F}from"./reply-split.js";class J{onExternalMessage;createReplyTarget;configs=new v;secrets=new N;adapters=new Map;completedReplyKeys=new Map;recentMessages=new Map;constructor(e,t,s={}){this.onExternalMessage=e,this.createReplyTarget=t;const o=new D(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(o.type,o);const r=new x(a=>this.ingest({...a,type:"external.message"}));this.adapters.set(r.type,r);const i=new B(a=>this.ingest(a),{createProductRunner:s.createWeChatRpaProductRunner,automationLane:s.weChatAutomationLane});this.adapters.set(i.type,i)}async start(){for(const e of this.configs.list().filter(t=>t.enabled))await this.adapters.get(e.type)?.connect(e).catch(()=>{})}async stop(){for(const e of this.configs.list())await this.adapters.get(e.type)?.disconnect(e).catch(()=>{})}ingest(e){const t=this.findRecentMessageDuplicate(e);if(t)return t;const s=this.configs.get(e.channelId),o=e.managerSessionId??s?.sessionId??s?.managerSessionId;if(!o)throw new Error(`No session bound for channel ${e.channelId}`);const r=e.replyTarget||this.createReplyTarget({managerSessionId:o,channelId:e.channelId,conversationId:e.conversationId,messageId:e.messageId}),i={...e,replyTarget:r};return this.onExternalMessage(o,i),this.recordRecentMessage(i),i}async reply(e){const t=this.configs.get(e.channelId);if(!t)return{ok:!1,error:`Unknown channel: ${e.channelId}`};if((t.sessionId??t.managerSessionId)!==e.managerSessionId)return{ok:!1,error:"Channel is not bound to this session"};const s=this.adapters.get(t.type);if(!s)return{ok:!1,error:`Unsupported channel type: ${t.type}`};try{const o=W(t.type,e);if(!o.length)return{ok:!1,error:"Reply text or attachment is required"};let r=!1;for(const i of o){const a=i.idempotencyKey;if(a&&this.isReplyCompleted(t,e.conversationId,a))continue;const c=await s.send(t,{...e,...i});if(c?.status==="queued"){r=!0;continue}if(c?.status==="manual-review")return{ok:!1,error:c.reason||"Reply requires manual review before retry"};a&&this.markReplyCompleted(t,e.conversationId,a)}return r?{ok:!0,pending:!0}:{ok:!0}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}}isReplyCompleted(e,t,s){return this.loadReplyCompletionSet(e).has(A(e.id,t,s))}markReplyCompleted(e,t,s){const o=this.loadReplyCompletionSet(e);o.add(A(e.id,t,s));try{$(e.workDir,o)}catch{}}loadReplyCompletionSet(e){const t=u.resolve(e.workDir),s=this.completedReplyKeys.get(t);if(s)return s;const o=T(e.workDir);return this.completedReplyKeys.set(t,o),o}async getDefaultReplyTarget(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)throw new Error("No enabled external channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.defaultConversation)throw new Error(`External channel ${t.type} has no default conversation`);const o=await s.defaultConversation(t);return{channelId:t.id,conversationId:o.conversationId}}getManagerChannel(e,t,s={}){const o=this.configs.list().filter(c=>(c.sessionId??c.managerSessionId)===e&&c.type===t),r=o.find(c=>c.enabled)??o.at(-1);if(!r)return null;const i=this.secrets.get(r.secretRef),a=this.adapters.get(r.type)?.runtimeStatus?.(r)??{};return{id:r.id,type:r.type,name:r.name,sessionId:r.sessionId??r.managerSessionId,managerSessionId:r.managerSessionId,workDir:r.workDir,agentType:r.agentType,agentSessionId:r.agentSessionId,modelId:r.modelId,enabled:r.enabled,wsUrl:i?.wsUrl??"",token:s.includeSecret?i?.token??"":"",tokenConfigured:!!i?.token,canReply:!!i?.canReply,systemPrompt:typeof i?.systemPrompt=="string"?i.systemPrompt:"",...k(i),...a}}getChannelById(e,t={}){const s=this.configs.get(e);if(!s)return null;const o=this.secrets.get(s.secretRef),r=this.adapters.get(s.type)?.runtimeStatus?.(s)??{};return{id:s.id,type:s.type,name:s.name,sessionId:s.sessionId??s.managerSessionId,managerSessionId:s.managerSessionId,workDir:s.workDir,agentType:s.agentType,agentSessionId:s.agentSessionId,modelId:s.modelId,enabled:s.enabled,wsUrl:o?.wsUrl??"",token:t.includeSecret?o?.token??"":"",tokenConfigured:!!o?.token,canReply:!!o?.canReply,systemPrompt:typeof o?.systemPrompt=="string"?o.systemPrompt:"",...k(o),...r}}getChannelStatusById(e){const t=this.configs.get(e);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}getManagerChannelStatus(e){const t=this.configs.list().find(r=>(r.sessionId??r.managerSessionId)===e&&r.enabled);if(!t)return null;const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}}listManagerChannelStatuses(){return this.configs.list().filter(e=>e.enabled).map(e=>({managerSessionId:e.sessionId??e.managerSessionId,status:this.getManagerChannelStatus(e.sessionId??e.managerSessionId)})).filter(e=>!!e.status)}listManagerExternalChannels(e){return this.configs.list().filter(t=>t.enabled&&(t.sessionId??t.managerSessionId)===e).map(t=>{const s=this.secrets.get(t.secretRef),o=this.adapters.get(t.type)?.runtimeStatus?.(t)??{};return{configured:!0,connected:y(t,s),type:t.type,channelId:t.id,name:t.name,canReply:!!s?.canReply,systemPrompt:typeof s?.systemPrompt=="string"?s.systemPrompt:"",...h(s),...o}})}async syncManagerWeChatRpaChannel(e){const t=this.configs.list().find(a=>a.enabled&&a.type==="wechat-rpa"&&(a.sessionId??a.managerSessionId)===e);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.syncNow)throw new Error("WeChat RPA channel does not support manual sync");const o=Date.now()-120*1e3,r=await s.syncNow(t)??[],i=K(r,this.getRecentMessages(t.id,o));return{channel:this.getManagerChannel(e,"wechat-rpa",{includeSecret:!0}),messages:r,recentMessages:i}}async cancelManagerWeChatRpaOutbound(e){const t=this.configs.list().find(r=>r.enabled&&r.type==="wechat-rpa"&&(r.sessionId??r.managerSessionId)===e.managerSessionId);if(!t)throw new Error("No enabled WeChat RPA channel is bound to this session");const s=this.adapters.get(t.type);if(!s?.cancelOutbound)throw new Error("WeChat RPA channel does not support outbound cancellation");const o=await s.cancelOutbound(t,{idempotencyKey:e.idempotencyKey,replyId:e.replyId,reason:e.reason});return{cancelled:o.cancelled,status:o.status,channel:this.getManagerChannel(e.managerSessionId,"wechat-rpa",{includeSecret:!0})}}recordRecentMessage(e){const t=this.recentMessages.get(e.channelId)??[];this.findRecentMessageDuplicate(e)||(t.push(e),this.recentMessages.set(e.channelId,t.slice(-50)))}findRecentMessageDuplicate(e){const t=I(e);return t?(this.recentMessages.get(e.channelId)??[]).find(o=>I(o)===t)??null:null}getRecentMessages(e,t){return(this.recentMessages.get(e)??[]).filter(o=>{const r=Date.parse(o.receivedAt);return!Number.isFinite(r)||r>=t})}async upsertManagerChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r={id:e.id,type:e.type,name:e.name?.trim()||t?.name||"\u5916\u90E8\u6D88\u606F\u901A\u9053",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},i=this.secrets.get(r.secretRef),a=e.wsUrl?.trim()||i?.wsUrl||"",c=e.token?.trim()||i?.token||"",p=e.canReply??i?.canReply??!1,m=e.systemPrompt??(typeof i?.systemPrompt=="string"?i.systemPrompt:"");if(r.enabled&&(!a||!c))throw new Error("WebSocket \u5730\u5740\u548C Token \u5FC5\u586B");const f=s.filter(l=>l.id!==r.id).map(l=>(l.sessionId??l.managerSessionId)===o&&l.type===e.type?{...l,enabled:!1}:l);f.push(r),this.configs.replaceAll(f),(a||c)&&this.secrets.upsert(r.secretRef,{type:"websocket",wsUrl:a,token:c,canReply:p,systemPrompt:m});const d=this.adapters.get(r.type);for(const l of s)(l.sessionId??l.managerSessionId)===o&&l.type===e.type&&l.enabled&&await this.adapters.get(l.type)?.disconnect(l).catch(()=>{});return r.enabled&&d?.connect(r).catch(()=>{}),this.getManagerChannel(o,e.type,{includeSecret:!0})}async upsertManagerWeChatRpaChannel(e){const t=this.configs.get(e.id),s=this.configs.list(),o=e.sessionId||e.managerSessionId,r=w(e.groups);if(e.enabled&&!r.length)throw new Error("WeChat RPA \u81F3\u5C11\u9700\u8981\u914D\u7F6E\u4E00\u4E2A\u7FA4");if(e.enabled&&r.length>1)throw new Error("WeChat RPA \u6BCF\u4E2A\u5BF9\u8BDD\u53EA\u80FD\u7ED1\u5B9A\u4E00\u4E2A\u7FA4");const i={id:e.id,type:"wechat-rpa",name:e.name?.trim()||t?.name||"\u672C\u673A\u5FAE\u4FE1 RPA",sessionId:o,managerSessionId:o,workDir:e.workDir,agentType:e.agentType||t?.agentType,agentSessionId:e.agentSessionId??t?.agentSessionId??null,modelId:e.modelId??t?.modelId??null,enabled:e.enabled,secretRef:t?.secretRef||`channel:${e.id}`},a=this.secrets.get(i.secretRef),c=e.source||(a?.source==="wechat-channel"||a?.source==="macos-probe"||a?.source==="fixture-jsonl"||a?.source==="macos-flow"||a?.source==="windows-visual-flow"||a?.source==="wechat-rpa-lab"?a.source:E());if(e.enabled&&c==="windows-visual-flow")throw new Error("\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF1BmacOS \u548C Windows \u6B63\u5F0F\u901A\u9053\u90FD\u4F7F\u7528 wechat-channel");const p=e.privacyConsentAccepted??!!a?.privacyConsentAccepted;if(e.enabled&&!p)throw new Error("\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743");const m=s.filter(d=>d.id!==i.id).map(d=>(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"?{...d,enabled:!1}:d);m.push(i),this.configs.replaceAll(m),this.secrets.upsert(i.secretRef,{type:"wechat-rpa",source:c,groups:r,pollIntervalMs:R(e.pollIntervalMs,a?.pollIntervalMs),recentLimit:R(e.recentLimit,a?.recentLimit),idleSeconds:R(e.idleSeconds,a?.idleSeconds),forceForeground:e.forceForeground??(a?.forceForeground===void 0?!0:!!a.forceForeground),noRestore:e.noRestore??(a?.noRestore===void 0?!0:!!a.noRestore),downloadAttachments:e.downloadAttachments??(a?.downloadAttachments===void 0?!0:!!a.downloadAttachments),downloadAttachmentsDir:e.downloadAttachmentsDir?.trim()||b(a?.downloadAttachmentsDir),selfNickname:e.selfNickname?.trim()||b(a?.selfNickname),selfTriggerMarker:e.selfTriggerMarker?.trim()||void 0,deferInitialPoll:e.deferInitialPoll===!0?!0:void 0,privacyConsentAccepted:p,flowScriptPath:e.flowScriptPath?.trim()||b(a?.flowScriptPath),canReply:e.canReply??a?.canReply??!1,systemPrompt:e.systemPrompt??(typeof a?.systemPrompt=="string"?a.systemPrompt:"")});const f=this.adapters.get(i.type);for(const d of s)(d.sessionId??d.managerSessionId)===o&&d.type==="wechat-rpa"&&d.enabled&&await this.adapters.get(d.type)?.disconnect(d).catch(()=>{});return i.enabled&&f?.connect(i).catch(()=>{}),this.getManagerChannel(o,"wechat-rpa",{includeSecret:!0})}}function y(n,e){return!e||e.type!==n.type?!1:n.type==="wechat-rpa"?!0:n.type==="websocket"?!!(e.wsUrl&&e.token):n.type==="wecom"?!!(e.token||e.botId||e.secret):!!e.token}function k(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:"",wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):void 0,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):void 0,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):void 0,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?void 0:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:"",selfNickname:typeof n.selfNickname=="string"?n.selfNickname:"",wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:C(n)}}function h(n){return!n||n.type!=="wechat-rpa"?{}:{wechatRpaSource:typeof n.source=="string"?n.source:null,wechatRpaGroups:w(Array.isArray(n.groups)?n.groups:[]),pollIntervalMs:Number.isFinite(n.pollIntervalMs)?Number(n.pollIntervalMs):null,recentLimit:Number.isFinite(n.recentLimit)?Number(n.recentLimit):null,idleSeconds:Number.isFinite(n.idleSeconds)?Number(n.idleSeconds):null,forceForeground:n.forceForeground===void 0?!0:!!n.forceForeground,noRestore:n.noRestore===void 0?null:!!n.noRestore,downloadAttachments:n.downloadAttachments===void 0?!0:!!n.downloadAttachments,downloadAttachmentsDir:typeof n.downloadAttachmentsDir=="string"?n.downloadAttachmentsDir:null,selfNickname:typeof n.selfNickname=="string"?n.selfNickname:null,wechatRpaPrivacyConsentAccepted:!!n.privacyConsentAccepted,wechatRpaServerDecisionAvailable:!0,wechatRpaPreflightChecks:C(n)}}function w(n){const e=new Set,t=[];for(const s of n){const o=String(s?.name||"").replace(/\s+/g," ").trim();!o||e.has(o)||(e.add(o),t.push({name:o}))}return t}function E(){return"wechat-channel"}function C(n){const e=[];if(n.lastHelperPermissions&&typeof n.lastHelperPermissions=="object"){const t=n.lastHelperPermissions;e.push({code:"wechat_window_unavailable",ok:t.wechatWindowAvailable!==!1,severity:"blocking",message:t.wechatWindowAvailable===!1?"\u5FAE\u4FE1\u7A97\u53E3\u4E0D\u53EF\u7528\uFF0C\u8BF7\u6253\u5F00\u5E76\u767B\u5F55\u5FAE\u4FE1\u540E\u518D\u8BD5\u3002":"\u5FAE\u4FE1\u7A97\u53E3\u53EF\u7528\u3002"})}return e.push({code:"platform_unsupported",ok:n.source!=="windows-visual-flow",severity:"blocking",message:n.source==="windows-visual-flow"?"\u65E7 Windows visual flow \u5DF2\u5F52\u6863\uFF0C\u8BF7\u6539\u7528 wechat-channel\u3002":"\u5F53\u524D\u914D\u7F6E\u4F7F\u7528\u8DE8\u5E73\u53F0\u5FAE\u4FE1\u901A\u9053\u3002"}),e.push({code:"privacy_consent_required",ok:!!n.privacyConsentAccepted,severity:"blocking",message:n.privacyConsentAccepted?"\u5DF2\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002":"\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1\u901A\u9053\u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002"}),e.push({code:"server_decision_unavailable",ok:!0,severity:"blocking",message:"\u670D\u52A1\u7AEF\u5224\u65AD\u80FD\u529B\u53EF\u7528\u3002"}),e}function W(n,e){const t=F(e.text);if(!t.length&&!e.attachment)return[];if(n==="wechat-rpa"&&e.attachment&&t.length<=1)return[{text:t[0]??"",attachment:e.attachment,idempotencyKey:e.idempotencyKey}];const s=t.map((o,r)=>({text:o,attachment:void 0,idempotencyKey:t.length>1&&e.idempotencyKey?`${e.idempotencyKey}:${r+1}`:e.idempotencyKey}));return e.attachment&&s.push({text:"",attachment:e.attachment,idempotencyKey:t.length&&e.idempotencyKey?`${e.idempotencyKey}:attachment`:e.idempotencyKey}),s}function K(...n){const e=new Set,t=[];for(const s of n.flat()){const o=I(s);if(!o){t.push(s);continue}e.has(o)||(e.add(o),t.push(s))}return t}function I(n){const e=S(n.channelId),t=S(n.conversationId),s=S(n.messageId);return!e||!t||!s?null:`${e}
|
|
2
2
|
${t}
|
|
3
|
-
${s}`}function S(n){return typeof n=="string"?n.trim():""}function A(n,e,t){return
|
|
3
|
+
${s}`}function S(n){return typeof n=="string"?n.trim():""}function A(n,e,t){return M.createHash("sha256").update(`${n}
|
|
4
4
|
${e}
|
|
5
5
|
${t}`).digest("hex").slice(0,32)}function P(n){return u.join(n,".shennian","external-reply-idempotency.json")}function T(n){try{const e=JSON.parse(g.readFileSync(P(n),"utf8")),t=Array.isArray(e.completed)?e.completed:[];return new Set(t.map(s=>typeof s=="string"?s:s&&typeof s=="object"&&typeof s.key=="string"?s.key:"").filter(Boolean))}catch{return new Set}}function $(n,e){const t=P(n);g.mkdirSync(u.dirname(t),{recursive:!0});const s=Array.from(e).slice(-500);g.writeFileSync(t,JSON.stringify({updatedAt:new Date().toISOString(),completed:s.map(o=>({key:o}))},null,2)),e.clear();for(const o of s)e.add(o)}function R(n,e){const t=Number(n??e);return Number.isFinite(t)&&t>=0?t:void 0}function b(n){return typeof n=="string"&&n.trim()?n.trim():void 0}export{J as ChannelRuntime,W as planExternalReplySends};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import f from"node:fs";import S from"node:path";import{normalizeWeChatAnchorText as u,weChatTextSimilarity as m}from"./anchor.js";const
|
|
2
|
-
`).trim():""}export{
|
|
1
|
+
import f from"node:fs";import S from"node:path";import{normalizeWeChatAnchorText as u,weChatTextSimilarity as m}from"./anchor.js";const h=500,A=2,x=600*1e3;function E(e,t){try{const n=JSON.parse(f.readFileSync(e,"utf8"));if(n?.version===1&&n.runtimeId===t&&Array.isArray(n.records))return n}catch{}return{version:1,runtimeId:t,records:[]}}function R(e,t){f.mkdirSync(S.dirname(e),{recursive:!0}),t.records=t.records.slice(-h),f.writeFileSync(e,JSON.stringify(t,null,2))}function w(e){const t=e.ledger.records.find(s=>s.idempotencyKey===e.idempotencyKey);if(t)return t;const n=(e.now??new Date).toISOString(),o=u(e.text),i={replyId:e.replyId,idempotencyKey:e.idempotencyKey,bindingId:e.bindingId,runtimeId:e.runtimeId,sessionId:e.sessionId,conversationName:e.conversationName,replyBaseRevision:e.replyBaseRevision,text:C(e.text)||void 0,textNormalized:o||void 0,attachmentLocalRefs:e.attachmentLocalRefs??[],createdAt:n,queuedAt:n,sendStatus:"queued",commitStage:"queued",copyableContentRef:`reply:${e.replyId}`,expectedEchoAnchor:o||void 0,observeAttemptsAfterSent:0};return e.ledger.records.push(i),i}function I(e){return e.currentLastInboundRevision<=e.record.replyBaseRevision?{ok:!0}:(e.record.sendStatus="stale",e.record.failureCode="reply_revision_stale",e.record.lastErrorSummary="Inbound revision advanced before reply send",e.record.commitStage=e.record.commitStage??"queued",{ok:!1,reason:"stale"})}function _(e){e.sendStatus="sending",e.failureCode=void 0,e.lastErrorSummary=void 0,e.deferReason=void 0}function T(e,t){e.commitStage=t}function W(e,t=new Date){e.sendStatus="sent_unconfirmed",e.sentAt=t.toISOString(),e.commitStage="sent",e.observeAttemptsAfterSent=0,e.failureCode=void 0,e.lastErrorSummary=void 0,e.deferReason=void 0,e.nextAttemptAt=void 0}function k(e,t,n){e.sendStatus="failed",e.failureCode=t,e.lastErrorSummary=n.slice(0,500)}function M(e,t,n,o){e.sendStatus="manual_review",e.failureCode=t,e.lastErrorSummary=n.slice(0,500),e.nextAttemptAt=void 0,e.deferReason=void 0,o&&(e.commitStage=o)}function N(e,t=new Date){e.sendStatus="failed",e.failureCode="user_active_timeout",e.lastErrorSummary="User stayed active until outbound send wait deadline expired",e.nextAttemptAt=void 0,e.deferReason="user_active_timeout",e.lastAttemptAt=t.toISOString()}function D(e,t="user_cancelled",n=new Date){e.sendStatus==="queued"&&(e.sendStatus="failed",e.failureCode=t,e.lastErrorSummary="Queued outbound send was cancelled",e.cancelledAt=n.toISOString(),e.nextAttemptAt=void 0)}function U(e){const t=e.now??new Date;e.record.sendStatus="queued",e.record.deferReason=e.reasonCode,e.record.nextAttemptAt=e.nextAttemptAt.toISOString(),e.record.lastAttemptAt=t.toISOString(),e.record.attemptCount=(e.record.attemptCount??0)+1,e.record.firstUserActivityBlockedAt??=t.toISOString(),e.record.commitStage??="queued",e.record.failureCode=void 0,e.record.lastErrorSummary=void 0}function F(e){if(e.record.sendStatus!=="queued"||!e.record.firstUserActivityBlockedAt)return!1;const t=new Date(e.record.firstUserActivityBlockedAt).getTime();return Number.isFinite(t)?(e.now??new Date).getTime()-t>=e.maxWaitMs:!1}function q(e){return e.sendStatus==="failed"||e.sendStatus==="manual_review"||e.sendStatus==="confirmed_echo"}function z(e){const t=e.now??new Date,n=[],o=[],i=e.ledger.records.filter(r=>r.bindingId===e.bindingId&&r.sendStatus==="sent_unconfirmed"),s=new Set;for(const r of i){const d=e.messages.findIndex((a,c)=>!s.has(c)&&l(r,a));if(d>=0){s.add(d);const a=e.messages[d];r.sendStatus="confirmed_echo",r.confirmedAt=t.toISOString(),r.commitStage="sent",r.confirmedEchoAnchor=u(a.anchorText||a.normalizedText||a.textExcerpt||"")||void 0,n.push(r)}for(const[a,c]of e.messages.entries())s.has(a)||g(r,c)&&s.add(a);d>=0||(r.observeAttemptsAfterSent=(r.observeAttemptsAfterSent??0)+1,b(r,t)&&(r.sendStatus="manual_review",r.failureCode="echo_confirmation_timeout",r.lastErrorSummary="Sent reply echo was not confirmed after observe threshold",r.commitStage="sent",o.push(r)))}return{remainingMessages:e.messages.filter((r,d)=>!s.has(d)),confirmedRecords:n,manualReviewRecords:o}}function B(e){return e.filter(t=>t.senderRole!=="self")}function l(e,t){if(t.senderRole!=="self")return!1;const n=e.expectedEchoAnchor||e.textNormalized||"",o=u(t.anchorText||t.normalizedText||t.textExcerpt||"");return!n||!o?!1:n===o?!0:Math.min(n.length,o.length)<24?!1:m(n,o)>=.9}function g(e,t){const n=e.expectedEchoAnchor||e.textNormalized||"",o=u(t.anchorText||t.normalizedText||t.textExcerpt||"");if(!n||!o)return!1;if(l(e,t)||m(n,o)>=.9)return!0;const i=n.replace(/\s+/g,""),s=o.replace(/\s+/g,"");return s.length>=y(s)&&i.includes(s)}function y(e){return Array.from(e).filter(n=>new RegExp("\\p{Script=Han}","u").test(n)).length>=3?4:8}function b(e,t){if((e.observeAttemptsAfterSent??0)>=A)return!0;if(!e.sentAt)return!1;const n=new Date(e.sentAt).getTime();return Number.isFinite(n)&&t.getTime()-n>=x}function C(e){return typeof e=="string"?e.replace(/\r\n/g,`
|
|
2
|
+
`).trim():""}export{D as cancelWeChatOutboundRecord,z as classifyWeChatOutboundEchoes,w as enqueueWeChatOutboundReply,I as guardWeChatOutboundRevision,q as isWeChatOutboundTerminalDeliveryStatus,E as loadWeChatChannelOutboundLedger,T as markWeChatOutboundCommitStage,k as markWeChatOutboundFailed,M as markWeChatOutboundManualReview,_ as markWeChatOutboundSending,W as markWeChatOutboundSentUnconfirmed,N as markWeChatOutboundUserActiveTimeout,U as markWeChatOutboundWaitingUserIdle,R as saveWeChatChannelOutboundLedger,F as shouldFailWeChatOutboundForUserActiveTimeout,B as suppressSelfOnlyWeChatMessages};
|