shennian 0.2.115 → 0.2.117
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.
- package/dist/publish-build-manifest.json +48 -48
- package/dist/src/agents/external-channel-instructions.js +5 -5
- package/dist/src/agents/model-registry/discovery.js +2 -2
- package/dist/src/agents/pi-context.d.ts +1 -1
- package/dist/src/agents/pi-context.js +3 -3
- package/dist/src/channels/registry.js +1 -1
- package/dist/src/channels/runtime.d.ts +1 -0
- package/dist/src/channels/runtime.js +3 -3
- package/dist/src/channels/secret-registry.js +1 -1
- package/dist/src/channels/wechat-channel/anchor.js +1 -1
- package/dist/src/channels/wechat-channel/automation-lane.js +2 -2
- package/dist/src/channels/wechat-channel/fingerprint.d.ts +3 -0
- package/dist/src/channels/wechat-channel/fingerprint.js +1 -1
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +1 -1
- package/dist/src/channels/wechat-channel/helper-assets.js +1 -1
- package/dist/src/channels/wechat-channel/helper-client.js +3 -3
- package/dist/src/channels/wechat-channel/ledger.js +2 -1
- package/dist/src/channels/wechat-channel/media-resolver.d.ts +1 -1
- package/dist/src/channels/wechat-channel/media-resolver.js +1 -1
- package/dist/src/channels/wechat-channel/observer.js +6 -6
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +1 -0
- package/dist/src/channels/wechat-channel/outbound-ledger.js +2 -2
- package/dist/src/channels/wechat-channel/outbound-sender.js +1 -1
- package/dist/src/channels/wechat-channel/runner.js +1 -1
- package/dist/src/channels/wechat-channel/scheduler.js +1 -1
- package/dist/src/channels/wechat-rpa.js +3 -3
- package/dist/src/commands/daemon.js +3 -3
- package/dist/src/commands/wechat/direct.js +2 -2
- package/dist/src/commands/wechat/operations.js +3 -3
- package/dist/src/commands/wechat/output.js +3 -3
- package/dist/src/commands/wechat/utils.d.ts +2 -0
- package/dist/src/commands/wechat/utils.js +1 -1
- package/dist/src/config/index.d.ts +1 -1
- package/dist/src/devtools/wechat-channel-action-smoke.d.ts +1 -0
- package/dist/src/devtools/wechat-channel-action-smoke.js +8 -8
- package/dist/src/index.js +2 -2
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{spawn as w}from"node:child_process";import{randomUUID as
|
|
2
|
-
`)}catch(i){throw await this.stop().catch(()=>{}),i}return s}async startDarwinAppSocketFresh(
|
|
3
|
-
`;if(this.socket){this.socket.write(r);return}if(this.child){this.child.stdin.write(r);return}throw new Error("WeChat channel helper is not started")}handleLine(
|
|
1
|
+
import{spawn as w}from"node:child_process";import{randomUUID as x}from"node:crypto";import f from"node:fs";import D from"node:net";import H from"node:os";import d from"node:path";import{createInterface as g}from"node:readline";import{decideWeChatChannelActivityGate as S,normalizeWeChatChannelActivitySnapshot as k}from"./human-coordination.js";import{createWeChatChannelHelperHello as E,extractWeChatChannelHelperWarmupSnapshot as q,timeoutForWeChatChannelHelperCommand as O,validateWeChatChannelHelperReady as C}from"./helper-protocol.js";const F=["en","v"].join(""),m=1500,N=1500,_=8e3,G="SHENNIAN_WECHAT_DANGEROUS_GUARD_THROTTLE_MS";function L(){const t=process.env[G];if(t===void 0||t==="")return _;const e=Number.parseInt(t,10);return!Number.isFinite(e)||e<0?_:e}class me{options;child=null;socket=null;lines=null;readyState=null;warmupState=null;stderrTail="";startPromise=null;requestQueueTail=Promise.resolve();lastGuardPassAtMs=0;pending=new Map;constructor(e){this.options=e}async start(){return this.hasTransport()&&this.readyState?this.readyState:this.startPromise?this.startPromise:(this.hasTransport()&&await this.stop(),this.startPromise=this.startFresh().catch(async e=>{throw await this.stop().catch(()=>{}),e}).finally(()=>{this.startPromise=null}),this.startPromise)}async startFresh(){const e=B(this.options.helperPath,this.options.args??[]);return e.transport==="macos-socket"?this.startDarwinAppSocketFresh(e):this.startStdioFresh(e)}async startStdioFresh(e){const r=w(e.command,e.args,{cwd:this.options.cwd,stdio:["pipe","pipe","pipe"],windowsHide:!0});this.child=r,this.stderrTail="",this.lines=g({input:r.stdout}),this.lines.on("line",i=>this.handleLine(i)),r.stderr.on("data",i=>{this.captureStderr(i)}),r.stdin.on("error",i=>{this.rejectAllPending(i instanceof Error?i:new Error(String(i)))}),r.once("error",i=>{this.child===r&&(this.child=null,this.readyState=null,this.lines?.close(),this.lines=null),this.rejectAllPending(i instanceof Error?i:new Error(String(i)))}),r.once("exit",(i,n)=>{this.child===r&&(this.child=null,this.readyState=null,this.lines?.close(),this.lines=null),this.rejectAllPending(new Error(this.formatHelperExitMessage(i,n)))});const s=new Promise((i,n)=>{const a=setTimeout(()=>n(new Error("WeChat channel helper handshake timed out")),1e4),l=h=>{clearTimeout(a),this.lines?.off("line",c),r.off("exit",o),n(new Error(`WeChat channel helper failed to start: ${h.message}`))},o=(h,u)=>{clearTimeout(a),r.off("error",l),this.lines?.off("line",c),n(new Error(this.formatHelperExitMessage(h,u)))},c=h=>{let u;try{u=JSON.parse(h)}catch{clearTimeout(a),r.off("error",l),this.lines?.off("line",c),n(new Error("WeChat channel helper sent invalid handshake JSON"));return}if(!A(u))return;clearTimeout(a),r.off("error",l),r.off("exit",o),this.lines?.off("line",c);const p=C(u,this.options.expectedHelperVersion,this.options.requiredCapabilities);p.ok?(this.readyState=u,this.captureWarmupSnapshot(u),i(u)):n(new Error(`${p.errorCode}: ${p.errorSummary}`))};r.once("error",l),r.once("exit",o),this.lines?.on("line",c)});try{r.stdin.write(`${JSON.stringify(E(this.options.expectedHelperVersion,this.options.requiredCapabilities))}
|
|
2
|
+
`)}catch(i){throw await this.stop().catch(()=>{}),i}return s}async startDarwinAppSocketFresh(e){const r=await this.connectDarwinHelperSocket(e);this.socket=r,this.stderrTail="",this.lines=g({input:r}),this.lines.on("line",i=>this.handleLine(i)),r.on("error",i=>{this.socket===r&&(this.socket=null,this.readyState=null,this.lines?.close(),this.lines=null),this.rejectAllPending(i instanceof Error?i:new Error(String(i)))}),r.once("close",()=>{this.socket===r&&(this.socket=null,this.readyState=null,this.lines?.close(),this.lines=null),this.rejectAllPending(new Error("WeChat channel helper socket closed"))});const s=new Promise((i,n)=>{const a=setTimeout(()=>n(new Error("WeChat channel helper socket handshake timed out")),1e4),l=h=>{clearTimeout(a),this.lines?.off("line",c),r.off("close",o),n(new Error(`WeChat channel helper socket failed: ${h.message}`))},o=()=>{clearTimeout(a),r.off("error",l),this.lines?.off("line",c),n(new Error("WeChat channel helper socket closed before handshake"))},c=h=>{let u;try{u=JSON.parse(h)}catch{clearTimeout(a),r.off("error",l),r.off("close",o),this.lines?.off("line",c),n(new Error("WeChat channel helper sent invalid socket handshake JSON"));return}if(!A(u))return;clearTimeout(a),r.off("error",l),r.off("close",o),this.lines?.off("line",c);const p=C(u,this.options.expectedHelperVersion,this.options.requiredCapabilities);p.ok?(this.readyState=u,this.captureWarmupSnapshot(u),i(u)):n(new Error(`${p.errorCode}: ${p.errorSummary}`))};r.once("error",l),r.once("close",o),this.lines?.on("line",c)});try{this.writeFrame(E(this.options.expectedHelperVersion,this.options.requiredCapabilities))}catch(i){throw await this.stop().catch(()=>{}),i}return s}async request(e,r,s){const i=this.requestQueueTail.catch(()=>{}).then(()=>this.sendRequest(e,r,s));return this.requestQueueTail=i.then(()=>{},()=>{}),i}async sendRequest(e,r,s){await this.guardUnsafeWindowsCommand(e,s);try{return await this.sendRawRequest(e,r,s)}finally{await this.cleanupWindowsOverlaysAfterCommand(e,s).catch(()=>{})}}async sendRawRequest(e,r,s){if((!this.hasTransport()||!this.readyState)&&await this.start(),!this.hasTransport())throw new Error("WeChat channel helper is not started");const i=x(),n=O(e),a=Date.now();this.emitRequestTrace({phase:"request",at:new Date(a).toISOString(),id:i,command:e,traceId:s,params:r,timeoutMs:n});const l=new Promise((o,c)=>{const h=setTimeout(()=>{this.pending.get(i)&&(this.pending.delete(i),this.stopAfterCommandTimeout(e).finally(()=>{c(new Error(`helper_command_timeout: ${e}`))}))},n);this.pending.set(i,{resolve:o,reject:c,timer:h})});try{this.writeFrame({id:i,command:e,params:r,traceId:s})}catch(o){const c=this.pending.get(i);throw c&&clearTimeout(c.timer),this.pending.delete(i),this.emitRequestTrace({phase:"error",at:new Date().toISOString(),id:i,command:e,traceId:s,durationMs:Date.now()-a,errorSummary:o instanceof Error?o.message:String(o)}),o}try{const o=await l;return this.emitRequestTrace({phase:"response",at:new Date().toISOString(),id:i,command:e,traceId:s,durationMs:Date.now()-a,ok:o.ok,errorCode:o.errorCode,errorSummary:o.errorSummary,latencyMs:o.latencyMs,result:o.result}),this.captureWarmupSnapshot(o),this.captureWarmupSnapshot(o.result),o}catch(o){throw this.emitRequestTrace({phase:"error",at:new Date().toISOString(),id:i,command:e,traceId:s,durationMs:Date.now()-a,errorSummary:o instanceof Error?o.message:String(o)}),o}}async guardUnsafeWindowsCommand(e,r){if(!this.options.guardUnsafeWindowsCommands||!ne(e))return;const s=L(),i=M(e)?Math.max(N,s):s;if(i>0&&this.lastGuardPassAtMs>0&&Date.now()-this.lastGuardPassAtMs<i){if(!M(e)){if(!this.options.skipUserActivityGuard&&$(e)){const o=await this.sendRawRequest("activity.snapshot",{},r);if(!o.ok)throw new Error(`${o.errorCode??"user_activity_unknown"}: ${o.errorSummary??e}`);const c=S({snapshot:k(o.result),stage:"dangerous_action"});if(!c.ok)throw new Error(`user_active:${c.reasonCode}`)}await this.cleanupWindowsOverlays("before",e,r)}return}let n=await this.sendRawRequest("permissions.check",{},r);if(!n.ok)throw new Error(`${n.errorCode??"permissions_check_failed"}: ${n.errorSummary??e}`);let a=n.result??{};if(a.wechatRunning!==!1&&I(a)&&await this.tryRecoverFromStuckShell(r)){if(n=await this.sendRawRequest("permissions.check",{},r),!n.ok)throw new Error(`${n.errorCode??"permissions_check_failed"}: ${n.errorSummary??e}`);a=n.result??{}}const l=await this.requestFirstMissingMacPermissionPrompt(a,r);if(l==="screen-recording")throw new Error("permission_screen_recording_missing");if(l==="accessibility")throw new Error("permission_accessibility_missing");if(l==="input-monitoring")throw new Error("permission_input_monitoring_missing");if(a.automation===!1)throw new Error("permission_automation_missing");if(a.wechatRunning===!1)throw new Error("wechat_not_running");if(V(a))throw new Error("wechat_login_required");if(J(a))throw new Error("windows_visible_desktop_unavailable");if(a.dpiMappingAvailable===!1||a.displayTopologySupported===!1)throw new Error("dpi_mapping_failed");if(a.wechatWindowAvailable===!1)throw new Error("wechat_window_unavailable");if(a.wechatMainWindowResponsive===!1)throw new Error("wechat_window_unresponsive");if(!this.options.skipUserActivityGuard&&$(e)){const o=await this.sendRawRequest("activity.snapshot",{},r);if(!o.ok)throw new Error(`${o.errorCode??"user_activity_unknown"}: ${o.errorSummary??e}`);const c=S({snapshot:k(o.result),stage:"dangerous_action"});if(!c.ok)throw new Error(`user_active:${c.reasonCode}`)}await this.cleanupWindowsOverlays("before",e,r),this.lastGuardPassAtMs=Date.now()}async tryRecoverFromStuckShell(e){try{const r=await this.sendRawRequest("wechat.healthProbe",{},e);if(!r.ok||r.result?.stuckShell!==!0)return!1;const s=await this.sendRawRequest("windows.recoverWeChat",{allowRestart:!0,onlyIfUnresponsive:!1,waitAfterStartMs:4e3},e);return s.ok===!0&&s.result?.started===!0}catch{return!1}}async requestFirstMissingMacPermissionPrompt(e,r){const s=re(e);if(!s||process.platform!=="darwin")return s;const i=ie(s);try{await this.sendRawRequest(i,{},r)}catch{}return s}async cleanupWindowsOverlaysAfterCommand(e,r){!this.options.guardUnsafeWindowsCommands||!oe(e)||await this.cleanupWindowsOverlays("after",e,r)}async cleanupWindowsOverlays(e,r,s){if(this.options.cleanupWindowsOverlays===!1)return;if(!this.readyState?.capabilities.includes("overlayCleanup"))throw new Error("helper_capability_missing: overlayCleanup");const i=await this.sendRawRequest("windows.cleanupOverlays",{stage:e,command:r,includeGeneratedMediaPreviews:!0,includeToolingTerminals:!1,waitMs:e==="after"?220:120},s);if(!i.ok)throw new Error(`${i.errorCode??"overlay_cleanup_failed"}: ${i.errorSummary??r}`)}async healthCheck(e){return this.request("health.check",{},e)}getReadyState(){return this.readyState?{...this.readyState,capabilities:[...this.readyState.capabilities]}:null}getWarmupState(){return this.warmupState?{warmState:this.warmupState.warmState,metrics:this.warmupState.metrics?{...this.warmupState.metrics}:void 0}:null}async stop(){const e=this.child,r=this.socket;this.child=null,this.socket=null,this.readyState=null,this.lines?.close(),this.lines=null,this.rejectAllPending(new Error("WeChat channel helper stopped")),r&&!r.destroyed&&r.destroy(),e&&await Y(e)}hasTransport(){return!!this.child||!!this.socket}writeFrame(e){const r=`${JSON.stringify(e)}
|
|
3
|
+
`;if(this.socket){this.socket.write(r);return}if(this.child){this.child.stdin.write(r);return}throw new Error("WeChat channel helper is not started")}handleLine(e){let r;try{r=JSON.parse(e)}catch{return}if(!se(r))return;const s=this.pending.get(r.id);s&&(clearTimeout(s.timer),this.pending.delete(r.id),s.resolve(r))}captureWarmupSnapshot(e){const r=q(e);r&&(this.warmupState=r)}captureStderr(e){const r=Buffer.isBuffer(e)?e.toString("utf8"):String(e??"");r&&(this.stderrTail=(this.stderrTail+r).slice(-2e3))}formatHelperExitMessage(e,r){const s=[e===null?null:`code=${e}`,r?`signal=${r}`:null,this.stderrTail.trim()?`stderr=${this.stderrTail.trim()}`:null].filter(Boolean);return s.length?`WeChat channel helper process exited (${s.join(", ")})`:"WeChat channel helper process exited"}rejectAllPending(e){for(const[r,s]of this.pending)clearTimeout(s.timer),s.reject(e),this.pending.delete(r)}emitRequestTrace(e){try{this.options.requestLogger?.(e)}catch{}}async stopAfterCommandTimeout(e){const r=this.child?.pid;if(await this.stop().catch(()=>{}),process.platform==="win32"){const s=typeof r=="number"&&r>0?[r]:[];await U(s).catch(()=>{})}this.emitRequestTrace({phase:"error",at:new Date().toISOString(),id:`timeout-cleanup:${e}`,command:e,errorSummary:"helper process stopped after command timeout"})}async connectDarwinHelperSocket(e){try{return await b(e.runtimeFile)}catch{f.rmSync(e.runtimeFile,{force:!0})}await W(e,{},this.options.openHelperAppForTest);const r=await P(e.runtimeFile,this.options.macosRuntimeInitialReadyTimeoutMs??5e3);if(r.ok)return r.socket;f.rmSync(e.runtimeFile,{force:!0}),await W(e,{forceNewInstance:!0},this.options.openHelperAppForTest);const s=await P(e.runtimeFile,this.options.macosRuntimeRelaunchReadyTimeoutMs??1e4);if(s.ok)return s.socket;throw new Error(`WeChat channel Helper.app socket did not become ready: ${s.error.message}`)}}async function U(t=[]){if(process.platform!=="win32")return;const e=t.filter(r=>Number.isInteger(r)&&r>0);if(e.length!==0)for(const r of e)await R(["taskkill","/PID",String(r),"/T","/F"],[0,128])}function I(t){return t.wechatWindowAvailable===!1&&(t.captureCandidateCount??0)===0&&(t.restoreCandidateCount??0)===0&&(t.hiddenRestoreCandidateCount??0)===0}function V(t){return t.wechatWindowAvailable!==!1?!1:![...t.captureCandidates??[],...t.restoreCandidates??[],...t.hiddenRestoreCandidates??[]].some(j)}function J(t){return t.windowsVisibleDesktopAvailable===!1||t.rdpVisibleDesktopAvailable===!1||t.desktopSessionVisible===!1||t.screenLocked===!0||t.rdpDisconnected===!0}function z(t){const e=String(t.appName||"").toLowerCase();return e==="wechat"||e==="weixin"}function j(t){return!(!z(t)||t.visible===!1||t.minimized===!0)}function B(t,e,r=process.platform){if(r==="darwin"){const s=Q(t);if(s&&e.length===0){const i=K();return{transport:"macos-socket",command:"/usr/bin/open",args:["-g",s,"--args","--socket-runtime",i],appPath:s,runtimeDir:i,runtimeFile:d.join(i,"runtime.json")}}}return{transport:"legacy-stdio",command:t,args:e}}function Q(t){const e=d.resolve(t),r=`${d.sep}Contents${d.sep}MacOS${d.sep}`,s=e.lastIndexOf(r);if(s<0)return null;const i=e.slice(0,s);return i.endsWith(".app")?i:null}function K(){const t=X().SHENNIAN_HELPER_RUNTIME_DIR?.trim();return t?d.resolve(t):d.join(H.homedir(),"Library","Application Support","Shennian","Helper")}async function Y(t){if(T(t))return;if(process.platform==="win32"&&t.pid){t.kill("SIGTERM"),await R(["taskkill","/PID",String(t.pid),"/T","/F"],[0,128]).catch(()=>{}),await y(t,m);return}t.kill("SIGTERM"),!await y(t,m)&&t.pid&&v(t.pid)&&(t.kill("SIGKILL"),await y(t,m))}function T(t){return t.exitCode!==null||t.signalCode!==null}function y(t,e){return T(t)?Promise.resolve(!0):new Promise(r=>{const s=setTimeout(()=>{t.off("exit",i),r(!1)},e),i=()=>{clearTimeout(s),r(!0)};t.once("exit",i)})}function R(t,e){return new Promise((r,s)=>{const[i,...n]=t,a=w(i,n,{stdio:"ignore",windowsHide:!0});a.once("error",s),a.once("exit",l=>{l!==null&&e.includes(l)?r():s(new Error(`${i} exited ${l}`))})})}function X(){return globalThis.process?.[F]??{}}function Z(t){let e;try{e=JSON.parse(f.readFileSync(t,"utf8"))}catch(i){throw new Error(`runtime_file_unreadable: ${i instanceof Error?i.message:String(i)}`)}if(!e||typeof e!="object")throw new Error("runtime_file_invalid");const r=e.socketPath;if(typeof r!="string"||!r.trim())throw new Error("runtime_socket_missing");const s=e.pid;return{socketPath:r,...typeof s=="number"&&Number.isInteger(s)&&s>0?{pid:s}:{}}}async function b(t){const{socketPath:e,pid:r}=Z(t);if(r&&!v(r))throw new Error(`runtime_process_stale: ${r}`);return new Promise((s,i)=>{const n=D.createConnection(e),a=setTimeout(()=>{n.destroy(),i(new Error(`runtime_socket_connect_timeout: ${e}`))},1e3);n.once("connect",()=>{clearTimeout(a),n.off("error",l),s(n)});const l=o=>{clearTimeout(a),n.destroy(),i(o)};n.once("error",l)})}async function P(t,e){const r=Date.now()+e;let s=null;for(;Date.now()<r;)try{return{ok:!0,socket:await b(t)}}catch(i){s=i instanceof Error?i:new Error(String(i));const n=r-Date.now();n>0&&await te(Math.min(150,n))}return{ok:!1,error:s??new Error("runtime file missing")}}async function W(t,e={},r=ee){f.mkdirSync(t.runtimeDir,{recursive:!0,mode:448});const s=e.forceNewInstance?["-n",...t.args]:t.args;try{await r(t.command,s)}catch(i){if(!(i instanceof Error?i.message:String(i)).includes("-1712"))throw i;await r(t.command,["-n",...t.args])}}function v(t){try{return process.kill(t,0),!0}catch{return!1}}async function ee(t,e){await new Promise((r,s)=>{const i=w(t,e,{stdio:["ignore","ignore","pipe"],windowsHide:!0});let n="";i.stderr.on("data",a=>{n=(n+String(a)).slice(-2e3)}),i.once("error",s),i.once("exit",(a,l)=>{a===0?r():s(new Error(`open Helper.app failed (${l?`signal=${l}`:`code=${a}`}${n.trim()?`, stderr=${n.trim()}`:""})`))})})}function te(t){return new Promise(e=>setTimeout(e,t))}function re(t){return t.screenRecording===!1?"screen-recording":t.accessibility===!1?"accessibility":t.inputMonitoring===!1?"input-monitoring":null}function ie(t){return t==="screen-recording"?"permissions.requestScreenRecording":t==="accessibility"?"permissions.requestAccessibility":"permissions.requestInputMonitoring"}function A(t){if(!t||typeof t!="object")return!1;const e=t;return e.type==="ready"&&typeof e.helperVersion=="string"&&typeof e.protocolVersion=="number"&&Array.isArray(e.capabilities)&&typeof e.pid=="number"}function se(t){if(!t||typeof t!="object")return!1;const e=t;return typeof e.id=="string"&&typeof e.ok=="boolean"&&typeof e.latencyMs=="number"}function ne(t){return t==="windows.focus"||t==="windows.capture"||t==="screen.capture"||t==="ocr.recognize"||t==="image.cropHash"||t==="wechat.searchConversation"||t==="wechat.focusMessageInput"||t==="wechat.pasteAndSubmit"||t==="keyboard.primeTextPaste"||t.startsWith("mouse.")||t.startsWith("keyboard.")||t.startsWith("clipboard.")||t==="menu.pickItem"||t==="savePanel.saveToPath"}function M(t){return t==="windows.capture"||t==="screen.capture"||t==="ocr.recognize"||t==="image.cropHash"}function oe(t){return t.startsWith("mouse.")||t.startsWith("keyboard.")||t.startsWith("clipboard.")||t==="menu.pickItem"||t==="savePanel.saveToPath"}function $(t){return t==="windows.focus"||t==="wechat.searchConversation"||t==="wechat.focusMessageInput"||t==="wechat.pasteAndSubmit"||t==="keyboard.primeTextPaste"||t.startsWith("mouse.")||t.startsWith("keyboard.")||t.startsWith("clipboard.set")||t==="clipboard.restore"||t==="menu.pickItem"||t==="savePanel.saveToPath"}export{me as WeChatChannelHelperClient,B as helperLaunchSpec,U as stopWindowsWeChatChannelHelperProcesses};
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import y from"node:fs";import m from"node:path";import{WECHAT_CHANNEL_RECENT_MESSAGE_WINDOW as R}from"./runtime.js";import{filterNewWeChatMessagesByAnchor as C,isLikelySameWeChatMessage as p}from"./anchor.js";import{normalizeWeChatObservedWindowForLedger as B}from"./message-key.js";function J(e,t){try{const n=JSON.parse(y.readFileSync(e,"utf8"));if(n?.version===1&&n.runtimeId===t&&n.bindings&&typeof n.bindings=="object")return n}catch{}return{version:1,runtimeId:t,bindings:{}}}function $(e,t){y.mkdirSync(m.dirname(e),{recursive:!0}),y.writeFileSync(e,JSON.stringify(t,null,2))}function G(e){const t=e.ledger.bindings[e.bindingId],n=B(e.observedMessages).map(E),r=L(t?.recent??[],n).slice(-R),s=e.baselineOnly||!t?.baselineEstablished||!!t?.disabledSince?[]:x(t?.recent??[],r),l={bindingId:e.bindingId,baselineEstablished:!0,disabledSince:null,revision:(t?.revision??0)+(s.length>0?1:0),recent:r,pendingSendKeys:t?.pendingSendKeys??[],attachmentStates:W(r,t?.attachmentStates),vectorReferences:I(r,t?.vectorReferences,e.vectorReferences),cooldown:t?.cooldown};return e.ledger.bindings[e.bindingId]=l,{binding:l,newMessages:s}}function E(e){return Array.isArray(e.visualBlocks)?{...e,visualBlocks:e.visualBlocks.map(t=>{const{vectorBase64:n,...r}=t;return r})}:e}function U(e){const t=e.ledger.bindings[e.bindingId],n={bindingId:e.bindingId,baselineEstablished:!1,disabledSince:(e.disabledAt??new Date).toISOString(),revision:t?.revision??0,recent:t?.recent??[],pendingSendKeys:t?.pendingSendKeys??[],attachmentStates:t?.attachmentStates,vectorReferences:t?.vectorReferences,cooldown:t?.cooldown};return e.ledger.bindings[e.bindingId]=n,n}function I(e,t,n){const r=new Map;for(const s of n??[]){const l=o(s.stableMessageKey);if(!l)continue;const c=r.get(l)??[];c.push(s),r.set(l,c)}const i={};for(const s of e){const l=r.get(s.stableMessageKey)??N(s)??t?.[s.stableMessageKey];l?.length&&(i[s.stableMessageKey]=l)}return Object.keys(i).length?i:void 0}function N(e){const n=(Array.isArray(e.visualBlocks)?e.visualBlocks:[]).flatMap(r=>{const i=o(r.vectorStoreKey),s=o(r.blockId),l=o(r.blockKind)||"visual",c=o(r.modelVersion)||o(r.model)||"server-visual-embedding",u=Number(r.dims);return!i||!s||!Number.isFinite(u)||u<1?[]:[{stableMessageKey:e.stableMessageKey,blockId:s,blockKind:l,vectorStoreKey:i,model:c,...r.modelVersion!==void 0?{modelVersion:r.modelVersion}:{},dims:Math.round(u),...o(r.signature)?{signature:o(r.signature)}:{},...r.bbox!==void 0?{bbox:r.bbox}:{},observedAt:e.observedAt||new Date(0).toISOString()}]});return n.length?n:void 0}function x(e,t){const n=C({previous:e,current:t}),r=new Set(n.map(a=>a.stableMessageKey)),i=new Set(t.map(a=>a.stableMessageKey)),s=[],l=t.filter(a=>{if(r.has(a.stableMessageKey))return!0;const S=e.find(g=>g.stableMessageKey===a.stableMessageKey)??e.find(g=>!i.has(g.stableMessageKey)&&p(g,a));return S?T(S,a):!1}),c=new Set(l.map(a=>a.stableMessageKey)),u=l.filter(a=>!(a.senderRole==="self"||a.isBaseline===!0||v(a.deliveryStatus)||b(a)&&!d(a))),w=new Set(u.map(a=>a.stableMessageKey));for(const a of t)s.push({stableMessageKey:a.stableMessageKey,kind:a.kind||null,senderRole:a.senderRole||null,anchorText:(a.anchorText||a.normalizedText||a.textExcerpt||"").slice(0,40),isNewByAnchor:r.has(a.stableMessageKey),isCandidate:c.has(a.stableMessageKey),delivered:w.has(a.stableMessageKey),isBaseline:a.isBaseline===!0,deliveryStatus:a.deliveryStatus??null,hasAttachmentCandidate:b(a),hasAgentReadableAttachment:d(a),dropReason:O(a,c.has(a.stableMessageKey))});return P(s),u}function O(e,t){return t?e.senderRole==="self"?"sender-self":e.isBaseline===!0?"baseline":v(e.deliveryStatus)?`status:${M(e.deliveryStatus)}`:b(e)&&!d(e)?"attachment-not-readable":null:"not-new-and-no-media-upgrade"}function P(e){const t=process.env.SHENNIAN_WECHAT_DELIVERABILITY_TRACE;if(t)try{const n=JSON.stringify({at:new Date().toISOString(),messages:e})+`
|
|
2
|
+
`;t==="1"||t==="stderr"?process.stderr.write(`[wechat-deliverability] ${n}`):(y.mkdirSync(m.dirname(t),{recursive:!0}),y.appendFileSync(t,n))}catch{}}function W(e,t){const n={};for(const r of e){const i=k(r),s=t?.[r.stableMessageKey];if(!i&&s){n[r.stableMessageKey]=s;continue}i&&(n[r.stableMessageKey]=D(s,i))}return Object.keys(n).length?n:void 0}function k(e){const t=h(e.mediaMetadata);if(!t.length&&!b(e)&&!v(e.deliveryStatus))return null;const n=A(e.mediaMetadata)??t[0]??{},r=M(e.deliveryStatus),i=o(n.availability)||o(e.mediaMetadata?.availability)||(r==="needs-review"?"needs-review":"metadata-only");return{stableMessageKey:e.stableMessageKey,kind:e.kind||o(n.type)||"unknown",availability:i,...r?{deliveryStatus:r}:{},...o(n.localPath)?{localPath:o(n.localPath)}:{},...o(n.url)?{url:o(n.url)}:{},...o(n.name)||o(n.fileName)?{name:o(n.name)||o(n.fileName)}:{},...o(n.providerError)?{providerError:o(n.providerError)}:{},...o(n.reasonCode)||o(e.mediaMetadata?.edgeResolveReasonCode)?{reasonCode:o(n.reasonCode)||o(e.mediaMetadata?.edgeResolveReasonCode)}:{}}}function D(e,t){return!e||K(t)?t:K(e)?e:t}function K(e){return e.availability==="edge-local"&&!!e.localPath||e.availability==="server-url"&&!!e.url}function v(e){const t=M(e);return t==="suppressed"||t==="pending"||t==="needs-review"||t==="manual-review"}function L(e,t){const n=new Set(t.map(r=>r.stableMessageKey));return t.map(r=>{if(d(r))return r;const i=e.find(s=>s.stableMessageKey===r.stableMessageKey&&d(s))??e.find(s=>!n.has(s.stableMessageKey)&&p(s,r)&&d(s));return i?{...r,mediaMetadata:V(r.mediaMetadata,i.mediaMetadata)}:r})}function T(e,t){return b(e)&&!d(e)&&d(t)}function b(e){return h(e.mediaMetadata).length>0||/image|photo|video|file|document/i.test(e.kind||"")}function d(e){return h(e.mediaMetadata).some(t=>{const n=typeof t.localPath=="string"?t.localPath.trim():"",r=typeof t.url=="string"?t.url.trim():"",i=typeof t.availability=="string"?t.availability:"";return i==="edge-local"&&!!n||i==="server-url"&&!!r})}function V(e,t){const n=f(e)?{...e}:{},r=f(t)?t:{},i=A(r);return i?{...n,availability:i.availability,mediaStatus:"downloaded",attachment:{...f(n.attachment)?n.attachment:{},...i}}:e}function A(e){return h(e).find(t=>{const n=typeof t.availability=="string"?t.availability:"",r=typeof t.localPath=="string"?t.localPath.trim():"",i=typeof t.url=="string"?t.url.trim():"";return n==="edge-local"&&!!r||n==="server-url"&&!!i})??null}function h(e){return f(e)?Array.isArray(e.attachments)?e.attachments.filter(f):f(e.attachment)?[e.attachment]:e.localPath||e.url||e.name||e.fileName||e.availability?[e]:[]:[]}function f(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function M(e){return String(e??"").trim().toLowerCase().replace(/_/g,"-")}function o(e){return typeof e=="string"?e.trim():""}export{x as filterDeliverableWeChatMessages,J as loadWeChatChannelLedger,U as markWeChatChannelBindingDisabled,$ as saveWeChatChannelLedger,G as updateWeChatChannelBindingLedger};
|
|
@@ -28,7 +28,7 @@ export type WeChatChannelVisibleMediaCandidate = {
|
|
|
28
28
|
fileName?: string | null;
|
|
29
29
|
mimeType?: string | null;
|
|
30
30
|
size?: number | null;
|
|
31
|
-
mediaStatus?: 'available' | 'not_downloaded' | 'metadata_only' | 'unsupported' | string | null;
|
|
31
|
+
mediaStatus?: 'available' | 'not_downloaded' | 'loading' | 'metadata_only' | 'unsupported' | string | null;
|
|
32
32
|
observedAt?: string | null;
|
|
33
33
|
contextText?: string | null;
|
|
34
34
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import B from"node:crypto";import g from"node:fs";import f from"node:path";import{resolveShennianPath as G}from"../../config/index.js";import{buildWeChatChannelMediaActionPlan as J}from"./core/media-action-plan.js";import{normalizeWeChatChannelMessageKind as F}from"./core/schema.js";import{findCachedWeChatInboundMedia as Z}from"./media-cache-resolver.js";const L=20*1024*1024,R=["\u5F15\u7528","\u5220\u9664","\u591A\u9009","\u8F6C\u53D1","\u6536\u85CF","\u63D0\u9192","\u7F16\u8F91","\u4FDD\u5B58","\u53E6\u5B58\u4E3A","\u6253\u5F00\u65B9\u5F0F","Quote","Delete","Forward","Favorite","Save","Save As","Save to Downloads","Open With"];function Pe(e,t,o){const n=B.createHash("sha256").update(`${t}:${o}`).digest("hex").slice(0,16);return G("wechat-rpa","attachments","inbound",n)}async function Fe(e){const t=[];for(const o of e.candidates)try{const n=q(o),a=$(o,n);if(!n.actions.length){t.push(y(o,n.reasonCode,a));continue}const r=await _(e,"before-media-action",o);if(S(a,"before-media-action",r),!r.ok){t.push(y(o,r.reasonCode,a));continue}const i=[],c=await O({helper:e.helper,candidate:o,actionPlan:n,resolveTrace:a,attachmentsDir:e.attachmentsDir,windowId:e.windowId,window:e.window,menuSearchBounds:K(o,e.window),traceId:e.traceId});if(c.attachment){t.push(await T(e,{messageKey:o.messageKey,attachment:c.attachment,reasonCode:"edge_local",resolveTrace:a},o,a));continue}i.push(...[c.reasonCode].filter(m=>!!m));const s=me({candidate:o,attachmentsDir:e.attachmentsDir,resolveTrace:a,platform:e.platform,cacheRoots:e.wechatCacheRoots});if(s.attachment){t.push(await T(e,{messageKey:o.messageKey,attachment:s.attachment,reasonCode:s.reasonCode||"edge_local_from_wechat_cache",resolveTrace:a},o,a,i));continue}if(s.reasonCode&&i.push(s.reasonCode),ee(o)){const m=await _(e,"before-media-action",o);if(S(a,"before-media-action",m),!m.ok){t.push({...y(o,m.reasonCode,a),attemptReasonCodes:b([...i,c.reasonCode,m.reasonCode])});continue}const d=await te({helper:e.helper,candidate:o,resolveTrace:a,windowId:e.windowId,traceId:e.traceId});if(d.ok){const l=await _(e,"before-media-action",o);if(S(a,"before-media-action",l),!l.ok){t.push({...y(o,l.reasonCode,a),attemptReasonCodes:b([...i,c.reasonCode,l.reasonCode])});continue}await x(800);const u=await O({helper:e.helper,candidate:{...o,mediaStatus:"available"},actionPlan:n,resolveTrace:a,retry:!0,attachmentsDir:e.attachmentsDir,windowId:e.windowId,window:e.window,menuSearchBounds:K(o,e.window),traceId:e.traceId});if(u.attachment){t.push(await T(e,{messageKey:o.messageKey,attachment:u.attachment,reasonCode:"edge_local_after_download",resolveTrace:a},o,a,[...i,c.reasonCode,d.reasonCode,u.reasonCode].filter(w=>!!w)));continue}i.push(...[d.reasonCode,u.reasonCode].filter(w=>!!w))}else d.reasonCode&&i.push(d.reasonCode)}t.push({...y(o,ue([...i,c.reasonCode])||"clipboard_attachment_unavailable",a),...i.length?{attemptReasonCodes:b(i)}:{}})}catch(n){t.push(y(o,k(n),$(o,q(o))))}return t}function ee(e){if(h(e.kind)!=="video"||!e.downloadActionBbox)return!1;const t=String(e.mediaStatus||"").trim().toLowerCase().replace(/-/g,"_");return t==="not_downloaded"||t==="pending_download"}async function te(e){const t=e.candidate.downloadActionBbox;if(!t)return{ok:!1,reasonCode:"download_action_bbox_missing"};const o={x:t.x+t.width/2,y:t.y+t.height/2,coordinateSpace:t.coordinateSpace},n=await e.helper.request("mouse.click",{x:o.x,y:o.y,coordinateSpace:o.coordinateSpace,windowId:e.windowId},e.traceId),a=n.ok===!0,r=a?"clicked_video_download_affordance":n.errorCode||"download_action_click_failed";return e.resolveTrace&&p(e.resolveTrace,{phase:"download-action",ok:a,reasonCode:a?void 0:r,downloadPoint:o}),{ok:a,reasonCode:r}}async function _(e,t,o){if(!e.stabilityCheck)return{ok:!0};const n=t==="after-media-action"?2:1;for(let a=0;a<n;a+=1)try{const r=await e.stabilityCheck({stage:t,candidate:o});if(r.ok)return r;if(r.reasonCode==="conversation_title_not_confirmed"&&a+1<n){await x(350);continue}return{ok:!1,reasonCode:r.reasonCode||"media_window_unstable"}}catch(r){const i=k(r);if(i==="conversation_title_not_confirmed"&&a+1<n){await x(350);continue}return{ok:!1,reasonCode:i}}return{ok:!1,reasonCode:"media_window_unstable"}}async function T(e,t,o,n,a=[]){const r=await _(e,"after-media-action",o);return n&&S(n,"after-media-action",r),r.ok?(n&&(n.finalReasonCode=t.reasonCode,n.attachmentValidation=z(t.attachment)),a.length?{...t,attemptReasonCodes:b(a),...n?{resolveTrace:n}:{}}:{...t,...n?{resolveTrace:n}:{}}):{...y(o,r.reasonCode,n),attemptReasonCodes:b([...a,t.reasonCode,r.reasonCode])}}async function O(e){let t=null;try{t=await e.helper.request("clipboard.snapshot",{},e.traceId),Me(t,"clipboard.snapshot");const o=v(t.result,"changeCount"),n=W(e.actionPlan,"right-click-media",e.retry?1:0)?.target??e.candidate.bbox;if(!n)return{attachment:null,reasonCode:"media_bbox_missing"};const a=ke(e.candidate,ge(e.actionPlan,e.retry)),r=Se(e.candidate,n,!!e.window?.bounds);let i;for(const[c,s]of r.entries()){c>0&&await oe(e.helper,e.traceId),e.resolveTrace&&p(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:c+1,pointRole:s.role,rightClickPoint:s,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],clipboardChangeCountBefore:o});const m=await e.helper.request("mouse.rightClick",{x:s.x,y:s.y,coordinateSpace:s.coordinateSpace,windowId:e.windowId},e.traceId);if(!m.ok){i=m.errorCode||"media_right_click_failed",e.resolveTrace&&p(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:c+1,pointRole:s.role,rightClickPoint:s,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],clipboardChangeCountBefore:o,ok:!1,reasonCode:i});continue}await x(180);const d=await ne({helper:e.helper,labels:a,point:s,windowId:e.windowId,window:e.window,menuSearchBounds:e.menuSearchBounds,traceId:e.traceId});if(e.resolveTrace&&p(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:c+1,pointRole:s.role,ok:d.ok,reasonCode:d.ok?void 0:d.reasonCode,rightClickPoint:s,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],pickedMethod:d.ok?"ocr-menu":void 0,pickedLabel:d.ok?d.label:void 0,pickedPoint:d.ok?d.point:void 0,ocrMenuCandidates:d.ocrMenuCandidates,disallowedLabels:R,clipboardChangeCountBefore:o}),!d.ok){i=d.reasonCode;continue}const l=await se({helper:e.helper,beforeChangeCount:o,candidate:e.candidate,traceId:e.traceId});e.resolveTrace&&p(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:c+1,pointRole:s.role,ok:!!l.result,reasonCode:l.reasonCode,rightClickPoint:s,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],pickedMethod:"ocr-menu",pickedLabel:d.label,pickedPoint:d.point,ocrMenuCandidates:d.ocrMenuCandidates,disallowedLabels:R,clipboardChangeCountBefore:o,clipboardChangeCountAfter:l.lastChangeCount??v(l.result,"changeCount"),clipboardPayload:le(l.result)});const u=ce(e.candidate,l.result,e.attachmentsDir);if(u&&e.resolveTrace&&(e.resolveTrace.attachmentValidation=z(u)),u)return{attachment:u,reasonCode:l.reasonCode};if(h(e.candidate.kind)==="image"&&l.reasonCode==="clipboard_attachment_unavailable"&&c+1<r.length){i=l.reasonCode;continue}return{attachment:null,reasonCode:l.reasonCode||"clipboard_attachment_unavailable"}}return{attachment:null,reasonCode:i||"menu_ocr_copy_not_found"}}catch(o){return e.resolveTrace&&p(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,ok:!1,reasonCode:k(o)}),{attachment:null,reasonCode:k(o)}}finally{try{t&&await e.helper.request("clipboard.restore",t.result&&typeof t.result=="object"?t.result:{},e.traceId)}catch{}}}async function oe(e,t){try{await e.request("keyboard.shortcut",{key:"escape",modifiers:[]},t)}catch{}}async function ne(e){const t=await ae(e);if(!t.ok)return t;const o=t.capture;if(!o.dataBase64||!o.width||!o.height)return{ok:!1,reasonCode:"menu_ocr_capture_failed",reason:"cannot capture menu"};const n=await e.helper.request("ocr.recognize",{mimeType:o.mimeType||"image/png",dataBase64:o.dataBase64,width:o.width,height:o.height},e.traceId);if(!n.ok)return{ok:!1,reasonCode:n.errorCode||"menu_ocr_failed",reason:n.errorSummary||"menu OCR failed"};const a=re({blocks:n.result?.blocks??[],labels:e.labels,point:e.point,screenshot:{width:Number(o.width),height:Number(o.height)},screenBounds:o.bounds,window:t.coordinateSpace==="window"?e.window:void 0});if(!a)return{ok:!1,reasonCode:"menu_ocr_copy_not_found",reason:"copy menu text not found near attachment",ocrMenuCandidates:ie({blocks:n.result?.blocks??[],labels:e.labels,point:e.point,screenshot:{width:Number(o.width),height:Number(o.height)},screenBounds:o.bounds,window:t.coordinateSpace==="window"?e.window:void 0})};const r=await e.helper.request("mouse.click",{x:Math.round(a.point.x),y:Math.round(a.point.y),coordinateSpace:"screen",windowId:e.windowId},e.traceId);return r.ok?{ok:!0,method:"ocr-menu",label:a.text,point:a.point,ocrMenuCandidates:a.candidates}:{ok:!1,reasonCode:r.errorCode||"menu_ocr_click_failed",reason:r.errorSummary||"cannot click OCR menu item",ocrMenuCandidates:a.candidates}}async function ae(e){if(e.menuSearchBounds){const o=await e.helper.request("screen.capture",{bounds:e.menuSearchBounds},e.traceId);if(o.ok&&o.result?.dataBase64&&o.result.width&&o.result.height)return{ok:!0,capture:{...o.result,bounds:o.result.bounds??e.menuSearchBounds},coordinateSpace:"screen"};if(o.errorCode&&o.errorCode!=="helper_unknown_command")return{ok:!1,reasonCode:o.errorCode||"menu_ocr_capture_failed",reason:o.errorSummary||"cannot capture menu"}}if(!e.windowId)return{ok:!1,reasonCode:"window_id_missing",reason:"window id is required for OCR menu fallback"};const t=await e.helper.request("windows.capture",{windowId:e.windowId,scope:"full-window"},e.traceId);return!t.ok||!t.result?.dataBase64||!t.result.width||!t.result.height?{ok:!1,reasonCode:t.errorCode||"menu_ocr_capture_failed",reason:t.errorSummary||"cannot capture menu"}:{ok:!0,capture:t.result,coordinateSpace:"window"}}function re(e){const t=e.labels.map(M).filter(Boolean),o=new Set(t.filter(H)),n=[];for(const r of e.blocks){const i=Q(r.text),c=M(i),s=U(r.bbox,e.screenshot,e.window,e.screenBounds);if(!i||!c||!s||Y(c))continue;const m=t.includes(c),d=o.has(c),l=!o.size&&t.some(u=>c.includes(u)||u.includes(c));!m&&!l||s.x<e.point.x-260||s.x>e.point.x+360||s.y<e.point.y-420||s.y>e.point.y+520||n.push({text:i,normalizedText:c,point:s,...r.bbox?{bbox:r.bbox}:{},exact:m,exactCopy:d,fuzzy:l,dangerous:!1,distance:Math.hypot(s.x-e.point.x,s.y-e.point.y)})}n.sort((r,i)=>Number(i.exactCopy)-Number(r.exactCopy)||Number(i.exact)-Number(r.exact)||r.point.y-i.point.y||r.distance-i.distance);const a=n[0];return a?{text:a.text,point:a.point,candidates:n.map(r=>({text:r.text,normalizedText:r.normalizedText,point:r.point,...r.bbox?{bbox:r.bbox}:{},exact:r.exact,exactCopy:r.exactCopy,fuzzy:r.fuzzy,dangerous:r.dangerous,selected:r===a}))}:null}function ie(e){const t=e.labels.map(M).filter(Boolean),o=new Set(t.filter(H)),n=[];for(const a of e.blocks){const r=Q(a.text),i=M(r),c=U(a.bbox,e.screenshot,e.window,e.screenBounds);if(!r||!i)continue;const s=t.includes(i),m=o.has(i),d=!o.size&&t.some(w=>i.includes(w)||w.includes(i)),l=Y(i);if(!(!(c&&c.x>=e.point.x-260&&c.x<=e.point.x+360&&c.y>=e.point.y-420&&c.y<=e.point.y+520)&&!s&&!d&&!l)&&(n.push({text:r,normalizedText:i,...c?{point:c}:{},...a.bbox?{bbox:a.bbox}:{},exact:s,exactCopy:m,fuzzy:d,dangerous:l}),n.length>=24))break}return n}function K(e,t){const o=e.bbox,n=t?.bounds;if(!o||!n)return;const a=o.coordinateSpace==="screen"?o.x:n.x+o.x,r=o.coordinateSpace==="screen"?o.y:n.y+o.y;if(![a,r,o.width,o.height].every(Number.isFinite))return;const i=Math.min(640,Math.max(360,Math.ceil(o.width+260))),c=Math.min(Math.max(760,Math.ceil(o.height+620)),Math.ceil(n.height+260));return{x:Math.max(0,Math.floor(a-140)),y:Math.max(0,Math.floor(r-Math.max(360,Math.ceil(c/2)))),width:i,height:c,coordinateSpace:"screen"}}async function se(e){const t=Date.now();let o=0;const n=h(e.candidate.kind);do{const a=await e.helper.request("clipboard.readAttachment",{},e.traceId);if(!a.ok)return{reasonCode:a.errorCode||"clipboard_read_failed"};const r=e.beforeChangeCount==null||Number(a.result?.changeCount)!==Number(e.beforeChangeCount);if(r&&xe(e.candidate,a.result))return{result:a.result,lastChangeCount:v(a.result,"changeCount")};if(r&&(o+=1,o>=(n==="image"?12:3)))break;await x(n==="image"?160:120)}while(Date.now()-t<(e.timeoutMs??2500));return{reasonCode:n==="image"?"clipboard_attachment_unavailable":"clipboard_file_url_unavailable",lastChangeCount:null}}function D(e,t,o,n){const a=g.statSync(t);if(!a.isFile())throw new Error("wechat_channel_attachment_not_file");if(a.size>L)return{type:h(e.kind),name:C(e.fileName||f.basename(t)),size:a.size,mimeType:e.mimeType||A(t),availability:"unavailable-large",providerError:"attachment_too_large"};g.mkdirSync(o,{recursive:!0});const r=g.readFileSync(t),i=B.createHash("sha256").update(r).digest("hex"),c=pe(e,t),s=Ce(e,t,c),m=f.extname(s)||f.extname(t)||X(c)||"",d=P(m),l=m?s.slice(0,-m.length):s,u=f.join(o,`${l}-${i.slice(0,12)}${m}`);return g.existsSync(u)||g.writeFileSync(u,r),{type:h(e.kind),name:s,mimeType:c,size:r.byteLength,...d?{extension:d}:{},localPath:u,hash:i,availability:"edge-local",...n?{sourceAction:n}:{},materializationKind:"original-file",isOriginal:!0,mimeKindMatches:!0}}function ce(e,t,o){const n=I(t);return n?j(e,n,t)?D(e,n,o,"materialize-clipboard"):null:h(e.kind)!=="image"?null:de(e,t,o)}function de(e,t,o){const n=typeof t?.dataBase64=="string"?t.dataBase64.trim():"";if(!n)return null;const a=Buffer.from(n,"base64");if(!a.length)return null;if(a.byteLength>L)return{type:"image",name:C(e.fileName||t?.suggestedFileName||"wechat-image.png"),size:a.byteLength,mimeType:e.mimeType||t?.mimeType||"image/png",availability:"unavailable-large",providerError:"attachment_too_large"};g.mkdirSync(o,{recursive:!0});const r=e.mimeType||t?.mimeType||"image/png",i=X(r)||".png",c=C(e.fileName||t?.suggestedFileName||`wechat-image${i}`),s=f.extname(c)?c:`${c}${i}`,m=B.createHash("sha256").update(a).digest("hex"),d=f.extname(s)||i,l=P(d),u=d?s.slice(0,-d.length):s,w=f.join(o,`${u}-${m.slice(0,12)}${d}`);return g.existsSync(w)||g.writeFileSync(w,a),{type:"image",name:s,mimeType:r,size:a.byteLength,extension:l,localPath:w,hash:m,availability:"edge-local",sourceAction:"materialize-clipboard",materializationKind:"clipboard-image",isOriginal:!0,mimeKindMatches:!0}}function y(e,t,o){return o&&(o.finalReasonCode=t),{messageKey:e.messageKey,reasonCode:t,...o?{resolveTrace:o}:{},attachment:{type:h(e.kind),name:C(e.fileName||`${e.kind||"attachment"}`),...e.mimeType?{mimeType:e.mimeType}:{},...Number.isFinite(e.size)?{size:Number(e.size)}:{},availability:e.mediaStatus==="not_downloaded"?"pending-download":"metadata-only",providerError:t,materializationKind:"metadata",isOriginal:!1,mimeKindMatches:!1}}}function $(e,t){return{candidateKind:String(e.kind||"unknown"),...e.bbox?{bbox:e.bbox}:{},...e.downloadActionBbox!==void 0?{downloadActionBbox:e.downloadActionBbox}:{},...e.mediaStatus!==void 0?{mediaStatus:e.mediaStatus}:{},actionPlan:{reasonCode:t.reasonCode,actions:t.actions.map(o=>({type:o.type,...o.reasonCode?{reasonCode:o.reasonCode}:{},...o.label?{label:o.label}:{},...o.target?{target:o.target}:{}}))},attempts:[]}}function S(e,t,o,n=!1){e.attempts.push({phase:"stability",stage:t,retry:n,ok:o.ok,...o.ok?{}:{reasonCode:o.reasonCode}})}function p(e,t){e.attempts.push({...t,...t.menuPickOrder?{menuPickOrder:[...t.menuPickOrder]}:{},...t.disallowedLabels?{disallowedLabels:[...t.disallowedLabels]}:{}})}function le(e){const t=e?.fileUrls??[],o=e?.filePaths??[],n=typeof e?.dataBase64=="string"?e.dataBase64.trim():"",a=[...o,...t].map(i=>I({filePaths:[i]})||i).map(i=>f.basename(i)).filter(Boolean),r=[...new Set(a.map(i=>P(f.extname(i||""))).filter(Boolean))];return{changeCount:v(e,"changeCount"),fileUrlCount:t.length,filePathCount:o.length,hasImageData:!!n,...n?{imageDataBytes:Buffer.from(n,"base64").byteLength}:{},...e?.mimeType?{mimeType:e.mimeType}:{},...e?.suggestedFileName?{suggestedFileName:e.suggestedFileName}:{},...a.length?{fileNames:a}:{},...r.length?{extensions:r}:{}}}function me(e){if(!fe(e.platform))return{attachment:null};if(h(e.candidate.kind)!=="video")return{attachment:null};const t=he(e.candidate),o=Z(e.candidate,{roots:e.cacheRoots,...t!==null?{minMtimeMs:t}:{}});if(e.resolveTrace&&p(e.resolveTrace,{phase:"cache-scan",ok:o.ok,reasonCode:o.reasonCode,cacheScan:o.trace}),!o.ok)return{attachment:null,reasonCode:o.reasonCode};try{const n=D(e.candidate,o.sourcePath,e.attachmentsDir,"wechat-cache-scan");return e.resolveTrace&&(e.resolveTrace.attachmentValidation=z(n)),{attachment:n,reasonCode:"edge_local_from_wechat_cache"}}catch(n){return{attachment:null,reasonCode:k(n)}}}function z(e){if(e)return{...e.availability?{availability:e.availability}:{},...e.type?{type:e.type}:{},...e.name?{name:e.name}:{},...e.localPath?{localPath:e.localPath}:{},...e.mimeType?{mimeType:e.mimeType}:{},...e.extension?{extension:e.extension}:{},...e.materializationKind?{materializationKind:e.materializationKind}:{},...typeof e.isOriginal=="boolean"?{isOriginal:e.isOriginal}:{},...typeof e.mimeKindMatches=="boolean"?{mimeKindMatches:e.mimeKindMatches}:{}}}function ue(e){const t=e.filter(o=>!!o);return t[t.length-1]}function q(e){return J({...e,kind:F(e.kind)})}function b(e){return[...new Set(e.filter(t=>!!t))]}function fe(e){return String(e||process.platform).toLowerCase()==="win32"}function he(e){return we(e.contextText)}function we(e){const o=String(e||"").match(/\b(20\d{12})\b/);if(!o)return null;const n=o[1],a=Number(n.slice(0,4)),r=Number(n.slice(4,6)),i=Number(n.slice(6,8)),c=Number(n.slice(8,10)),s=Number(n.slice(10,12)),m=Number(n.slice(12,14)),d=Date.UTC(a,r-1,i,c,s,m);return Number.isFinite(d)?d:null}function W(e,t,o=0){return e.actions.filter(n=>n.type===t)[o]}function ge(e,t){return W(e,"ocr-click-menu-item",t?1:0)?.label}function ye(e){const t=F(e);if(t==="image")return"image";if(t==="video-file")return"video";if(t==="file")return"file";if(t!=="unknown")return null;const o=String(e||"").toLowerCase();return o.includes("video")?"video":o.includes("image")||o.includes("photo")?"image":o.includes("file")||o.includes("document")?"file":null}function h(e){const t=ye(e);return t||"file"}function pe(e,t){const o=h(e.kind),n=String(e.mimeType||"").trim().toLowerCase();return n&&N(n,o)?n:A(t)}function Ce(e,t,o){const n=h(e.kind),a=e.fileName?C(e.fileName):"";return a&&be(a,o,n)?a:C(f.basename(t)||a||"attachment")}function be(e,t,o){if(o==="file")return!0;const n=f.extname(e).toLowerCase();return n?E(n,o):N(t,o)}function N(e,t){return t==="image"?e.startsWith("image/"):t==="video"?e.startsWith("video/"):!0}function E(e,t){return t==="image"?[".png",".jpg",".jpeg",".gif",".webp",".heic",".tiff",".bmp"].includes(e):t==="video"?[".mp4",".mov",".m4v",".avi",".mkv",".webm"].includes(e):!0}function ke(e,t){const o=h(e.kind),n=o==="image"?["\u590D\u5236\u56FE\u7247","\u62F7\u8D1D\u56FE\u7247","\u590D\u5236\u56FE\u50CF","\u62F7\u8D1D\u56FE\u50CF","\u590D\u5236","\u62F7\u8D1D","Copy Image","Copy"]:o==="video"?["\u590D\u5236\u89C6\u9891","\u62F7\u8D1D\u89C6\u9891","\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","\u590D\u5236","\u62F7\u8D1D","Copy Video","Copy File","Copy"]:["\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","\u590D\u5236","\u62F7\u8D1D","Copy File","Copy"];return t?[t,...n.filter(a=>a!==t)]:n}function I(e){const t=e?.filePaths?.[0]||e?.fileUrls?.[0];return t?t.startsWith("file://")?decodeURIComponent(new URL(t).pathname):t:null}function xe(e,t){const o=I(t);return o?j(e,o,t):h(e.kind)==="image"&&!!t?.dataBase64}function j(e,t,o){const n=h(e.kind),a=String(o?.mimeType||e.mimeType||A(t)).toLowerCase(),r=f.extname(t).toLowerCase();return n==="image"||n==="video"?N(a,n)||E(r,n):n==="file"}function k(e){const o=(e instanceof Error?e.message:String(e)).split(":",1)[0]?.trim();return/^[a-z0-9_]+$/i.test(o||"")?o:"media_resolve_failed"}function _e(e){return{x:e.x+e.width/2,y:e.y+e.height/2,coordinateSpace:e.coordinateSpace}}function Se(e,t,o=!1){const n={..._e(t),role:"center"};if(h(e.kind)!=="file"){if(!o)return[n];const r=Math.max(18,Math.min(48,t.width*.18)),i=Math.max(18,Math.min(48,t.height*.18));return V([{x:t.x+r,y:t.y+i,coordinateSpace:t.coordinateSpace,role:"media-top-left"},{x:t.x+Math.max(r,t.width-r),y:t.y+i,coordinateSpace:t.coordinateSpace,role:"media-top-right"},{x:t.x+r,y:t.y+Math.max(i,t.height-i),coordinateSpace:t.coordinateSpace,role:"media-bottom-left"},{x:t.x+Math.max(r,t.width-r),y:t.y+Math.max(i,t.height-i),coordinateSpace:t.coordinateSpace,role:"media-bottom-right"},n])}const a=[{x:t.x+Math.min(Math.max(96,t.width*.34),Math.max(24,t.width-36)),y:t.y+Math.min(Math.max(36,t.height*.32),Math.max(12,t.height-24)),coordinateSpace:t.coordinateSpace,role:"file-title"},{x:t.x+Math.min(Math.max(128,t.width*.46),Math.max(24,t.width-36)),y:t.y+Math.min(Math.max(64,t.height*.58),Math.max(12,t.height-24)),coordinateSpace:t.coordinateSpace,role:"file-body"},n];return V(a)}function V(e){const t=new Set,o=[];for(const n of e){const a=`${Math.round(n.x)}:${Math.round(n.y)}`;t.has(a)||(t.add(a),o.push(n))}return o}function U(e,t,o,n){if(!e)return null;const a=Number(e.x),r=Number(e.y),i=Number(e.width),c=Number(e.height);if(![a,r,i,c].every(Number.isFinite))return null;const s={x:a+i/2,y:r+c/2};if(n){const l=t.width&&n.width?t.width/n.width:1,u=t.height&&n.height?t.height/n.height:l;return{x:n.x+s.x/l,y:n.y+s.y/u}}if(e.coordinateSpace==="screen"||!o?.bounds)return s;const m=t.width&&o.bounds.width?t.width/o.bounds.width:1,d=t.height&&o.bounds.height?t.height/o.bounds.height:m;return{x:o.bounds.x+s.x/m,y:o.bounds.y+s.y/d}}function M(e){return String(e||"").replace(/\s+/g,"").replace(/[.。…⋯·]/g,"").trim()}function H(e){return["\u590D\u5236","\u62F7\u8D1D","\u590D\u5236\u56FE\u7247","\u62F7\u8D1D\u56FE\u7247","\u590D\u5236\u56FE\u50CF","\u62F7\u8D1D\u56FE\u50CF","\u590D\u5236\u89C6\u9891","\u62F7\u8D1D\u89C6\u9891","\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","copy","copyimage","copyvideo","copyfile"].includes(e.toLowerCase())}function Y(e){return/^(引用|删除|多选|转发|收藏|提醒|编辑|另存为|保存|打开方式|delete|quote|forward|favorite|save|saveas)$/i.test(e)}function C(e){return f.basename(e||"attachment").normalize("NFKC").replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").replace(/\s+/g," ").replace(/^[ ._]+|[ ._]+$/g,"")||"attachment"}function A(e){const t=f.extname(e).toLowerCase();return t===".png"?"image/png":t===".jpg"||t===".jpeg"?"image/jpeg":t===".gif"?"image/gif":t===".webp"?"image/webp":t===".mp4"?"video/mp4":t===".mov"?"video/quicktime":t===".pdf"?"application/pdf":t===".txt"?"text/plain":"application/octet-stream"}function X(e){const t=e.toLowerCase();return t==="image/png"?".png":t==="image/jpeg"?".jpg":t==="image/gif"?".gif":t==="image/webp"?".webp":t==="video/mp4"?".mp4":t==="video/quicktime"?".mov":t==="application/pdf"?".pdf":t==="text/plain"?".txt":null}function P(e){const t=String(e||"").trim().toLowerCase();return t?t.startsWith(".")?t:`.${t}`:""}function Q(e){return typeof e=="string"?e.trim():""}function v(e,t){const o=t&&e&&typeof e=="object"?e[t]:e,n=Number(o);return Number.isFinite(n)?n:null}function x(e){return new Promise(t=>setTimeout(t,e))}function Me(e,t){if(!e.ok)throw new Error(`${e.errorCode||"helper_command_failed"}: ${e.errorSummary||t}`)}export{Pe as defaultWeChatChannelAttachmentDir,D as materializeLocalAttachment,y as metadataOnlyResult,Fe as resolveVisibleWeChatChannelMedia};
|
|
1
|
+
import M from"node:crypto";import p from"node:fs";import h from"node:path";import{resolveShennianPath as G}from"../../config/index.js";import{buildWeChatChannelMediaActionPlan as J}from"./core/media-action-plan.js";import{normalizeWeChatChannelMessageKind as L}from"./core/schema.js";import{findCachedWeChatInboundMedia as Z}from"./media-cache-resolver.js";const R=20*1024*1024,O=["\u5F15\u7528","\u5220\u9664","\u591A\u9009","\u8F6C\u53D1","\u6536\u85CF","\u63D0\u9192","\u7F16\u8F91","\u4FDD\u5B58","\u53E6\u5B58\u4E3A","\u6253\u5F00\u65B9\u5F0F","Quote","Delete","Forward","Favorite","Save","Save As","Save to Downloads","Open With"];function Fe(e,t,o){const n=M.createHash("sha256").update(`${t}:${o}`).digest("hex").slice(0,16);return G("wechat-rpa","attachments","inbound",n)}async function Le(e){const t=[];for(const o of e.candidates)try{const n=q(o),a=D(o,n);if(!n.actions.length){t.push(w(o,n.reasonCode,a));continue}const r=await v(e,"before-media-action",o);if(T(a,"before-media-action",r),!r.ok){t.push(w(o,r.reasonCode,a));continue}const i=ee(o);if(i==="loading"){t.push(w(o,"download_in_progress_waiting",a));continue}if(i==="pending"){const d=$({candidate:o,attachmentsDir:e.attachmentsDir,resolveTrace:a,platform:e.platform,cacheRoots:e.wechatCacheRoots});if(d.attachment){t.push(await B(e,{messageKey:o.messageKey,attachment:d.attachment,reasonCode:d.reasonCode||"edge_local_from_wechat_cache",resolveTrace:a},o,a));continue}const l=await v(e,"before-media-action",o);if(T(a,"before-media-action",l),!l.ok){t.push({...w(o,l.reasonCode,a),...d.reasonCode?{attemptReasonCodes:b([d.reasonCode,l.reasonCode])}:{}});continue}const u=await te({helper:e.helper,candidate:o,resolveTrace:a,windowId:e.windowId,traceId:e.traceId}),g=u.ok?"download_triggered_pending_next_observe":u.reasonCode||"download_action_click_failed",F=b([d.reasonCode,u.reasonCode]);t.push({...w(o,g,a),...F.length?{attemptReasonCodes:F}:{}});continue}const s=[],c=await oe({helper:e.helper,candidate:o,actionPlan:n,resolveTrace:a,attachmentsDir:e.attachmentsDir,windowId:e.windowId,window:e.window,menuSearchBounds:se(o,e.window),traceId:e.traceId});if(c.attachment){t.push(await B(e,{messageKey:o.messageKey,attachment:c.attachment,reasonCode:"edge_local",resolveTrace:a},o,a));continue}s.push(...[c.reasonCode].filter(d=>!!d));const m=$({candidate:o,attachmentsDir:e.attachmentsDir,resolveTrace:a,platform:e.platform,cacheRoots:e.wechatCacheRoots});if(m.attachment){t.push(await B(e,{messageKey:o.messageKey,attachment:m.attachment,reasonCode:m.reasonCode||"edge_local_from_wechat_cache",resolveTrace:a},o,a,s));continue}m.reasonCode&&s.push(m.reasonCode),t.push({...w(o,he([...s,c.reasonCode])||"clipboard_attachment_unavailable",a),...s.length?{attemptReasonCodes:b(s)}:{}})}catch(n){t.push(w(o,k(n),D(o,q(o))))}return t}function ee(e){if(f(e.kind)!=="video")return null;const t=String(e.mediaStatus||"").trim().toLowerCase().replace(/-/g,"_");return t==="loading"||t==="downloading"||t==="in_progress"?"loading":e.downloadActionBbox&&(t==="not_downloaded"||t==="pending_download")?"pending":null}async function te(e){const t=e.candidate.downloadActionBbox;if(!t)return{ok:!1,reasonCode:"download_action_bbox_missing"};const o={x:t.x+t.width/2,y:t.y+t.height/2,coordinateSpace:t.coordinateSpace},n=await e.helper.request("mouse.click",{x:o.x,y:o.y,coordinateSpace:o.coordinateSpace,windowId:e.windowId},e.traceId),a=n.ok===!0,r=a?"clicked_video_download_affordance":n.errorCode||"download_action_click_failed";return e.resolveTrace&&y(e.resolveTrace,{phase:"download-action",ok:a,reasonCode:a?void 0:r,downloadPoint:o}),{ok:a,reasonCode:r}}async function v(e,t,o){if(!e.stabilityCheck)return{ok:!0};const n=t==="after-media-action"?2:1;for(let a=0;a<n;a+=1)try{const r=await e.stabilityCheck({stage:t,candidate:o});if(r.ok)return r;if(r.reasonCode==="conversation_title_not_confirmed"&&a+1<n){await S(350);continue}return{ok:!1,reasonCode:r.reasonCode||"media_window_unstable"}}catch(r){const i=k(r);if(i==="conversation_title_not_confirmed"&&a+1<n){await S(350);continue}return{ok:!1,reasonCode:i}}return{ok:!1,reasonCode:"media_window_unstable"}}async function B(e,t,o,n,a=[]){const r=await v(e,"after-media-action",o);return n&&T(n,"after-media-action",r),r.ok?(n&&(n.finalReasonCode=t.reasonCode,n.attachmentValidation=z(t.attachment)),a.length?{...t,attemptReasonCodes:b(a),...n?{resolveTrace:n}:{}}:{...t,...n?{resolveTrace:n}:{}}):{...w(o,r.reasonCode,n),attemptReasonCodes:b([...a,t.reasonCode,r.reasonCode])}}async function oe(e){let t=null;try{t=await e.helper.request("clipboard.snapshot",{},e.traceId),ve(t,"clipboard.snapshot");const o=_(t.result,"changeCount"),n=W(e.actionPlan,"right-click-media",e.retry?1:0)?.target??e.candidate.bbox;if(!n)return{attachment:null,reasonCode:"media_bbox_missing"};const a=xe(e.candidate,we(e.actionPlan,e.retry)),r=Me(e.candidate,n,!!e.window?.bounds);let i;for(const[s,c]of r.entries()){s>0&&await ne(e.helper,e.traceId),e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],clipboardChangeCountBefore:o});const m=await e.helper.request("mouse.rightClick",{x:c.x,y:c.y,coordinateSpace:c.coordinateSpace,windowId:e.windowId},e.traceId);if(!m.ok){i=m.errorCode||"media_right_click_failed",e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],clipboardChangeCountBefore:o,ok:!1,reasonCode:i});continue}await S(180);const d=await ae({helper:e.helper,labels:a,point:c,windowId:e.windowId,window:e.window,menuSearchBounds:e.menuSearchBounds,traceId:e.traceId});if(e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,ok:d.ok,reasonCode:d.ok?void 0:d.reasonCode,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],pickedMethod:d.ok?"ocr-menu":void 0,pickedLabel:d.ok?d.label:void 0,pickedPoint:d.ok?d.point:void 0,ocrMenuCandidates:d.ocrMenuCandidates,disallowedLabels:O,clipboardChangeCountBefore:o}),!d.ok){i=d.reasonCode;continue}const l=await de({helper:e.helper,beforeChangeCount:o,candidate:e.candidate,traceId:e.traceId});e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,ok:!!l.result,reasonCode:l.reasonCode,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],pickedMethod:"ocr-menu",pickedLabel:d.label,pickedPoint:d.point,ocrMenuCandidates:d.ocrMenuCandidates,disallowedLabels:O,clipboardChangeCountBefore:o,clipboardChangeCountAfter:l.lastChangeCount??_(l.result,"changeCount"),clipboardPayload:ue(l.result)});const u=le(e.candidate,l.result,e.attachmentsDir);if(u&&e.resolveTrace&&(e.resolveTrace.attachmentValidation=z(u)),u)return{attachment:u,reasonCode:l.reasonCode};if(f(e.candidate.kind)==="image"&&l.reasonCode==="clipboard_attachment_unavailable"&&s+1<r.length){i=l.reasonCode;continue}return{attachment:null,reasonCode:l.reasonCode||"clipboard_attachment_unavailable"}}return{attachment:null,reasonCode:i||"menu_ocr_copy_not_found"}}catch(o){return e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,ok:!1,reasonCode:k(o)}),{attachment:null,reasonCode:k(o)}}finally{try{t&&await e.helper.request("clipboard.restore",t.result&&typeof t.result=="object"?t.result:{},e.traceId)}catch{}}}async function ne(e,t){try{await e.request("keyboard.shortcut",{key:"escape",modifiers:[]},t)}catch{}}async function ae(e){const t=await re(e);if(!t.ok)return t;const o=t.capture;if(!o.dataBase64||!o.width||!o.height)return{ok:!1,reasonCode:"menu_ocr_capture_failed",reason:"cannot capture menu"};const n=await e.helper.request("ocr.recognize",{mimeType:o.mimeType||"image/png",dataBase64:o.dataBase64,width:o.width,height:o.height},e.traceId);if(!n.ok)return{ok:!1,reasonCode:n.errorCode||"menu_ocr_failed",reason:n.errorSummary||"menu OCR failed"};const a=ie({blocks:n.result?.blocks??[],labels:e.labels,point:e.point,screenshot:{width:Number(o.width),height:Number(o.height)},screenBounds:o.bounds,window:t.coordinateSpace==="window"?e.window:void 0});if(!a)return{ok:!1,reasonCode:"menu_ocr_copy_not_found",reason:"copy menu text not found near attachment",ocrMenuCandidates:ce({blocks:n.result?.blocks??[],labels:e.labels,point:e.point,screenshot:{width:Number(o.width),height:Number(o.height)},screenBounds:o.bounds,window:t.coordinateSpace==="window"?e.window:void 0})};const r=await e.helper.request("mouse.click",{x:Math.round(a.point.x),y:Math.round(a.point.y),coordinateSpace:"screen",windowId:e.windowId},e.traceId);return r.ok?{ok:!0,method:"ocr-menu",label:a.text,point:a.point,ocrMenuCandidates:a.candidates}:{ok:!1,reasonCode:r.errorCode||"menu_ocr_click_failed",reason:r.errorSummary||"cannot click OCR menu item",ocrMenuCandidates:a.candidates}}async function re(e){if(e.menuSearchBounds){const o=await e.helper.request("screen.capture",{bounds:e.menuSearchBounds},e.traceId);if(o.ok&&o.result?.dataBase64&&o.result.width&&o.result.height)return{ok:!0,capture:{...o.result,bounds:o.result.bounds??e.menuSearchBounds},coordinateSpace:"screen"};if(o.errorCode&&o.errorCode!=="helper_unknown_command")return{ok:!1,reasonCode:o.errorCode||"menu_ocr_capture_failed",reason:o.errorSummary||"cannot capture menu"}}if(!e.windowId)return{ok:!1,reasonCode:"window_id_missing",reason:"window id is required for OCR menu fallback"};const t=await e.helper.request("windows.capture",{windowId:e.windowId,scope:"full-window"},e.traceId);return!t.ok||!t.result?.dataBase64||!t.result.width||!t.result.height?{ok:!1,reasonCode:t.errorCode||"menu_ocr_capture_failed",reason:t.errorSummary||"cannot capture menu"}:{ok:!0,capture:t.result,coordinateSpace:"window"}}function ie(e){const t=e.labels.map(x).filter(Boolean),o=new Set(t.filter(H)),n=[];for(const r of e.blocks){const i=Q(r.text),s=x(i),c=V(r.bbox,e.screenshot,e.window,e.screenBounds);if(!i||!s||!c||Y(s))continue;const m=t.includes(s),d=o.has(s),l=!o.size&&t.some(u=>s.includes(u)||u.includes(s));!m&&!l||c.x<e.point.x-260||c.x>e.point.x+360||c.y<e.point.y-420||c.y>e.point.y+520||n.push({text:i,normalizedText:s,point:c,...r.bbox?{bbox:r.bbox}:{},exact:m,exactCopy:d,fuzzy:l,dangerous:!1,distance:Math.hypot(c.x-e.point.x,c.y-e.point.y)})}n.sort((r,i)=>Number(i.exactCopy)-Number(r.exactCopy)||Number(i.exact)-Number(r.exact)||r.point.y-i.point.y||r.distance-i.distance);const a=n[0];return a?{text:a.text,point:a.point,candidates:n.map(r=>({text:r.text,normalizedText:r.normalizedText,point:r.point,...r.bbox?{bbox:r.bbox}:{},exact:r.exact,exactCopy:r.exactCopy,fuzzy:r.fuzzy,dangerous:r.dangerous,selected:r===a}))}:null}function ce(e){const t=e.labels.map(x).filter(Boolean),o=new Set(t.filter(H)),n=[];for(const a of e.blocks){const r=Q(a.text),i=x(r),s=V(a.bbox,e.screenshot,e.window,e.screenBounds);if(!r||!i)continue;const c=t.includes(i),m=o.has(i),d=!o.size&&t.some(g=>i.includes(g)||g.includes(i)),l=Y(i);if(!(!(s&&s.x>=e.point.x-260&&s.x<=e.point.x+360&&s.y>=e.point.y-420&&s.y<=e.point.y+520)&&!c&&!d&&!l)&&(n.push({text:r,normalizedText:i,...s?{point:s}:{},...a.bbox?{bbox:a.bbox}:{},exact:c,exactCopy:m,fuzzy:d,dangerous:l}),n.length>=24))break}return n}function se(e,t){const o=e.bbox,n=t?.bounds;if(!o||!n)return;const a=o.coordinateSpace==="screen"?o.x:n.x+o.x,r=o.coordinateSpace==="screen"?o.y:n.y+o.y;if(![a,r,o.width,o.height].every(Number.isFinite))return;const i=Math.min(640,Math.max(360,Math.ceil(o.width+260))),s=Math.min(Math.max(760,Math.ceil(o.height+620)),Math.ceil(n.height+260));return{x:Math.max(0,Math.floor(a-140)),y:Math.max(0,Math.floor(r-Math.max(360,Math.ceil(s/2)))),width:i,height:s,coordinateSpace:"screen"}}async function de(e){const t=Date.now();let o=0;const n=f(e.candidate.kind);do{const a=await e.helper.request("clipboard.readAttachment",{},e.traceId);if(!a.ok)return{reasonCode:a.errorCode||"clipboard_read_failed"};const r=e.beforeChangeCount==null||Number(a.result?.changeCount)!==Number(e.beforeChangeCount);if(r&&_e(e.candidate,a.result))return{result:a.result,lastChangeCount:_(a.result,"changeCount")};if(r&&(o+=1,o>=(n==="image"?12:3)))break;await S(n==="image"?160:120)}while(Date.now()-t<(e.timeoutMs??2500));return{reasonCode:n==="image"?"clipboard_attachment_unavailable":"clipboard_file_url_unavailable",lastChangeCount:null}}function K(e,t,o,n){const a=p.statSync(t);if(!a.isFile())throw new Error("wechat_channel_attachment_not_file");if(a.size>R)return{type:f(e.kind),name:C(e.fileName||h.basename(t)),size:a.size,mimeType:e.mimeType||P(t),availability:"unavailable-large",providerError:"attachment_too_large"};p.mkdirSync(o,{recursive:!0});const r=p.readFileSync(t),i=M.createHash("sha256").update(r).digest("hex"),s=Ce(e,t),c=be(e,t,s),m=h.extname(c)||h.extname(t)||X(s)||"",d=A(m),l=m?c.slice(0,-m.length):c,u=h.join(o,`${l}-${i.slice(0,12)}${m}`);return p.existsSync(u)||p.writeFileSync(u,r),{type:f(e.kind),name:c,mimeType:s,size:r.byteLength,...d?{extension:d}:{},localPath:u,hash:i,availability:"edge-local",...n?{sourceAction:n}:{},materializationKind:"original-file",isOriginal:!0,mimeKindMatches:!0}}function le(e,t,o){const n=I(t);return n?j(e,n,t)?K(e,n,o,"materialize-clipboard"):null:f(e.kind)!=="image"?null:me(e,t,o)}function me(e,t,o){const n=typeof t?.dataBase64=="string"?t.dataBase64.trim():"";if(!n)return null;const a=Buffer.from(n,"base64");if(!a.length)return null;if(a.byteLength>R)return{type:"image",name:C(e.fileName||t?.suggestedFileName||"wechat-image.png"),size:a.byteLength,mimeType:e.mimeType||t?.mimeType||"image/png",availability:"unavailable-large",providerError:"attachment_too_large"};p.mkdirSync(o,{recursive:!0});const r=e.mimeType||t?.mimeType||"image/png",i=X(r)||".png",s=C(e.fileName||t?.suggestedFileName||`wechat-image${i}`),c=h.extname(s)?s:`${s}${i}`,m=M.createHash("sha256").update(a).digest("hex"),d=h.extname(c)||i,l=A(d),u=d?c.slice(0,-d.length):c,g=h.join(o,`${u}-${m.slice(0,12)}${d}`);return p.existsSync(g)||p.writeFileSync(g,a),{type:"image",name:c,mimeType:r,size:a.byteLength,extension:l,localPath:g,hash:m,availability:"edge-local",sourceAction:"materialize-clipboard",materializationKind:"clipboard-image",isOriginal:!0,mimeKindMatches:!0}}function w(e,t,o){return o&&(o.finalReasonCode=t),{messageKey:e.messageKey,reasonCode:t,...o?{resolveTrace:o}:{},attachment:{type:f(e.kind),name:C(e.fileName||`${e.kind||"attachment"}`),...e.mimeType?{mimeType:e.mimeType}:{},...Number.isFinite(e.size)?{size:Number(e.size)}:{},availability:e.mediaStatus==="not_downloaded"||e.mediaStatus==="loading"?"pending-download":"metadata-only",providerError:t,materializationKind:"metadata",isOriginal:!1,mimeKindMatches:!1}}}function D(e,t){return{candidateKind:String(e.kind||"unknown"),...e.bbox?{bbox:e.bbox}:{},...e.downloadActionBbox!==void 0?{downloadActionBbox:e.downloadActionBbox}:{},...e.mediaStatus!==void 0?{mediaStatus:e.mediaStatus}:{},actionPlan:{reasonCode:t.reasonCode,actions:t.actions.map(o=>({type:o.type,...o.reasonCode?{reasonCode:o.reasonCode}:{},...o.label?{label:o.label}:{},...o.target?{target:o.target}:{}}))},attempts:[]}}function T(e,t,o,n=!1){e.attempts.push({phase:"stability",stage:t,retry:n,ok:o.ok,...o.ok?{}:{reasonCode:o.reasonCode}})}function y(e,t){e.attempts.push({...t,...t.menuPickOrder?{menuPickOrder:[...t.menuPickOrder]}:{},...t.disallowedLabels?{disallowedLabels:[...t.disallowedLabels]}:{}})}function ue(e){const t=e?.fileUrls??[],o=e?.filePaths??[],n=typeof e?.dataBase64=="string"?e.dataBase64.trim():"",a=[...o,...t].map(i=>I({filePaths:[i]})||i).map(i=>h.basename(i)).filter(Boolean),r=[...new Set(a.map(i=>A(h.extname(i||""))).filter(Boolean))];return{changeCount:_(e,"changeCount"),fileUrlCount:t.length,filePathCount:o.length,hasImageData:!!n,...n?{imageDataBytes:Buffer.from(n,"base64").byteLength}:{},...e?.mimeType?{mimeType:e.mimeType}:{},...e?.suggestedFileName?{suggestedFileName:e.suggestedFileName}:{},...a.length?{fileNames:a}:{},...r.length?{extensions:r}:{}}}function $(e){if(!fe(e.platform))return{attachment:null};if(f(e.candidate.kind)!=="video")return{attachment:null};const t=ge(e.candidate),o=Z(e.candidate,{roots:e.cacheRoots,...t!==null?{minMtimeMs:t}:{}});if(e.resolveTrace&&y(e.resolveTrace,{phase:"cache-scan",ok:o.ok,reasonCode:o.reasonCode,cacheScan:o.trace}),!o.ok)return{attachment:null,reasonCode:o.reasonCode};try{const n=K(e.candidate,o.sourcePath,e.attachmentsDir,"wechat-cache-scan");return e.resolveTrace&&(e.resolveTrace.attachmentValidation=z(n)),{attachment:n,reasonCode:"edge_local_from_wechat_cache"}}catch(n){return{attachment:null,reasonCode:k(n)}}}function z(e){if(e)return{...e.availability?{availability:e.availability}:{},...e.type?{type:e.type}:{},...e.name?{name:e.name}:{},...e.localPath?{localPath:e.localPath}:{},...e.mimeType?{mimeType:e.mimeType}:{},...e.extension?{extension:e.extension}:{},...e.materializationKind?{materializationKind:e.materializationKind}:{},...typeof e.isOriginal=="boolean"?{isOriginal:e.isOriginal}:{},...typeof e.mimeKindMatches=="boolean"?{mimeKindMatches:e.mimeKindMatches}:{}}}function he(e){const t=e.filter(o=>!!o);return t[t.length-1]}function q(e){return J({...e,kind:L(e.kind)})}function b(e){return[...new Set(e.filter(t=>!!t))]}function fe(e){return String(e||process.platform).toLowerCase()==="win32"}function ge(e){return pe(e.contextText)}function pe(e){const o=String(e||"").match(/\b(20\d{12})\b/);if(!o)return null;const n=o[1],a=Number(n.slice(0,4)),r=Number(n.slice(4,6)),i=Number(n.slice(6,8)),s=Number(n.slice(8,10)),c=Number(n.slice(10,12)),m=Number(n.slice(12,14)),d=Date.UTC(a,r-1,i,s,c,m);return Number.isFinite(d)?d:null}function W(e,t,o=0){return e.actions.filter(n=>n.type===t)[o]}function we(e,t){return W(e,"ocr-click-menu-item",t?1:0)?.label}function ye(e){const t=L(e);if(t==="image")return"image";if(t==="video-file")return"video";if(t==="file")return"file";if(t!=="unknown")return null;const o=String(e||"").toLowerCase();return o.includes("video")?"video":o.includes("image")||o.includes("photo")?"image":o.includes("file")||o.includes("document")?"file":null}function f(e){const t=ye(e);return t||"file"}function Ce(e,t){const o=f(e.kind),n=String(e.mimeType||"").trim().toLowerCase();return n&&N(n,o)?n:P(t)}function be(e,t,o){const n=f(e.kind),a=e.fileName?C(e.fileName):"";return a&&ke(a,o,n)?a:C(h.basename(t)||a||"attachment")}function ke(e,t,o){if(o==="file")return!0;const n=h.extname(e).toLowerCase();return n?E(n,o):N(t,o)}function N(e,t){return t==="image"?e.startsWith("image/"):t==="video"?e.startsWith("video/"):!0}function E(e,t){return t==="image"?[".png",".jpg",".jpeg",".gif",".webp",".heic",".tiff",".bmp"].includes(e):t==="video"?[".mp4",".mov",".m4v",".avi",".mkv",".webm"].includes(e):!0}function xe(e,t){const o=f(e.kind),n=o==="image"?["\u590D\u5236\u56FE\u7247","\u62F7\u8D1D\u56FE\u7247","\u590D\u5236\u56FE\u50CF","\u62F7\u8D1D\u56FE\u50CF","\u590D\u5236","\u62F7\u8D1D","Copy Image","Copy"]:o==="video"?["\u590D\u5236\u89C6\u9891","\u62F7\u8D1D\u89C6\u9891","\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","\u590D\u5236","\u62F7\u8D1D","Copy Video","Copy File","Copy"]:["\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","\u590D\u5236","\u62F7\u8D1D","Copy File","Copy"];return t?[t,...n.filter(a=>a!==t)]:n}function I(e){const t=e?.filePaths?.[0]||e?.fileUrls?.[0];return t?t.startsWith("file://")?decodeURIComponent(new URL(t).pathname):t:null}function _e(e,t){const o=I(t);return o?j(e,o,t):f(e.kind)==="image"&&!!t?.dataBase64}function j(e,t,o){const n=f(e.kind),a=String(o?.mimeType||e.mimeType||P(t)).toLowerCase(),r=h.extname(t).toLowerCase();return n==="image"||n==="video"?N(a,n)||E(r,n):n==="file"}function k(e){const o=(e instanceof Error?e.message:String(e)).split(":",1)[0]?.trim();return/^[a-z0-9_]+$/i.test(o||"")?o:"media_resolve_failed"}function Se(e){return{x:e.x+e.width/2,y:e.y+e.height/2,coordinateSpace:e.coordinateSpace}}function Me(e,t,o=!1){const n={...Se(t),role:"center"};if(f(e.kind)!=="file"){if(!o)return[n];const r=Math.max(18,Math.min(48,t.width*.18)),i=Math.max(18,Math.min(48,t.height*.18));return U([{x:t.x+r,y:t.y+i,coordinateSpace:t.coordinateSpace,role:"media-top-left"},{x:t.x+Math.max(r,t.width-r),y:t.y+i,coordinateSpace:t.coordinateSpace,role:"media-top-right"},{x:t.x+r,y:t.y+Math.max(i,t.height-i),coordinateSpace:t.coordinateSpace,role:"media-bottom-left"},{x:t.x+Math.max(r,t.width-r),y:t.y+Math.max(i,t.height-i),coordinateSpace:t.coordinateSpace,role:"media-bottom-right"},n])}const a=[{x:t.x+Math.min(Math.max(96,t.width*.34),Math.max(24,t.width-36)),y:t.y+Math.min(Math.max(36,t.height*.32),Math.max(12,t.height-24)),coordinateSpace:t.coordinateSpace,role:"file-title"},{x:t.x+Math.min(Math.max(128,t.width*.46),Math.max(24,t.width-36)),y:t.y+Math.min(Math.max(64,t.height*.58),Math.max(12,t.height-24)),coordinateSpace:t.coordinateSpace,role:"file-body"},n];return U(a)}function U(e){const t=new Set,o=[];for(const n of e){const a=`${Math.round(n.x)}:${Math.round(n.y)}`;t.has(a)||(t.add(a),o.push(n))}return o}function V(e,t,o,n){if(!e)return null;const a=Number(e.x),r=Number(e.y),i=Number(e.width),s=Number(e.height);if(![a,r,i,s].every(Number.isFinite))return null;const c={x:a+i/2,y:r+s/2};if(n){const l=t.width&&n.width?t.width/n.width:1,u=t.height&&n.height?t.height/n.height:l;return{x:n.x+c.x/l,y:n.y+c.y/u}}if(e.coordinateSpace==="screen"||!o?.bounds)return c;const m=t.width&&o.bounds.width?t.width/o.bounds.width:1,d=t.height&&o.bounds.height?t.height/o.bounds.height:m;return{x:o.bounds.x+c.x/m,y:o.bounds.y+c.y/d}}function x(e){return String(e||"").replace(/\s+/g,"").replace(/[.。…⋯·]/g,"").trim()}function H(e){return["\u590D\u5236","\u62F7\u8D1D","\u590D\u5236\u56FE\u7247","\u62F7\u8D1D\u56FE\u7247","\u590D\u5236\u56FE\u50CF","\u62F7\u8D1D\u56FE\u50CF","\u590D\u5236\u89C6\u9891","\u62F7\u8D1D\u89C6\u9891","\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","copy","copyimage","copyvideo","copyfile"].includes(e.toLowerCase())}function Y(e){return/^(引用|删除|多选|转发|收藏|提醒|编辑|另存为|保存|打开方式|delete|quote|forward|favorite|save|saveas)$/i.test(e)}function C(e){return h.basename(e||"attachment").normalize("NFKC").replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").replace(/\s+/g," ").replace(/^[ ._]+|[ ._]+$/g,"")||"attachment"}function P(e){const t=h.extname(e).toLowerCase();return t===".png"?"image/png":t===".jpg"||t===".jpeg"?"image/jpeg":t===".gif"?"image/gif":t===".webp"?"image/webp":t===".mp4"?"video/mp4":t===".mov"?"video/quicktime":t===".pdf"?"application/pdf":t===".txt"?"text/plain":"application/octet-stream"}function X(e){const t=e.toLowerCase();return t==="image/png"?".png":t==="image/jpeg"?".jpg":t==="image/gif"?".gif":t==="image/webp"?".webp":t==="video/mp4"?".mp4":t==="video/quicktime"?".mov":t==="application/pdf"?".pdf":t==="text/plain"?".txt":null}function A(e){const t=String(e||"").trim().toLowerCase();return t?t.startsWith(".")?t:`.${t}`:""}function Q(e){return typeof e=="string"?e.trim():""}function _(e,t){const o=t&&e&&typeof e=="object"?e[t]:e,n=Number(o);return Number.isFinite(n)?n:null}function S(e){return new Promise(t=>setTimeout(t,e))}function ve(e,t){if(!e.ok)throw new Error(`${e.errorCode||"helper_command_failed"}: ${e.errorSummary||t}`)}export{Fe as defaultWeChatChannelAttachmentDir,K as materializeLocalAttachment,w as metadataOnlyResult,Le as resolveVisibleWeChatChannelMedia};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import P from"node:fs";import
|
|
2
|
-
`,"utf8")}catch{}}function et(e){if(!e||typeof e!="object")return null;const t=e,n=typeof t.windowId=="string"?t.windowId:"",r=typeof t.boundsKey=="string"?t.boundsKey:"";if(!r)return null;const i=re(t.messageInputPoint??t.point),o=re(t.searchInputPoint);return{windowId:n,boundsKey:r,messageInputPoint:i,searchInputPoint:o,...typeof t.updatedAt=="string"?{updatedAt:t.updatedAt}:{}}}function re(e){if(!e||typeof e!="object")return null;const t=e,n=Number(t.x),r=Number(t.y);return!Number.isFinite(n)||!Number.isFinite(r)?null:{x:Math.round(n),y:Math.round(r),coordinateSpace:"screen"}}function tt(e){const t=e.bounds;return[Math.round(Number(t?.x??0)),Math.round(Number(t?.y??0)),Math.round(Number(t?.width??0)),Math.round(Number(t?.height??0))].join(",")}function ie(e,t,n,r="message-input"){const i=Number(e?.x),o=Number(e?.y),s=Number(e?.width),a=Number(e?.height);if(![i,o,s,a].every(Number.isFinite)||s<=0||a<=0)return null;const c=e?.coordinateSpace==="screen"?{x:i,y:o,width:s,height:a,coordinateSpace:"screen"}:{x:i/999*t.width,y:o/999*t.height,width:s/999*t.width,height:a/999*t.height,coordinateSpace:"screenshotPixel"},l=nt(c,t,n,r);return l?{x:Math.round(l.x),y:Math.round(l.y),coordinateSpace:"screen"}:null}function nt(e,t,n,r="message-input"){const i=r==="message-input"?.28:.55,o=rt({x:e.x+e.width*.54,y:e.y+e.height*i,coordinateSpace:e.coordinateSpace},t,n);return o?{x:o.x,y:o.y,coordinateSpace:"screen"}:null}function rt(e,t,n){if(![e.x,e.y].every(Number.isFinite))return null;if(e.coordinateSpace==="screen"||!n.bounds)return{x:e.x,y:e.y};const r=t.width&&n.bounds.width?t.width/n.bounds.width:1,i=t.height&&n.bounds.height?t.height/n.bounds.height:r,o=Math.max(0,(t.width-n.bounds.width*r)/2),s=Math.max(0,(t.height-n.bounds.height*i)/2);return{x:n.bounds.x+(e.x-o)/r,y:n.bounds.y+(e.y-s)/i}}async function oe(e){if(!e.api.classifyWindow)throw new Error("wechat_window_classifier_unavailable");const t=await e.helper.request("windows.list",{},e.traceId);m(t,"windows.list");const n=(t.result?.windows??[]).filter(q).filter(s=>s.visible!==!1&&s.minimized!==!0&&!!s.windowId),r=at(n.length?n:[e.fallback],e.fallback);if(!r.length)throw new Error("wechat_window_not_found");const i=[];for(const s of r)try{const a=await R(e.helper,s.windowId,e.traceId,s.bounds),c=await e.api.classifyWindow(e.runtime,e.binding,{screenshot:{mimeType:a.mimeType,dataBase64:a.dataBase64,width:a.width,height:a.height,windowId:s.windowId},traceId:e.traceId});i.push({window:s,classification:c,score:st(c,e.requireTargetConversation===!0)})}catch(a){if(it(a))throw a;i.push({window:s,classification:null,errorSummary:a instanceof Error?a.message:String(a||"window classification failed"),score:-1})}const o=i.filter(s=>s.score>0).sort((s,a)=>a.score-s.score)[0];if(!o){const s=i.map(a=>({windowId:a.window.windowId,appName:a.window.appName,title:a.window.title,score:a.score,errorSummary:a.errorSummary,classification:a.classification?{windowKind:a.classification.windowKind,reasonCode:a.classification.reasonCode,confidence:a.classification.confidence,conversationTitle:a.classification.conversationTitle,isTargetConversation:a.classification.isTargetConversation}:null}));throw new Error(`wechat_chat_main_window_not_found: ${JSON.stringify(s)}`)}return o.window}async function Tn(e,t,n){if(e.runtime.policy.platform!=="win32")return;const r=t.filter(i=>{if(i.window.windowId===n.window.windowId||!i.window.windowId)return!1;const o=i.classification?.windowKind;return o==="chat_main"||o==="login"});if(r.length!==0)for(const i of r)try{await e.helper.request("windows.closeWindow",{windowId:i.window.windowId},e.traceId)}catch{}}function it(e){const t=ot(e);return t==="insufficient_credits"||t==="entitlement_required"||t==="manual_review_required"||t==="wechat_channel_network_failed"||t==="wechat_channel_invalid_response"}function ot(e){if(e instanceof Re||e&&typeof e=="object"&&typeof e.reasonCode=="string")return e.reasonCode.trim().toLowerCase();const t=e instanceof Error?e.message:String(e||"");return/classify-window (?:network )?failed:\s*([a-z][a-z0-9_]*)/i.exec(t)?.[1]?.trim().toLowerCase()||""}function at(e,t){const n=[],r=i=>{i?.windowId&&(n.some(o=>o.windowId===i.windowId)||n.push(i))};r(e.find(i=>i.windowId===t.windowId));for(const i of e)r(i);return n}function st(e,t){if(!e||e.windowKind!=="chat_main")return 0;const n=Number(e.confidence??0);return t&&e.isTargetConversation!==!0?0:100+(e.isTargetConversation?50:0)+Math.round(Math.max(0,Math.min(1,n))*100)}function ct(e,t,n){if(!t)return{helper:e,withLease:async(a,c,l)=>await l(e)};let r=null;const i=a=>{t.onEvent?.({...a,at:new Date().toISOString()})},o=async(a,c,l={})=>{if(r){const u=await e.request("automation.lease.status",{},n),d=u.result??{},f=u.ok&&d.interrupted?ae(d.interruptReason):u.ok?void 0:u.errorCode||"user_activity_unknown";if(i({phase:"lease-status",stage:a,action:c,ok:u.ok===!0&&!d.interrupted,...f?{reasonCode:f}:{}}),!u.ok)throw new N({reasonCode:u.errorCode||"user_activity_unknown",stage:a,action:c});if(d.active===!1||d.leaseId!==r||!d.interrupted)return;throw new N({reasonCode:ae(d.interruptReason),stage:a,action:c})}const w=Date.now()+lt(t.preflightIdleSettleTimeoutMs);for(;;){const u=await e.request("activity.snapshot",{},n);if(!u.ok)throw i({phase:"snapshot",stage:a,action:c,ok:!1,reasonCode:u.errorCode||"user_activity_unknown"}),new N({reasonCode:u.errorCode||"user_activity_unknown",stage:a,action:c});const d=je({snapshot:Ge(u.result),stage:a,policy:t.policy});if(i({phase:"snapshot",stage:a,action:c,ok:d.ok,...d.ok?{}:{reasonCode:d.reasonCode,waitMs:d.waitMs}}),d.ok)return;const f=new N({reasonCode:d.reasonCode,stage:a,action:c});if(!l.settle)throw f;const Y=w-Date.now();if(Y<=0)throw f;await j(Math.max(50,Math.min(d.waitMs,Y)))}},s={request:async(a,c,l)=>{const w=dt(a);w&&await o(w.stage,`${a}:before`);const u=await e.request(a,c,l);return w&&u.ok&&await o(w.stage,`${a}:after`),u}};return{helper:s,async withLease(a,c,l){if(await Ft(e,n),await o(a,`${c}:preflight`,{settle:!0}),t.useAutomationLease===!1)return await l(s);const w=await e.request("automation.lease.acquire",{owner:"wechat-channel",purpose:`observe:${c}`,ttlMs:12e4},n);if(r=typeof w.result?.leaseId=="string"?w.result.leaseId:null,i({phase:"lease-acquire",stage:a,action:c,ok:w.ok===!0,...w.ok?{}:{reasonCode:w.errorCode||"user_activity_unknown"}}),!w.ok)throw r=null,new N({reasonCode:w.errorCode||"user_activity_unknown",stage:a,action:c});try{const u=await l(s);return await o(a,`${c}:complete`),u}finally{const u=r;if(r=null,u){const d=await e.request("automation.lease.release",{leaseId:u},n).catch(f=>({ok:!1,errorCode:"automation_lease_release_failed",errorSummary:f instanceof Error?f.message:String(f)}));i({phase:"lease-release",stage:a,action:c,ok:d.ok===!0,...d.ok?{}:{reasonCode:d.errorCode||"automation_lease_release_failed"}})}}}}}function dt(e){return e==="windows.ensureReady"||e==="windows.focus"||e==="wechat.searchConversation"?{stage:"open_conversation"}:e==="keyboard.shortcut"||e==="mouse.click"||e==="mouse.rightClick"||e==="mouse.scroll"||e==="clipboard.snapshot"||e==="clipboard.readAttachment"||e==="menu.pickItem"?{stage:"dangerous_action"}:null}function ae(e){return e==="recent_mouse_activity"||e==="recent_mouse_click"||e==="recent_scroll_activity"||e==="recent_keyboard_activity"||e==="frontmost_app_changed"?e:"user_activity_unknown"}function lt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:Xe}function se(e){return e.observePipeline==="edge-structure"?!0:e.observePipeline==="server-observe"?!1:!!e.api.structureWindow}async function K(e){const t=await Ie(e),n=await e.api.observe(e.runtime,e.binding,{screenshots:[{captureIndex:0,mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height}],edgeOcrBlocks:e.ocr.blocks??[],visibleConversationFingerprints:e.ocr.visibleConversationFingerprints??[],localLedgerTailAnchors:e.localLedgerTailAnchors??[],traceId:e.traceId}),r=await we({helper:e.helper,runtime:e.runtime,binding:e.binding,messages:n.observedMessages??[],workDir:e.workDir,attachmentsDir:e.attachmentsDir,window:e.window,screenshot:t,windowId:e.window.windowId,traceId:e.traceId,mediaAnchorText:e.mediaAnchorText});return Be(r,Te({ocr:e.ocr,screenshot:t,binding:e.binding,anchors:e.localOutboundEchoAnchors??[]}))}async function ce(e){if(!e.api.structureWindow)throw new Error("wechat_structure_window_unavailable");const t=await Ie(e);let n;try{n=await e.api.structureWindow(e.runtime,e.binding,{screenshots:[{captureIndex:0,mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height}],edgeOcrBlocks:e.ocr.blocks??[],visibleConversationFingerprints:e.ocr.visibleConversationFingerprints??[],localLedgerTailAnchors:e.localLedgerTailAnchors??[],traceId:e.traceId})}catch(c){if(ut(c))return K(e);throw c}const r=pt(n.structuredMessages??n.observedMessages??[]),i=await wt({...e,messages:r,screenshot:t}),o=await we({helper:e.helper,runtime:e.runtime,binding:e.binding,messages:i.messages,workDir:e.workDir,attachmentsDir:e.attachmentsDir,window:e.window,screenshot:t,windowId:e.window.windowId,traceId:e.traceId,mediaAnchorText:e.mediaAnchorText}),s=Be(o,Te({ocr:e.ocr,screenshot:t,binding:e.binding,anchors:e.localOutboundEchoAnchors??[]}));return e.localLedger?De({ledger:e.localLedger,bindingId:e.binding.bindingId,observedMessages:s,baselineOnly:e.baselineOnly,vectorReferences:i.vectorReferences}).newMessages:s}function ut(e){return e instanceof Error&&/\bedge_runtime_disabled\b/.test(e.message)}async function wt(e){const t=ht(e.messages);if(!t.length)return{messages:e.messages,vectorReferences:[]};const n=e.api.embedVisual?await mt({...e,seedBlocks:t}):t.filter(s=>h(s.vectorBase64)||h(s.signature));if(!n.length)return{messages:e.messages,vectorReferences:[]};const r=e.vectorStorePath??Le(e.workDir||process.cwd(),e.runtime.runtimeId),i=Oe(r,e.runtime.runtimeId),o=$e({store:i,bindingId:e.binding.bindingId,blocks:n});return o.length?(Ke(r,i),{messages:yt(e.messages,o),vectorReferences:o}):{messages:e.messages,vectorReferences:[]}}function ht(e){const t=[];for(const n of e)for(const[r,i]of(n.visualBlocks??[]).entries()){const o=h(i.blockId)||`${n.stableMessageKey}:visual-${r}`,s=h(i.blockKind)||n.kind||"visual";t.push({...i,stableMessageKey:n.stableMessageKey,blockId:o,blockKind:s,...i.bbox!==void 0?{bbox:i.bbox}:n.bbox!==void 0?{bbox:n.bbox}:{}})}return t}async function ft(e){if(!e.api.embedVisual)return[];const t=await e.api.embedVisual(e.runtime,e.binding,{screenshots:[{captureIndex:0,mimeType:e.screenshot.mimeType,dataBase64:e.screenshot.dataBase64,width:e.screenshot.width,height:e.screenshot.height}],visualBlocks:e.seedBlocks,traceId:e.traceId});return gt(t.visualBlocks??t.embeddedBlocks??[],e.seedBlocks)}async function mt(e){try{return await ft(e)}catch(t){if(bt(t))throw t;return[]}}function bt(e){return!e||typeof e!="object"?!1:e.reasonCode==="insufficient_credits"?!0:e instanceof Error&&/\binsufficient_credits\b/.test(e.message)}function gt(e,t){return e.map((n,r)=>{const i=t[r];return{...n,stableMessageKey:h(n.stableMessageKey)||h(i?.stableMessageKey),blockId:h(n.blockId)||h(i?.blockId),blockKind:h(n.blockKind)||h(i?.blockKind)||"visual",...n.bbox!==void 0?{bbox:n.bbox}:i?.bbox!==void 0?{bbox:i.bbox}:{}}}).filter(n=>h(n.stableMessageKey)&&h(n.blockId))}function yt(e,t){const n=new Map;for(const r of t){const i=n.get(r.stableMessageKey)??[];i.push(r),n.set(r.stableMessageKey,i)}return e.map(r=>{const i=n.get(r.stableMessageKey);return i?.length?{...r,visualBlocks:xt(r,i)}:r})}function xt(e,t){const r=(e.visualBlocks??[]).map((o,s)=>{const a=h(o.blockId)||`${e.stableMessageKey}:visual-${s}`,c=t.find(l=>l.blockId===a);return c?de(c,o):le(o)}),i=new Set(r.map(o=>o.blockId));for(const o of t)i.has(o.blockId)||r.push(de(o));return r}function de(e,t){return{...t?le(t):{},stableMessageKey:e.stableMessageKey,blockId:e.blockId,blockKind:e.blockKind,vectorStoreKey:e.vectorStoreKey,model:e.model,...e.modelVersion!==void 0?{modelVersion:e.modelVersion}:{},dims:e.dims,...e.signature?{signature:e.signature}:{},...e.bbox!==void 0?{bbox:e.bbox}:{}}}function le(e){const{vectorBase64:t,...n}=e;return n}function pt(e){return e.map((t,n)=>vt(t,n)).filter(t=>t!=null)}function vt(e,t){if(!b(e))return null;const n=ze(e.kind),r=_t(e.senderRole),i=g(e.normalizedText),o=g(e.anchorText)??i??g(e.textExcerpt),s=h(e.stableMessageKey)||Ct({message:e,index:t,senderRole:r,kind:n,anchorText:o});return{stableMessageKey:s,senderRole:r,...g(e.senderName)!==null?{senderName:g(e.senderName)}:{},kind:n,...i!==null?{normalizedText:i}:{},...o!==null?{anchorText:o}:{},...I(e,"anchorMetadata")?{anchorMetadata:e.anchorMetadata}:{},...I(e,"neighborContext")?{neighborContext:e.neighborContext}:{},...g(e.textExcerpt)!==null?{textExcerpt:g(e.textExcerpt)}:{},...I(e,"bbox")?{bbox:e.bbox}:{},...I(e,"mediaMetadata")?{mediaMetadata:It(e.mediaMetadata)}:{},...typeof e.isBaseline=="boolean"?{isBaseline:e.isBaseline}:{},...g(e.deliveryStatus)!==null?{deliveryStatus:g(e.deliveryStatus)??void 0}:{},...g(e.observedAt)!==null?{observedAt:g(e.observedAt)??void 0}:{},...Array.isArray(e.visualBlocks)?{visualBlocks:e.visualBlocks}:{},...o?{}:{anchorText:s}}}function Ct(e){const t=b(e.message.bbox)?JSON.stringify(e.message.bbox):"";return`structured-window:${[e.index,e.senderRole,e.kind,e.anchorText||h(e.message.textExcerpt)||"",t].join(":").slice(0,180)}`}function It(e){if(!b(e))return e;const t={...e};return I(t,"availability")&&(t.availability=X(t.availability)),b(t.attachment)&&(t.attachment=ue(t.attachment)),Array.isArray(t.attachments)&&(t.attachments=t.attachments.map(n=>b(n)?ue(n):n)),t}function ue(e){const t={...e};return I(t,"availability")&&(t.availability=X(t.availability)),t}function _t(e){return e==="self"||e==="contact"||e==="system"||e==="unknown"?e:"unknown"}async function we(e){if(e.binding.downloadMedia===!1)return e.messages;const t=e.messages.map((o,s)=>Et(o,e.screenshot,e.window,Bt(e.messages,s))).filter((o,s)=>kt(e.messages,s,e.mediaAnchorText)).filter(o=>o!=null);if(!t.length)return e.messages;const n=e.attachmentsDir??Fe(e.workDir||process.cwd(),e.runtime.runtimeId,e.binding.bindingId),r=await Ae({helper:e.helper,candidates:t,attachmentsDir:n,screenshot:e.screenshot,windowId:e.windowId,window:e.window,traceId:e.traceId,platform:e.runtime.policy.platform,stabilityCheck:async()=>{const o=await M({helper:e.helper,window:e.window,binding:e.binding,traceId:e.traceId});return o.ok?{ok:!0}:{ok:!1,reasonCode:o.reason}}});if(!r.length)return e.messages;const i=new Map(r.map(o=>[o.messageKey,o]));return e.messages.map(o=>{const s=i.get(o.stableMessageKey);return s?{...o,mediaMetadata:Pt(o.mediaMetadata,s.attachment,s.reasonCode,s.attemptReasonCodes,s.resolveTrace)}:o})}function kt(e,t,n){const r=fe(n);if(!r)return!0;const i=St(r),o=e.map((s,a)=>fe(Tt(s)).includes(r)?a:-1).filter(s=>s>=0);if(!o.length)return t===Mt(e,i);for(const s of o)if(t>=s&&t<=s+8||t===s-1&&!e.slice(s+1,Math.min(e.length,s+9)).some(he))return!0;return!1}function St(e){return e.includes("video")||e.includes("vide0")?"video":e.includes("image")||e.includes("photo")||e.includes("ph0t0")||e.includes("picture")?"image":e.includes("file")||e.includes("document")?"file":null}function Mt(e,t=null){for(let n=e.length-1;n>=0;n-=1)if(he(e[n]))return Nt(e[n],t)?n:-1;return-1}function he(e){if(!e)return!1;const t=String(e.kind||"").toLowerCase(),n=b(e.mediaMetadata)?e.mediaMetadata:{},r=b(n.attachment)?n.attachment:{};return me(t,n,r)}function Nt(e,t){if(!e||!t)return!0;const n=String(e.kind||"").toLowerCase(),r=b(e.mediaMetadata)?e.mediaMetadata:{},i=b(r.attachment)?r.attachment:{},o=String(i.type||"").toLowerCase(),s=String(i.mimeType||"").toLowerCase(),a=String(i.name||i.localPath||e.anchorText||e.textExcerpt||"").toLowerCase();return t==="video"?n.includes("video")||o==="video"||s.startsWith("video/")||/\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(a):t==="image"?/image|photo|picture/.test(n)||o==="image"||s.startsWith("image/")||/\.(png|jpe?g|gif|webp|heic|tiff?|bmp)$/i.test(a):/file|document/.test(n)||o==="file"||!/image|photo|picture|video/.test(n)&&o!=="image"&&o!=="video"&&!s.startsWith("image/")&&!s.startsWith("video/")}function Tt(e){if(!e)return"";const t=e;return[e.normalizedText,e.anchorText,e.textExcerpt,t.text].map(n=>String(n||"")).join(`
|
|
3
|
-
`)}function
|
|
4
|
-
`)||null}function Et(e,t,n,r){const i=String(e.kind||"").toLowerCase(),o=b(e.mediaMetadata)?e.mediaMetadata:{},s=b(o.attachment)?o.attachment:{},a=h(s.availability)||h(o.availability),c=h(s.localPath)||h(o.localPath);if(a==="edge-local"&&c||!me(i,o,s))return null;const l=W(e.bbox)??W(o.bbox)??W(o.downloadActionBbox),w=W(o.downloadActionBbox),u=be(l,t,n),d=Rt(l,t,n),f=be(w,t,n);return{messageKey:e.stableMessageKey,kind:h(s.type)||h(s.kind)||h(o.messageType)||i,fileName:h(s.name)||h(s.fileName)||h(o.fileName)||null,mimeType:h(s.mimeType)||h(o.mimeType)||null,size:_(s.size)??_(o.size),mediaStatus:Wt(o,s),observedAt:e.observedAt??null,contextText:r??e.normalizedText??e.anchorText??e.textExcerpt??null,...u?{bbox:u}:{},...d?{screenshotBbox:d}:{},...f?{downloadActionBbox:f}:{}}}function Pt(e,t,n,r,i){const o=b(e)?{...e}:{};return{...o,availability:b(t)?t.availability:o.availability,mediaStatus:b(t)&&t.availability==="edge-local"?"downloaded":o.mediaStatus,attachment:t,edgeResolveReasonCode:n,...r?.length?{edgeResolveAttempts:r}:{},...i?{edgeResolveTrace:i}:{}}}function Wt(e,t){const n=h(e.mediaStatus);if(n==="not_downloaded")return"not_downloaded";if(n==="downloaded"||n==="available")return"available";const r=h(t.availability)||h(e.availability);return r==="pending-download"?"not_downloaded":r==="metadata-only"?"metadata_only":n||null}function me(e,t,n){const r=`${e} ${h(t.messageType)} ${h(n.type)} ${h(n.kind)}`.toLowerCase();return/image|photo|video|file|document/.test(r)}function W(e){if(!b(e))return null;const t=_(e.x),n=_(e.y),r=_(e.width),i=_(e.height);return t==null||n==null||r==null||i==null?null:{x:t,y:n,width:r,height:i,...typeof e.coordinateSpace=="string"?{coordinateSpace:e.coordinateSpace}:{}}}function be(e,t,n){if(!e)return null;if(e.coordinateSpace==="screen")return e;const r=L(e,t,n);if(!r)return e;const i=n.bounds;if(!i?.width||!i?.height)return{...e,x:r.x-e.width/2,y:r.y-e.height/2,coordinateSpace:"screen"};const o=i.width/t.width,s=i.height/t.height,a=r.x,c=r.y;return{x:a-e.width*o/2,y:c-e.height*s/2,width:e.width*o,height:e.height*s,coordinateSpace:"screen"}}function Rt(e,t,n){if(!e)return null;if(e.coordinateSpace!=="screen")return{...e,coordinateSpace:"screenshotPixel"};const r=n.bounds;if(!r?.width||!r?.height)return null;const i=t.width/r.width,o=t.height/r.height;return{x:(e.x-r.x)*i,y:(e.y-r.y)*o,width:e.width*i,height:e.height*o,coordinateSpace:"screenshotPixel"}}function b(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function I(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function h(e){return typeof e=="string"?e.trim():""}function g(e){return h(e)||null}function _(e){const t=Number(e);return Number.isFinite(t)?t:null}async function Bn(e,t){await ye(e,t)}async function Ft(e,t){await ge(e,t)}async function ge(e,t){const n=await e.request("permissions.check",{},t);m(n,"permissions.check");const r=n.result??{},i=await At(e,r,t);if(i==="screen-recording")throw new Error("permission_screen_recording_missing");if(i==="accessibility")throw new Error("permission_accessibility_missing");if(i==="input-monitoring")throw new Error("permission_input_monitoring_missing");if(r.automation===!1)throw new Error("permission_automation_missing");return r}async function ye(e,t,n={}){const r=await ge(e,t),i=String(r.platform??"").toLowerCase();if(r.wechatRunning===!1)throw new Error("wechat_not_running");if(Kt(r))throw new Error("windows_visible_desktop_unavailable");if(r.dpiMappingAvailable===!1||r.displayTopologySupported===!1)throw new Error("dpi_mapping_failed");if(r.wechatMainWindowResponsive===!1)throw new Error("wechat_window_unresponsive");if(r.wechatWindowAvailable===!1&&i!=="win32"&&n.allowUnavailableWindow!==!0)throw new Error("wechat_window_unavailable");return r}async function At(e,t,n){const r=Dt(t);if(!r||process.platform!=="darwin")return r;const i=Lt(r);try{await e.request(i,{},n)}catch{}return r}function Dt(e){return e.screenRecording===!1?"screen-recording":e.accessibility===!1?"accessibility":e.inputMonitoring===!1?"input-monitoring":null}function Lt(e){return e==="screen-recording"?"permissions.requestScreenRecording":e==="accessibility"?"permissions.requestAccessibility":"permissions.requestInputMonitoring"}async function Ot(e,t,n={}){const i=(n.foreground??"required")!=="background",o=await ye(e,t,{allowUnavailableWindow:i});if(String(o.platform??"").toLowerCase()==="win32"){const c=await e.request("windows.ensureReady",{activate:i,allowRecovery:!1,allowLaunch:!1},t);m(c,"windows.ensureReady");const l=c.result;if(!l?.windowId)throw new Error("helper_invalid_response: windows.ensureReady missing WeChat window data");return l}const s=await e.request("windows.ensureReady",{restore:i,focus:i},t);m(s,"windows.ensureReady");const a=s.result;if(!a?.windowId)throw new Error("helper_invalid_response: windows.ensureReady missing WeChat window data");return a}function Kt(e){return e.windowsVisibleDesktopAvailable===!1||e.rdpVisibleDesktopAvailable===!1||e.desktopSessionVisible===!1||e.screenLocked===!0||e.rdpDisconnected===!0}function xe(e){const t=e.filter(q),n=t.filter(i=>i.visible!==!1&&i.minimized!==!0);return(n.length?n:t)[0]??null}async function En(e,t){let n=await e.request("windows.list",{},t);m(n,"windows.list");let r=n.result?.windows??[],i=xe(r);if(!i)throw new Error("wechat_window_not_found");const o=await e.request("windows.focus",{windowId:i.windowId},t);return m(o,"windows.focus"),await ve(e,i,t)}async function pe(e,t,n){if(!t.windowId)throw new Error("wechat_window_not_found");const r=await e.request("windows.focus",{windowId:t.windowId},n);return m(r,"windows.focus"),t}async function $t(e,t){const n=await e.request("windows.list",{},t);m(n,"windows.list");const r=n.result?.windows??[],i=xe(r);if(!i)throw new Error("wechat_window_not_found");const o=await e.request("windows.focus",{windowId:i.windowId},t);return m(o,"windows.focus"),await ve(e,i,t)}async function ve(e,t,n){let r;try{r=await e.request("windows.list",{},n)}catch{return t}if(!r.ok)return t;const i=(r.result?.windows??[]).filter(q);return i.find(o=>o.windowId===t.windowId)??i[0]??t}async function $(e){const{capture:t,ocr:n}=e.observation??await k(e),r=B({capture:t,ocr:n,window:e.window});if(r)return{opened:!1,reason:r};const i=qe({visibleItems:Jt(n,t,e.allowOcrTitleRows!==!1),targets:[{bindingId:e.binding.bindingId,conversationDisplayName:e.binding.conversationDisplayName}]})[0];if(!i)return{opened:!1,reason:"conversation_not_visible"};const o=fn(i.item.bbox,t,e.window);if(!o)return{opened:!1,reason:"conversation_bbox_missing"};const s=await e.helper.request("mouse.click",{x:o.x,y:o.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);return m(s,"mouse.click"),{opened:!0,reason:i.reason}}async function z(e){let t={opened:!1,reason:"conversation_not_opened"};for(let r=0;r<He;r+=1){if(t=await zt(e),t.opened||t.reason!=="conversation_title_not_confirmed")return t;await S(e,"open-retry",`retry:${r}`)}const n=await Ce(e);return n.opened?{opened:!0,reason:`${n.reason}:final-visible-recovery`}:t}async function zt(e){const t=await k(e),n=B({capture:t.capture,ocr:t.ocr,window:e.window});if(n)return{opened:!1,reason:n};let r=!1;if(D(t.ocr,t.capture,e.binding.conversationDisplayName))return e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId,observation:t}),{opened:!0,reason:"current-conversation-title-confirmed"};if(!r){const u=await $({...e,observation:t});if(u.opened){if(await S(e,"open-click-settle","visible-initial"),(await M(e)).ok)return{opened:!0,reason:u.reason};const f=await Ce(e);if(f.opened)return f}}const i=await Yt(e,t.capture);if(!i.ok)return{opened:!1,reason:i.reason};const o=await e.helper.request("wechat.searchConversation",{conversationName:e.binding.conversationDisplayName,windowId:e.window.windowId,waitMs:e.searchDelayMs??F(e,"search-input-settle","search-input"),searchPoint:i.point},e.traceId);m(o,"wechat.searchConversation");const s=await Vt(e);if(s.opened){await S(e,"open-click-settle","search-result-click");const u=await M(e);return u.ok?(e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:s.reason}):{opened:!1,reason:u.reason}}let a=s.observation;const c=y(e.binding.conversationDisplayName)&&s.reason==="search_result_not_visible";if(!y(e.binding.conversationDisplayName)){await Xt(e.helper,e.traceId),await S(e,"open-click-settle","search-return");const u=await M(e);if(u.ok)return e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:u.reason};const d=await e.helper.request("wechat.searchConversation",{conversationName:e.binding.conversationDisplayName,windowId:e.window.windowId,waitMs:e.searchDelayMs??F(e,"search-input-settle","search-input-retry-after-return"),searchPoint:i.point},e.traceId);m(d,"wechat.searchConversation"),a=void 0}const l=await $({...e,...a?{observation:a}:{},allowOcrTitleRows:!c});if(!l.opened)return l;await S(e,"open-click-settle","visible-final");const w=await M(e);return w.ok?(e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:l.reason}):{opened:!1,reason:w.reason}}async function Ce(e){const t=await $(e);if(!t.opened)return t;await S(e,"open-click-settle","visible-retry");const n=await M(e);return n.ok?(e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:`${t.reason}:retry-visible-title-confirmed`}):{opened:!1,reason:n.reason}}async function Vt(e){let t;const n=e.searchDelayMs===0?0:F(e,"search-result-probe","search-result-probe"),r=y(e.binding.conversationDisplayName)?Ye:1;for(let i=0;i<r;i+=1){i>0&&n>0&&await j(n);const o=await qt(e);t=o;const{capture:s,ocr:a}=o,c=B({capture:s,ocr:a,window:e.window});if(c)return{opened:!1,reason:c,observation:o};const l=en(a,s,e.binding.conversationDisplayName);if(!l){if(tn(a)||nn(a,e.binding.conversationDisplayName))break;continue}const w=L(l.bbox,s,jt(s,e.window));if(!w)return{opened:!1,reason:"search_result_bbox_missing",observation:o};const u=await e.helper.request("mouse.click",{x:w.x,y:w.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);return m(u,"mouse.click"),{opened:!0,reason:l.reason,observation:o}}return{opened:!1,reason:"search_result_not_visible",observation:t}}async function qt(e){if(e.window.bounds&&y(e.binding.conversationDisplayName)){const t=await e.helper.request("screen.capture",{bounds:e.window.bounds},e.traceId);if(t.ok&&t.result?.dataBase64&&t.result.width&&t.result.height){const n={...t.result,windowId:e.window.windowId,bounds:t.result.bounds??e.window.bounds},r=await _e(e.helper,n,e.traceId);return{capture:n,ocr:r}}t.errorCode&&t.errorCode!=="helper_unknown_command"&&t.errorCode!=="helper_command_unsupported"&&m(t,"screen.capture")}return k(e)}function jt(e,t){return e.bounds?{...t,bounds:e.bounds}:t}async function k(e){let{capture:t,ocr:n}=await V(e.helper,e.window.windowId,e.traceId,e.window.bounds);return await Gt({helper:e.helper,window:e.window,capture:t,ocr:n,traceId:e.traceId})&&(await J("preview-dismiss-settle",`${e.traceId||""}:${e.window.windowId}:preview-dismiss`),{capture:t,ocr:n}=await V(e.helper,e.window.windowId,e.traceId,e.window.bounds)),{capture:t,ocr:n}}async function Gt(e){const t=Ht(e.ocr,e.capture,e.window);if(!t)return!1;for(const n of[async()=>e.helper.request("keyboard.shortcut",{key:"escape",modifiers:[]},e.traceId),async()=>e.helper.request("mouse.click",{x:t.x,y:t.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId)])if((await n()).ok)return!0;return!1}function Ht(e,t,n){const r=e.blocks??[],i=r.find(c=>{const l=String(c.text||""),w=c.bbox;if(!w)return!1;const u=Number(w.x),d=Number(w.y);return Number.isFinite(u)&&Number.isFinite(d)&&d>t.height*.06&&d<t.height*.22&&u>t.width*.3&&/查看原视频|查看原图|原视频|原图|视频|图片|图像/.test(l)});if(!i)return null;const o=i.bbox,s=Number(o?.y);if(!Number.isFinite(s))return null;const a=r.filter(c=>{const l=String(c.text||"").trim(),w=c.bbox;if(!w||l!=="\xD7")return!1;const u=Number(w.x),d=Number(w.y);return Number.isFinite(u)&&Number.isFinite(d)&&u>t.width*.55&&u<t.width*.9&&Math.abs(d-s)<t.height*.08}).sort((c,l)=>Number(l.bbox?.x??0)-Number(c.bbox?.x??0))[0];return L(a?.bbox,t,n)}async function Yt(e,t){if(!e.runtime||!e.api?.classifyWindow)return{ok:!1,reason:"wechat_search_input_detector_unavailable"};try{return{ok:!0,point:await Qe({runtime:e.runtime,binding:e.binding,helper:e.helper,api:e.api,workDir:e.workDir,traceId:e.traceId,window:e.window,...t.dataBase64?{screenshot:t}:{}})}}catch(n){return{ok:!1,reason:n instanceof Error?n.message:"wechat_search_input_not_found"}}}async function R(e,t,n,r){const i=await e.request("windows.capture",{windowId:t,scope:"full-window",...r?{bounds:r}:{}},n);m(i,"windows.capture");const o=i.result;if(!o?.dataBase64||!o.mimeType||!o.width||!o.height)throw new Error("helper_invalid_response: windows.capture missing screenshot data");return o}async function Ie(e){return e.capture.dataBase64?e.capture:R(e.helper,e.window.windowId,e.traceId,e.window.bounds)}async function V(e,t,n,r){const i=await e.request("windows.captureAndOcr",{windowId:t,scope:"full-window",...r?{bounds:r}:{}},n);if(i.ok&&i.result?.capture&&i.result?.ocr)return{capture:i.result.capture,ocr:i.result.ocr};!i.ok&&i.errorCode&&i.errorCode!=="helper_unknown_command"&&i.errorCode!=="helper_command_unsupported"&&m(i,"windows.captureAndOcr");const o=await R(e,t,n,r),s=await _e(e,o,n);return{capture:o,ocr:s}}async function _e(e,t,n){const r=await e.request("ocr.recognize",{mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height},n);return m(r,"ocr.recognize"),r.result??{}}function m(e,t){if(!e.ok)throw new Error(`${e.errorCode||"helper_command_failed"}: ${e.errorSummary||t}`)}function q(e){const t=String(e.appName||"").toLowerCase();return t==="wechat"||t==="weixin"||t==="\u5FAE\u4FE1"}function j(e){return new Promise(t=>setTimeout(t,e))}function F(e,t,n){return e.searchDelayMs===0?0:Ve(t,Ut(e,n))}async function S(e,t,n){const r=F(e,t,n);r>0&&await j(r)}function Ut(e,t){return`${e.traceId||""}:${e.binding.conversationDisplayName}:${t}`}async function Xt(e,t){const n=await e.request("keyboard.shortcut",{key:"return",modifiers:[]},t);m(n,"keyboard.shortcut")}async function T(e){if(!e.window.bounds)return;const t=e.observation,n=mn(t?.ocr,t?.capture,e.window);if(n){const r=await e.helper.request("mouse.click",{x:n.x,y:n.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);m(r,"mouse.click"),await J("jump-latest-settle",`${e.traceId||""}:${e.window.windowId}:jump-latest`)}}async function M(e){const{capture:t,ocr:n}=await V(e.helper,e.window.windowId,e.traceId,e.window.bounds),r=B({capture:t,ocr:n,window:e.window});return r?{ok:!1,reason:r}:D(n,t,e.binding.conversationDisplayName)?{ok:!0,reason:"target-conversation-title-confirmed"}:{ok:!1,reason:"conversation_title_not_confirmed"}}function B(e){const n=(e.ocr.blocks??[]).map(r=>on(r.text)).filter(Boolean).join("");return/(扫码登录|仅传输文件|重新登录|为了安全|安全验证|登录微信|微信登录|该账号已登录|帐号已登录|账号已登录|当前账号已登录|当前帐号已登录|已登录|进入微信|進入微信)/u.test(n)?Ue:null}function Jt(e,t,n=!0){const r=n?Zt(e.blocks??[],t):[];return r.length?r:e.visibleConversationFingerprints??[]}function Zt(e,t){const n=e.map(i=>ke(i)).filter(i=>!!i).filter(i=>i.text.length>=2).filter(i=>i.x>t.width*.08&&i.x<t.width*.38).filter(i=>i.y>t.height*.06&&i.y<t.height*.96).filter(i=>!Se(i.text)),r=new Set;return n.filter(i=>!Qt(i,n,t)).sort((i,o)=>i.y-o.y||i.x-o.x).map(i=>{const o=i.text.trim();return{title:o,bbox:{x:Math.max(0,i.x-24),y:Math.max(0,i.y-Math.max(24,i.height)),width:Math.max(120,t.width*.3),height:Math.max(48,i.height+40),coordinateSpace:"screenshotPixel"},fingerprint:o.toLowerCase()}}).filter(i=>{const o=E(i.title);return!o||r.has(o)?!1:(r.add(o),!0)})}function ke(e){const t=e.bbox,n=String(e.text||"").normalize("NFKC").trim(),r=Number(t?.x),i=Number(t?.y),o=Number(t?.width),s=Number(t?.height);return!n||![r,i,o,s].every(Number.isFinite)?null:{text:n,x:r,y:i,width:o,height:s}}function Qt(e,t,n){const r=Math.max(36,Math.min(64,n.height*.058));return t.some(i=>i!==e&&i.y<e.y&&e.y-i.y<=r&&Math.abs(i.x-e.x)<=16&&i.height>=e.height*.85)}function Se(e){const t=p(e);return/^(搜索|微信|通讯录|收藏|设置|search)$/iu.test(t)||A(t)||rn(t)||/^包含[::]?/u.test(t)||/搜索网络结果/u.test(t)}function en(e,t,n){const r=(e.blocks??[]).map(a=>ke(a)).filter(a=>!!a),i=r.filter(a=>A(p(a.text))).sort((a,c)=>a.y-c.y||a.x-c.x),o=["\u7FA4\u804A","GroupChats","\u8054\u7CFB\u4EBA","Contacts"];for(const a of o){const c=i.findIndex(d=>p(d.text)===a);if(c<0)continue;const l=i[c],w=i[c+1]?.y??Number.POSITIVE_INFINITY,u=r.filter(d=>d.y>l.y&&d.y<w).filter(d=>d.x<t.width*.7).filter(d=>d.text.length>=2).filter(d=>!A(p(d.text))).filter(d=>!Ne(d,r)).filter(d=>H(d.text,n)).sort((d,f)=>d.y-f.y||d.x-f.x)[0];if(u)return{bbox:Me(u,t),reason:"search-result-title"}}const s=r.filter(a=>a.y>t.height*.12&&a.y<t.height*.82).filter(a=>a.x>t.width*.08&&a.x<t.width*.45).filter(a=>a.text.length>=2).filter(a=>!Se(a.text)).filter(a=>!Ne(a,r)).filter(a=>H(a.text,n)).sort((a,c)=>a.y-c.y||a.x-c.x)[0];return y(n)?null:s?{bbox:Me(s,t),reason:"search-result-title"}:null}function Me(e,t){return{x:Math.max(0,e.x-24),y:Math.max(0,e.y-12),width:Math.max(e.width+t.width*.18,160),height:Math.max(e.height+28,44),coordinateSpace:"screenshotPixel"}}function A(e){return/^(群聊|联系人|聊天记录|公众号|小程序|GroupChats|Contacts|ChatHistory|OfficialAccounts|MiniPrograms)$/u.test(e)}function tn(e){return(e.blocks??[]).some(t=>A(p(t.text)))}function nn(e,t){return(e.visibleConversationFingerprints??[]).some(n=>H(n.title,t))}function p(e){return String(e||"").normalize("NFKC").replace(/[^\p{L}\p{N}_-]/gu,"").trim()}function Ne(e,t){return/^包含[::]?/u.test(e.text.trim())?!0:t.some(n=>n!==e&&Math.abs(n.y-e.y)<=Math.max(18,e.height)&&n.x<e.x&&/^包含[::]?/u.test(n.text.trim()))}function rn(e){const t=String(e||"").trim();return!!(/^(星期[一二三四五六日天]|周[一二三四五六日天])\s*\d{1,2}:\d{2}$/u.test(t)||/^\d{1,2}:\d{2}(?::\d{2})?$/u.test(t)||/^\d{4}[-/.年]\d{1,2}(?:[-/.月]\d{1,2}日?)?$/u.test(t)||/^\d{1,2}[-/.月]\d{1,2}日?$/u.test(t))}function on(e){return String(e||"").normalize("NFKC").replace(/\s+/g,"").trim()}function D(e,t,n){const r=y(n)?E(n):O(n);return r?(e.blocks??[]).some(i=>{const o=y(n)?E(i.text):O(i.text);if(!o||!Ee(o,r))return!1;const s=i.bbox;if(!s)return!1;const a=Number(s.x),c=Number(s.y);if(!Number.isFinite(a)||!Number.isFinite(c))return!1;const l=a>t.width*.32&&a<t.width*.78&&c<t.height*.16,w=a<t.width*.18&&c<t.height*.12;return l||w}):!1}function G(e){if(D(e.ocr,e.capture,e.binding.conversationDisplayName))return!1;const t=(e.ocr.blocks??[]).map(a=>String(a.text||"").normalize("NFKC").replace(/\s+/g," ").trim()).filter(Boolean),n=t.join(`
|
|
1
|
+
import P from"node:fs";import J from"node:path";import{WeChatChannelApiError as Ae}from"./client.js";import{defaultWeChatChannelAttachmentDir as Fe,resolveVisibleWeChatChannelMedia as De}from"./media-resolver.js";import{updateWeChatChannelBindingLedger as Le}from"./ledger.js";import{defaultWeChatChannelVectorStorePath as Oe,loadWeChatChannelVectorStore as Ke,saveWeChatChannelVectorStore as $e,upsertWeChatChannelVectorReferences as Ve}from"./vector-store.js";import{normalizeWeChatChannelAttachmentAvailability as Z,normalizeWeChatChannelMessageKind as ze}from"./core/schema.js";import{waitForWeChatChannelPacing as Q,weChatChannelPacingDelayMs as qe}from"./pacing.js";import{matchWeChatConversationFingerprints as je}from"./fingerprint.js";import{normalizeWeChatAnchorText as v,weChatTextSimilarity as ee}from"./anchor.js";import{decideWeChatChannelActivityGate as Ge,normalizeWeChatChannelActivitySnapshot as He}from"./human-coordination.js";const Ue=3,Ye=5,Xe="wechat_login_required",Je=5500;class N extends Error{reasonCode;stage;action;constructor(t){super(`user_active:${t.reasonCode}:${t.stage}:${t.action}`),this.name="WeChatChannelUserActivityAbort",this.reasonCode=t.reasonCode,this.stage=t.stage,this.action=t.action}}async function Tn(e){return await lt(e.helper,e.activityGuard,e.traceId).withLease("observe","observe-binding",async n=>Ze({...e,helper:n}))}async function Ze(e){const t=e.foregroundMode??"required";let n=await Qe(e,{foregroundMode:t});if(t!=="background"&&(n=await pe(e.helper,n,e.traceId)),t==="background"){const{capture:s,ocr:a}=await k({helper:e.helper,window:n,traceId:e.traceId}),c=E({capture:s,ocr:a,window:n});if(c)throw new Error(c);if(!O(a,s,e.binding.conversationDisplayName))throw new Error("conversation_not_visible_background");if(U({capture:s,ocr:a,binding:e.binding}))throw new Error("wechat_window_obstructed_background");return e.onObservationEvidence?.({window:n,capture:s,ocr:a}),ce(e)?de({...e,window:n,capture:s,ocr:a}):V({...e,window:n,capture:s,ocr:a})}const r=await q({helper:e.helper,window:n,binding:e.binding,runtime:e.runtime,api:e.api,workDir:e.workDir,traceId:e.traceId});if(!r.opened){const s=await ae({...e,fallback:n,requireTargetConversation:!1,force:!0});if(s.windowId!==n.windowId){n=await pe(e.helper,s,e.traceId);const a=await q({helper:e.helper,window:n,binding:e.binding,runtime:e.runtime,api:e.api,workDir:e.workDir,traceId:e.traceId});if(!a.opened)throw new Error(a.reason||r.reason||"conversation_not_opened")}else throw new Error(r.reason||"conversation_not_opened")}let{capture:i,ocr:o}=await k({helper:e.helper,window:n,traceId:e.traceId});if(U({capture:i,ocr:o,binding:e.binding})){n=await zt(e.helper,e.traceId);const s=await q({helper:e.helper,window:n,binding:e.binding,runtime:e.runtime,api:e.api,workDir:e.workDir,traceId:e.traceId});if(!s.opened)throw new Error(s.reason||"wechat_window_obstructed");if({capture:i,ocr:o}=await k({helper:e.helper,window:n,traceId:e.traceId}),U({capture:i,ocr:o,binding:e.binding}))throw new Error("wechat_window_obstructed")}return e.onObservationEvidence?.({window:n,capture:i,ocr:o}),ce(e)?de({...e,window:n,capture:i,ocr:o}):V({...e,window:n,capture:i,ocr:o})}async function Qe(e,t={}){const n=t.foregroundMode??e.foregroundMode??"required",r=await $t(e.helper,e.traceId,{foreground:n});return n==="background"?r:ae({...e,fallback:r,requireTargetConversation:!1,force:t.forceVision})}const x=new Map;function et(){return process.env.SHENNIAN_WECHAT_VISION_LAYOUT_REUSE!=="0"}function tt(e){if(!et()||!e.classification||e.classification.windowKind!=="chat_main")return;const t=e.window.windowId;if(!t)return;const n=oe(e.window),r=R(e.classification.layout?.messageInputRect,e.screenshot,e.window,"message-input"),i=R(e.classification.layout?.searchInputRect,e.screenshot,e.window,"search-input");if(!r&&!i)return;const o={windowId:t,boundsKey:n,messageInputPoint:r,searchInputPoint:i,updatedAt:new Date().toISOString()},s=`${e.runtime.runtimeId}:${e.binding.bindingId}:${t}`,a=`${e.runtime.runtimeId}:window:${t}:${n}`;x.set(s,o),x.set(a,o),W(e,s,o),W(e,a,o)}async function En(e){const t=await te(e,"messageInputPoint");if(!t.messageInputPoint)throw new Error("wechat_message_input_not_found:vision_rect_missing");return t.messageInputPoint}async function nt(e){const t=await te(e,"searchInputPoint");if(!t.searchInputPoint)throw new Error("wechat_search_input_not_found:vision_rect_missing");return t.searchInputPoint}async function te(e,t){const n=t==="searchInputPoint"?"wechat_search_input":"wechat_message_input";if(!e.api.classifyWindow)throw new Error(`${n}_detector_unavailable`);const r=e.window.windowId,i=oe(e.window),o=`${e.runtime.runtimeId}:${e.binding.bindingId}:${r||"unknown"}`,s=`${e.runtime.runtimeId}:window:${r||"unknown"}:${i}`,a=x.get(o)??x.get(s)??re(e,o)??re(e,s);if(a&&a.windowId===r&&a.boundsKey===i&&(!t||a[t]))return x.set(o,a),x.set(s,a),a;const c=e.screenshot??await F(e.helper,r,e.traceId,e.window.bounds),l=await e.api.classifyWindow(e.runtime,e.binding,{screenshot:{mimeType:c.mimeType,dataBase64:c.dataBase64,width:c.width,height:c.height,windowId:r},traceId:e.traceId});if(l.windowKind!=="chat_main")throw new Error(`${n}_not_found:${l.windowKind||"unknown_window"}`);const w=R(l.layout?.messageInputRect,c,e.window,"message-input"),u=R(l.layout?.searchInputRect,c,e.window,"search-input"),d={windowId:r||"",boundsKey:i,messageInputPoint:w,searchInputPoint:u,updatedAt:new Date().toISOString()};return x.set(o,d),x.set(s,d),W(e,o,d),W(e,s,d),d}function ne(e){const t=e.workDir;return t?J.join(t,"wechat-channel",e.runtime.runtimeId,"vision-layout-point-cache.json"):null}function re(e,t){const n=ne(e);if(!n)return null;try{const r=JSON.parse(P.readFileSync(n,"utf8"));return rt(r[t])}catch{return null}}function W(e,t,n){const r=ne(e);if(r)try{let i={};try{i=JSON.parse(P.readFileSync(r,"utf8"))}catch{i={}}i[t]=n,P.mkdirSync(J.dirname(r),{recursive:!0}),P.writeFileSync(r,`${JSON.stringify(i,null,2)}
|
|
2
|
+
`,"utf8")}catch{}}function rt(e){if(!e||typeof e!="object")return null;const t=e,n=typeof t.windowId=="string"?t.windowId:"",r=typeof t.boundsKey=="string"?t.boundsKey:"";if(!r)return null;const i=ie(t.messageInputPoint??t.point),o=ie(t.searchInputPoint);return{windowId:n,boundsKey:r,messageInputPoint:i,searchInputPoint:o,...typeof t.updatedAt=="string"?{updatedAt:t.updatedAt}:{}}}function ie(e){if(!e||typeof e!="object")return null;const t=e,n=Number(t.x),r=Number(t.y);return!Number.isFinite(n)||!Number.isFinite(r)?null:{x:Math.round(n),y:Math.round(r),coordinateSpace:"screen"}}function oe(e){const t=e.bounds;return[Math.round(Number(t?.x??0)),Math.round(Number(t?.y??0)),Math.round(Number(t?.width??0)),Math.round(Number(t?.height??0))].join(",")}function R(e,t,n,r="message-input"){const i=Number(e?.x),o=Number(e?.y),s=Number(e?.width),a=Number(e?.height);if(![i,o,s,a].every(Number.isFinite)||s<=0||a<=0)return null;const c=e?.coordinateSpace==="screen"?{x:i,y:o,width:s,height:a,coordinateSpace:"screen"}:{x:i/999*t.width,y:o/999*t.height,width:s/999*t.width,height:a/999*t.height,coordinateSpace:"screenshotPixel"},l=it(c,t,n,r);return l?{x:Math.round(l.x),y:Math.round(l.y),coordinateSpace:"screen"}:null}function it(e,t,n,r="message-input"){const i=r==="message-input"?.28:.55,o=ot({x:e.x+e.width*.54,y:e.y+e.height*i,coordinateSpace:e.coordinateSpace},t,n);return o?{x:o.x,y:o.y,coordinateSpace:"screen"}:null}function ot(e,t,n){if(![e.x,e.y].every(Number.isFinite))return null;if(e.coordinateSpace==="screen"||!n.bounds)return{x:e.x,y:e.y};const r=t.width&&n.bounds.width?t.width/n.bounds.width:1,i=t.height&&n.bounds.height?t.height/n.bounds.height:r,o=Math.max(0,(t.width-n.bounds.width*r)/2),s=Math.max(0,(t.height-n.bounds.height*i)/2);return{x:n.bounds.x+(e.x-o)/r,y:n.bounds.y+(e.y-s)/i}}async function ae(e){if(!e.api.classifyWindow)throw new Error("wechat_window_classifier_unavailable");const t=await e.helper.request("windows.list",{},e.traceId);m(t,"windows.list");const n=(t.result?.windows??[]).filter(G).filter(s=>s.visible!==!1&&s.minimized!==!0&&!!s.windowId),r=ct(n.length?n:[e.fallback],e.fallback);if(!r.length)throw new Error("wechat_window_not_found");const i=[];for(const s of r)try{const a=await F(e.helper,s.windowId,e.traceId,s.bounds),c=await e.api.classifyWindow(e.runtime,e.binding,{screenshot:{mimeType:a.mimeType,dataBase64:a.dataBase64,width:a.width,height:a.height,windowId:s.windowId},traceId:e.traceId});i.push({window:s,classification:c,screenshot:a,score:dt(c,e.requireTargetConversation===!0)})}catch(a){if(at(a))throw a;i.push({window:s,classification:null,errorSummary:a instanceof Error?a.message:String(a||"window classification failed"),score:-1})}const o=i.filter(s=>s.score>0).sort((s,a)=>a.score-s.score)[0];if(!o){const s=i.map(a=>({windowId:a.window.windowId,appName:a.window.appName,title:a.window.title,score:a.score,errorSummary:a.errorSummary,classification:a.classification?{windowKind:a.classification.windowKind,reasonCode:a.classification.reasonCode,confidence:a.classification.confidence,conversationTitle:a.classification.conversationTitle,isTargetConversation:a.classification.isTargetConversation}:null}));throw new Error(`wechat_chat_main_window_not_found: ${JSON.stringify(s)}`)}return o.screenshot&&tt({helper:e.helper,runtime:e.runtime,binding:e.binding,workDir:e.workDir,traceId:e.traceId,window:o.window,classification:o.classification,screenshot:o.screenshot}),o.window}async function Bn(e,t,n){if(e.runtime.policy.platform!=="win32")return;const r=t.filter(i=>{if(i.window.windowId===n.window.windowId||!i.window.windowId)return!1;const o=i.classification?.windowKind;return o==="chat_main"||o==="login"});if(r.length!==0)for(const i of r)try{await e.helper.request("windows.closeWindow",{windowId:i.window.windowId},e.traceId)}catch{}}function at(e){const t=st(e);return t==="insufficient_credits"||t==="entitlement_required"||t==="manual_review_required"||t==="wechat_channel_network_failed"||t==="wechat_channel_invalid_response"}function st(e){if(e instanceof Ae||e&&typeof e=="object"&&typeof e.reasonCode=="string")return e.reasonCode.trim().toLowerCase();const t=e instanceof Error?e.message:String(e||"");return/classify-window (?:network )?failed:\s*([a-z][a-z0-9_]*)/i.exec(t)?.[1]?.trim().toLowerCase()||""}function ct(e,t){const n=[],r=i=>{i?.windowId&&(n.some(o=>o.windowId===i.windowId)||n.push(i))};r(e.find(i=>i.windowId===t.windowId));for(const i of e)r(i);return n}function dt(e,t){if(!e||e.windowKind!=="chat_main")return 0;const n=Number(e.confidence??0);return t&&e.isTargetConversation!==!0?0:100+(e.isTargetConversation?50:0)+Math.round(Math.max(0,Math.min(1,n))*100)}function lt(e,t,n){if(!t)return{helper:e,withLease:async(a,c,l)=>await l(e)};let r=null;const i=a=>{t.onEvent?.({...a,at:new Date().toISOString()})},o=async(a,c,l={})=>{if(r){const u=await e.request("automation.lease.status",{},n),d=u.result??{},f=u.ok&&d.interrupted?se(d.interruptReason):u.ok?void 0:u.errorCode||"user_activity_unknown";if(i({phase:"lease-status",stage:a,action:c,ok:u.ok===!0&&!d.interrupted,...f?{reasonCode:f}:{}}),!u.ok)throw new N({reasonCode:u.errorCode||"user_activity_unknown",stage:a,action:c});if(d.active===!1||d.leaseId!==r||!d.interrupted)return;throw new N({reasonCode:se(d.interruptReason),stage:a,action:c})}const w=Date.now()+wt(t.preflightIdleSettleTimeoutMs);for(;;){const u=await e.request("activity.snapshot",{},n);if(!u.ok)throw i({phase:"snapshot",stage:a,action:c,ok:!1,reasonCode:u.errorCode||"user_activity_unknown"}),new N({reasonCode:u.errorCode||"user_activity_unknown",stage:a,action:c});const d=Ge({snapshot:He(u.result),stage:a,policy:t.policy});if(i({phase:"snapshot",stage:a,action:c,ok:d.ok,...d.ok?{}:{reasonCode:d.reasonCode,waitMs:d.waitMs}}),d.ok)return;const f=new N({reasonCode:d.reasonCode,stage:a,action:c});if(!l.settle)throw f;const X=w-Date.now();if(X<=0)throw f;await H(Math.max(50,Math.min(d.waitMs,X)))}},s={request:async(a,c,l)=>{const w=ut(a);w&&await o(w.stage,`${a}:before`);const u=await e.request(a,c,l);return w&&u.ok&&await o(w.stage,`${a}:after`),u}};return{helper:s,async withLease(a,c,l){if(await Dt(e,n),await o(a,`${c}:preflight`,{settle:!0}),t.useAutomationLease===!1)return await l(s);const w=await e.request("automation.lease.acquire",{owner:"wechat-channel",purpose:`observe:${c}`,ttlMs:12e4},n);if(r=typeof w.result?.leaseId=="string"?w.result.leaseId:null,i({phase:"lease-acquire",stage:a,action:c,ok:w.ok===!0,...w.ok?{}:{reasonCode:w.errorCode||"user_activity_unknown"}}),!w.ok)throw r=null,new N({reasonCode:w.errorCode||"user_activity_unknown",stage:a,action:c});try{const u=await l(s);return await o(a,`${c}:complete`),u}finally{const u=r;if(r=null,u){const d=await e.request("automation.lease.release",{leaseId:u},n).catch(f=>({ok:!1,errorCode:"automation_lease_release_failed",errorSummary:f instanceof Error?f.message:String(f)}));i({phase:"lease-release",stage:a,action:c,ok:d.ok===!0,...d.ok?{}:{reasonCode:d.errorCode||"automation_lease_release_failed"}})}}}}}function ut(e){return e==="windows.ensureReady"||e==="windows.focus"||e==="wechat.searchConversation"?{stage:"open_conversation"}:e==="keyboard.shortcut"||e==="mouse.click"||e==="mouse.rightClick"||e==="mouse.scroll"||e==="clipboard.snapshot"||e==="clipboard.readAttachment"||e==="menu.pickItem"?{stage:"dangerous_action"}:null}function se(e){return e==="recent_mouse_activity"||e==="recent_mouse_click"||e==="recent_scroll_activity"||e==="recent_keyboard_activity"||e==="frontmost_app_changed"?e:"user_activity_unknown"}function wt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:Je}function ce(e){return e.observePipeline==="edge-structure"?!0:e.observePipeline==="server-observe"?!1:!!e.api.structureWindow}async function V(e){const t=await _e(e),n=await e.api.observe(e.runtime,e.binding,{screenshots:[{captureIndex:0,mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height}],edgeOcrBlocks:e.ocr.blocks??[],visibleConversationFingerprints:e.ocr.visibleConversationFingerprints??[],localLedgerTailAnchors:e.localLedgerTailAnchors??[],traceId:e.traceId}),r=await he({helper:e.helper,runtime:e.runtime,binding:e.binding,messages:n.observedMessages??[],workDir:e.workDir,attachmentsDir:e.attachmentsDir,window:e.window,screenshot:t,windowId:e.window.windowId,traceId:e.traceId,mediaAnchorText:e.mediaAnchorText});return Be(r,Ee({ocr:e.ocr,screenshot:t,binding:e.binding,anchors:e.localOutboundEchoAnchors??[]}))}async function de(e){if(!e.api.structureWindow)throw new Error("wechat_structure_window_unavailable");const t=await _e(e);let n;try{n=await e.api.structureWindow(e.runtime,e.binding,{screenshots:[{captureIndex:0,mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height}],edgeOcrBlocks:e.ocr.blocks??[],visibleConversationFingerprints:e.ocr.visibleConversationFingerprints??[],localLedgerTailAnchors:e.localLedgerTailAnchors??[],traceId:e.traceId})}catch(c){if(ht(c))return V(e);throw c}const r=Ct(n.structuredMessages??n.observedMessages??[]),i=await ft({...e,messages:r,screenshot:t}),o=await he({helper:e.helper,runtime:e.runtime,binding:e.binding,messages:i.messages,workDir:e.workDir,attachmentsDir:e.attachmentsDir,window:e.window,screenshot:t,windowId:e.window.windowId,traceId:e.traceId,mediaAnchorText:e.mediaAnchorText}),s=Be(o,Ee({ocr:e.ocr,screenshot:t,binding:e.binding,anchors:e.localOutboundEchoAnchors??[]}));return e.localLedger?Le({ledger:e.localLedger,bindingId:e.binding.bindingId,observedMessages:s,baselineOnly:e.baselineOnly,vectorReferences:i.vectorReferences}).newMessages:s}function ht(e){return e instanceof Error&&/\bedge_runtime_disabled\b/.test(e.message)}async function ft(e){const t=mt(e.messages);if(!t.length)return{messages:e.messages,vectorReferences:[]};const n=e.api.embedVisual?await gt({...e,seedBlocks:t}):t.filter(s=>h(s.vectorBase64)||h(s.signature));if(!n.length)return{messages:e.messages,vectorReferences:[]};const r=e.vectorStorePath??Oe(e.workDir||process.cwd(),e.runtime.runtimeId),i=Ke(r,e.runtime.runtimeId),o=Ve({store:i,bindingId:e.binding.bindingId,blocks:n});return o.length?($e(r,i),{messages:vt(e.messages,o),vectorReferences:o}):{messages:e.messages,vectorReferences:[]}}function mt(e){const t=[];for(const n of e)for(const[r,i]of(n.visualBlocks??[]).entries()){const o=h(i.blockId)||`${n.stableMessageKey}:visual-${r}`,s=h(i.blockKind)||n.kind||"visual";t.push({...i,stableMessageKey:n.stableMessageKey,blockId:o,blockKind:s,...i.bbox!==void 0?{bbox:i.bbox}:n.bbox!==void 0?{bbox:n.bbox}:{}})}return t}async function bt(e){if(!e.api.embedVisual)return[];const t=await e.api.embedVisual(e.runtime,e.binding,{screenshots:[{captureIndex:0,mimeType:e.screenshot.mimeType,dataBase64:e.screenshot.dataBase64,width:e.screenshot.width,height:e.screenshot.height}],visualBlocks:e.seedBlocks,traceId:e.traceId});return xt(t.visualBlocks??t.embeddedBlocks??[],e.seedBlocks)}async function gt(e){try{return await bt(e)}catch(t){if(yt(t))throw t;return[]}}function yt(e){return!e||typeof e!="object"?!1:e.reasonCode==="insufficient_credits"?!0:e instanceof Error&&/\binsufficient_credits\b/.test(e.message)}function xt(e,t){return e.map((n,r)=>{const i=t[r];return{...n,stableMessageKey:h(n.stableMessageKey)||h(i?.stableMessageKey),blockId:h(n.blockId)||h(i?.blockId),blockKind:h(n.blockKind)||h(i?.blockKind)||"visual",...n.bbox!==void 0?{bbox:n.bbox}:i?.bbox!==void 0?{bbox:i.bbox}:{}}}).filter(n=>h(n.stableMessageKey)&&h(n.blockId))}function vt(e,t){const n=new Map;for(const r of t){const i=n.get(r.stableMessageKey)??[];i.push(r),n.set(r.stableMessageKey,i)}return e.map(r=>{const i=n.get(r.stableMessageKey);return i?.length?{...r,visualBlocks:pt(r,i)}:r})}function pt(e,t){const r=(e.visualBlocks??[]).map((o,s)=>{const a=h(o.blockId)||`${e.stableMessageKey}:visual-${s}`,c=t.find(l=>l.blockId===a);return c?le(c,o):ue(o)}),i=new Set(r.map(o=>o.blockId));for(const o of t)i.has(o.blockId)||r.push(le(o));return r}function le(e,t){return{...t?ue(t):{},stableMessageKey:e.stableMessageKey,blockId:e.blockId,blockKind:e.blockKind,vectorStoreKey:e.vectorStoreKey,model:e.model,...e.modelVersion!==void 0?{modelVersion:e.modelVersion}:{},dims:e.dims,...e.signature?{signature:e.signature}:{},...e.bbox!==void 0?{bbox:e.bbox}:{}}}function ue(e){const{vectorBase64:t,...n}=e;return n}function Ct(e){return e.map((t,n)=>It(t,n)).filter(t=>t!=null)}function It(e,t){if(!b(e))return null;const n=ze(e.kind),r=St(e.senderRole),i=g(e.normalizedText),o=g(e.anchorText)??i??g(e.textExcerpt),s=h(e.stableMessageKey)||_t({message:e,index:t,senderRole:r,kind:n,anchorText:o});return{stableMessageKey:s,senderRole:r,...g(e.senderName)!==null?{senderName:g(e.senderName)}:{},kind:n,...i!==null?{normalizedText:i}:{},...o!==null?{anchorText:o}:{},...I(e,"anchorMetadata")?{anchorMetadata:e.anchorMetadata}:{},...I(e,"neighborContext")?{neighborContext:e.neighborContext}:{},...g(e.textExcerpt)!==null?{textExcerpt:g(e.textExcerpt)}:{},...I(e,"bbox")?{bbox:e.bbox}:{},...I(e,"mediaMetadata")?{mediaMetadata:kt(e.mediaMetadata)}:{},...typeof e.isBaseline=="boolean"?{isBaseline:e.isBaseline}:{},...g(e.deliveryStatus)!==null?{deliveryStatus:g(e.deliveryStatus)??void 0}:{},...g(e.observedAt)!==null?{observedAt:g(e.observedAt)??void 0}:{},...Array.isArray(e.visualBlocks)?{visualBlocks:e.visualBlocks}:{},...o?{}:{anchorText:s}}}function _t(e){const t=b(e.message.bbox)?JSON.stringify(e.message.bbox):"";return`structured-window:${[e.index,e.senderRole,e.kind,e.anchorText||h(e.message.textExcerpt)||"",t].join(":").slice(0,180)}`}function kt(e){if(!b(e))return e;const t={...e};return I(t,"availability")&&(t.availability=Z(t.availability)),b(t.attachment)&&(t.attachment=we(t.attachment)),Array.isArray(t.attachments)&&(t.attachments=t.attachments.map(n=>b(n)?we(n):n)),t}function we(e){const t={...e};return I(t,"availability")&&(t.availability=Z(t.availability)),t}function St(e){return e==="self"||e==="contact"||e==="system"||e==="unknown"?e:"unknown"}async function he(e){if(e.binding.downloadMedia===!1)return e.messages;const t=e.messages.map((o,s)=>Wt(o,e.screenshot,e.window,Pt(e.messages,s))).filter((o,s)=>Mt(e.messages,s,e.mediaAnchorText)).filter(o=>o!=null);if(!t.length)return e.messages;const n=e.attachmentsDir??Fe(e.workDir||process.cwd(),e.runtime.runtimeId,e.binding.bindingId),r=await De({helper:e.helper,candidates:t,attachmentsDir:n,screenshot:e.screenshot,windowId:e.windowId,window:e.window,traceId:e.traceId,platform:e.runtime.policy.platform,stabilityCheck:async()=>{const o=await M({helper:e.helper,window:e.window,binding:e.binding,traceId:e.traceId});return o.ok?{ok:!0}:{ok:!1,reasonCode:o.reason}}});if(!r.length)return e.messages;const i=new Map(r.map(o=>[o.messageKey,o]));return e.messages.map(o=>{const s=i.get(o.stableMessageKey);return s?{...o,mediaMetadata:Rt(o.mediaMetadata,s.attachment,s.reasonCode,s.attemptReasonCodes,s.resolveTrace)}:o})}function Mt(e,t,n){const r=me(n);if(!r)return!0;const i=Nt(r),o=e.map((s,a)=>me(Bt(s)).includes(r)?a:-1).filter(s=>s>=0);if(!o.length)return t===Tt(e,i);for(const s of o)if(t>=s&&t<=s+8||t===s-1&&!e.slice(s+1,Math.min(e.length,s+9)).some(fe))return!0;return!1}function Nt(e){return e.includes("video")||e.includes("vide0")?"video":e.includes("image")||e.includes("photo")||e.includes("ph0t0")||e.includes("picture")?"image":e.includes("file")||e.includes("document")?"file":null}function Tt(e,t=null){for(let n=e.length-1;n>=0;n-=1)if(fe(e[n]))return Et(e[n],t)?n:-1;return-1}function fe(e){if(!e)return!1;const t=String(e.kind||"").toLowerCase(),n=b(e.mediaMetadata)?e.mediaMetadata:{},r=b(n.attachment)?n.attachment:{};return be(t,n,r)}function Et(e,t){if(!e||!t)return!0;const n=String(e.kind||"").toLowerCase(),r=b(e.mediaMetadata)?e.mediaMetadata:{},i=b(r.attachment)?r.attachment:{},o=String(i.type||"").toLowerCase(),s=String(i.mimeType||"").toLowerCase(),a=String(i.name||i.localPath||e.anchorText||e.textExcerpt||"").toLowerCase();return t==="video"?n.includes("video")||o==="video"||s.startsWith("video/")||/\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(a):t==="image"?/image|photo|picture/.test(n)||o==="image"||s.startsWith("image/")||/\.(png|jpe?g|gif|webp|heic|tiff?|bmp)$/i.test(a):/file|document/.test(n)||o==="file"||!/image|photo|picture|video/.test(n)&&o!=="image"&&o!=="video"&&!s.startsWith("image/")&&!s.startsWith("video/")}function Bt(e){if(!e)return"";const t=e;return[e.normalizedText,e.anchorText,e.textExcerpt,t.text].map(n=>String(n||"")).join(`
|
|
3
|
+
`)}function me(e){return String(e||"").normalize("NFKC").replace(/[o]/giu,"0").replace(/[^\p{L}\p{N}]/gu,"").toLowerCase()}function Pt(e,t){return[e[t-1],e[t],e[t+1]].map(r=>r&&(r.normalizedText||r.anchorText||r.textExcerpt)||"").map(r=>String(r||"").trim()).filter(Boolean).join(`
|
|
4
|
+
`)||null}function Wt(e,t,n,r){const i=String(e.kind||"").toLowerCase(),o=b(e.mediaMetadata)?e.mediaMetadata:{},s=b(o.attachment)?o.attachment:{},a=h(s.availability)||h(o.availability),c=h(s.localPath)||h(o.localPath);if(a==="edge-local"&&c||!be(i,o,s))return null;const l=A(e.bbox)??A(o.bbox)??A(o.downloadActionBbox),w=A(o.downloadActionBbox),u=ge(l,t,n),d=Ft(l,t,n),f=ge(w,t,n);return{messageKey:e.stableMessageKey,kind:h(s.type)||h(s.kind)||h(o.messageType)||i,fileName:h(s.name)||h(s.fileName)||h(o.fileName)||null,mimeType:h(s.mimeType)||h(o.mimeType)||null,size:_(s.size)??_(o.size),mediaStatus:At(o,s),observedAt:e.observedAt??null,contextText:r??e.normalizedText??e.anchorText??e.textExcerpt??null,...u?{bbox:u}:{},...d?{screenshotBbox:d}:{},...f?{downloadActionBbox:f}:{}}}function Rt(e,t,n,r,i){const o=b(e)?{...e}:{};return{...o,availability:b(t)?t.availability:o.availability,mediaStatus:b(t)&&t.availability==="edge-local"?"downloaded":o.mediaStatus,attachment:t,edgeResolveReasonCode:n,...r?.length?{edgeResolveAttempts:r}:{},...i?{edgeResolveTrace:i}:{}}}function At(e,t){const n=h(e.mediaStatus);if(n==="not_downloaded")return"not_downloaded";if(n==="loading"||n==="downloading"||n==="in_progress")return"loading";if(n==="downloaded"||n==="available")return"available";const r=h(t.availability)||h(e.availability);return r==="pending-download"?"not_downloaded":r==="metadata-only"?"metadata_only":n||null}function be(e,t,n){const r=`${e} ${h(t.messageType)} ${h(n.type)} ${h(n.kind)}`.toLowerCase();return/image|photo|video|file|document/.test(r)}function A(e){if(!b(e))return null;const t=_(e.x),n=_(e.y),r=_(e.width),i=_(e.height);return t==null||n==null||r==null||i==null?null:{x:t,y:n,width:r,height:i,...typeof e.coordinateSpace=="string"?{coordinateSpace:e.coordinateSpace}:{}}}function ge(e,t,n){if(!e)return null;if(e.coordinateSpace==="screen")return e;const r=K(e,t,n);if(!r)return e;const i=n.bounds;if(!i?.width||!i?.height)return{...e,x:r.x-e.width/2,y:r.y-e.height/2,coordinateSpace:"screen"};const o=i.width/t.width,s=i.height/t.height,a=r.x,c=r.y;return{x:a-e.width*o/2,y:c-e.height*s/2,width:e.width*o,height:e.height*s,coordinateSpace:"screen"}}function Ft(e,t,n){if(!e)return null;if(e.coordinateSpace!=="screen")return{...e,coordinateSpace:"screenshotPixel"};const r=n.bounds;if(!r?.width||!r?.height)return null;const i=t.width/r.width,o=t.height/r.height;return{x:(e.x-r.x)*i,y:(e.y-r.y)*o,width:e.width*i,height:e.height*o,coordinateSpace:"screenshotPixel"}}function b(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function I(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function h(e){return typeof e=="string"?e.trim():""}function g(e){return h(e)||null}function _(e){const t=Number(e);return Number.isFinite(t)?t:null}async function Pn(e,t){await xe(e,t)}async function Dt(e,t){await ye(e,t)}async function ye(e,t){const n=await e.request("permissions.check",{},t);m(n,"permissions.check");const r=n.result??{},i=await Lt(e,r,t);if(i==="screen-recording")throw new Error("permission_screen_recording_missing");if(i==="accessibility")throw new Error("permission_accessibility_missing");if(i==="input-monitoring")throw new Error("permission_input_monitoring_missing");if(r.automation===!1)throw new Error("permission_automation_missing");return r}async function xe(e,t,n={}){const r=await ye(e,t),i=String(r.platform??"").toLowerCase();if(r.wechatRunning===!1)throw new Error("wechat_not_running");if(Vt(r))throw new Error("windows_visible_desktop_unavailable");if(r.dpiMappingAvailable===!1||r.displayTopologySupported===!1)throw new Error("dpi_mapping_failed");if(r.wechatMainWindowResponsive===!1)throw new Error("wechat_window_unresponsive");if(r.wechatWindowAvailable===!1&&i!=="win32"&&n.allowUnavailableWindow!==!0)throw new Error("wechat_window_unavailable");return r}async function Lt(e,t,n){const r=Ot(t);if(!r||process.platform!=="darwin")return r;const i=Kt(r);try{await e.request(i,{},n)}catch{}return r}function Ot(e){return e.screenRecording===!1?"screen-recording":e.accessibility===!1?"accessibility":e.inputMonitoring===!1?"input-monitoring":null}function Kt(e){return e==="screen-recording"?"permissions.requestScreenRecording":e==="accessibility"?"permissions.requestAccessibility":"permissions.requestInputMonitoring"}async function $t(e,t,n={}){const i=(n.foreground??"required")!=="background",o=await xe(e,t,{allowUnavailableWindow:i});if(String(o.platform??"").toLowerCase()==="win32"){const c=await e.request("windows.ensureReady",{activate:i,allowRecovery:!1,allowLaunch:!1},t);m(c,"windows.ensureReady");const l=c.result;if(!l?.windowId)throw new Error("helper_invalid_response: windows.ensureReady missing WeChat window data");return l}const s=await e.request("windows.ensureReady",{restore:i,focus:i},t);m(s,"windows.ensureReady");const a=s.result;if(!a?.windowId)throw new Error("helper_invalid_response: windows.ensureReady missing WeChat window data");return a}function Vt(e){return e.windowsVisibleDesktopAvailable===!1||e.rdpVisibleDesktopAvailable===!1||e.desktopSessionVisible===!1||e.screenLocked===!0||e.rdpDisconnected===!0}function ve(e){const t=e.filter(G),n=t.filter(i=>i.visible!==!1&&i.minimized!==!0);return(n.length?n:t)[0]??null}async function Wn(e,t){let n=await e.request("windows.list",{},t);m(n,"windows.list");let r=n.result?.windows??[],i=ve(r);if(!i)throw new Error("wechat_window_not_found");const o=await e.request("windows.focus",{windowId:i.windowId},t);return m(o,"windows.focus"),await Ce(e,i,t)}async function pe(e,t,n){if(!t.windowId)throw new Error("wechat_window_not_found");const r=await e.request("windows.focus",{windowId:t.windowId},n);return m(r,"windows.focus"),t}async function zt(e,t){const n=await e.request("windows.list",{},t);m(n,"windows.list");const r=n.result?.windows??[],i=ve(r);if(!i)throw new Error("wechat_window_not_found");const o=await e.request("windows.focus",{windowId:i.windowId},t);return m(o,"windows.focus"),await Ce(e,i,t)}async function Ce(e,t,n){let r;try{r=await e.request("windows.list",{},n)}catch{return t}if(!r.ok)return t;const i=(r.result?.windows??[]).filter(G);return i.find(o=>o.windowId===t.windowId)??i[0]??t}async function z(e){const{capture:t,ocr:n}=e.observation??await k(e),r=E({capture:t,ocr:n,window:e.window});if(r)return{opened:!1,reason:r};const i=je({visibleItems:Qt(n,t,e.allowOcrTitleRows!==!1),targets:[{bindingId:e.binding.bindingId,conversationDisplayName:e.binding.conversationDisplayName}]})[0];if(!i)return{opened:!1,reason:"conversation_not_visible"};const o=bn(i.item.bbox,t,e.window);if(!o)return{opened:!1,reason:"conversation_bbox_missing"};const s=await e.helper.request("mouse.click",{x:o.x,y:o.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);return m(s,"mouse.click"),{opened:!0,reason:i.reason}}async function q(e){let t={opened:!1,reason:"conversation_not_opened"};for(let r=0;r<Ue;r+=1){if(t=await qt(e),t.opened||t.reason!=="conversation_title_not_confirmed")return t;await S(e,"open-retry",`retry:${r}`)}const n=await Ie(e);return n.opened?{opened:!0,reason:`${n.reason}:final-visible-recovery`}:t}async function qt(e){const t=await k(e),n=E({capture:t.capture,ocr:t.ocr,window:e.window});if(n)return{opened:!1,reason:n};let r=!1;if(O(t.ocr,t.capture,e.binding.conversationDisplayName))return e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId,observation:t}),{opened:!0,reason:"current-conversation-title-confirmed"};if(!r){const u=await z({...e,observation:t});if(u.opened){if(await S(e,"open-click-settle","visible-initial"),(await M(e)).ok)return{opened:!0,reason:u.reason};const f=await Ie(e);if(f.opened)return f}}const i=await Xt(e,t.capture);if(!i.ok)return{opened:!1,reason:i.reason};const o=await e.helper.request("wechat.searchConversation",{conversationName:e.binding.conversationDisplayName,windowId:e.window.windowId,waitMs:e.searchDelayMs??D(e,"search-input-settle","search-input"),searchPoint:i.point},e.traceId);m(o,"wechat.searchConversation");const s=await jt(e);if(s.opened){await S(e,"open-click-settle","search-result-click");const u=await M(e);return u.ok?(e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:s.reason}):{opened:!1,reason:u.reason}}let a=s.observation;const c=y(e.binding.conversationDisplayName)&&s.reason==="search_result_not_visible";if(!y(e.binding.conversationDisplayName)){await Zt(e.helper,e.traceId),await S(e,"open-click-settle","search-return");const u=await M(e);if(u.ok)return e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:u.reason};const d=await e.helper.request("wechat.searchConversation",{conversationName:e.binding.conversationDisplayName,windowId:e.window.windowId,waitMs:e.searchDelayMs??D(e,"search-input-settle","search-input-retry-after-return"),searchPoint:i.point},e.traceId);m(d,"wechat.searchConversation"),a=void 0}const l=await z({...e,...a?{observation:a}:{},allowOcrTitleRows:!c});if(!l.opened)return l;await S(e,"open-click-settle","visible-final");const w=await M(e);return w.ok?(e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:l.reason}):{opened:!1,reason:w.reason}}async function Ie(e){const t=await z(e);if(!t.opened)return t;await S(e,"open-click-settle","visible-retry");const n=await M(e);return n.ok?(e.settleToBottom===!0&&await T({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:`${t.reason}:retry-visible-title-confirmed`}):{opened:!1,reason:n.reason}}async function jt(e){let t;const n=e.searchDelayMs===0?0:D(e,"search-result-probe","search-result-probe"),r=y(e.binding.conversationDisplayName)?Ye:1;for(let i=0;i<r;i+=1){i>0&&n>0&&await H(n);const o=await Gt(e);t=o;const{capture:s,ocr:a}=o,c=E({capture:s,ocr:a,window:e.window});if(c)return{opened:!1,reason:c,observation:o};const l=nn(a,s,e.binding.conversationDisplayName);if(!l){if(rn(a)||on(a,e.binding.conversationDisplayName))break;continue}const w=K(l.bbox,s,Ht(s,e.window));if(!w)return{opened:!1,reason:"search_result_bbox_missing",observation:o};const u=await e.helper.request("mouse.click",{x:w.x,y:w.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);return m(u,"mouse.click"),{opened:!0,reason:l.reason,observation:o}}return{opened:!1,reason:"search_result_not_visible",observation:t}}async function Gt(e){if(e.window.bounds&&y(e.binding.conversationDisplayName)){const t=await e.helper.request("screen.capture",{bounds:e.window.bounds},e.traceId);if(t.ok&&t.result?.dataBase64&&t.result.width&&t.result.height){const n={...t.result,windowId:e.window.windowId,bounds:t.result.bounds??e.window.bounds},r=await ke(e.helper,n,e.traceId);return{capture:n,ocr:r}}t.errorCode&&t.errorCode!=="helper_unknown_command"&&t.errorCode!=="helper_command_unsupported"&&m(t,"screen.capture")}return k(e)}function Ht(e,t){return e.bounds?{...t,bounds:e.bounds}:t}async function k(e){let{capture:t,ocr:n}=await j(e.helper,e.window.windowId,e.traceId,e.window.bounds);return await Ut({helper:e.helper,window:e.window,capture:t,ocr:n,traceId:e.traceId})&&(await Q("preview-dismiss-settle",`${e.traceId||""}:${e.window.windowId}:preview-dismiss`),{capture:t,ocr:n}=await j(e.helper,e.window.windowId,e.traceId,e.window.bounds)),{capture:t,ocr:n}}async function Ut(e){const t=Yt(e.ocr,e.capture,e.window);if(!t)return!1;for(const n of[async()=>e.helper.request("keyboard.shortcut",{key:"escape",modifiers:[]},e.traceId),async()=>e.helper.request("mouse.click",{x:t.x,y:t.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId)])if((await n()).ok)return!0;return!1}function Yt(e,t,n){const r=e.blocks??[],i=r.find(c=>{const l=String(c.text||""),w=c.bbox;if(!w)return!1;const u=Number(w.x),d=Number(w.y);return Number.isFinite(u)&&Number.isFinite(d)&&d>t.height*.06&&d<t.height*.22&&u>t.width*.3&&/查看原视频|查看原图|原视频|原图|视频|图片|图像/.test(l)});if(!i)return null;const o=i.bbox,s=Number(o?.y);if(!Number.isFinite(s))return null;const a=r.filter(c=>{const l=String(c.text||"").trim(),w=c.bbox;if(!w||l!=="\xD7")return!1;const u=Number(w.x),d=Number(w.y);return Number.isFinite(u)&&Number.isFinite(d)&&u>t.width*.55&&u<t.width*.9&&Math.abs(d-s)<t.height*.08}).sort((c,l)=>Number(l.bbox?.x??0)-Number(c.bbox?.x??0))[0];return K(a?.bbox,t,n)}async function Xt(e,t){if(!e.runtime||!e.api?.classifyWindow)return{ok:!1,reason:"wechat_search_input_detector_unavailable"};try{return{ok:!0,point:await nt({runtime:e.runtime,binding:e.binding,helper:e.helper,api:e.api,workDir:e.workDir,traceId:e.traceId,window:e.window,...t.dataBase64?{screenshot:t}:{}})}}catch(n){return{ok:!1,reason:n instanceof Error?n.message:"wechat_search_input_not_found"}}}async function F(e,t,n,r){const i=await e.request("windows.capture",{windowId:t,scope:"full-window",...r?{bounds:r}:{}},n);m(i,"windows.capture");const o=i.result;if(!o?.dataBase64||!o.mimeType||!o.width||!o.height)throw new Error("helper_invalid_response: windows.capture missing screenshot data");return o}async function _e(e){return e.capture.dataBase64?e.capture:F(e.helper,e.window.windowId,e.traceId,e.window.bounds)}async function j(e,t,n,r){const i=await e.request("windows.captureAndOcr",{windowId:t,scope:"full-window",...r?{bounds:r}:{}},n);if(i.ok&&i.result?.capture&&i.result?.ocr)return{capture:i.result.capture,ocr:i.result.ocr};!i.ok&&i.errorCode&&i.errorCode!=="helper_unknown_command"&&i.errorCode!=="helper_command_unsupported"&&m(i,"windows.captureAndOcr");const o=await F(e,t,n,r),s=await ke(e,o,n);return{capture:o,ocr:s}}async function ke(e,t,n){const r=await e.request("ocr.recognize",{mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height},n);return m(r,"ocr.recognize"),r.result??{}}function m(e,t){if(!e.ok)throw new Error(`${e.errorCode||"helper_command_failed"}: ${e.errorSummary||t}`)}function G(e){const t=String(e.appName||"").toLowerCase();return t==="wechat"||t==="weixin"||t==="\u5FAE\u4FE1"}function H(e){return new Promise(t=>setTimeout(t,e))}function D(e,t,n){return e.searchDelayMs===0?0:qe(t,Jt(e,n))}async function S(e,t,n){const r=D(e,t,n);r>0&&await H(r)}function Jt(e,t){return`${e.traceId||""}:${e.binding.conversationDisplayName}:${t}`}async function Zt(e,t){const n=await e.request("keyboard.shortcut",{key:"return",modifiers:[]},t);m(n,"keyboard.shortcut")}async function T(e){if(!e.window.bounds)return;const t=e.observation,n=gn(t?.ocr,t?.capture,e.window);if(n){const r=await e.helper.request("mouse.click",{x:n.x,y:n.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);m(r,"mouse.click"),await Q("jump-latest-settle",`${e.traceId||""}:${e.window.windowId}:jump-latest`)}}async function M(e){const{capture:t,ocr:n}=await j(e.helper,e.window.windowId,e.traceId,e.window.bounds),r=E({capture:t,ocr:n,window:e.window});return r?{ok:!1,reason:r}:O(n,t,e.binding.conversationDisplayName)?{ok:!0,reason:"target-conversation-title-confirmed"}:{ok:!1,reason:"conversation_title_not_confirmed"}}function E(e){const n=(e.ocr.blocks??[]).map(r=>sn(r.text)).filter(Boolean).join("");return/(扫码登录|仅传输文件|重新登录|为了安全|安全验证|登录微信|微信登录|该账号已登录|帐号已登录|账号已登录|当前账号已登录|当前帐号已登录|已登录|进入微信|進入微信)/u.test(n)?Xe:null}function Qt(e,t,n=!0){const r=n?en(e.blocks??[],t):[];return r.length?r:e.visibleConversationFingerprints??[]}function en(e,t){const n=e.map(i=>Se(i)).filter(i=>!!i).filter(i=>i.text.length>=2).filter(i=>i.x>t.width*.08&&i.x<t.width*.38).filter(i=>i.y>t.height*.06&&i.y<t.height*.96).filter(i=>!Me(i.text)),r=new Set;return n.filter(i=>!tn(i,n,t)).sort((i,o)=>i.y-o.y||i.x-o.x).map(i=>{const o=i.text.trim();return{title:o,bbox:{x:Math.max(0,i.x-24),y:Math.max(0,i.y-Math.max(24,i.height)),width:Math.max(120,t.width*.3),height:Math.max(48,i.height+40),coordinateSpace:"screenshotPixel"},fingerprint:o.toLowerCase()}}).filter(i=>{const o=B(i.title);return!o||r.has(o)?!1:(r.add(o),!0)})}function Se(e){const t=e.bbox,n=String(e.text||"").normalize("NFKC").trim(),r=Number(t?.x),i=Number(t?.y),o=Number(t?.width),s=Number(t?.height);return!n||![r,i,o,s].every(Number.isFinite)?null:{text:n,x:r,y:i,width:o,height:s}}function tn(e,t,n){const r=Math.max(36,Math.min(64,n.height*.058));return t.some(i=>i!==e&&i.y<e.y&&e.y-i.y<=r&&Math.abs(i.x-e.x)<=16&&i.height>=e.height*.85)}function Me(e){const t=p(e);return/^(搜索|微信|通讯录|收藏|设置|search)$/iu.test(t)||L(t)||an(t)||/^包含[::]?/u.test(t)||/搜索网络结果/u.test(t)}function nn(e,t,n){const r=(e.blocks??[]).map(a=>Se(a)).filter(a=>!!a),i=r.filter(a=>L(p(a.text))).sort((a,c)=>a.y-c.y||a.x-c.x),o=["\u7FA4\u804A","GroupChats","\u8054\u7CFB\u4EBA","Contacts"];for(const a of o){const c=i.findIndex(d=>p(d.text)===a);if(c<0)continue;const l=i[c],w=i[c+1]?.y??Number.POSITIVE_INFINITY,u=r.filter(d=>d.y>l.y&&d.y<w).filter(d=>d.x<t.width*.7).filter(d=>d.text.length>=2).filter(d=>!L(p(d.text))).filter(d=>!Te(d,r)).filter(d=>Y(d.text,n)).sort((d,f)=>d.y-f.y||d.x-f.x)[0];if(u)return{bbox:Ne(u,t),reason:"search-result-title"}}const s=r.filter(a=>a.y>t.height*.12&&a.y<t.height*.82).filter(a=>a.x>t.width*.08&&a.x<t.width*.45).filter(a=>a.text.length>=2).filter(a=>!Me(a.text)).filter(a=>!Te(a,r)).filter(a=>Y(a.text,n)).sort((a,c)=>a.y-c.y||a.x-c.x)[0];return y(n)?null:s?{bbox:Ne(s,t),reason:"search-result-title"}:null}function Ne(e,t){return{x:Math.max(0,e.x-24),y:Math.max(0,e.y-12),width:Math.max(e.width+t.width*.18,160),height:Math.max(e.height+28,44),coordinateSpace:"screenshotPixel"}}function L(e){return/^(群聊|联系人|聊天记录|公众号|小程序|GroupChats|Contacts|ChatHistory|OfficialAccounts|MiniPrograms)$/u.test(e)}function rn(e){return(e.blocks??[]).some(t=>L(p(t.text)))}function on(e,t){return(e.visibleConversationFingerprints??[]).some(n=>Y(n.title,t))}function p(e){return String(e||"").normalize("NFKC").replace(/[^\p{L}\p{N}_-]/gu,"").trim()}function Te(e,t){return/^包含[::]?/u.test(e.text.trim())?!0:t.some(n=>n!==e&&Math.abs(n.y-e.y)<=Math.max(18,e.height)&&n.x<e.x&&/^包含[::]?/u.test(n.text.trim()))}function an(e){const t=String(e||"").trim();return!!(/^(星期[一二三四五六日天]|周[一二三四五六日天])\s*\d{1,2}:\d{2}$/u.test(t)||/^\d{1,2}:\d{2}(?::\d{2})?$/u.test(t)||/^\d{4}[-/.年]\d{1,2}(?:[-/.月]\d{1,2}日?)?$/u.test(t)||/^\d{1,2}[-/.月]\d{1,2}日?$/u.test(t))}function sn(e){return String(e||"").normalize("NFKC").replace(/\s+/g,"").trim()}function O(e,t,n){const r=y(n)?B(n):$(n);return r?(e.blocks??[]).some(i=>{const o=y(n)?B(i.text):$(i.text);if(!o||!Pe(o,r))return!1;const s=i.bbox;if(!s)return!1;const a=Number(s.x),c=Number(s.y);if(!Number.isFinite(a)||!Number.isFinite(c))return!1;const l=a>t.width*.32&&a<t.width*.78&&c<t.height*.16,w=a<t.width*.18&&c<t.height*.12;return l||w}):!1}function U(e){if(O(e.ocr,e.capture,e.binding.conversationDisplayName))return!1;const t=(e.ocr.blocks??[]).map(a=>String(a.text||"").normalize("NFKC").replace(/\s+/g," ").trim()).filter(Boolean),n=t.join(`
|
|
5
5
|
`),i=[{pattern:/UTF-?8/iu,source:n},{pattern:/Unix\s*\(LF\)/iu,source:n},{pattern:/纯文本/u,source:n},{pattern:/\d+\s*个字符/u,source:n},{pattern:/\bH1\b/u,source:n},{pattern:/^查看$/u,source:t}].reduce((a,c)=>{const l=Array.isArray(c.source)?c.source.some(w=>c.pattern.test(w)):c.pattern.test(c.source);return a+(l?1:0)},0);if(i>=2)return!0;const o=(e.ocr.blocks??[]).filter(a=>Number(a.bbox?.y)<e.capture.height*.14).map(a=>String(a.text||"")).join(`
|
|
6
|
-
`);return/\.(txt|md|rtf|docx?|pdf)\b/i.test(o)&&i>=1||/\.(png|jpe?g|gif|webp|bmp|heic|mp4|mov|m4v|avi|mkv|webm)\b/i.test(o)&&
|
|
7
|
-
`);if(/\b\d+\s*x\s*\d+\b/i.test(r)&&/\b\d+(\.\d+)?\s*(B|KB|MB|GB)\b/i.test(r)||/\b100%\b/.test(r)&&n.length<=20)return!0;const i=n.filter(o=>!/^(□|×|\+|…|\.\.\.|100%|\d+|发送)$/u.test(o));return e.width>600&&e.height>500&&i.length<=6}function
|
|
6
|
+
`);return/\.(txt|md|rtf|docx?|pdf)\b/i.test(o)&&i>=1||/\.(png|jpe?g|gif|webp|bmp|heic|mp4|mov|m4v|avi|mkv|webm)\b/i.test(o)&&cn(e.capture,e.ocr)?!0:((e.ocr.visibleConversationFingerprints??[]).some(a=>{const c=y(e.binding.conversationDisplayName)?B(a.title):$(a.title),l=y(e.binding.conversationDisplayName)?B(e.binding.conversationDisplayName):$(e.binding.conversationDisplayName);return!!(c&&l&&Pe(c,l))}),!1)}function cn(e,t){const n=(t.blocks??[]).map(o=>String(o.text||"").normalize("NFKC").trim()).filter(Boolean),r=n.join(`
|
|
7
|
+
`);if(/\b\d+\s*x\s*\d+\b/i.test(r)&&/\b\d+(\.\d+)?\s*(B|KB|MB|GB)\b/i.test(r)||/\b100%\b/.test(r)&&n.length<=20)return!0;const i=n.filter(o=>!/^(□|×|\+|…|\.\.\.|100%|\d+|发送)$/u.test(o));return e.width>600&&e.height>500&&i.length<=6}function Ee(e){const t=e.anchors.map(o=>({...o,normalized:v(o.expectedEchoAnchor)})).filter(o=>o.normalized);if(!t.length)return[];const n=[],r=new Set,i=dn(e.ocr,e.screenshot).sort((o,s)=>v(s.text).length-v(o.text).length);for(const o of i){const s=v(o.text);if(!s)continue;const a=t.find(l=>ln(l.normalized,s));if(!a)continue;const c=`local-outbound-echo:${e.binding.bindingId}:${a.idempotencyKey||a.replyId||a.normalized}`;r.has(c)||(r.add(c),n.push({stableMessageKey:c,senderRole:"self",kind:"text",normalizedText:s,anchorText:s,textExcerpt:o.text.trim(),bbox:o.bbox??null,observedAt:new Date().toISOString(),deliveryStatus:"suppressed"}))}return n}function dn(e,t){const n=(e.blocks??[]).filter(i=>mn(i,t)&&v(i.text)).sort((i,o)=>C(i.bbox,"y")-C(o.bbox,"y")),r=n.map(i=>({text:String(i.text||"").trim(),bbox:i.bbox}));for(let i=0;i<n.length;i+=1){const o=[n[i]];for(let s=i+1;s<n.length&&o.length<5;s+=1){const a=n[s];if(!un(o[o.length-1],a,t))break;o.push(a),r.push({text:wn(o.map(c=>String(c.text||"").trim())),bbox:fn(o.map(c=>c.bbox))})}}return r}function ln(e,t){if(!e||!t)return!1;if(ee(e,t)>=.88)return!0;const n=e.replace(/\s+/g,""),r=t.replace(/\s+/g,"");return r.length>=8&&n.includes(r)}function un(e,t,n){const r=C(e.bbox,"x"),i=C(e.bbox,"y"),o=C(e.bbox,"height"),s=C(t.bbox,"x"),a=C(t.bbox,"y");if(![r,i,o,s,a].every(Number.isFinite)||r<n.width*.5||s<n.width*.5)return!1;const c=a-(i+o);return c>=-8&&c<=Math.max(64,n.height*.04)&&Math.abs(s-r)<=120}function wn(e){return e.reduce((t,n)=>t?n?`${t}${hn(t,n)?" ":""}${n}`:t:n,"")}function hn(e,t){return/[A-Za-z0-9]$/u.test(e)&&/^[A-Za-z0-9]/u.test(t)}function fn(e){const t=e.filter(c=>!!c);if(!t.length)return;const n=t.map(c=>Number(c.x)).filter(Number.isFinite),r=t.map(c=>Number(c.y)).filter(Number.isFinite),i=t.map(c=>Number(c.x)+Number(c.width)).filter(Number.isFinite),o=t.map(c=>Number(c.y)+Number(c.height)).filter(Number.isFinite);if(!n.length||!r.length||!i.length||!o.length)return t[0];const s=Math.min(...n),a=Math.min(...r);return{x:s,y:a,width:Math.max(...i)-s,height:Math.max(...o)-a,coordinateSpace:t.find(c=>c.coordinateSpace)?.coordinateSpace}}function C(e,t){const n=Number(e?.[t]);return Number.isFinite(n)?n:Number.NaN}function Be(e,t){if(!t.length)return e;const n=[...e];for(const r of t){const i=v(r.anchorText||r.normalizedText||r.textExcerpt);n.some(s=>{if(s.senderRole!=="self")return!1;const a=v(s.anchorText||s.normalizedText||s.textExcerpt);return a&&i&&ee(a,i)>=.9})||n.push(r)}return n}function mn(e,t){const n=e.bbox;if(!n)return!1;const r=Number(n.x),i=Number(n.y);return!Number.isFinite(r)||!Number.isFinite(i)?!1:r>t.width*.34&&r<t.width*.96&&i>t.height*.12&&i<t.height*.86}function bn(e,t,n){if(!e||typeof e!="object")return null;const r=e,i=Number(r.x),o=Number(r.y),s=Number(r.width),a=Number(r.height);if(![i,o,s,a].every(Number.isFinite))return null;const c=typeof r.coordinateSpace=="string"?r.coordinateSpace:void 0,l=t.width&&n.bounds?.width?t.width/n.bounds.width:1,w=t.height&&n.bounds?.height?t.height/n.bounds.height:l,u={x:i+Math.min(s*.35,110*l),y:o+Math.min(a-8*w,Math.max(18*w,a/2))};if(c==="screen"||!n.bounds)return u;const d=Math.max(0,(t.width-n.bounds.width*l)/2),f=Math.max(0,(t.height-n.bounds.height*w)/2);return{x:n.bounds.x+(u.x-d)/l,y:n.bounds.y+(u.y-f)/w}}function K(e,t,n){if(!e||typeof e!="object")return null;const r=e,i=Number(r.x),o=Number(r.y),s=Number(r.width),a=Number(r.height);if(![i,o,s,a].every(Number.isFinite))return null;const c=typeof r.coordinateSpace=="string"?r.coordinateSpace:void 0,l={x:i+s/2,y:o+a/2};if(c==="screen"||!n.bounds)return l;const w=t.width&&n.bounds.width?t.width/n.bounds.width:1,u=t.height&&n.bounds.height?t.height/n.bounds.height:w,d=Math.max(0,(t.width-n.bounds.width*w)/2),f=Math.max(0,(t.height-n.bounds.height*u)/2);return{x:n.bounds.x+(l.x-d)/w,y:n.bounds.y+(l.y-f)/u}}function gn(e,t,n){if(!e?.blocks?.length||!t)return null;const r=e.blocks.find(i=>{const o=String(i.text||"").trim(),s=i.bbox;if(!s||!o)return!1;const a=Number(s.x),c=Number(s.y);return!Number.isFinite(a)||!Number.isFinite(c)||!/跳转到最新消息|回到最新消息|jump\s+to\s+latest/i.test(o)?!1:a>t.width*.55&&c>t.height*.45&&c<t.height*.92});return K(r?.bbox,t,n)}function Pe(e,t){return y(t)?Re(e,t):e===t||e.includes(t)||t.includes(e)}function Y(e,t){if(y(t))return Re(e,t);const n=We(p(e)),r=We(p(t));return!n||!r?!1:n===r?!0:n.replace(/\d+$/u,"")===r}function We(e){return e.toLowerCase().replace(/[l1]/g,"i")}function $(e){return String(e||"").normalize("NFKC").replace(/[((]\d+[))]/g,"").replace(/\s+/g,"").replace(/[l1]/gi,"i").toLowerCase().trim()}function B(e){return String(e||"").normalize("NFKC").replace(/[((]\d+[))]/g,"").replace(/\s+/g,"").trim()}function y(e){const t=String(e||"").trim();return/^[A-Z0-9_-]{1,6}$/.test(t)&&/[A-Z]/.test(t)}function Re(e,t){const n=String(e||"").normalize("NFKC").replace(/[((]\d+[))]/g,"").replace(/\s+/g,"").trim(),r=String(t||"").normalize("NFKC").replace(/[((]\d+[))]/g,"").replace(/\s+/g,"").trim();return!!(n&&r&&(n===r||n.replace(/\d+$/u,"")===r))}export{N as WeChatChannelUserActivityAbort,j as captureAndRecognizeWeChatWindow,F as captureWeChatWindow,En as detectWeChatMessageInputPointByServerVision,nt as detectWeChatSearchInputPointByServerVision,Dt as ensureHelperPermissionPreflight,Pn as ensureHelperPreflight,$t as ensureWeChatWindowReady,zt as focusExistingWeChatWindow,pe as focusKnownWeChatWindow,Wn as focusWeChatWindow,Tn as observeWeChatChannelBindingViaHelper,q as openConversationBySearch,z as openConversationInVisibleList,ke as recognizeWeChatScreenshot,Qe as selectWeChatWindowForBinding};
|
|
@@ -44,6 +44,7 @@ export type EchoClassificationResult = {
|
|
|
44
44
|
};
|
|
45
45
|
export declare function loadWeChatChannelOutboundLedger(filePath: string, runtimeId: string): WeChatChannelOutboundLedger;
|
|
46
46
|
export declare function saveWeChatChannelOutboundLedger(filePath: string, ledger: WeChatChannelOutboundLedger): void;
|
|
47
|
+
export declare function saveWeChatChannelOutboundLedgerMerging(filePath: string, ledger: WeChatChannelOutboundLedger): void;
|
|
47
48
|
export declare function enqueueWeChatOutboundReply(input: {
|
|
48
49
|
ledger: WeChatChannelOutboundLedger;
|
|
49
50
|
replyId: string;
|