shennian 0.3.1 → 0.3.2
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/README.md +3 -1
- package/dist/publish-build-manifest.json +273 -343
- package/dist/src/agents/command-spec.js +2 -2
- package/dist/src/agents/detect.js +1 -1
- package/dist/src/agents/model-registry/discovery.js +2 -2
- package/dist/src/agents/model-registry/parsers.d.ts +1 -0
- package/dist/src/agents/model-registry/parsers.js +4 -4
- package/dist/src/agents/native-capabilities.d.ts +10 -0
- package/dist/src/agents/native-capabilities.js +1 -0
- package/dist/src/agents/platform-instructions.js +5 -5
- package/dist/src/agents/workbuddy.d.ts +44 -0
- package/dist/src/agents/workbuddy.js +3 -0
- package/dist/src/commands/daemon.d.ts +1 -0
- package/dist/src/commands/daemon.js +9 -9
- package/dist/src/commands/integration.d.ts +2 -0
- package/dist/src/commands/integration.js +1 -0
- package/dist/src/commands/manager.js +1 -2
- package/dist/src/commands/pair-browser.d.ts +43 -0
- package/dist/src/commands/pair-browser.js +1 -0
- package/dist/src/commands/pair.d.ts +2 -0
- package/dist/src/commands/pair.js +11 -8
- package/dist/src/commands/room.d.ts +13 -0
- package/dist/src/commands/room.js +4 -0
- package/dist/src/commands/upgrade.d.ts +3 -0
- package/dist/src/commands/upgrade.js +1 -1
- package/dist/src/config/index.d.ts +3 -1
- package/dist/src/config/index.js +2 -1
- package/dist/src/daemon-ipc/client.d.ts +8 -0
- package/dist/src/daemon-ipc/client.js +3 -0
- package/dist/src/daemon-ipc/paths.d.ts +7 -0
- package/dist/src/daemon-ipc/paths.js +1 -0
- package/dist/src/daemon-ipc/protocol.d.ts +30 -0
- package/dist/src/daemon-ipc/protocol.js +1 -0
- package/dist/src/daemon-ipc/secret.d.ts +3 -0
- package/dist/src/daemon-ipc/secret.js +3 -0
- package/dist/src/daemon-ipc/server.d.ts +13 -0
- package/dist/src/daemon-ipc/server.js +3 -0
- package/dist/src/index.js +2 -2
- package/dist/src/integrations/claude-room-plugin-lifecycle.d.ts +47 -0
- package/dist/src/integrations/claude-room-plugin-lifecycle.js +1 -0
- package/dist/src/integrations/codex-room-plugin-lifecycle.d.ts +49 -0
- package/dist/src/integrations/codex-room-plugin-lifecycle.js +1 -0
- package/dist/src/integrations/room-plugin-bundles.d.ts +23 -0
- package/dist/src/integrations/room-plugin-bundles.js +1 -0
- package/dist/src/integrations/room-plugin-lifecycle-common.d.ts +17 -0
- package/dist/src/integrations/room-plugin-lifecycle-common.js +1 -0
- package/dist/src/integrations/room-plugin-shared.d.ts +23 -0
- package/dist/src/integrations/room-plugin-shared.js +2 -0
- package/dist/src/integrations/room-session-hook.d.ts +30 -0
- package/dist/src/integrations/room-session-hook.js +2 -0
- package/dist/src/integrations/workbuddy-plugin-bundle.d.ts +15 -0
- package/dist/src/integrations/workbuddy-plugin-bundle.js +1 -0
- package/dist/src/integrations/workbuddy-plugin-lifecycle.d.ts +52 -0
- package/dist/src/integrations/workbuddy-plugin-lifecycle.js +2 -0
- package/dist/src/integrations/workbuddy-session-hook.d.ts +22 -0
- package/dist/src/integrations/workbuddy-session-hook.js +1 -0
- package/dist/src/manager/prompt.d.ts +1 -1
- package/dist/src/manager/prompt.js +1 -1
- package/dist/src/manager/retired-external-channel-compat.d.ts +78 -0
- package/dist/src/manager/retired-external-channel-compat.js +1 -0
- package/dist/src/manager/runtime.d.ts +1 -3
- package/dist/src/manager/runtime.js +7 -7
- package/dist/src/relay/client.d.ts +2 -0
- package/dist/src/relay/client.js +1 -1
- package/dist/src/room/activation-audit.d.ts +15 -0
- package/dist/src/room/activation-audit.js +2 -0
- package/dist/src/room/activation-policy.d.ts +8 -0
- package/dist/src/room/activation-policy.js +1 -0
- package/dist/src/room/activation-service.d.ts +25 -0
- package/dist/src/room/activation-service.js +2 -0
- package/dist/src/room/attachment-cache.d.ts +40 -0
- package/dist/src/room/attachment-cache.js +2 -0
- package/dist/src/room/attachment-upload.d.ts +20 -0
- package/dist/src/room/attachment-upload.js +1 -0
- package/dist/src/room/authorized-action-coordinator.d.ts +40 -0
- package/dist/src/room/authorized-action-coordinator.js +1 -0
- package/dist/src/room/authorized-action-ipc.d.ts +11 -0
- package/dist/src/room/authorized-action-ipc.js +1 -0
- package/dist/src/room/device-authorization-client.d.ts +49 -0
- package/dist/src/room/device-authorization-client.js +1 -0
- package/dist/src/room/host-session-observation-ipc.d.ts +9 -0
- package/dist/src/room/host-session-observation-ipc.js +1 -0
- package/dist/src/room/host-session-observations.d.ts +54 -0
- package/dist/src/room/host-session-observations.js +2 -0
- package/dist/src/room/invite-bootstrap.d.ts +35 -0
- package/dist/src/room/invite-bootstrap.js +1 -0
- package/dist/src/room/invocation-token-ipc.d.ts +9 -0
- package/dist/src/room/invocation-token-ipc.js +1 -0
- package/dist/src/room/invocation-token.d.ts +53 -0
- package/dist/src/room/invocation-token.js +1 -0
- package/dist/src/room/jsonl-mirror.d.ts +73 -0
- package/dist/src/room/jsonl-mirror.js +6 -0
- package/dist/src/room/managed-room-session.d.ts +143 -0
- package/dist/src/room/managed-room-session.js +3 -0
- package/dist/src/room/mirror-sync-service.d.ts +33 -0
- package/dist/src/room/mirror-sync-service.js +1 -0
- package/dist/src/room/operator-ipc.d.ts +11 -0
- package/dist/src/room/operator-ipc.js +1 -0
- package/dist/src/room/pending-authorized-actions.d.ts +69 -0
- package/dist/src/room/pending-authorized-actions.js +3 -0
- package/dist/src/room/room-action-client.d.ts +208 -0
- package/dist/src/room/room-action-client.js +1 -0
- package/dist/src/room/room-action-ipc.d.ts +33 -0
- package/dist/src/room/room-action-ipc.js +1 -0
- package/dist/src/room/room-action-schema.d.ts +3 -0
- package/dist/src/room/room-action-schema.js +1 -0
- package/dist/src/room/room-authorized-action-executor.d.ts +23 -0
- package/dist/src/room/room-authorized-action-executor.js +1 -0
- package/dist/src/room/room-binding-client.d.ts +51 -0
- package/dist/src/room/room-binding-client.js +1 -0
- package/dist/src/room/room-binding-ipc.d.ts +29 -0
- package/dist/src/room/room-binding-ipc.js +1 -0
- package/dist/src/room/session-registry-ipc.d.ts +14 -0
- package/dist/src/room/session-registry-ipc.js +1 -0
- package/dist/src/room/session-registry.d.ts +128 -0
- package/dist/src/room/session-registry.js +2 -0
- package/dist/src/room/tool-schema.d.ts +114 -0
- package/dist/src/room/tool-schema.js +1 -0
- package/dist/src/room/tool-server.d.ts +5 -0
- package/dist/src/room/tool-server.js +3 -0
- package/dist/src/session/handlers/agent-capabilities.d.ts +3 -0
- package/dist/src/session/handlers/agent-capabilities.js +1 -0
- package/dist/src/session/handlers/agent-config.js +1 -1
- package/dist/src/session/handlers/chat.js +2 -2
- package/dist/src/session/handlers/control.js +1 -1
- package/dist/src/session/handlers/fs.d.ts +1 -0
- package/dist/src/session/handlers/fs.js +1 -1
- package/dist/src/session/manager.d.ts +16 -6
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/types.d.ts +5 -0
- package/dist/src/upgrade/engine.d.ts +14 -1
- package/dist/src/upgrade/engine.js +2 -2
- package/dist/src/upgrade/scheduler.d.ts +45 -0
- package/dist/src/upgrade/scheduler.js +1 -0
- package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts +17 -0
- package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts.map +1 -0
- package/node_modules/@shennian/wire/dist/agent-capabilities.js +2 -0
- package/node_modules/@shennian/wire/dist/agent-capabilities.js.map +1 -0
- package/node_modules/@shennian/wire/dist/index.d.ts +2 -1
- package/node_modules/@shennian/wire/dist/index.d.ts.map +1 -1
- package/node_modules/@shennian/wire/dist/index.js +2 -1
- package/node_modules/@shennian/wire/dist/index.js.map +1 -1
- package/node_modules/@shennian/wire/dist/machine.d.ts +1 -0
- package/node_modules/@shennian/wire/dist/machine.d.ts.map +1 -1
- package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
- package/node_modules/@shennian/wire/dist/methods.d.ts.map +1 -1
- package/node_modules/@shennian/wire/dist/room.d.ts +112 -0
- package/node_modules/@shennian/wire/dist/room.d.ts.map +1 -0
- package/node_modules/@shennian/wire/dist/room.js +4 -0
- package/node_modules/@shennian/wire/dist/room.js.map +1 -0
- package/node_modules/@shennian/wire/dist/session.d.ts +2 -2
- package/node_modules/@shennian/wire/dist/session.d.ts.map +1 -1
- package/node_modules/@shennian/wire/dist/session.js +1 -1
- package/node_modules/@shennian/wire/dist/session.js.map +1 -1
- package/package.json +3 -5
- package/dist/scripts/wechat-rpa-confirmation.mjs +0 -5
- package/dist/src/agents/pi-context.d.ts +0 -42
- package/dist/src/agents/pi-context.js +0 -12
- package/dist/src/agents/pi.d.ts +0 -70
- package/dist/src/agents/pi.js +0 -17
- package/dist/src/channels/base.d.ts +0 -144
- package/dist/src/channels/base.js +0 -1
- package/dist/src/channels/registry.d.ts +0 -8
- package/dist/src/channels/registry.js +0 -1
- package/dist/src/channels/reply-split.d.ts +0 -1
- package/dist/src/channels/reply-split.js +0 -10
- package/dist/src/channels/runtime.d.ts +0 -138
- package/dist/src/channels/runtime.js +0 -5
- package/dist/src/channels/secret-registry.d.ts +0 -35
- package/dist/src/channels/secret-registry.js +0 -1
- package/dist/src/channels/websocket.d.ts +0 -55
- package/dist/src/channels/websocket.js +0 -8
- package/dist/src/channels/wechat-channel/anchor.d.ts +0 -10
- package/dist/src/channels/wechat-channel/anchor.js +0 -1
- package/dist/src/channels/wechat-channel/automation-lane.d.ts +0 -35
- package/dist/src/channels/wechat-channel/automation-lane.js +0 -2
- package/dist/src/channels/wechat-channel/client.d.ts +0 -283
- package/dist/src/channels/wechat-channel/client.js +0 -1
- package/dist/src/channels/wechat-channel/cooldown.d.ts +0 -21
- package/dist/src/channels/wechat-channel/cooldown.js +0 -1
- package/dist/src/channels/wechat-channel/core/fixture-compare.d.ts +0 -52
- package/dist/src/channels/wechat-channel/core/fixture-compare.js +0 -1
- package/dist/src/channels/wechat-channel/core/media-action-plan.d.ts +0 -3
- package/dist/src/channels/wechat-channel/core/media-action-plan.js +0 -1
- package/dist/src/channels/wechat-channel/core/schema.d.ts +0 -67
- package/dist/src/channels/wechat-channel/core/schema.js +0 -1
- package/dist/src/channels/wechat-channel/core/trace-comparator.d.ts +0 -28
- package/dist/src/channels/wechat-channel/core/trace-comparator.js +0 -1
- package/dist/src/channels/wechat-channel/fingerprint.d.ts +0 -31
- package/dist/src/channels/wechat-channel/fingerprint.js +0 -1
- package/dist/src/channels/wechat-channel/helper-assets.d.ts +0 -103
- package/dist/src/channels/wechat-channel/helper-assets.js +0 -1
- package/dist/src/channels/wechat-channel/helper-client.d.ts +0 -87
- package/dist/src/channels/wechat-channel/helper-client.js +0 -3
- package/dist/src/channels/wechat-channel/helper-protocol.d.ts +0 -122
- package/dist/src/channels/wechat-channel/helper-protocol.js +0 -1
- package/dist/src/channels/wechat-channel/human-coordination.d.ts +0 -25
- package/dist/src/channels/wechat-channel/human-coordination.js +0 -1
- package/dist/src/channels/wechat-channel/index.d.ts +0 -21
- package/dist/src/channels/wechat-channel/index.js +0 -1
- package/dist/src/channels/wechat-channel/ledger.d.ts +0 -48
- package/dist/src/channels/wechat-channel/ledger.js +0 -2
- package/dist/src/channels/wechat-channel/media-cache-resolver.d.ts +0 -42
- package/dist/src/channels/wechat-channel/media-cache-resolver.js +0 -1
- package/dist/src/channels/wechat-channel/media-resolver.d.ts +0 -186
- package/dist/src/channels/wechat-channel/media-resolver.js +0 -1
- package/dist/src/channels/wechat-channel/message-key.d.ts +0 -19
- package/dist/src/channels/wechat-channel/message-key.js +0 -1
- package/dist/src/channels/wechat-channel/observer.d.ts +0 -171
- package/dist/src/channels/wechat-channel/observer.js +0 -7
- package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +0 -96
- package/dist/src/channels/wechat-channel/outbound-ledger.js +0 -2
- package/dist/src/channels/wechat-channel/outbound-sender.d.ts +0 -74
- package/dist/src/channels/wechat-channel/outbound-sender.js +0 -1
- package/dist/src/channels/wechat-channel/pacing.d.ts +0 -3
- package/dist/src/channels/wechat-channel/pacing.js +0 -1
- package/dist/src/channels/wechat-channel/preflight.d.ts +0 -46
- package/dist/src/channels/wechat-channel/preflight.js +0 -1
- package/dist/src/channels/wechat-channel/runner.d.ts +0 -43
- package/dist/src/channels/wechat-channel/runner.js +0 -1
- package/dist/src/channels/wechat-channel/runtime.d.ts +0 -50
- package/dist/src/channels/wechat-channel/runtime.js +0 -1
- package/dist/src/channels/wechat-channel/scheduler.d.ts +0 -74
- package/dist/src/channels/wechat-channel/scheduler.js +0 -1
- package/dist/src/channels/wechat-channel/vector-store.d.ts +0 -44
- package/dist/src/channels/wechat-channel/vector-store.js +0 -1
- package/dist/src/channels/wechat-rpa/macos-flow.d.ts +0 -55
- package/dist/src/channels/wechat-rpa/macos-flow.js +0 -1
- package/dist/src/channels/wechat-rpa/macos.d.ts +0 -11
- package/dist/src/channels/wechat-rpa/macos.js +0 -21
- package/dist/src/channels/wechat-rpa/normalizer.d.ts +0 -49
- package/dist/src/channels/wechat-rpa/normalizer.js +0 -7
- package/dist/src/channels/wechat-rpa/product-channel.d.ts +0 -76
- package/dist/src/channels/wechat-rpa/product-channel.js +0 -16
- package/dist/src/channels/wechat-rpa-session-sync.d.ts +0 -26
- package/dist/src/channels/wechat-rpa-session-sync.js +0 -1
- package/dist/src/channels/wechat-rpa.d.ts +0 -104
- package/dist/src/channels/wechat-rpa.js +0 -6
- package/dist/src/channels/wecom.d.ts +0 -51
- package/dist/src/channels/wecom.js +0 -4
- package/dist/src/commands/external-attachments.d.ts +0 -9
- package/dist/src/commands/external-attachments.js +0 -1
- package/dist/src/commands/external.d.ts +0 -2
- package/dist/src/commands/external.js +0 -1
- package/dist/src/commands/helper-runtime-official-download.d.ts +0 -80
- package/dist/src/commands/helper-runtime-official-download.js +0 -1
- package/dist/src/commands/runtime.d.ts +0 -120
- package/dist/src/commands/runtime.js +0 -1
- package/dist/src/commands/wechat/command.d.ts +0 -3
- package/dist/src/commands/wechat/command.js +0 -1
- package/dist/src/commands/wechat/direct.d.ts +0 -14
- package/dist/src/commands/wechat/direct.js +0 -2
- package/dist/src/commands/wechat/doctor.d.ts +0 -2
- package/dist/src/commands/wechat/doctor.js +0 -1
- package/dist/src/commands/wechat/ipc.d.ts +0 -9
- package/dist/src/commands/wechat/ipc.js +0 -1
- package/dist/src/commands/wechat/operations.d.ts +0 -3
- package/dist/src/commands/wechat/operations.js +0 -4
- package/dist/src/commands/wechat/output.d.ts +0 -7
- package/dist/src/commands/wechat/output.js +0 -4
- package/dist/src/commands/wechat/types.d.ts +0 -142
- package/dist/src/commands/wechat/types.js +0 -1
- package/dist/src/commands/wechat/utils.d.ts +0 -16
- package/dist/src/commands/wechat/utils.js +0 -1
- package/dist/src/commands/wechat.d.ts +0 -6
- package/dist/src/commands/wechat.js +0 -1
- package/dist/src/devtools/wechat-channel-action-smoke.d.ts +0 -105
- package/dist/src/devtools/wechat-channel-action-smoke.js +0 -10
- package/dist/src/devtools/wechat-channel-download-report.d.ts +0 -111
- package/dist/src/devtools/wechat-channel-download-report.js +0 -2
- package/dist/src/devtools/wechat-channel-markdown-report.d.ts +0 -6
- package/dist/src/devtools/wechat-channel-markdown-report.js +0 -5
- package/dist/src/devtools/wechat-channel-product-steps.d.ts +0 -9
- package/dist/src/devtools/wechat-channel-product-steps.js +0 -40
- package/dist/src/session/handlers/skills.d.ts +0 -7
- package/dist/src/session/handlers/skills.js +0 -1
- package/dist/src/session/handlers/wechat-helper-runtime.d.ts +0 -33
- package/dist/src/session/handlers/wechat-helper-runtime.js +0 -1
- package/dist/src/skills/registry.d.ts +0 -16
- package/dist/src/skills/registry.js +0 -15
- package/dist/src/skills/setup.d.ts +0 -11
- package/dist/src/skills/setup.js +0 -1
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import R from"node:fs";import Z from"node:path";import{WeChatChannelApiError as Le}from"./client.js";import{defaultWeChatChannelAttachmentDir as De,resolveVisibleWeChatChannelMedia as Ke}from"./media-resolver.js";import{updateWeChatChannelBindingLedger as Oe}from"./ledger.js";import{defaultWeChatChannelVectorStorePath as $e,loadWeChatChannelVectorStore as ze,saveWeChatChannelVectorStore as Ve,upsertWeChatChannelVectorReferences as qe}from"./vector-store.js";import{normalizeWeChatChannelAttachmentAvailability as Q,normalizeWeChatChannelMessageKind as je}from"./core/schema.js";import{waitForWeChatChannelPacing as ee,weChatChannelPacingDelayMs as Ge}from"./pacing.js";import{matchWeChatConversationFingerprints as He}from"./fingerprint.js";import{normalizeWeChatAnchorText as v,weChatTextSimilarity as te}from"./anchor.js";import{decideWeChatChannelActivityGate as Ue,normalizeWeChatChannelActivitySnapshot as Ye}from"./human-coordination.js";const Xe=3,Je=5,Ze="wechat_login_required",Qe=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 An(e){return await ft(e.helper,e.activityGuard,e.traceId).withLease("observe","observe-binding",async n=>et({...e,helper:n}))}async function et(e){const t=e.foregroundMode??"required";let n=await tt(e,{foregroundMode:t});if(t!=="background"&&(n=await Ie(e.helper,n,e.traceId)),t==="background"){const{capture:a,ocr:s}=await k({helper:e.helper,window:n,traceId:e.traceId}),c=W({capture:a,ocr:s,window:n});if(c)throw new Error(c);if(!O(s,a,e.binding.conversationDisplayName))throw new Error("conversation_not_visible_background");if(X({capture:a,ocr:s,binding:e.binding}))throw new Error("wechat_window_obstructed_background");return e.onObservationEvidence?.({window:n,capture:a,ocr:s}),le(e)?ue({...e,window:n,capture:a,ocr:s}):q({...e,window:n,capture:a,ocr:s})}const r=await H({helper:e.helper,window:n,binding:e.binding,runtime:e.runtime,api:e.api,workDir:e.workDir,traceId:e.traceId});if(!r.opened){const a=await ce({...e,fallback:n,requireTargetConversation:!1,force:!0});if(a.windowId!==n.windowId){n=await Ie(e.helper,a,e.traceId);const s=await H({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||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(X({capture:i,ocr:o,binding:e.binding})){n=await Ut(e.helper,e.traceId);const a=await H({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||"wechat_window_obstructed");if({capture:i,ocr:o}=await k({helper:e.helper,window:n,traceId:e.traceId}),X({capture:i,ocr:o,binding:e.binding}))throw new Error("wechat_window_obstructed")}return e.onObservationEvidence?.({window:n,capture:i,ocr:o}),le(e)?ue({...e,window:n,capture:i,ocr:o}):q({...e,window:n,capture:i,ocr:o})}async function tt(e,t={}){const n=t.foregroundMode??e.foregroundMode??"required",r=await jt(e.helper,e.traceId,{foreground:n});return n==="background"?r:ce({...e,fallback:r,requireTargetConversation:!1,force:t.forceVision})}const x=new Map;function nt(){return process.env.SHENNIAN_WECHAT_VISION_LAYOUT_REUSE!=="0"}function ne(e){if(!nt()||!e.classification||e.classification.windowKind!=="chat_main")return;const t=e.window.windowId;if(!t)return;const n=se(e.window),r=A(e.classification.layout?.messageInputRect,e.screenshot,e.window,"message-input"),i=A(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()},a=`${e.runtime.runtimeId}:${e.binding.bindingId}:${t}`,s=`${e.runtime.runtimeId}:window:${t}:${n}`;x.set(a,o),x.set(s,o),F(e,a,o),F(e,s,o)}async function Ln(e){const t=await re(e,"messageInputPoint");if(!t.messageInputPoint)throw new Error("wechat_message_input_not_found:vision_rect_missing");return t.messageInputPoint}async function rt(e){const t=await re(e,"searchInputPoint");if(!t.searchInputPoint)throw new Error("wechat_search_input_not_found:vision_rect_missing");return t.searchInputPoint}async function re(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=se(e.window),o=`${e.runtime.runtimeId}:${e.binding.bindingId}:${r||"unknown"}`,a=`${e.runtime.runtimeId}:window:${r||"unknown"}:${i}`,s=x.get(o)??x.get(a)??oe(e,o)??oe(e,a);if(s&&s.windowId===r&&s.boundsKey===i&&(!t||s[t]))return x.set(o,s),x.set(a,s),s;const c=e.screenshot??await T(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=A(l.layout?.messageInputRect,c,e.window,"message-input"),u=A(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(a,d),F(e,o,d),F(e,a,d),d}function ie(e){const t=e.workDir;return t?Z.join(t,"wechat-channel",e.runtime.runtimeId,"vision-layout-point-cache.json"):null}function oe(e,t){const n=ie(e);if(!n)return null;try{const r=JSON.parse(R.readFileSync(n,"utf8"));return it(r[t])}catch{return null}}function F(e,t,n){const r=ie(e);if(r)try{let i={};try{i=JSON.parse(R.readFileSync(r,"utf8"))}catch{i={}}i[t]=n,R.mkdirSync(Z.dirname(r),{recursive:!0}),R.writeFileSync(r,`${JSON.stringify(i,null,2)}
|
|
2
|
-
`,"utf8")}catch{}}function it(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=ae(t.messageInputPoint??t.point),o=ae(t.searchInputPoint);return{windowId:n,boundsKey:r,messageInputPoint:i,searchInputPoint:o,...typeof t.updatedAt=="string"?{updatedAt:t.updatedAt}:{}}}function ae(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 se(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 A(e,t,n,r="message-input"){const i=Number(e?.x),o=Number(e?.y),a=Number(e?.width),s=Number(e?.height);if(![i,o,a,s].every(Number.isFinite)||a<=0||s<=0)return null;const c=e?.coordinateSpace==="screen"?{x:i,y:o,width:a,height:s,coordinateSpace:"screen"}:{x:i/999*t.width,y:o/999*t.height,width:a/999*t.width,height:s/999*t.height,coordinateSpace:"screenshotPixel"},l=ot(c,t,n,r);return l?{x:Math.round(l.x),y:Math.round(l.y),coordinateSpace:"screen"}:null}function ot(e,t,n,r="message-input"){const i=r==="message-input"?.28:.55,o=at({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 at(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),a=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-a)/i}}async function ce(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(B).filter(a=>a.visible!==!1&&a.minimized!==!0&&!!a.windowId),r=dt(n.length?n:[e.fallback],e.fallback);if(!r.length)throw new Error("wechat_window_not_found");const i=[];for(const a of r)try{const s=await T(e.helper,a.windowId,e.traceId,a.bounds),c=await e.api.classifyWindow(e.runtime,e.binding,{screenshot:{mimeType:s.mimeType,dataBase64:s.dataBase64,width:s.width,height:s.height,windowId:a.windowId},traceId:e.traceId});i.push({window:a,classification:c,screenshot:s,score:lt(c,e.requireTargetConversation===!0)})}catch(s){if(st(s))throw s;i.push({window:a,classification:null,errorSummary:s instanceof Error?s.message:String(s||"window classification failed"),score:-1})}const o=i.filter(a=>a.score>0).sort((a,s)=>s.score-a.score)[0];if(!o){const a=ut(i,e.fallback);if(a)return console.warn(`[wechat-channel] window classifier fallback to local Windows WeChat shell windowId=${a.window.windowId}`),a.window;const s=i.map(c=>({windowId:c.window.windowId,appName:c.window.appName,title:c.window.title,score:c.score,errorSummary:c.errorSummary,classification:c.classification?{windowKind:c.classification.windowKind,reasonCode:c.classification.reasonCode,confidence:c.classification.confidence,conversationTitle:c.classification.conversationTitle,isTargetConversation:c.classification.isTargetConversation}:null}));throw new Error(`wechat_chat_main_window_not_found: ${JSON.stringify(s)}`)}return o.screenshot&&ne({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 Dn(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 st(e){const t=ct(e);return t==="insufficient_credits"||t==="entitlement_required"||t==="manual_review_required"||t==="wechat_channel_network_failed"||t==="wechat_channel_invalid_response"}function ct(e){if(e instanceof Le||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 dt(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 lt(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 ut(e,t){const n=e.filter(i=>i.score<=0).filter(i=>i.classification?.reasonCode==="server_window_classified").filter(i=>wt(i.window));return n.length===1?n[0]:n.find(i=>i.window.windowId===t.windowId)??null}function wt(e){if(!B(e)||e.visible===!1||e.minimized===!0||!j(e.title))return!1;const t=String(e.className??"");if(!/^Qt\d+QWindowIcon$/i.test(t))return!1;const n=e.bounds;return n?Number(n.width)>=700&&Number(n.height)>=500:!1}function ft(e,t,n){if(!t)return{helper:e,withLease:async(s,c,l)=>await l(e)};let r=null;const i=s=>{t.onEvent?.({...s,at:new Date().toISOString()})},o=async(s,c,l={})=>{if(r){const u=await e.request("automation.lease.status",{},n),d=u.result??{},h=u.ok&&d.interrupted?de(d.interruptReason):u.ok?void 0:u.errorCode||"user_activity_unknown";if(i({phase:"lease-status",stage:s,action:c,ok:u.ok===!0&&!d.interrupted,...h?{reasonCode:h}:{}}),!u.ok)throw new N({reasonCode:u.errorCode||"user_activity_unknown",stage:s,action:c});if(d.active===!1||d.leaseId!==r||!d.interrupted)return;throw new N({reasonCode:de(d.interruptReason),stage:s,action:c})}const w=Date.now()+mt(t.preflightIdleSettleTimeoutMs);for(;;){const u=await e.request("activity.snapshot",{},n);if(!u.ok)throw i({phase:"snapshot",stage:s,action:c,ok:!1,reasonCode:u.errorCode||"user_activity_unknown"}),new N({reasonCode:u.errorCode||"user_activity_unknown",stage:s,action:c});const d=Ue({snapshot:Ye(u.result),stage:s,policy:t.policy});if(i({phase:"snapshot",stage:s,action:c,ok:d.ok,...d.ok?{}:{reasonCode:d.reasonCode,waitMs:d.waitMs}}),d.ok)return;const h=new N({reasonCode:d.reasonCode,stage:s,action:c});if(!l.settle)throw h;const J=w-Date.now();if(J<=0)throw h;await Y(Math.max(50,Math.min(d.waitMs,J)))}},a={request:async(s,c,l)=>{const w=ht(s);w&&await o(w.stage,`${s}:before`);const u=await e.request(s,c,l);return w&&u.ok&&await o(w.stage,`${s}:after`),u}};return{helper:a,async withLease(s,c,l){if(await Ot(e,n),await o(s,`${c}:preflight`,{settle:!0}),t.useAutomationLease===!1)return await l(a);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:s,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:s,action:c});try{const u=await l(a);return await o(s,`${c}:complete`),u}finally{const u=r;if(r=null,u){const d=await e.request("automation.lease.release",{leaseId:u},n).catch(h=>({ok:!1,errorCode:"automation_lease_release_failed",errorSummary:h instanceof Error?h.message:String(h)}));i({phase:"lease-release",stage:s,action:c,ok:d.ok===!0,...d.ok?{}:{reasonCode:d.errorCode||"automation_lease_release_failed"}})}}}}}function ht(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 de(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 mt(e){return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:Qe}function le(e){return e.observePipeline==="edge-structure"?!0:e.observePipeline==="server-observe"?!1:!!e.api.structureWindow}async function q(e){const t=await Se(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 me({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 Pe(r,We({ocr:e.ocr,screenshot:t,binding:e.binding,anchors:e.localOutboundEchoAnchors??[]}))}async function ue(e){if(!e.api.structureWindow)throw new Error("wechat_structure_window_unavailable");const t=await Se(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(bt(c))return q(e);throw c}const r=kt(n.structuredMessages??n.observedMessages??[]),i=await gt({...e,messages:r,screenshot:t}),o=await me({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}),a=Pe(o,We({ocr:e.ocr,screenshot:t,binding:e.binding,anchors:e.localOutboundEchoAnchors??[]}));return e.localLedger?Oe({ledger:e.localLedger,bindingId:e.binding.bindingId,observedMessages:a,baselineOnly:e.baselineOnly,vectorReferences:i.vectorReferences}).newMessages:a}function bt(e){return e instanceof Error&&/\bedge_runtime_disabled\b/.test(e.message)}async function gt(e){const t=yt(e.messages);if(!t.length)return{messages:e.messages,vectorReferences:[]};const n=e.api.embedVisual?await vt({...e,seedBlocks:t}):t.filter(a=>f(a.vectorBase64)||f(a.signature));if(!n.length)return{messages:e.messages,vectorReferences:[]};const r=e.vectorStorePath??$e(e.workDir||process.cwd(),e.runtime.runtimeId),i=ze(r,e.runtime.runtimeId),o=qe({store:i,bindingId:e.binding.bindingId,blocks:n});return o.length?(Ve(r,i),{messages:It(e.messages,o),vectorReferences:o}):{messages:e.messages,vectorReferences:[]}}function yt(e){const t=[];for(const n of e)for(const[r,i]of(n.visualBlocks??[]).entries()){const o=f(i.blockId)||`${n.stableMessageKey}:visual-${r}`,a=f(i.blockKind)||n.kind||"visual";t.push({...i,stableMessageKey:n.stableMessageKey,blockId:o,blockKind:a,...i.bbox!==void 0?{bbox:i.bbox}:n.bbox!==void 0?{bbox:n.bbox}:{}})}return t}async function xt(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 Ct(t.visualBlocks??t.embeddedBlocks??[],e.seedBlocks)}async function vt(e){try{return await xt(e)}catch(t){if(pt(t))throw t;return[]}}function pt(e){return!e||typeof e!="object"?!1:e.reasonCode==="insufficient_credits"?!0:e instanceof Error&&/\binsufficient_credits\b/.test(e.message)}function Ct(e,t){return e.map((n,r)=>{const i=t[r];return{...n,stableMessageKey:f(n.stableMessageKey)||f(i?.stableMessageKey),blockId:f(n.blockId)||f(i?.blockId),blockKind:f(n.blockKind)||f(i?.blockKind)||"visual",...n.bbox!==void 0?{bbox:n.bbox}:i?.bbox!==void 0?{bbox:i.bbox}:{}}}).filter(n=>f(n.stableMessageKey)&&f(n.blockId))}function It(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:_t(r,i)}:r})}function _t(e,t){const r=(e.visualBlocks??[]).map((o,a)=>{const s=f(o.blockId)||`${e.stableMessageKey}:visual-${a}`,c=t.find(l=>l.blockId===s);return c?we(c,o):fe(o)}),i=new Set(r.map(o=>o.blockId));for(const o of t)i.has(o.blockId)||r.push(we(o));return r}function we(e,t){return{...t?fe(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 fe(e){const{vectorBase64:t,...n}=e;return n}function kt(e){return e.map((t,n)=>St(t,n)).filter(t=>t!=null)}function St(e,t){if(!b(e))return null;const n=je(e.kind),r=Tt(e.senderRole),i=g(e.normalizedText),o=g(e.anchorText)??i??g(e.textExcerpt),a=f(e.stableMessageKey)||Mt({message:e,index:t,senderRole:r,kind:n,anchorText:o});return{stableMessageKey:a,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:Nt(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:a}}}function Mt(e){const t=b(e.message.bbox)?JSON.stringify(e.message.bbox):"";return`structured-window:${[e.index,e.senderRole,e.kind,e.anchorText||f(e.message.textExcerpt)||"",t].join(":").slice(0,180)}`}function Nt(e){if(!b(e))return e;const t={...e};return I(t,"availability")&&(t.availability=Q(t.availability)),b(t.attachment)&&(t.attachment=he(t.attachment)),Array.isArray(t.attachments)&&(t.attachments=t.attachments.map(n=>b(n)?he(n):n)),t}function he(e){const t={...e};return I(t,"availability")&&(t.availability=Q(t.availability)),t}function Tt(e){return e==="self"||e==="contact"||e==="system"||e==="unknown"?e:"unknown"}async function me(e){if(e.binding.downloadMedia===!1)return e.messages;const t=e.messages.map((o,a)=>At(o,e.screenshot,e.window,Ft(e.messages,a))).filter((o,a)=>Bt(e.messages,a,e.mediaAnchorText)).filter(o=>o!=null);if(!t.length)return e.messages;const n=e.attachmentsDir??De(e.workDir||process.cwd(),e.runtime.runtimeId,e.binding.bindingId),r=await Ke({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 a=i.get(o.stableMessageKey);return a?{...o,mediaMetadata:Lt(o.mediaMetadata,a.attachment,a.reasonCode,a.attemptReasonCodes,a.resolveTrace)}:o})}function Bt(e,t,n){const r=ge(n);if(!r)return!0;const i=Et(r),o=e.map((a,s)=>ge(Rt(a)).includes(r)?s:-1).filter(a=>a>=0);if(!o.length)return t===Wt(e,i);for(const a of o)if(t>=a&&t<=a+8||t===a-1&&!e.slice(a+1,Math.min(e.length,a+9)).some(be))return!0;return!1}function Et(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 Wt(e,t=null){for(let n=e.length-1;n>=0;n-=1)if(be(e[n]))return Pt(e[n],t)?n:-1;return-1}function be(e){if(!e)return!1;const t=String(e.kind||"").toLowerCase(),n=b(e.mediaMetadata)?e.mediaMetadata:{},r=b(n.attachment)?n.attachment:{};return ye(t,n,r)}function Pt(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(),a=String(i.mimeType||"").toLowerCase(),s=String(i.name||i.localPath||e.anchorText||e.textExcerpt||"").toLowerCase();return t==="video"?n.includes("video")||o==="video"||a.startsWith("video/")||/\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(s):t==="image"?/image|photo|picture/.test(n)||o==="image"||a.startsWith("image/")||/\.(png|jpe?g|gif|webp|heic|tiff?|bmp)$/i.test(s):/file|document/.test(n)||o==="file"||!/image|photo|picture|video/.test(n)&&o!=="image"&&o!=="video"&&!a.startsWith("image/")&&!a.startsWith("video/")}function Rt(e){if(!e)return"";const t=e;return[e.normalizedText,e.anchorText,e.textExcerpt,t.text].map(n=>String(n||"")).join(`
|
|
3
|
-
`)}function ge(e){return String(e||"").normalize("NFKC").replace(/[o]/giu,"0").replace(/[^\p{L}\p{N}]/gu,"").toLowerCase()}function Ft(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 At(e,t,n,r){const i=String(e.kind||"").toLowerCase(),o=b(e.mediaMetadata)?e.mediaMetadata:{},a=b(o.attachment)?o.attachment:{},s=f(a.availability)||f(o.availability),c=f(a.localPath)||f(o.localPath);if(s==="edge-local"&&c||!ye(i,o,a))return null;const l=L(e.bbox)??L(o.bbox)??L(o.downloadActionBbox),w=L(o.downloadActionBbox),u=xe(l,t,n),d=Kt(l,t,n),h=xe(w,t,n);return{messageKey:e.stableMessageKey,kind:f(a.type)||f(a.kind)||f(o.messageType)||i,fileName:f(a.name)||f(a.fileName)||f(o.fileName)||null,mimeType:f(a.mimeType)||f(o.mimeType)||null,size:_(a.size)??_(o.size),mediaStatus:Dt(o,a),observedAt:e.observedAt??null,contextText:r??e.normalizedText??e.anchorText??e.textExcerpt??null,...u?{bbox:u}:{},...d?{screenshotBbox:d}:{},...h?{downloadActionBbox:h}:{}}}function Lt(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 Dt(e,t){const n=f(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=f(t.availability)||f(e.availability);return r==="pending-download"?"not_downloaded":r==="metadata-only"?"metadata_only":n||null}function ye(e,t,n){const r=`${e} ${f(t.messageType)} ${f(n.type)} ${f(n.kind)}`.toLowerCase();return/image|photo|video|file|document/.test(r)}function L(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 xe(e,t,n){if(!e)return null;if(e.coordinateSpace==="screen")return e;const r=$(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,a=i.height/t.height,s=r.x,c=r.y;return{x:s-e.width*o/2,y:c-e.height*a/2,width:e.width*o,height:e.height*a,coordinateSpace:"screen"}}function Kt(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 f(e){return typeof e=="string"?e.trim():""}function g(e){return f(e)||null}function _(e){const t=Number(e);return Number.isFinite(t)?t:null}async function Kn(e,t){await pe(e,t)}async function Ot(e,t){await ve(e,t)}async function ve(e,t){const n=await e.request("permissions.check",{},t);m(n,"permissions.check");const r=n.result??{};if(Vt(r.platform)){const i=await $t(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 pe(e,t,n={}){const r=await ve(e,t),i=String(r.platform??"").toLowerCase();if(r.wechatRunning===!1)throw new Error("wechat_not_running");if(Ht(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 $t(e,t,n){const r=zt(t);if(!r||process.platform!=="darwin")return r;const i=qt(r);try{await e.request(i,{},n)}catch{}return r}function zt(e){return e.screenRecording===!1?"screen-recording":e.accessibility===!1?"accessibility":e.inputMonitoring===!1?"input-monitoring":null}function Vt(e){const t=String(e||"").toLowerCase();return t?t.includes("darwin")||t.includes("mac"):!0}function qt(e){return e==="screen-recording"?"permissions.requestScreenRecording":e==="accessibility"?"permissions.requestAccessibility":"permissions.requestInputMonitoring"}async function jt(e,t,n={}){const i=(n.foreground??"required")!=="background",o=await pe(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 await Gt(e,l,t)}const a=await e.request("windows.ensureReady",{restore:i,focus:i},t);m(a,"windows.ensureReady");const s=a.result;if(!s?.windowId)throw new Error("helper_invalid_response: windows.ensureReady missing WeChat window data");return s}async function Gt(e,t,n){if(j(t.title))return t;try{const r=await e.request("windows.list",{},n);m(r,"windows.list");const o=(r.result?.windows??[]).find(a=>a.windowId&&a.visible!==!1&&a.minimized!==!0&&B(a)&&j(a.title));if(!o)return t;if(t.windowId&&t.windowId!==o.windowId)try{await e.request("windows.closeWindow",{windowId:t.windowId},n)}catch{}return o}catch{return t}}function j(e){const t=String(e??"").normalize("NFKC").trim().toLowerCase();return t==="\u5FAE\u4FE1"||t==="wechat"||t==="weixin"}function Ht(e){return e.windowsVisibleDesktopAvailable===!1||e.rdpVisibleDesktopAvailable===!1||e.desktopSessionVisible===!1||e.screenLocked===!0||e.rdpDisconnected===!0}function Ce(e){const t=e.filter(B),n=t.filter(i=>i.visible!==!1&&i.minimized!==!0);return(n.length?n:t)[0]??null}async function On(e,t){let n=await e.request("windows.list",{},t);m(n,"windows.list");let r=n.result?.windows??[],i=Ce(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 _e(e,i,t)}async function Ie(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 Ut(e,t){const n=await e.request("windows.list",{},t);m(n,"windows.list");const r=n.result?.windows??[],i=Ce(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 _e(e,i,t)}async function _e(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(B);return i.find(o=>o.windowId===t.windowId)??i[0]??t}async function G(e){const{capture:t,ocr:n}=e.observation??await k(e),r=W({capture:t,ocr:n,window:e.window});if(r)return{opened:!1,reason:r};const i=He({visibleItems:sn(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=In(i.item.bbox,t,e.window);if(!o)return{opened:!1,reason:"conversation_bbox_missing"};const a=await e.helper.request("mouse.click",{x:o.x,y:o.y,coordinateSpace:"screen",windowId:e.window.windowId},e.traceId);return m(a,"mouse.click"),{opened:!0,reason:i.reason}}async function H(e){let t={opened:!1,reason:"conversation_not_opened"};for(let r=0;r<Xe;r+=1){if(t=await Yt(e),t.opened||t.reason!=="conversation_title_not_confirmed")return t;await S(e,"open-retry",`retry:${r}`)}const n=await ke(e);return n.opened?{opened:!0,reason:`${n.reason}:final-visible-recovery`}:t}async function Yt(e){const t=await k(e),n=W({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 E({helper:e.helper,window:e.window,traceId:e.traceId,observation:t}),{opened:!0,reason:"current-conversation-title-confirmed"};if(!r){const u=await G({...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 h=await ke(e);if(h.opened)return h}}const i=await tn(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 a=await Xt(e);if(a.opened){await S(e,"open-click-settle","search-result-click");const u=await M(e);return u.ok?(e.settleToBottom===!0&&await E({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:a.reason}):{opened:!1,reason:u.reason}}let s=a.observation;const c=y(e.binding.conversationDisplayName)&&a.reason==="search_result_not_visible";if(!y(e.binding.conversationDisplayName)){await rn(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 E({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"),s=void 0}const l=await G({...e,...s?{observation:s}:{},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 E({helper:e.helper,window:e.window,traceId:e.traceId}),{opened:!0,reason:l.reason}):{opened:!1,reason:w.reason}}async function ke(e){const t=await G(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 E({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 Xt(e){let t;const n=e.searchDelayMs===0?0:D(e,"search-result-probe","search-result-probe"),r=y(e.binding.conversationDisplayName)?Je:1;for(let i=0;i<r;i+=1){i>0&&n>0&&await Y(n);const o=await Jt(e);t=o;const{capture:a,ocr:s}=o,c=W({capture:a,ocr:s,window:e.window});if(c)return{opened:!1,reason:c,observation:o};const l=ln(s,a,e.binding.conversationDisplayName);if(!l){if(un(s)||wn(s,e.binding.conversationDisplayName))break;continue}const w=$(l.bbox,a,Zt(a,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 Jt(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 Me(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 Zt(e,t){return e.bounds?{...t,bounds:e.bounds}:t}async function k(e){let{capture:t,ocr:n}=await U(e.helper,e.window.windowId,e.traceId,e.window.bounds);return await Qt({helper:e.helper,window:e.window,capture:t,ocr:n,traceId:e.traceId})&&(await ee("preview-dismiss-settle",`${e.traceId||""}:${e.window.windowId}:preview-dismiss`),{capture:t,ocr:n}=await U(e.helper,e.window.windowId,e.traceId,e.window.bounds)),{capture:t,ocr:n}}async function Qt(e){const t=en(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 en(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,a=Number(o?.y);if(!Number.isFinite(a))return null;const s=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-a)<t.height*.08}).sort((c,l)=>Number(l.bbox?.x??0)-Number(c.bbox?.x??0))[0];return $(s?.bbox,t,n)}async function tn(e,t){if(!e.runtime||!e.api?.classifyWindow)return{ok:!1,reason:"wechat_search_input_detector_unavailable"};try{return{ok:!0,point:await rt({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 T(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 Se(e){return e.capture.dataBase64?e.capture:T(e.helper,e.window.windowId,e.traceId,e.window.bounds)}async function U(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 T(e,t,n,r),a=await Me(e,o,n);return{capture:o,ocr:a}}async function Me(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 B(e){const t=String(e.appName||"").toLowerCase();return t==="wechat"||t==="weixin"||t==="\u5FAE\u4FE1"}function Y(e){return new Promise(t=>setTimeout(t,e))}function D(e,t,n){return e.searchDelayMs===0?0:Ge(t,nn(e,n))}async function S(e,t,n){const r=D(e,t,n);r>0&&await Y(r)}function nn(e,t){return`${e.traceId||""}:${e.binding.conversationDisplayName}:${t}`}async function rn(e,t){const n=await e.request("keyboard.shortcut",{key:"return",modifiers:[]},t);m(n,"keyboard.shortcut")}async function E(e){if(!e.window.bounds)return;const t=e.observation,n=_n(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 ee("jump-latest-settle",`${e.traceId||""}:${e.window.windowId}:jump-latest`)}}async function M(e){const{capture:t,ocr:n}=await U(e.helper,e.window.windowId,e.traceId,e.window.bounds),r=W({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"}:!on(n)&&await an({...e,capture:t})?{ok:!0,reason:"target-conversation-title-confirmed-by-vision"}:{ok:!1,reason:"conversation_title_not_confirmed"}}function on(e){return(e.blocks??[]).length>0?!0:String(e.text??"").trim().length>0}async function an(e){if(!e.runtime||!e.api?.classifyWindow)return!1;try{const t=e.capture.dataBase64?e.capture:await T(e.helper,e.window.windowId,e.traceId,e.window.bounds),n=await e.api.classifyWindow(e.runtime,e.binding,{screenshot:{mimeType:t.mimeType,dataBase64:t.dataBase64,width:t.width,height:t.height,windowId:e.window.windowId},traceId:e.traceId});return n.windowKind!=="chat_main"||!(n.isTargetConversation===!0||z(n.conversationTitle,e.binding.conversationDisplayName))?!1:(ne({helper:e.helper,runtime:e.runtime,binding:e.binding,workDir:e.workDir,traceId:e.traceId,window:e.window,classification:n,screenshot:t}),!0)}catch{return!1}}function W(e){const t=(e.ocr.blocks??[]).map(r=>hn(r.text)).filter(Boolean);if(t.length===0)return null;const n=t.join("");return/(扫码登录|仅传输文件|重新登录|为了安全|安全验证|登录微信|微信登录|该账号已登录|帐号已登录|账号已登录|当前账号已登录|当前帐号已登录|进入微信|進入微信)/u.test(n)?Ze:null}function sn(e,t,n=!0){const r=n?cn(e.blocks??[],t):[];return r.length?r:e.visibleConversationFingerprints??[]}function cn(e,t){const n=e.map(i=>Ne(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=>!Te(i.text)),r=new Set;return n.filter(i=>!dn(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=P(i.title);return!o||r.has(o)?!1:(r.add(o),!0)})}function Ne(e){const t=e.bbox,n=String(e.text||"").normalize("NFKC").trim(),r=Number(t?.x),i=Number(t?.y),o=Number(t?.width),a=Number(t?.height);return!n||![r,i,o,a].every(Number.isFinite)?null:{text:n,x:r,y:i,width:o,height:a}}function dn(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 Te(e){const t=p(e);return/^(搜索|微信|通讯录|收藏|设置|search)$/iu.test(t)||K(t)||fn(t)||/^包含[::]?/u.test(t)||/搜索网络结果/u.test(t)}function ln(e,t,n){const r=(e.blocks??[]).map(s=>Ne(s)).filter(s=>!!s),i=r.filter(s=>K(p(s.text))).sort((s,c)=>s.y-c.y||s.x-c.x),o=["\u7FA4\u804A","GroupChats","\u8054\u7CFB\u4EBA","Contacts"];for(const s of o){const c=i.findIndex(d=>p(d.text)===s);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=>!K(p(d.text))).filter(d=>!Ee(d,r)).filter(d=>z(d.text,n)).sort((d,h)=>d.y-h.y||d.x-h.x)[0];if(u)return{bbox:Be(u,t),reason:"search-result-title"}}const a=r.filter(s=>s.y>t.height*.12&&s.y<t.height*.82).filter(s=>s.x>t.width*.08&&s.x<t.width*.45).filter(s=>s.text.length>=2).filter(s=>!Te(s.text)).filter(s=>!Ee(s,r)).filter(s=>z(s.text,n)).sort((s,c)=>s.y-c.y||s.x-c.x)[0];return y(n)?null:a?{bbox:Be(a,t),reason:"search-result-title"}:null}function Be(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 K(e){return/^(群聊|联系人|聊天记录|公众号|小程序|GroupChats|Contacts|ChatHistory|OfficialAccounts|MiniPrograms)$/u.test(e)}function un(e){return(e.blocks??[]).some(t=>K(p(t.text)))}function wn(e,t){return(e.visibleConversationFingerprints??[]).some(n=>z(n.title,t))}function p(e){return String(e||"").normalize("NFKC").replace(/[^\p{L}\p{N}_-]/gu,"").trim()}function Ee(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 fn(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 hn(e){return String(e||"").normalize("NFKC").replace(/\s+/g,"").trim()}function O(e,t,n){const r=y(n)?P(n):V(n);return r?(e.blocks??[]).some(i=>{const o=y(n)?P(i.text):V(i.text);if(!o||!Re(o,r))return!1;const a=i.bbox;if(!a)return!1;const s=Number(a.x),c=Number(a.y);if(!Number.isFinite(s)||!Number.isFinite(c))return!1;const l=s>t.width*.32&&s<t.width*.78&&c<t.height*.16,w=s<t.width*.18&&c<t.height*.12;return l||w}):!1}function X(e){if(O(e.ocr,e.capture,e.binding.conversationDisplayName))return!1;const t=(e.ocr.blocks??[]).map(s=>String(s.text||"").normalize("NFKC").replace(/\s+/g," ").trim()).filter(Boolean),n=t.join(`
|
|
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((s,c)=>{const l=Array.isArray(c.source)?c.source.some(w=>c.pattern.test(w)):c.pattern.test(c.source);return s+(l?1:0)},0);if(i>=2)return!0;const o=(e.ocr.blocks??[]).filter(s=>Number(s.bbox?.y)<e.capture.height*.14).map(s=>String(s.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)&&mn(e.capture,e.ocr)?!0:((e.ocr.visibleConversationFingerprints??[]).some(s=>{const c=y(e.binding.conversationDisplayName)?P(s.title):V(s.title),l=y(e.binding.conversationDisplayName)?P(e.binding.conversationDisplayName):V(e.binding.conversationDisplayName);return!!(c&&l&&Re(c,l))}),!1)}function mn(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 We(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=bn(e.ocr,e.screenshot).sort((o,a)=>v(a.text).length-v(o.text).length);for(const o of i){const a=v(o.text);if(!a)continue;const s=t.find(l=>gn(l.normalized,a));if(!s)continue;const c=`local-outbound-echo:${e.binding.bindingId}:${s.idempotencyKey||s.replyId||s.normalized}`;r.has(c)||(r.add(c),n.push({stableMessageKey:c,senderRole:"self",kind:"text",normalizedText:a,anchorText:a,textExcerpt:o.text.trim(),bbox:o.bbox??null,observedAt:new Date().toISOString(),deliveryStatus:"suppressed"}))}return n}function bn(e,t){const n=(e.blocks??[]).filter(i=>Cn(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 a=i+1;a<n.length&&o.length<5;a+=1){const s=n[a];if(!yn(o[o.length-1],s,t))break;o.push(s),r.push({text:xn(o.map(c=>String(c.text||"").trim())),bbox:pn(o.map(c=>c.bbox))})}}return r}function gn(e,t){if(!e||!t)return!1;if(te(e,t)>=.88)return!0;const n=e.replace(/\s+/g,""),r=t.replace(/\s+/g,"");return r.length>=8&&n.includes(r)}function yn(e,t,n){const r=C(e.bbox,"x"),i=C(e.bbox,"y"),o=C(e.bbox,"height"),a=C(t.bbox,"x"),s=C(t.bbox,"y");if(![r,i,o,a,s].every(Number.isFinite)||r<n.width*.5||a<n.width*.5)return!1;const c=s-(i+o);return c>=-8&&c<=Math.max(64,n.height*.04)&&Math.abs(a-r)<=120}function xn(e){return e.reduce((t,n)=>t?n?`${t}${vn(t,n)?" ":""}${n}`:t:n,"")}function vn(e,t){return/[A-Za-z0-9]$/u.test(e)&&/^[A-Za-z0-9]/u.test(t)}function pn(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 a=Math.min(...n),s=Math.min(...r);return{x:a,y:s,width:Math.max(...i)-a,height:Math.max(...o)-s,coordinateSpace:t.find(c=>c.coordinateSpace)?.coordinateSpace}}function C(e,t){const n=Number(e?.[t]);return Number.isFinite(n)?n:Number.NaN}function Pe(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(a=>{if(a.senderRole!=="self")return!1;const s=v(a.anchorText||a.normalizedText||a.textExcerpt);return s&&i&&te(s,i)>=.9})||n.push(r)}return n}function Cn(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 In(e,t,n){if(!e||typeof e!="object")return null;const r=e,i=Number(r.x),o=Number(r.y),a=Number(r.width),s=Number(r.height);if(![i,o,a,s].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(a*.35,110*l),y:o+Math.min(s-8*w,Math.max(18*w,s/2))};if(c==="screen"||!n.bounds)return u;const d=Math.max(0,(t.width-n.bounds.width*l)/2),h=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-h)/w}}function $(e,t,n){if(!e||typeof e!="object")return null;const r=e,i=Number(r.x),o=Number(r.y),a=Number(r.width),s=Number(r.height);if(![i,o,a,s].every(Number.isFinite))return null;const c=typeof r.coordinateSpace=="string"?r.coordinateSpace:void 0,l={x:i+a/2,y:o+s/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),h=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-h)/u}}function _n(e,t,n){if(!e?.blocks?.length||!t)return null;const r=e.blocks.find(i=>{const o=String(i.text||"").trim(),a=i.bbox;if(!a||!o)return!1;const s=Number(a.x),c=Number(a.y);return!Number.isFinite(s)||!Number.isFinite(c)||!/跳转到最新消息|回到最新消息|jump\s+to\s+latest/i.test(o)?!1:s>t.width*.55&&c>t.height*.45&&c<t.height*.92});return $(r?.bbox,t,n)}function Re(e,t){return y(t)?Ae(e,t):e===t||e.includes(t)||t.includes(e)}function z(e,t){if(y(t))return Ae(e,t);const n=Fe(p(e)),r=Fe(p(t));return!n||!r?!1:n===r?!0:n.replace(/\d+$/u,"")===r}function Fe(e){return e.toLowerCase().replace(/[l1]/g,"i")}function V(e){return String(e||"").normalize("NFKC").replace(/[((]\d+[))]/g,"").replace(/\s+/g,"").replace(/[l1]/gi,"i").toLowerCase().trim()}function P(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 Ae(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,U as captureAndRecognizeWeChatWindow,T as captureWeChatWindow,Ln as detectWeChatMessageInputPointByServerVision,rt as detectWeChatSearchInputPointByServerVision,Ot as ensureHelperPermissionPreflight,Kn as ensureHelperPreflight,jt as ensureWeChatWindowReady,Ut as focusExistingWeChatWindow,Ie as focusKnownWeChatWindow,On as focusWeChatWindow,An as observeWeChatChannelBindingViaHelper,H as openConversationBySearch,G as openConversationInVisibleList,Me as recognizeWeChatScreenshot,tt as selectWeChatWindowForBinding};
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import type { WeChatChannelHumanActivityReasonCode } from './helper-protocol.js';
|
|
2
|
-
import type { WeChatChannelObservedMessage } from './client.js';
|
|
3
|
-
export type WeChatChannelOutboundStatus = 'queued' | 'sending' | 'sent_unconfirmed' | 'confirmed_echo' | 'failed' | 'stale' | 'manual_review';
|
|
4
|
-
export type WeChatChannelOutboundCommitStage = 'queued' | 'open_conversation' | 'focus_input' | 'clipboard_snapshot' | 'clipboard_set' | 'paste' | 'before_return' | 'after_return' | 'sent';
|
|
5
|
-
export type WeChatChannelOutboundRecord = {
|
|
6
|
-
replyId: string;
|
|
7
|
-
idempotencyKey: string;
|
|
8
|
-
bindingId: string;
|
|
9
|
-
runtimeId: string;
|
|
10
|
-
sessionId: string;
|
|
11
|
-
conversationName: string;
|
|
12
|
-
replyBaseRevision: number;
|
|
13
|
-
text?: string;
|
|
14
|
-
textNormalized?: string;
|
|
15
|
-
attachmentLocalRefs?: string[];
|
|
16
|
-
createdAt: string;
|
|
17
|
-
queuedAt?: string;
|
|
18
|
-
sentAt?: string;
|
|
19
|
-
confirmedAt?: string;
|
|
20
|
-
sendStatus: WeChatChannelOutboundStatus;
|
|
21
|
-
expectedEchoAnchor?: string;
|
|
22
|
-
confirmedEchoAnchor?: string;
|
|
23
|
-
observeAttemptsAfterSent?: number;
|
|
24
|
-
failureCode?: string;
|
|
25
|
-
lastErrorSummary?: string;
|
|
26
|
-
deferReason?: WeChatChannelHumanActivityReasonCode | 'user_takeover_aborted' | string;
|
|
27
|
-
nextAttemptAt?: string;
|
|
28
|
-
lastAttemptAt?: string;
|
|
29
|
-
attemptCount?: number;
|
|
30
|
-
firstUserActivityBlockedAt?: string;
|
|
31
|
-
commitStage?: WeChatChannelOutboundCommitStage;
|
|
32
|
-
copyableContentRef?: string;
|
|
33
|
-
cancelledAt?: string;
|
|
34
|
-
};
|
|
35
|
-
export type WeChatChannelOutboundLedger = {
|
|
36
|
-
version: 1;
|
|
37
|
-
runtimeId: string;
|
|
38
|
-
records: WeChatChannelOutboundRecord[];
|
|
39
|
-
};
|
|
40
|
-
export type EchoClassificationResult = {
|
|
41
|
-
remainingMessages: WeChatChannelObservedMessage[];
|
|
42
|
-
confirmedRecords: WeChatChannelOutboundRecord[];
|
|
43
|
-
manualReviewRecords: WeChatChannelOutboundRecord[];
|
|
44
|
-
};
|
|
45
|
-
export declare function loadWeChatChannelOutboundLedger(filePath: string, runtimeId: string): WeChatChannelOutboundLedger;
|
|
46
|
-
export declare function saveWeChatChannelOutboundLedger(filePath: string, ledger: WeChatChannelOutboundLedger): void;
|
|
47
|
-
export declare function saveWeChatChannelOutboundLedgerMerging(filePath: string, ledger: WeChatChannelOutboundLedger): void;
|
|
48
|
-
export declare function enqueueWeChatOutboundReply(input: {
|
|
49
|
-
ledger: WeChatChannelOutboundLedger;
|
|
50
|
-
replyId: string;
|
|
51
|
-
idempotencyKey: string;
|
|
52
|
-
bindingId: string;
|
|
53
|
-
runtimeId: string;
|
|
54
|
-
sessionId: string;
|
|
55
|
-
conversationName: string;
|
|
56
|
-
replyBaseRevision: number;
|
|
57
|
-
text?: string;
|
|
58
|
-
attachmentLocalRefs?: string[];
|
|
59
|
-
now?: Date;
|
|
60
|
-
}): WeChatChannelOutboundRecord;
|
|
61
|
-
export declare function guardWeChatOutboundRevision(input: {
|
|
62
|
-
record: WeChatChannelOutboundRecord;
|
|
63
|
-
currentLastInboundRevision: number;
|
|
64
|
-
now?: Date;
|
|
65
|
-
}): {
|
|
66
|
-
ok: true;
|
|
67
|
-
} | {
|
|
68
|
-
ok: false;
|
|
69
|
-
reason: 'stale';
|
|
70
|
-
};
|
|
71
|
-
export declare function markWeChatOutboundSending(record: WeChatChannelOutboundRecord): void;
|
|
72
|
-
export declare function markWeChatOutboundCommitStage(record: WeChatChannelOutboundRecord, stage: WeChatChannelOutboundCommitStage): void;
|
|
73
|
-
export declare function markWeChatOutboundSentUnconfirmed(record: WeChatChannelOutboundRecord, now?: Date): void;
|
|
74
|
-
export declare function markWeChatOutboundFailed(record: WeChatChannelOutboundRecord, failureCode: string, errorSummary: string): void;
|
|
75
|
-
export declare function markWeChatOutboundManualReview(record: WeChatChannelOutboundRecord, failureCode: string, errorSummary: string, commitStage?: WeChatChannelOutboundCommitStage): void;
|
|
76
|
-
export declare function markWeChatOutboundUserActiveTimeout(record: WeChatChannelOutboundRecord, now?: Date): void;
|
|
77
|
-
export declare function cancelWeChatOutboundRecord(record: WeChatChannelOutboundRecord, reason?: string, now?: Date): void;
|
|
78
|
-
export declare function markWeChatOutboundWaitingUserIdle(input: {
|
|
79
|
-
record: WeChatChannelOutboundRecord;
|
|
80
|
-
reasonCode: WeChatChannelHumanActivityReasonCode | 'user_activity_unknown' | 'user_takeover_aborted';
|
|
81
|
-
nextAttemptAt: Date;
|
|
82
|
-
now?: Date;
|
|
83
|
-
}): void;
|
|
84
|
-
export declare function shouldFailWeChatOutboundForUserActiveTimeout(input: {
|
|
85
|
-
record: WeChatChannelOutboundRecord;
|
|
86
|
-
now?: Date;
|
|
87
|
-
maxWaitMs: number;
|
|
88
|
-
}): boolean;
|
|
89
|
-
export declare function isWeChatOutboundTerminalDeliveryStatus(record: WeChatChannelOutboundRecord): boolean;
|
|
90
|
-
export declare function classifyWeChatOutboundEchoes(input: {
|
|
91
|
-
ledger: WeChatChannelOutboundLedger;
|
|
92
|
-
bindingId: string;
|
|
93
|
-
messages: WeChatChannelObservedMessage[];
|
|
94
|
-
now?: Date;
|
|
95
|
-
}): EchoClassificationResult;
|
|
96
|
-
export declare function suppressSelfOnlyWeChatMessages(messages: WeChatChannelObservedMessage[]): WeChatChannelObservedMessage[];
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import f from"node:fs";import S from"node:path";import{normalizeWeChatAnchorText as u,weChatTextSimilarity as m}from"./anchor.js";const h=500,A=2,x=600*1e3;function y(e,t){try{const n=JSON.parse(f.readFileSync(e,"utf8"));if(n?.version===1&&n.runtimeId===t&&Array.isArray(n.records))return n}catch{}return{version:1,runtimeId:t,records:[]}}function g(e,t){f.mkdirSync(S.dirname(e),{recursive:!0}),t.records=t.records.slice(-h),f.writeFileSync(e,JSON.stringify(t,null,2))}function R(e,t){const n=y(e,t.runtimeId),r=new Set(t.records.map(s=>s.idempotencyKey)),a=t.records.concat(n.records.filter(s=>!r.has(s.idempotencyKey)));g(e,{...t,records:a})}function I(e){const t=e.ledger.records.find(s=>s.idempotencyKey===e.idempotencyKey);if(t)return t;const n=(e.now??new Date).toISOString(),r=u(e.text),a={replyId:e.replyId,idempotencyKey:e.idempotencyKey,bindingId:e.bindingId,runtimeId:e.runtimeId,sessionId:e.sessionId,conversationName:e.conversationName,replyBaseRevision:e.replyBaseRevision,text:v(e.text)||void 0,textNormalized:r||void 0,attachmentLocalRefs:e.attachmentLocalRefs??[],createdAt:n,queuedAt:n,sendStatus:"queued",commitStage:"queued",copyableContentRef:`reply:${e.replyId}`,expectedEchoAnchor:r||void 0,observeAttemptsAfterSent:0};return e.ledger.records.push(a),a}function _(e){return e.currentLastInboundRevision<=e.record.replyBaseRevision?{ok:!0}:(e.record.sendStatus="stale",e.record.failureCode="reply_revision_stale",e.record.lastErrorSummary="Inbound revision advanced before reply send",e.record.commitStage=e.record.commitStage??"queued",{ok:!1,reason:"stale"})}function T(e){e.sendStatus="sending",e.failureCode=void 0,e.lastErrorSummary=void 0,e.deferReason=void 0}function W(e,t){e.commitStage=t}function k(e,t=new Date){e.sendStatus="sent_unconfirmed",e.sentAt=t.toISOString(),e.commitStage="sent",e.observeAttemptsAfterSent=0,e.failureCode=void 0,e.lastErrorSummary=void 0,e.deferReason=void 0,e.nextAttemptAt=void 0}function M(e,t,n){e.sendStatus="failed",e.failureCode=t,e.lastErrorSummary=n.slice(0,500)}function D(e,t,n,r){e.sendStatus="manual_review",e.failureCode=t,e.lastErrorSummary=n.slice(0,500),e.nextAttemptAt=void 0,e.deferReason=void 0,r&&(e.commitStage=r)}function N(e,t=new Date){e.sendStatus="failed",e.failureCode="user_active_timeout",e.lastErrorSummary="User stayed active until outbound send wait deadline expired",e.nextAttemptAt=void 0,e.deferReason="user_active_timeout",e.lastAttemptAt=t.toISOString()}function U(e,t="user_cancelled",n=new Date){e.sendStatus==="queued"&&(e.sendStatus="failed",e.failureCode=t,e.lastErrorSummary="Queued outbound send was cancelled",e.cancelledAt=n.toISOString(),e.nextAttemptAt=void 0)}function F(e){const t=e.now??new Date;e.record.sendStatus="queued",e.record.deferReason=e.reasonCode,e.record.nextAttemptAt=e.nextAttemptAt.toISOString(),e.record.lastAttemptAt=t.toISOString(),e.record.attemptCount=(e.record.attemptCount??0)+1,e.record.firstUserActivityBlockedAt??=t.toISOString(),e.record.commitStage??="queued",e.record.failureCode=void 0,e.record.lastErrorSummary=void 0}function q(e){if(e.record.sendStatus!=="queued"||!e.record.firstUserActivityBlockedAt)return!1;const t=new Date(e.record.firstUserActivityBlockedAt).getTime();return Number.isFinite(t)?(e.now??new Date).getTime()-t>=e.maxWaitMs:!1}function z(e){return e.sendStatus==="failed"||e.sendStatus==="manual_review"||e.sendStatus==="confirmed_echo"}function L(e){const t=e.now??new Date,n=[],r=[],a=e.ledger.records.filter(o=>o.bindingId===e.bindingId&&o.sendStatus==="sent_unconfirmed"),s=new Set;for(const o of a){const d=e.messages.findIndex((i,c)=>!s.has(c)&&l(o,i));if(d>=0){s.add(d);const i=e.messages[d];o.sendStatus="confirmed_echo",o.confirmedAt=t.toISOString(),o.commitStage="sent",o.confirmedEchoAnchor=u(i.anchorText||i.normalizedText||i.textExcerpt||"")||void 0,n.push(o)}for(const[i,c]of e.messages.entries())s.has(i)||b(o,c)&&s.add(i);d>=0||(o.observeAttemptsAfterSent=(o.observeAttemptsAfterSent??0)+1,C(o,t)&&(o.sendStatus="manual_review",o.failureCode="echo_confirmation_timeout",o.lastErrorSummary="Sent reply echo was not confirmed after observe threshold",o.commitStage="sent",r.push(o)))}return{remainingMessages:e.messages.filter((o,d)=>!s.has(d)),confirmedRecords:n,manualReviewRecords:r}}function B(e){return e.filter(t=>t.senderRole!=="self")}function l(e,t){if(t.senderRole!=="self")return!1;const n=e.expectedEchoAnchor||e.textNormalized||"",r=u(t.anchorText||t.normalizedText||t.textExcerpt||"");return!n||!r?!1:n===r?!0:Math.min(n.length,r.length)<24?!1:m(n,r)>=.9}function b(e,t){const n=e.expectedEchoAnchor||e.textNormalized||"",r=u(t.anchorText||t.normalizedText||t.textExcerpt||"");if(!n||!r)return!1;if(l(e,t)||m(n,r)>=.9)return!0;const a=n.replace(/\s+/g,""),s=r.replace(/\s+/g,"");return s.length>=p(s)&&a.includes(s)}function p(e){return Array.from(e).filter(n=>new RegExp("\\p{Script=Han}","u").test(n)).length>=3?4:8}function C(e,t){if((e.observeAttemptsAfterSent??0)>=A)return!0;if(!e.sentAt)return!1;const n=new Date(e.sentAt).getTime();return Number.isFinite(n)&&t.getTime()-n>=x}function v(e){return typeof e=="string"?e.replace(/\r\n/g,`
|
|
2
|
-
`).trim():""}export{U as cancelWeChatOutboundRecord,L as classifyWeChatOutboundEchoes,I as enqueueWeChatOutboundReply,_ as guardWeChatOutboundRevision,z as isWeChatOutboundTerminalDeliveryStatus,y as loadWeChatChannelOutboundLedger,W as markWeChatOutboundCommitStage,M as markWeChatOutboundFailed,D as markWeChatOutboundManualReview,T as markWeChatOutboundSending,k as markWeChatOutboundSentUnconfirmed,N as markWeChatOutboundUserActiveTimeout,F as markWeChatOutboundWaitingUserIdle,g as saveWeChatChannelOutboundLedger,R as saveWeChatChannelOutboundLedgerMerging,q as shouldFailWeChatOutboundForUserActiveTimeout,B as suppressSelfOnlyWeChatMessages};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { WeChatChannelHelperTransport, WeChatChannelScreenPoint } from './observer.js';
|
|
2
|
-
import { type WeChatChannelOutboundLedger, type WeChatChannelOutboundRecord, type WeChatChannelOutboundCommitStage } from './outbound-ledger.js';
|
|
3
|
-
import { type WeChatChannelActivityGatePolicy } from './human-coordination.js';
|
|
4
|
-
import type { WeChatChannelHumanActivityReasonCode } from './helper-protocol.js';
|
|
5
|
-
export type WeChatChannelOutboundSendResult = {
|
|
6
|
-
sentRecords: WeChatChannelOutboundRecord[];
|
|
7
|
-
staleRecords: WeChatChannelOutboundRecord[];
|
|
8
|
-
failedRecords: WeChatChannelOutboundRecord[];
|
|
9
|
-
waitingRecords: WeChatChannelOutboundRecord[];
|
|
10
|
-
manualReviewRecords: WeChatChannelOutboundRecord[];
|
|
11
|
-
};
|
|
12
|
-
export declare function sendQueuedWeChatOutboundRecords(input: {
|
|
13
|
-
ledger: WeChatChannelOutboundLedger;
|
|
14
|
-
bindingId: string;
|
|
15
|
-
currentLastInboundRevision: number;
|
|
16
|
-
sender: WeChatChannelOutboundSender;
|
|
17
|
-
now?: Date;
|
|
18
|
-
maxUserActivityWaitMs?: number;
|
|
19
|
-
}): Promise<WeChatChannelOutboundSendResult>;
|
|
20
|
-
export declare class WeChatChannelOutboundSender {
|
|
21
|
-
private options;
|
|
22
|
-
private activeAutomationLeaseId;
|
|
23
|
-
private focus?;
|
|
24
|
-
private windowsTextClipboardPrimed;
|
|
25
|
-
constructor(options: {
|
|
26
|
-
helper: WeChatChannelHelperTransport;
|
|
27
|
-
openConversation: (conversationName: string) => Promise<{
|
|
28
|
-
opened: boolean;
|
|
29
|
-
reason: string;
|
|
30
|
-
windowId?: string | null;
|
|
31
|
-
inputPoint?: WeChatChannelScreenPoint | null;
|
|
32
|
-
}>;
|
|
33
|
-
traceId?: string;
|
|
34
|
-
activityGatePolicy?: Partial<WeChatChannelActivityGatePolicy>;
|
|
35
|
-
takeoverCheck?: boolean;
|
|
36
|
-
platform?: NodeJS.Platform | string;
|
|
37
|
-
postPasteSettleMs?: number;
|
|
38
|
-
onAfterPaste?: (input: {
|
|
39
|
-
record: WeChatChannelOutboundRecord;
|
|
40
|
-
kind: 'text' | 'attachment';
|
|
41
|
-
}) => Promise<void> | void;
|
|
42
|
-
});
|
|
43
|
-
canStart(_record: WeChatChannelOutboundRecord, now?: Date): Promise<{
|
|
44
|
-
ok: true;
|
|
45
|
-
} | {
|
|
46
|
-
ok: false;
|
|
47
|
-
reasonCode: WeChatChannelHumanActivityReasonCode;
|
|
48
|
-
nextAttemptAt: Date;
|
|
49
|
-
}>;
|
|
50
|
-
send(record: WeChatChannelOutboundRecord): Promise<void>;
|
|
51
|
-
private sendWithLease;
|
|
52
|
-
private sendTextIfPresent;
|
|
53
|
-
private primeWindowsTextPasteIfNeeded;
|
|
54
|
-
private sendAttachmentsIfPresent;
|
|
55
|
-
private withAutomationLease;
|
|
56
|
-
private releaseAutomationLease;
|
|
57
|
-
private waitAfterPaste;
|
|
58
|
-
private focusMessageInputWithRetry;
|
|
59
|
-
private ensureStageIdle;
|
|
60
|
-
private activitySnapshot;
|
|
61
|
-
private automationLeaseDecision;
|
|
62
|
-
}
|
|
63
|
-
export declare class WeChatChannelUserTakeoverAbort extends Error {
|
|
64
|
-
readonly reasonCode: WeChatChannelHumanActivityReasonCode;
|
|
65
|
-
readonly nextAttemptAt: Date;
|
|
66
|
-
readonly stage: WeChatChannelOutboundCommitStage;
|
|
67
|
-
readonly replyId: string;
|
|
68
|
-
constructor(input: {
|
|
69
|
-
reasonCode: WeChatChannelHumanActivityReasonCode;
|
|
70
|
-
nextAttemptAt: Date;
|
|
71
|
-
stage: WeChatChannelOutboundCommitStage;
|
|
72
|
-
replyId: string;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import g from"node:fs";import A from"node:path";import{waitForWeChatChannelPacing as d}from"./pacing.js";import{guardWeChatOutboundRevision as C,markWeChatOutboundFailed as v,markWeChatOutboundManualReview as S,markWeChatOutboundCommitStage as o,markWeChatOutboundSending as x,markWeChatOutboundSentUnconfirmed as P,markWeChatOutboundUserActiveTimeout as h,markWeChatOutboundWaitingUserIdle as _,shouldFailWeChatOutboundForUserActiveTimeout as l}from"./outbound-ledger.js";import{decideWeChatChannelActivityGate as I,nextWeChatChannelActivityRetryAt as b,normalizeWeChatChannelActivitySnapshot as k}from"./human-coordination.js";const W=600*1e3,f=520;function T(){return process.env.SHENNIAN_WECHAT_FOCUS_SINGLE_CALL!=="0"}async function J(e){const t={sentRecords:[],staleRecords:[],failedRecords:[],waitingRecords:[],manualReviewRecords:[]},s=e.now??new Date,n=e.maxUserActivityWaitMs??W,a=e.ledger.records.filter(i=>i.bindingId===e.bindingId&&i.sendStatus==="queued");for(const i of a){if(l({record:i,now:s,maxWaitMs:n})){h(i,s),t.failedRecords.push(i);continue}if(!C({record:i,currentLastInboundRevision:e.currentLastInboundRevision,now:s}).ok){t.staleRecords.push(i);continue}try{const r=await e.sender.canStart(i,s);if(r.ok===!1){_({record:i,reasonCode:r.reasonCode,nextAttemptAt:r.nextAttemptAt,now:s}),l({record:i,now:s,maxWaitMs:n})?(h(i,s),t.failedRecords.push(i)):t.waitingRecords.push(i);continue}x(i),await e.sender.send(i),P(i,s),t.sentRecords.push(i)}catch(r){if(r instanceof m){if(j(r)){S(i,"user_takeover_before_return","User activity was detected after paste and before Return; manual WeChat inspection is required",r.stage),t.manualReviewRecords.push(i);continue}_({record:i,reasonCode:r.reasonCode,nextAttemptAt:r.nextAttemptAt,now:s}),l({record:i,now:s,maxWaitMs:n})?(h(i,s),t.failedRecords.push(i)):t.waitingRecords.push(i);continue}v(i,H(r),r instanceof Error?r.message:String(r)),t.failedRecords.push(i)}}return t}class X{options;activeAutomationLeaseId=null;focus;windowsTextClipboardPrimed=!1;constructor(t){this.options=t}async canStart(t,s=new Date){const n=await this.activitySnapshot();await $(this.options.helper,n,this.options.platform,this.options.traceId);const a=I({snapshot:n,stage:"send_start",policy:this.options.activityGatePolicy});return a.ok===!1?{ok:!1,reasonCode:a.reasonCode,nextAttemptAt:b(s,a.waitMs)}:{ok:!0}}async send(t){await this.withAutomationLease(t,()=>this.sendWithLease(t))}async sendWithLease(t){await this.ensureStageIdle(t,"open_conversation"),o(t,"open_conversation");const s=await this.options.openConversation(t.conversationName);if(!s.opened)throw new Error(s.reason||"conversation_not_opened");if(N(this.options.platform)&&!s.inputPoint)throw new Error("wechat_message_input_point_required: Windows send requires a vision-detected message input point");o(t,"focus_input"),this.focus={windowId:s.windowId??void 0,inputPoint:s.inputPoint??void 0},await this.focusMessageInputWithRetry(t),await this.ensureStageIdle(t,"clipboard_snapshot"),o(t,"clipboard_snapshot");const n=await this.options.helper.request("clipboard.snapshot",{},this.options.traceId);u(n,"clipboard.snapshot");let a=!1;try{await this.sendTextIfPresent(t,()=>{a=!0}),await this.sendAttachmentsIfPresent(t,()=>{a=!0})}finally{const i=n.result&&typeof n.result=="object"?n.result:{},c=await this.options.helper.request("clipboard.restore",i,this.options.traceId);a||u(c,"clipboard.restore")}}async sendTextIfPresent(t,s){if(!t.text)return;if(D(this.options.platform)){await this.ensureStageIdle(t,"clipboard_set"),o(t,"clipboard_set"),await this.ensureStageIdle(t,"paste"),o(t,"paste");const a=await this.options.helper.request("wechat.pasteAndSubmit",{text:t.text,waitMs:f,pasteWaitMs:this.options.postPasteSettleMs??900,...this.focus?.windowId?{windowId:this.focus.windowId}:{},...this.focus?.inputPoint?{inputPoint:this.focus.inputPoint}:{}},this.options.traceId);u(a,"wechat.pasteAndSubmit"),s(),o(t,"after_return");return}await this.ensureStageIdle(t,"clipboard_set"),o(t,"clipboard_set"),O(this.options.platform)||(await p(this.options.helper,"a",w(this.options.platform),this.options.traceId),await p(this.options.helper,"backspace",[],this.options.traceId));const n=await this.options.helper.request("clipboard.setText",{text:t.text},this.options.traceId);u(n,"clipboard.setText"),U(this.options.platform)&&await this.focusMessageInputWithRetry(t,"clipboard_set"),await this.ensureStageIdle(t,"paste"),o(t,"paste"),await this.primeWindowsTextPasteIfNeeded(t),await p(this.options.helper,"v",w(this.options.platform),this.options.traceId),await this.waitAfterPaste(t),await this.options.onAfterPaste?.({record:t,kind:"text"}),await this.ensureStageIdle(t,"before_return"),o(t,"before_return"),await p(this.options.helper,"return",[],this.options.traceId),s(),o(t,"after_return")}async primeWindowsTextPasteIfNeeded(t){if(!F(this.options.platform)||this.windowsTextClipboardPrimed)return;const s=await this.options.helper.request("keyboard.primeTextPaste",{},this.options.traceId);u(s,"keyboard.primeTextPaste"),this.windowsTextClipboardPrimed=!0,await this.ensureStageIdle(t,"paste")}async sendAttachmentsIfPresent(t,s){for(const n of t.attachmentLocalRefs??[]){q(n),await this.ensureStageIdle(t,"clipboard_set"),o(t,"clipboard_set");const a=L(n),i=a==="image"&&y(this.options.platform)?await this.options.helper.request("clipboard.setImage",{filePath:n},this.options.traceId):await this.options.helper.request("clipboard.setFiles",{filePaths:[n]},this.options.traceId);u(i,a==="image"&&y(this.options.platform)?"clipboard.setImage":"clipboard.setFiles"),await this.ensureStageIdle(t,"paste"),o(t,"paste"),await p(this.options.helper,"v",w(this.options.platform),this.options.traceId),await this.waitAfterPaste(t),await this.options.onAfterPaste?.({record:t,kind:"attachment"}),await this.ensureStageIdle(t,"before_return"),o(t,"before_return"),await p(this.options.helper,"return",[],this.options.traceId),s(),o(t,"after_return")}}async withAutomationLease(t,s){const n=await this.options.helper.request("automation.lease.acquire",{owner:"wechat-channel",purpose:`send:${t.bindingId}`,ttlMs:6e4},this.options.traceId);u(n,"automation.lease.acquire");const a=typeof n.result?.leaseId=="string"?n.result.leaseId:"";try{this.activeAutomationLeaseId=a||null,await s()}finally{this.activeAutomationLeaseId=null,a&&await this.releaseAutomationLease(a)}}async releaseAutomationLease(t){try{await this.options.helper.request("automation.lease.release",{leaseId:t},this.options.traceId)}catch{}}async waitAfterPaste(t){const s=(this.options.platform??process.platform)==="win32"?1e3:void 0;await d("send-post-paste",`${this.options.traceId||""}:${t.replyId}:post-paste`,this.options.postPasteSettleMs??s)}async focusMessageInputWithRetry(t,s="focus_input"){await M(this.options.helper,this.options.traceId,E(this.focus)),await this.ensureStageIdle(t,s)}async ensureStageIdle(t,s){if(this.options.takeoverCheck===!1)return;if(this.activeAutomationLeaseId){const i=await this.automationLeaseDecision();if(i.ok===!1)throw new m({reasonCode:i.reasonCode,nextAttemptAt:i.nextAttemptAt,stage:s,replyId:t.replyId});return}const n=await this.activitySnapshot(),a=I({snapshot:n,stage:R(s),policy:this.options.activityGatePolicy});if(!a.ok)throw new m({reasonCode:a.reasonCode,nextAttemptAt:b(new Date,a.waitMs),stage:s,replyId:t.replyId})}async activitySnapshot(){const t=await this.options.helper.request("activity.snapshot",{},this.options.traceId);return u(t,"activity.snapshot"),k(t.result)}async automationLeaseDecision(){if(!this.activeAutomationLeaseId)return{ok:!0};const t=await this.options.helper.request("automation.lease.status",{},this.options.traceId);u(t,"automation.lease.status");const s=t.result??{};return s.active===!1||s.leaseId!==this.activeAutomationLeaseId||!s.interrupted?{ok:!0}:{ok:!1,reasonCode:z(s.interruptReason),nextAttemptAt:new Date(Date.now()+1e3)}}}class m extends Error{reasonCode;nextAttemptAt;stage;replyId;constructor(t){super(`user_takeover_aborted:${t.reasonCode}:${t.stage}`),this.name="WeChatChannelUserTakeoverAbort",this.reasonCode=t.reasonCode,this.nextAttemptAt=t.nextAttemptAt,this.stage=t.stage,this.replyId=t.replyId}}function R(e){return e==="open_conversation"?"open_conversation":e==="queued"?"send_start":"dangerous_action"}async function M(e,t,s){const n={waitMs:f,...s?.windowId?{windowId:s.windowId}:{},...s?.inputPoint?{inputPoint:s.inputPoint}:{}};if((await e.request("wechat.focusMessageInput",n,t)).ok){if(T())return;await d("send-focus-stabilize",`${t||""}:focus-stabilize`);const c=await e.request("wechat.focusMessageInput",n,t);u(c,"wechat.focusMessageInput");return}await d("send-focus-retry",`${t||""}:focus-retry`);const i=await e.request("wechat.focusMessageInput",{...n,waitMs:Math.max(f,700)},t);u(i,"wechat.focusMessageInput")}async function p(e,t,s,n){const a=await e.request("keyboard.shortcut",{key:t,modifiers:s},n);u(a,"keyboard.shortcut")}function q(e){if(!g.statSync(e).isFile())throw new Error(`wechat_channel_attachment_not_file:${e}`)}function L(e){const t=A.extname(e).toLowerCase();return[".png",".jpg",".jpeg",".gif",".webp",".heic",".tiff",".bmp"].includes(t)?"image":[".mp4",".mov",".m4v",".avi",".mkv",".webm"].includes(t)?"video":"file"}function y(e){return(e??process.platform)==="win32"}function w(e){return(e??process.platform)==="win32"?["control"]:["command"]}function E(e){if(e)return{...e.windowId?{windowId:e.windowId}:{},...e.inputPoint?{inputPoint:e.inputPoint}:{}}}function O(e){return(e??process.platform)==="win32"}function U(e){return(e??process.platform)==="win32"}function F(e){return(e??process.platform)==="win32"}function D(e){return(e??process.platform)==="win32"}function N(e){return(e??process.platform)==="win32"}async function $(e,t,s,n){if((s??process.platform)!=="darwin")return;const a=t?.permissions;if(!a)return;const i=a.accessibilityTrusted===!1?"accessibility":a.iohidListenGranted===!1?"input-monitoring":null;if(i)throw await G(e,i==="accessibility"?"permissions.requestAccessibility":"permissions.requestInputMonitoring",n),new Error(`permission_missing:mac_input:${i}`)}async function G(e,t,s){try{await e.request(t,{},s)}catch{}}function H(e){const t=e instanceof Error?e.message:String(e);return/conversation_not|conversation.*visible|conversation.*open/i.test(t)?"conversation_not_opened":/wechat_message_input_point_required|wechat_message_input_not_found/i.test(t)?"wechat_message_input_not_found":/permission|accessibility|screen|automation/i.test(t)?"permission_missing":/clipboard/i.test(t)?"clipboard_failed":/attachment|not_file|ENOENT|no such file/i.test(t)?"attachment_unavailable":"send_failed"}function z(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 j(e){return e.stage==="before_return"}function u(e,t){if(!e.ok)throw new Error(`${e.errorCode||"helper_command_failed"}: ${e.errorSummary||t}`)}export{X as WeChatChannelOutboundSender,m as WeChatChannelUserTakeoverAbort,J as sendQueuedWeChatOutboundRecords};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export type WeChatChannelPacingProfile = 'open-retry' | 'open-click-settle' | 'search-input-settle' | 'search-result-probe' | 'preview-dismiss-settle' | 'jump-latest-settle' | 'send-focus-stabilize' | 'send-focus-retry' | 'send-post-paste' | 'send-after-submit' | 'observe-retry';
|
|
2
|
-
export declare function weChatChannelPacingDelayMs(profile: WeChatChannelPacingProfile, seed?: string): number;
|
|
3
|
-
export declare function waitForWeChatChannelPacing(profile: WeChatChannelPacingProfile, seed?: string, overrideMs?: number): Promise<number>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import i from"node:crypto";const o={"open-retry":{minMs:320,maxMs:560},"open-click-settle":{minMs:760,maxMs:1180},"search-input-settle":{minMs:620,maxMs:980},"search-result-probe":{minMs:360,maxMs:640},"preview-dismiss-settle":{minMs:260,maxMs:480},"jump-latest-settle":{minMs:620,maxMs:920},"send-focus-stabilize":{minMs:90,maxMs:190},"send-focus-retry":{minMs:280,maxMs:540},"send-post-paste":{minMs:420,maxMs:1040},"send-after-submit":{minMs:820,maxMs:1680},"observe-retry":{minMs:1100,maxMs:2600}};function M(t,e){const s=o[t],n=Math.max(0,Math.floor(s.minMs)),m=Math.max(n,Math.floor(s.maxMs))-n+1;if(m<=1)return n;const r=i.createHash("sha256").update(`${t}:${e||""}`).digest().readUInt32BE(0);return n+r%m}function c(t){if(t<=0)return t;const e=Math.round(t*.35);if(e<=0)return t;const s=i.randomInt(-e,e+1);return Math.max(0,t+s)}async function f(t,e,s){const n=typeof s=="number"&&Number.isFinite(s)?Math.max(0,Math.floor(s)):c(M(t,e));return n>0&&await new Promise(a=>setTimeout(a,n)),n}export{f as waitForWeChatChannelPacing,M as weChatChannelPacingDelayMs};
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { type WeChatChannelHelperCapability, type WeChatChannelHelperReady, type WeChatChannelHelperErrorCode } from './helper-protocol.js';
|
|
2
|
-
import type { WeChatChannelRuntime, WeChatChannelBindingConfig } from './runtime.js';
|
|
3
|
-
export type WeChatChannelPreflightSeverity = 'blocking' | 'warning';
|
|
4
|
-
export type WeChatChannelPreflightCode = 'ok' | 'mac_only' | 'enterprise_required' | 'privacy_consent_required' | 'server_decision_unavailable' | 'same_machine_required' | 'local_agent_unavailable' | 'helper_not_ready' | 'platform_unsupported' | WeChatChannelHelperErrorCode;
|
|
5
|
-
export type WeChatChannelPreflightCheck = {
|
|
6
|
-
code: WeChatChannelPreflightCode;
|
|
7
|
-
ok: boolean;
|
|
8
|
-
severity: WeChatChannelPreflightSeverity;
|
|
9
|
-
message: string;
|
|
10
|
-
};
|
|
11
|
-
export type WeChatChannelPreflightInput = {
|
|
12
|
-
platform: string;
|
|
13
|
-
accountTier?: string | null;
|
|
14
|
-
privacyConsentAccepted?: boolean;
|
|
15
|
-
serverDecisionAvailable?: boolean;
|
|
16
|
-
currentMachineId?: string | null;
|
|
17
|
-
localAgentMachineId?: string | null;
|
|
18
|
-
localAgentAvailable?: boolean;
|
|
19
|
-
runtime: WeChatChannelRuntime;
|
|
20
|
-
binding?: WeChatChannelBindingConfig | null;
|
|
21
|
-
expectedHelperVersion: string;
|
|
22
|
-
helperReady?: WeChatChannelHelperReady | null;
|
|
23
|
-
requiredHelperCapabilities?: WeChatChannelHelperCapability[] | null;
|
|
24
|
-
permissions?: {
|
|
25
|
-
screenRecording?: boolean;
|
|
26
|
-
accessibility?: boolean;
|
|
27
|
-
automation?: boolean;
|
|
28
|
-
wechatRunning?: boolean;
|
|
29
|
-
wechatWindowAvailable?: boolean;
|
|
30
|
-
wechatMainWindowResponsive?: boolean;
|
|
31
|
-
windowsVisibleDesktopAvailable?: boolean;
|
|
32
|
-
rdpVisibleDesktopAvailable?: boolean;
|
|
33
|
-
desktopSessionVisible?: boolean;
|
|
34
|
-
screenLocked?: boolean;
|
|
35
|
-
rdpDisconnected?: boolean;
|
|
36
|
-
dpiMappingAvailable?: boolean;
|
|
37
|
-
displayTopologySupported?: boolean;
|
|
38
|
-
} | null;
|
|
39
|
-
};
|
|
40
|
-
export type WeChatChannelPreflightResult = {
|
|
41
|
-
ok: boolean;
|
|
42
|
-
canEnable: boolean;
|
|
43
|
-
status: 'ready' | 'blocked';
|
|
44
|
-
checks: WeChatChannelPreflightCheck[];
|
|
45
|
-
};
|
|
46
|
-
export declare function evaluateWeChatChannelPreflight(input: WeChatChannelPreflightInput): WeChatChannelPreflightResult;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{requiredWeChatChannelHelperCapabilitiesForProfile as o,requiredWindowsWeChatChannelHelperCapabilitiesForProfile as d,validateWeChatChannelHelperReady as t}from"./helper-protocol.js";function p(e){const a=[],l=e.platform==="darwin"||e.platform==="win32";if(a.push(i(l,"platform_unsupported","\u5FAE\u4FE1 Channel \u5F53\u524D\u652F\u6301 macOS \u548C Windows \u684C\u9762\u5FAE\u4FE1\u3002")),a.push(i(e.accountTier==="enterprise","enterprise_required","\u5F53\u524D\u9636\u6BB5\u5FAE\u4FE1 Channel \u4EC5\u4F01\u4E1A\u7248\u8D26\u53F7\u53EF\u7528\u3002")),a.push(i(!!e.privacyConsentAccepted,"privacy_consent_required","\u542F\u7528\u524D\u9700\u8981\u786E\u8BA4\u5FAE\u4FE1 Channel \u6570\u636E\u4E0E\u9690\u79C1\u6388\u6743\u3002")),a.push(i(!!e.serverDecisionAvailable,"server_decision_unavailable","\u670D\u52A1\u7AEF\u5224\u65AD\u80FD\u529B\u4E0D\u53EF\u7528\uFF0C\u6682\u4E0D\u80FD\u542F\u7528\u3002")),e.currentMachineId&&e.runtime.machineId&&a.push(i(e.currentMachineId===e.runtime.machineId,"same_machine_required","\u7B2C\u4E00\u7248\u53EA\u652F\u6301\u540C\u673A\u5FAE\u4FE1\u4E0E\u540C\u673A\u795E\u5FF5\u8FD0\u884C\u65F6\u7ED1\u5B9A\u3002")),e.localAgentMachineId&&e.runtime.machineId&&a.push(i(e.localAgentMachineId===e.runtime.machineId,"same_machine_required","\u7ED1\u5B9A\u7684 Agent \u5FC5\u987B\u4E0E\u5FAE\u4FE1\u8FD0\u884C\u65F6\u5728\u540C\u4E00\u53F0\u673A\u5668\u3002")),a.push(i(e.localAgentAvailable!==!1,"local_agent_unavailable","\u672C\u673A Agent \u4E0D\u53EF\u7528\uFF0C\u65E0\u6CD5\u5B89\u5168\u63A5\u7BA1\u5FAE\u4FE1\u56DE\u590D\u3002")),!e.helperReady)a.push(i(!1,"helper_not_ready","\u5E73\u53F0 helper \u672A\u5C31\u7EEA\u3002"));else{const n=t(e.helperReady,e.expectedHelperVersion,e.requiredHelperCapabilities??c(e.platform,e.binding));n.ok?a.push(i(!0,"ok",e.platform==="win32"?"Windows helper \u7248\u672C\u4E0E\u80FD\u529B\u68C0\u67E5\u901A\u8FC7\u3002":"macOS helper \u7248\u672C\u4E0E\u80FD\u529B\u68C0\u67E5\u901A\u8FC7\u3002")):a.push(i(!1,n.errorCode,n.errorSummary))}const r=e.permissions;r&&(e.platform==="darwin"&&(a.push(i(r.screenRecording!==!1,"permission_screen_recording_missing","\u7F3A\u5C11\u5C4F\u5E55\u5F55\u5236\u6743\u9650\u3002")),a.push(i(r.automation!==!1,"permission_automation_missing","\u7F3A\u5C11\u81EA\u52A8\u5316\u63A7\u5236\u6743\u9650\u3002"))),a.push(i(r.wechatRunning!==!1,"wechat_not_running","\u5FAE\u4FE1\u672A\u8FD0\u884C\u3002")),a.push(i(r.wechatWindowAvailable!==!1,"wechat_window_unavailable","\u5FAE\u4FE1\u7A97\u53E3\u4E0D\u53EF\u7528\u3002")),a.push(i(r.wechatMainWindowResponsive!==!1,"wechat_window_unresponsive","\u5FAE\u4FE1\u7A97\u53E3\u65E0\u54CD\u5E94\uFF0C\u9700\u6062\u590D\u540E\u518D\u7EE7\u7EED\u3002")),a.push(i(r.windowsVisibleDesktopAvailable!==!1&&r.rdpVisibleDesktopAvailable!==!1&&r.desktopSessionVisible!==!1&&r.screenLocked!==!0&&r.rdpDisconnected!==!0,"windows_visible_desktop_unavailable","Windows \u53EF\u89C1\u684C\u9762\u4E0D\u53EF\u7528\uFF0C\u8BF7\u89E3\u9501\u6216\u4FDD\u6301 RDP \u53EF\u89C1\u684C\u9762\u4F1A\u8BDD\u540E\u518D\u542F\u7528\u3002")),a.push(i(r.dpiMappingAvailable!==!1&&r.displayTopologySupported!==!1,"dpi_mapping_failed","Windows DPI / \u591A\u5C4F\u5750\u6807\u6620\u5C04\u4E0D\u53EF\u7528\uFF0C\u8BF7\u628A\u5FAE\u4FE1\u5B8C\u6574\u653E\u5728\u4E00\u4E2A\u53EF\u89C1\u663E\u793A\u5668\u4E0A\u540E\u518D\u542F\u7528\u3002")));const s=a.filter(n=>!n.ok&&n.severity==="blocking");return{ok:s.length===0,canEnable:s.length===0,status:s.length===0?"ready":"blocked",checks:a}}function i(e,a,l){return{ok:e,code:e?"ok":a,severity:"blocking",message:l}}function c(e,a){const l=e==="win32"?d:o;return!a||a.allowReply!==!1?l("send"):a.downloadMedia!==!1?l("download"):l("observe")}export{p as evaluateWeChatChannelPreflight};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import type { WeChatChannelRuntime, WeChatChannelBindingConfig } from './runtime.js';
|
|
2
|
-
import { type WeChatChannelApiClient, type WeChatChannelObservedMessage } from './client.js';
|
|
3
|
-
import { type WeChatChannelHelperClientOptions, type WeChatChannelHelperRequestTraceEvent } from './helper-client.js';
|
|
4
|
-
import type { WeChatChannelHelperTransport } from './observer.js';
|
|
5
|
-
import { type WeChatChannelObserveApi } from './observer.js';
|
|
6
|
-
import { WeChatChannelScheduler, type WeChatChannelSchedulerTickOptions, type WeChatChannelSchedulerTickResult } from './scheduler.js';
|
|
7
|
-
import { type WeChatAutomationLane } from './automation-lane.js';
|
|
8
|
-
export declare const WECHAT_CHANNEL_UNCHANGED_FINGERPRINT_MAX_SKIP_MS: number;
|
|
9
|
-
export type WeChatChannelProductRunnerOptions = {
|
|
10
|
-
runtime: WeChatChannelRuntime;
|
|
11
|
-
workDir: string;
|
|
12
|
-
api?: WeChatChannelRunnerApi;
|
|
13
|
-
helper?: WeChatChannelHelperTransport & {
|
|
14
|
-
start?: () => Promise<unknown>;
|
|
15
|
-
stop?: () => Promise<void>;
|
|
16
|
-
};
|
|
17
|
-
helperClientOptions?: WeChatChannelHelperClientOptions;
|
|
18
|
-
helperRequestLogger?: (event: WeChatChannelHelperRequestTraceEvent) => void;
|
|
19
|
-
ledgerPath?: string;
|
|
20
|
-
outboundLedgerPath?: string;
|
|
21
|
-
lane?: WeChatAutomationLane;
|
|
22
|
-
onInboundMessages?: (binding: WeChatChannelBindingConfig, messages: WeChatChannelObservedMessage[]) => Promise<void> | void;
|
|
23
|
-
};
|
|
24
|
-
export type WeChatChannelRunnerApi = Pick<WeChatChannelApiClient, 'upsertRuntime' | 'ingest' | 'reportRunStatus'> & Partial<Pick<WeChatChannelApiClient, 'reportOutboundStatus'>> & WeChatChannelObserveApi;
|
|
25
|
-
export declare class WeChatChannelProductRunner {
|
|
26
|
-
private options;
|
|
27
|
-
readonly scheduler: WeChatChannelScheduler;
|
|
28
|
-
readonly helper: WeChatChannelHelperTransport & {
|
|
29
|
-
start?: () => Promise<unknown>;
|
|
30
|
-
stop?: () => Promise<void>;
|
|
31
|
-
};
|
|
32
|
-
private helperStarted;
|
|
33
|
-
private readonly lane;
|
|
34
|
-
constructor(options: WeChatChannelProductRunnerOptions);
|
|
35
|
-
start(): Promise<void>;
|
|
36
|
-
tick(options?: WeChatChannelSchedulerTickOptions): Promise<WeChatChannelSchedulerTickResult | void>;
|
|
37
|
-
stop(): Promise<void>;
|
|
38
|
-
private ensureHelperStarted;
|
|
39
|
-
private shouldSkipObserveForUnchangedFingerprint;
|
|
40
|
-
}
|
|
41
|
-
export declare function createWeChatChannelProductRunner(options: WeChatChannelProductRunnerOptions): WeChatChannelProductRunner;
|
|
42
|
-
export declare function resolveWeChatOutboundBindingForConversation(runtime: WeChatChannelRuntime, conversationName: string): WeChatChannelBindingConfig;
|
|
43
|
-
export declare function buildLocalLedgerTailAnchors(ledgerPath: string, runtimeId: string, bindingId: string, limit?: number): Array<Record<string, unknown>>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import u from"node:path";import h from"node:fs";import{createWeChatChannelApiClient as m}from"./client.js";import{WeChatChannelHelperClient as g}from"./helper-client.js";import{resolveWeChatChannelHelperAsset as W,WECHAT_CHANNEL_HELPER_VERSION as S}from"./helper-assets.js";import{requiredWindowsWeChatChannelHelperCapabilitiesForProfile as c}from"./helper-protocol.js";import{captureWeChatWindow as I,detectWeChatMessageInputPointByServerVision as P,focusKnownWeChatWindow as w,observeWeChatChannelBindingViaHelper as A,openConversationBySearch as D,recognizeWeChatScreenshot as O,selectWeChatWindowForBinding as C}from"./observer.js";import{WeChatChannelScheduler as F}from"./scheduler.js";import{loadWeChatChannelLedger as M}from"./ledger.js";import{buildWeChatConversationFingerprint as _,matchWeChatConversationFingerprints as T}from"./fingerprint.js";import{WeChatChannelOutboundSender as x}from"./outbound-sender.js";import{SerialWeChatAutomationLane as N}from"./automation-lane.js";import{decideWeChatChannelActivityGate as L,nextWeChatChannelActivityRetryAt as H,normalizeWeChatChannelActivitySnapshot as R}from"./human-coordination.js";const E=120*1e3;class q{options;scheduler;helper;helperStarted=!1;lane;constructor(e){this.options=e;const n=e.api??m();this.helper=e.helper??G(e),this.lane=e.lane??new N,this.scheduler=new F({runtime:e.runtime,workDir:e.workDir,api:n,ledgerPath:e.ledgerPath,outboundLedgerPath:e.outboundLedgerPath,onInboundMessages:e.onInboundMessages,activityGate:{canObserve:async(a,t)=>{if(e.runtime.foregroundPolicy==="work")return{ok:!0};const o=await this.helper.request("activity.snapshot",{});if(!o.ok)return{ok:!1,reasonCode:"user_activity_unknown",nextAttemptAt:new Date(t.getTime()+5e3)};const i=L({snapshot:R(o.result),stage:"observe"});return i.ok?{ok:!0}:{ok:!1,reasonCode:i.reasonCode,nextAttemptAt:H(t,i.waitMs)}}},shouldSkipObserve:(a,t)=>this.shouldSkipObserveForUnchangedFingerprint(a,t.foregroundMode),outboundSender:new x({helper:this.helper,platform:e.runtime.policy.platform,activityGatePolicy:e.runtime.foregroundPolicy==="work"?{mouseMovedThresholdMs:0,mouseClickThresholdMs:0,scrollWheelThresholdMs:0,keyDownThresholdMs:0}:void 0,takeoverCheck:e.runtime.foregroundPolicy!=="work",openConversation:async a=>{const t=B(e.runtime,a),o=await C({runtime:e.runtime,binding:t,helper:this.helper,api:n,workDir:e.workDir}),i=await w(this.helper,o),s=await D({helper:this.helper,window:i,settleToBottom:!1,binding:t,runtime:e.runtime,api:n,workDir:e.workDir});if(!s.opened)return{...s,windowId:i.windowId,inputPoint:null};const l=await P({runtime:e.runtime,binding:t,helper:this.helper,api:n,workDir:e.workDir,window:i});return{...s,windowId:i.windowId,inputPoint:l}}}),observeBinding:(a,t)=>A({runtime:e.runtime,binding:a,helper:this.helper,api:n,workDir:e.workDir,localLedgerTailAnchors:U(e.ledgerPath??z(e.workDir,e.runtime.runtimeId),e.runtime.runtimeId,a.bindingId),localOutboundEchoAnchors:t?.localOutboundEchoAnchors,foregroundMode:t?.foregroundMode,onObservationEvidence:({ocr:o})=>{j({statePath:v(e.workDir,e.runtime.runtimeId),runtimeId:e.runtime.runtimeId,binding:a,ocr:o})}})})}async start(){return this.lane.run("wechat.runner.start",async()=>{await this.ensureHelperStarted(),await this.scheduler.start()})}async tick(e){return this.lane.run("wechat.runner.tick",async()=>(await this.ensureHelperStarted(),this.scheduler.tick(e)))}async stop(){return this.lane.run("wechat.runner.stop",async()=>{await this.scheduler.stop(),this.helperStarted&&this.helper.stop&&await this.helper.stop(),this.helperStarted=!1})}async ensureHelperStarted(){this.helperStarted||(this.helper.start&&await this.helper.start(),this.helperStarted=!0)}async shouldSkipObserveForUnchangedFingerprint(e,n="required"){if(this.options.runtime.policy.platform!=="darwin"&&this.options.runtime.policy.platform!=="win32")return{skip:!1};const a=v(this.options.workDir,this.options.runtime.runtimeId),t=f(a,this.options.runtime.runtimeId).bindings[e.bindingId];if(!t?.fingerprint)return{skip:!1};if(K(t))return{skip:!1};try{const o=this.options.api??m(),i=await C({runtime:this.options.runtime,binding:e,helper:this.helper,api:o,workDir:this.options.workDir},{foregroundMode:n}),s=n==="background"?i:await w(this.helper,i),l=await I(this.helper,s.windowId,void 0,s.bounds),k=await O(this.helper,l),d=y({binding:e,ocr:k,prior:t});return!d?.fingerprint||d.fingerprint!==t.fingerprint?{skip:!1}:{skip:!0,reasonCode:"conversation_fingerprint_unchanged",fingerprint:d.fingerprint}}catch{return{skip:!1}}}}function le(r){return new q(r)}function B(r,e){const n=p(e),a=r.bindings.find(t=>t.enabled!==!1&&t.allowReply!==!1&&p(t.conversationDisplayName)===n)??r.bindings.find(t=>t.enabled!==!1&&p(t.conversationDisplayName)===n);return a||{bindingId:`outbound:${e}`,sessionId:"outbound",conversationDisplayName:e,enabled:!0,allowReply:!0,downloadMedia:!0}}function p(r){return String(r??"").normalize("NFKC").replace(/\s+/g," ").trim()}function U(r,e,n,a=3){return(M(r,e).bindings[n]?.recent??[]).slice(-a).map(i=>({stableMessageKey:i.stableMessageKey,senderRole:i.senderRole,kind:i.kind,anchorText:i.anchorText??i.normalizedText??i.textExcerpt??null,anchorMetadata:i.anchorMetadata??null}))}function G(r){if(r.helperClientOptions)return new g({...r.helperClientOptions,requiredCapabilities:r.helperClientOptions.requiredCapabilities??b(r.runtime),guardUnsafeWindowsCommands:r.helperClientOptions.guardUnsafeWindowsCommands??r.runtime.policy.platform==="win32",skipUserActivityGuard:r.helperClientOptions.skipUserActivityGuard??r.runtime.foregroundPolicy==="work",cleanupWindowsOverlays:r.helperClientOptions.cleanupWindowsOverlays??r.runtime.policy.platform==="win32",requestLogger:r.helperClientOptions.requestLogger??r.helperRequestLogger});const e=W();if(!e.ok)throw new Error(`${e.reasonCode}: ${e.message}`);return new g({helperPath:e.helperPath,expectedHelperVersion:e.version||S,requiredCapabilities:b(r.runtime),guardUnsafeWindowsCommands:r.runtime.policy.platform==="win32",skipUserActivityGuard:r.runtime.foregroundPolicy==="work",cleanupWindowsOverlays:r.runtime.policy.platform==="win32",requestLogger:r.helperRequestLogger})}function b(r){if(r.policy.platform==="win32")return r.bindings.some(e=>e.enabled!==!1&&e.allowReply!==!1)?c("send"):r.bindings.some(e=>e.enabled!==!1&&e.downloadMedia!==!1)?c("download"):c("observe")}function z(r,e){return u.join(r,"wechat-channel",`${e}.ledger.json`)}function v(r,e){return u.join(r,"wechat-channel",`${V(e)}.conversation-fingerprints.json`)}function f(r,e){try{const n=JSON.parse(h.readFileSync(r,"utf8"));if(n?.version===1&&n.runtimeId===e&&n.bindings&&typeof n.bindings=="object")return n}catch{}return{version:1,runtimeId:e,bindings:{}}}function $(r,e){h.mkdirSync(u.dirname(r),{recursive:!0}),h.writeFileSync(r,JSON.stringify(e,null,2))}function j(r){const e=y({binding:r.binding,ocr:r.ocr,prior:f(r.statePath,r.runtimeId).bindings[r.binding.bindingId]});if(!e?.fingerprint)return;const n=f(r.statePath,r.runtimeId);n.bindings[r.binding.bindingId]={bindingId:r.binding.bindingId,fingerprint:e.fingerprint,title:e.item.title??null,preview:e.item.preview??null,timeText:e.item.timeText??null,unreadText:e.item.unreadText??null,observedAt:new Date().toISOString()},$(r.statePath,n)}function K(r){const e=Date.parse(r.observedAt||"");return Number.isFinite(e)?Date.now()-e>=E:!0}function y(r){const e=r.ocr.visibleConversationFingerprints??[],n=T({visibleItems:e,targets:[{bindingId:r.binding.bindingId,conversationDisplayName:r.binding.conversationDisplayName,lastConversationFingerprint:r.prior?.fingerprint,lastPreview:r.prior?.preview??void 0}]})[0];if(!n)return null;const a=_(n.item);return a?{item:n.item,fingerprint:a,reason:n.reason}:null}function V(r){return String(r||"").trim().replace(/[^a-zA-Z0-9._-]+/g,"_").replace(/^_+|_+$/g,"")||"wechat-channel-runtime"}export{E as WECHAT_CHANNEL_UNCHANGED_FINGERPRINT_MAX_SKIP_MS,q as WeChatChannelProductRunner,U as buildLocalLedgerTailAnchors,le as createWeChatChannelProductRunner,B as resolveWeChatOutboundBindingForConversation};
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
export declare const WECHAT_CHANNEL_RUNTIME_KIND: "wechat_channel";
|
|
2
|
-
export declare const WECHAT_CHANNEL_RUNTIME_VERSION = 1;
|
|
3
|
-
export declare const WECHAT_CHANNEL_RECENT_MESSAGE_WINDOW = 20;
|
|
4
|
-
export declare const WECHAT_CHANNEL_DEFAULT_POLL_INTERVAL_MS: number;
|
|
5
|
-
export declare const WECHAT_CHANNEL_MIN_POLL_INTERVAL_MS: number;
|
|
6
|
-
export declare const WECHAT_CHANNEL_MAX_POLL_INTERVAL_MS: number;
|
|
7
|
-
export declare const WECHAT_CHANNEL_DEFAULT_FOREGROUND_POLICY: "work";
|
|
8
|
-
export type WeChatChannelForegroundPolicy = 'polite' | 'work';
|
|
9
|
-
export type WeChatChannelRuntimePlatform = 'darwin' | 'win32';
|
|
10
|
-
export type WeChatChannelRuntimePolicy = {
|
|
11
|
-
kind: typeof WECHAT_CHANNEL_RUNTIME_KIND;
|
|
12
|
-
runtimeVersion: number;
|
|
13
|
-
platform: WeChatChannelRuntimePlatform;
|
|
14
|
-
pollIntervalMs: number;
|
|
15
|
-
minPollIntervalMs: number;
|
|
16
|
-
maxPollIntervalMs: number;
|
|
17
|
-
recentMessageWindow: number;
|
|
18
|
-
requiresServerDecision: true;
|
|
19
|
-
requiresPlatformHelper: true;
|
|
20
|
-
productRuntimeUsesLabFacade: false;
|
|
21
|
-
};
|
|
22
|
-
export type WeChatChannelBindingConfig = {
|
|
23
|
-
bindingId: string;
|
|
24
|
-
sessionId: string;
|
|
25
|
-
conversationDisplayName: string;
|
|
26
|
-
enabled: boolean;
|
|
27
|
-
allowReply: boolean;
|
|
28
|
-
downloadMedia: boolean;
|
|
29
|
-
selfTriggerMarker?: string | null;
|
|
30
|
-
};
|
|
31
|
-
export type WeChatChannelRuntimeConfig = {
|
|
32
|
-
runtimeId: string;
|
|
33
|
-
machineId: string;
|
|
34
|
-
platform?: WeChatChannelRuntimePlatform | null;
|
|
35
|
-
pollIntervalMs?: number | null;
|
|
36
|
-
foregroundPolicy?: WeChatChannelForegroundPolicy | null;
|
|
37
|
-
bindings?: WeChatChannelBindingConfig[] | null;
|
|
38
|
-
};
|
|
39
|
-
export type WeChatChannelRuntime = {
|
|
40
|
-
kind: typeof WECHAT_CHANNEL_RUNTIME_KIND;
|
|
41
|
-
runtimeId: string;
|
|
42
|
-
machineId: string;
|
|
43
|
-
foregroundPolicy: WeChatChannelForegroundPolicy;
|
|
44
|
-
policy: WeChatChannelRuntimePolicy;
|
|
45
|
-
bindings: WeChatChannelBindingConfig[];
|
|
46
|
-
};
|
|
47
|
-
export declare function defaultWeChatChannelRuntimePolicy(pollIntervalMs?: number | null, platform?: WeChatChannelRuntimePlatform | null): WeChatChannelRuntimePolicy;
|
|
48
|
-
export declare function normalizeWeChatChannelPollIntervalMs(value?: number | null): number;
|
|
49
|
-
export declare function createWeChatChannelRuntime(config: WeChatChannelRuntimeConfig): WeChatChannelRuntime;
|
|
50
|
-
export declare function normalizeWeChatChannelForegroundPolicy(policy?: WeChatChannelForegroundPolicy | null): WeChatChannelForegroundPolicy;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const a="wechat_channel",u=1,L=20,C=6e4,c=3e4,I=3e5,_="work";function N(n,e){return{kind:a,runtimeVersion:1,platform:s(e),pollIntervalMs:l(n),minPollIntervalMs:3e4,maxPollIntervalMs:3e5,recentMessageWindow:20,requiresServerDecision:!0,requiresPlatformHelper:!0,productRuntimeUsesLabFacade:!1}}function l(n){return Number.isFinite(n)?Math.min(3e5,Math.max(3e4,Number(n))):6e4}function m(n){const e=o(n.runtimeId,"runtimeId"),t=o(n.machineId,"machineId"),r=l(n.pollIntervalMs),i=s(n.platform);return{kind:a,runtimeId:e,machineId:t,foregroundPolicy:E(n.foregroundPolicy),policy:N(r,i),bindings:d(n.bindings??[])}}function E(n){return n==="polite"?"polite":_}function s(n){return n==="win32"?"win32":n==="darwin"?"darwin":process.platform==="win32"?"win32":"darwin"}function d(n){const e=new Set,t=[];for(const r of n){const i=o(r.bindingId,"bindingId");e.has(i)||(e.add(i),t.push({bindingId:i,sessionId:o(r.sessionId,"sessionId"),conversationDisplayName:o(r.conversationDisplayName,"conversationDisplayName"),enabled:r.enabled!==!1,allowReply:r.allowReply!==!1,downloadMedia:r.downloadMedia!==!1,selfTriggerMarker:A(r.selfTriggerMarker)}))}return t}function o(n,e){const t=String(n||"").trim();if(!t)throw new Error(`WeChat channel ${e} is required`);return t}function A(n){return String(n||"").trim()||null}export{_ as WECHAT_CHANNEL_DEFAULT_FOREGROUND_POLICY,C as WECHAT_CHANNEL_DEFAULT_POLL_INTERVAL_MS,I as WECHAT_CHANNEL_MAX_POLL_INTERVAL_MS,c as WECHAT_CHANNEL_MIN_POLL_INTERVAL_MS,L as WECHAT_CHANNEL_RECENT_MESSAGE_WINDOW,a as WECHAT_CHANNEL_RUNTIME_KIND,u as WECHAT_CHANNEL_RUNTIME_VERSION,m as createWeChatChannelRuntime,N as defaultWeChatChannelRuntimePolicy,E as normalizeWeChatChannelForegroundPolicy,l as normalizeWeChatChannelPollIntervalMs};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import type { WeChatChannelRuntime, WeChatChannelBindingConfig } from './runtime.js';
|
|
2
|
-
import type { WeChatChannelApiClient, WeChatChannelObservedMessage, WeChatChannelRunStatusInput } from './client.js';
|
|
3
|
-
import { type WeChatChannelBindingLedger } from './ledger.js';
|
|
4
|
-
import { type WeChatChannelOutboundRecord } from './outbound-ledger.js';
|
|
5
|
-
import { type WeChatChannelOutboundSender } from './outbound-sender.js';
|
|
6
|
-
import type { WeChatChannelForegroundMode, WeChatChannelLocalOutboundEchoAnchor } from './observer.js';
|
|
7
|
-
import type { WeChatChannelHumanActivityReasonCode } from './helper-protocol.js';
|
|
8
|
-
export type WeChatChannelSchedulerOptions = {
|
|
9
|
-
runtime: WeChatChannelRuntime;
|
|
10
|
-
workDir: string;
|
|
11
|
-
api: Pick<WeChatChannelApiClient, 'upsertRuntime' | 'ingest'> & {
|
|
12
|
-
reportRunStatus: (runtime: WeChatChannelRuntime, binding: WeChatChannelBindingConfig, input: WeChatChannelRunStatusInput) => Promise<unknown>;
|
|
13
|
-
} & Partial<Pick<WeChatChannelApiClient, 'reportOutboundStatus'>>;
|
|
14
|
-
observeBinding: (binding: WeChatChannelBindingConfig, context?: {
|
|
15
|
-
localOutboundEchoAnchors?: WeChatChannelLocalOutboundEchoAnchor[];
|
|
16
|
-
foregroundMode?: WeChatChannelForegroundMode;
|
|
17
|
-
}) => Promise<WeChatChannelObservedMessage[]>;
|
|
18
|
-
shouldSkipObserve?: (binding: WeChatChannelBindingConfig, context: {
|
|
19
|
-
ledgerBinding?: WeChatChannelBindingLedger;
|
|
20
|
-
outboundRecords: WeChatChannelOutboundRecord[];
|
|
21
|
-
now: Date;
|
|
22
|
-
foregroundMode: WeChatChannelForegroundMode;
|
|
23
|
-
}) => Promise<WeChatChannelObserveSkipDecision> | WeChatChannelObserveSkipDecision;
|
|
24
|
-
onInboundMessages?: (binding: WeChatChannelBindingConfig, messages: WeChatChannelObservedMessage[]) => Promise<void> | void;
|
|
25
|
-
outboundSender?: WeChatChannelOutboundSender;
|
|
26
|
-
activityGate?: WeChatChannelSchedulerActivityGate;
|
|
27
|
-
ledgerPath?: string;
|
|
28
|
-
outboundLedgerPath?: string;
|
|
29
|
-
maxUserActivityWaitMs?: number;
|
|
30
|
-
};
|
|
31
|
-
export type WeChatChannelSchedulerTickOptions = {
|
|
32
|
-
forceObserve?: boolean;
|
|
33
|
-
};
|
|
34
|
-
export type WeChatChannelSchedulerActivityGate = {
|
|
35
|
-
canObserve: (binding: WeChatChannelBindingConfig, now: Date) => Promise<{
|
|
36
|
-
ok: true;
|
|
37
|
-
} | {
|
|
38
|
-
ok: false;
|
|
39
|
-
reasonCode: WeChatChannelHumanActivityReasonCode | 'user_activity_unknown';
|
|
40
|
-
nextAttemptAt: Date;
|
|
41
|
-
}>;
|
|
42
|
-
};
|
|
43
|
-
export type WeChatChannelSchedulerTickResult = {
|
|
44
|
-
bindingId: string;
|
|
45
|
-
observedCount: number;
|
|
46
|
-
newInboundCount: number;
|
|
47
|
-
outboundSentCount: number;
|
|
48
|
-
staleOutboundCount: number;
|
|
49
|
-
failedOutboundCount: number;
|
|
50
|
-
waitingOutboundCount: number;
|
|
51
|
-
confirmedEchoCount: number;
|
|
52
|
-
manualReviewCount: number;
|
|
53
|
-
revision: number;
|
|
54
|
-
}[];
|
|
55
|
-
export type WeChatChannelObserveSkipDecision = {
|
|
56
|
-
skip: true;
|
|
57
|
-
reasonCode: 'conversation_fingerprint_unchanged' | 'conversation_not_visible_background';
|
|
58
|
-
fingerprint?: string | null;
|
|
59
|
-
} | {
|
|
60
|
-
skip: false;
|
|
61
|
-
reasonCode?: string;
|
|
62
|
-
};
|
|
63
|
-
export declare class WeChatChannelScheduler {
|
|
64
|
-
private options;
|
|
65
|
-
private timer;
|
|
66
|
-
private running;
|
|
67
|
-
private runningTick;
|
|
68
|
-
constructor(options: WeChatChannelSchedulerOptions);
|
|
69
|
-
start(): Promise<void>;
|
|
70
|
-
stop(): Promise<void>;
|
|
71
|
-
tick(options?: WeChatChannelSchedulerTickOptions): Promise<WeChatChannelSchedulerTickResult | void>;
|
|
72
|
-
noteInterruption(bindingId: string, reason?: string, now?: Date): void;
|
|
73
|
-
private reportOutboundProjections;
|
|
74
|
-
}
|