shennian 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/README.md +3 -1
  2. package/dist/publish-build-manifest.json +291 -341
  3. package/dist/src/agents/codex.js +1 -1
  4. package/dist/src/agents/command-spec.js +2 -2
  5. package/dist/src/agents/detect.js +1 -1
  6. package/dist/src/agents/model-registry/discovery.js +2 -2
  7. package/dist/src/agents/model-registry/parsers.d.ts +1 -0
  8. package/dist/src/agents/model-registry/parsers.js +4 -4
  9. package/dist/src/agents/model-registry/service.js +1 -1
  10. package/dist/src/agents/native-capabilities.d.ts +10 -0
  11. package/dist/src/agents/native-capabilities.js +1 -0
  12. package/dist/src/agents/platform-instructions.js +5 -5
  13. package/dist/src/agents/runtime-compatibility.d.ts +11 -0
  14. package/dist/src/agents/runtime-compatibility.js +1 -0
  15. package/dist/src/agents/workbuddy.d.ts +44 -0
  16. package/dist/src/agents/workbuddy.js +3 -0
  17. package/dist/src/commands/daemon.d.ts +1 -0
  18. package/dist/src/commands/daemon.js +9 -9
  19. package/dist/src/commands/integration.d.ts +2 -0
  20. package/dist/src/commands/integration.js +1 -0
  21. package/dist/src/commands/manager.js +1 -2
  22. package/dist/src/commands/pair-browser.d.ts +43 -0
  23. package/dist/src/commands/pair-browser.js +1 -0
  24. package/dist/src/commands/pair.d.ts +2 -0
  25. package/dist/src/commands/pair.js +11 -8
  26. package/dist/src/commands/room.d.ts +13 -0
  27. package/dist/src/commands/room.js +4 -0
  28. package/dist/src/commands/upgrade.d.ts +3 -0
  29. package/dist/src/commands/upgrade.js +1 -1
  30. package/dist/src/config/index.d.ts +3 -1
  31. package/dist/src/config/index.js +2 -1
  32. package/dist/src/daemon-ipc/client.d.ts +8 -0
  33. package/dist/src/daemon-ipc/client.js +3 -0
  34. package/dist/src/daemon-ipc/paths.d.ts +7 -0
  35. package/dist/src/daemon-ipc/paths.js +1 -0
  36. package/dist/src/daemon-ipc/protocol.d.ts +30 -0
  37. package/dist/src/daemon-ipc/protocol.js +1 -0
  38. package/dist/src/daemon-ipc/secret.d.ts +3 -0
  39. package/dist/src/daemon-ipc/secret.js +3 -0
  40. package/dist/src/daemon-ipc/server.d.ts +13 -0
  41. package/dist/src/daemon-ipc/server.js +3 -0
  42. package/dist/src/index.js +2 -2
  43. package/dist/src/integrations/claude-room-plugin-lifecycle.d.ts +47 -0
  44. package/dist/src/integrations/claude-room-plugin-lifecycle.js +1 -0
  45. package/dist/src/integrations/codex-room-plugin-lifecycle.d.ts +49 -0
  46. package/dist/src/integrations/codex-room-plugin-lifecycle.js +1 -0
  47. package/dist/src/integrations/room-plugin-bundles.d.ts +23 -0
  48. package/dist/src/integrations/room-plugin-bundles.js +1 -0
  49. package/dist/src/integrations/room-plugin-lifecycle-common.d.ts +17 -0
  50. package/dist/src/integrations/room-plugin-lifecycle-common.js +1 -0
  51. package/dist/src/integrations/room-plugin-shared.d.ts +24 -0
  52. package/dist/src/integrations/room-plugin-shared.js +2 -0
  53. package/dist/src/integrations/room-session-hook.d.ts +30 -0
  54. package/dist/src/integrations/room-session-hook.js +2 -0
  55. package/dist/src/integrations/workbuddy-plugin-bundle.d.ts +15 -0
  56. package/dist/src/integrations/workbuddy-plugin-bundle.js +1 -0
  57. package/dist/src/integrations/workbuddy-plugin-lifecycle.d.ts +52 -0
  58. package/dist/src/integrations/workbuddy-plugin-lifecycle.js +2 -0
  59. package/dist/src/integrations/workbuddy-session-hook.d.ts +22 -0
  60. package/dist/src/integrations/workbuddy-session-hook.js +1 -0
  61. package/dist/src/manager/prompt.d.ts +1 -1
  62. package/dist/src/manager/prompt.js +1 -1
  63. package/dist/src/manager/retired-external-channel-compat.d.ts +78 -0
  64. package/dist/src/manager/retired-external-channel-compat.js +1 -0
  65. package/dist/src/manager/runtime.d.ts +1 -3
  66. package/dist/src/manager/runtime.js +7 -7
  67. package/dist/src/relay/client.d.ts +2 -0
  68. package/dist/src/relay/client.js +1 -1
  69. package/dist/src/room/activation-audit.d.ts +15 -0
  70. package/dist/src/room/activation-audit.js +2 -0
  71. package/dist/src/room/activation-policy.d.ts +8 -0
  72. package/dist/src/room/activation-policy.js +1 -0
  73. package/dist/src/room/activation-service.d.ts +25 -0
  74. package/dist/src/room/activation-service.js +2 -0
  75. package/dist/src/room/agent-tool.d.ts +62 -0
  76. package/dist/src/room/agent-tool.js +1 -0
  77. package/dist/src/room/attachment-cache.d.ts +40 -0
  78. package/dist/src/room/attachment-cache.js +2 -0
  79. package/dist/src/room/attachment-upload.d.ts +20 -0
  80. package/dist/src/room/attachment-upload.js +1 -0
  81. package/dist/src/room/authorized-action-coordinator.d.ts +40 -0
  82. package/dist/src/room/authorized-action-coordinator.js +1 -0
  83. package/dist/src/room/authorized-action-ipc.d.ts +11 -0
  84. package/dist/src/room/authorized-action-ipc.js +1 -0
  85. package/dist/src/room/device-authorization-client.d.ts +49 -0
  86. package/dist/src/room/device-authorization-client.js +1 -0
  87. package/dist/src/room/host-session-observation-ipc.d.ts +9 -0
  88. package/dist/src/room/host-session-observation-ipc.js +1 -0
  89. package/dist/src/room/host-session-observations.d.ts +54 -0
  90. package/dist/src/room/host-session-observations.js +2 -0
  91. package/dist/src/room/invite-bootstrap.d.ts +35 -0
  92. package/dist/src/room/invite-bootstrap.js +1 -0
  93. package/dist/src/room/invocation-token-ipc.d.ts +9 -0
  94. package/dist/src/room/invocation-token-ipc.js +1 -0
  95. package/dist/src/room/invocation-token.d.ts +53 -0
  96. package/dist/src/room/invocation-token.js +1 -0
  97. package/dist/src/room/jsonl-mirror.d.ts +73 -0
  98. package/dist/src/room/jsonl-mirror.js +6 -0
  99. package/dist/src/room/managed-room-binding.d.ts +42 -0
  100. package/dist/src/room/managed-room-binding.js +1 -0
  101. package/dist/src/room/managed-room-session.d.ts +143 -0
  102. package/dist/src/room/managed-room-session.js +3 -0
  103. package/dist/src/room/mirror-sync-service.d.ts +33 -0
  104. package/dist/src/room/mirror-sync-service.js +1 -0
  105. package/dist/src/room/operator-ipc.d.ts +11 -0
  106. package/dist/src/room/operator-ipc.js +1 -0
  107. package/dist/src/room/pending-authorized-actions.d.ts +69 -0
  108. package/dist/src/room/pending-authorized-actions.js +3 -0
  109. package/dist/src/room/room-action-client.d.ts +210 -0
  110. package/dist/src/room/room-action-client.js +1 -0
  111. package/dist/src/room/room-action-ipc.d.ts +33 -0
  112. package/dist/src/room/room-action-ipc.js +1 -0
  113. package/dist/src/room/room-action-schema.d.ts +3 -0
  114. package/dist/src/room/room-action-schema.js +1 -0
  115. package/dist/src/room/room-authorized-action-executor.d.ts +23 -0
  116. package/dist/src/room/room-authorized-action-executor.js +1 -0
  117. package/dist/src/room/room-binding-client.d.ts +51 -0
  118. package/dist/src/room/room-binding-client.js +1 -0
  119. package/dist/src/room/room-binding-ipc.d.ts +29 -0
  120. package/dist/src/room/room-binding-ipc.js +1 -0
  121. package/dist/src/room/session-registry-ipc.d.ts +14 -0
  122. package/dist/src/room/session-registry-ipc.js +1 -0
  123. package/dist/src/room/session-registry.d.ts +128 -0
  124. package/dist/src/room/session-registry.js +2 -0
  125. package/dist/src/room/tool-schema.d.ts +118 -0
  126. package/dist/src/room/tool-schema.js +1 -0
  127. package/dist/src/room/tool-server.d.ts +5 -0
  128. package/dist/src/room/tool-server.js +3 -0
  129. package/dist/src/session/handlers/agent-capabilities.d.ts +3 -0
  130. package/dist/src/session/handlers/agent-capabilities.js +1 -0
  131. package/dist/src/session/handlers/agent-config.js +1 -1
  132. package/dist/src/session/handlers/chat.js +2 -2
  133. package/dist/src/session/handlers/control.js +1 -1
  134. package/dist/src/session/handlers/fs.d.ts +1 -0
  135. package/dist/src/session/handlers/fs.js +1 -1
  136. package/dist/src/session/handlers/room-managed.d.ts +4 -0
  137. package/dist/src/session/handlers/room-managed.js +1 -0
  138. package/dist/src/session/manager.d.ts +18 -6
  139. package/dist/src/session/manager.js +1 -1
  140. package/dist/src/session/types.d.ts +5 -0
  141. package/dist/src/upgrade/engine.d.ts +14 -1
  142. package/dist/src/upgrade/engine.js +2 -2
  143. package/dist/src/upgrade/scheduler.d.ts +45 -0
  144. package/dist/src/upgrade/scheduler.js +1 -0
  145. package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts +17 -0
  146. package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts.map +1 -0
  147. package/node_modules/@shennian/wire/dist/agent-capabilities.js +2 -0
  148. package/node_modules/@shennian/wire/dist/agent-capabilities.js.map +1 -0
  149. package/node_modules/@shennian/wire/dist/agent-workspace.d.ts +41 -0
  150. package/node_modules/@shennian/wire/dist/agent-workspace.d.ts.map +1 -0
  151. package/node_modules/@shennian/wire/dist/agent-workspace.js +3 -0
  152. package/node_modules/@shennian/wire/dist/agent-workspace.js.map +1 -0
  153. package/node_modules/@shennian/wire/dist/index.d.ts +3 -1
  154. package/node_modules/@shennian/wire/dist/index.d.ts.map +1 -1
  155. package/node_modules/@shennian/wire/dist/index.js +3 -1
  156. package/node_modules/@shennian/wire/dist/index.js.map +1 -1
  157. package/node_modules/@shennian/wire/dist/machine.d.ts +1 -0
  158. package/node_modules/@shennian/wire/dist/machine.d.ts.map +1 -1
  159. package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
  160. package/node_modules/@shennian/wire/dist/methods.d.ts.map +1 -1
  161. package/node_modules/@shennian/wire/dist/room.d.ts +112 -0
  162. package/node_modules/@shennian/wire/dist/room.d.ts.map +1 -0
  163. package/node_modules/@shennian/wire/dist/room.js +4 -0
  164. package/node_modules/@shennian/wire/dist/room.js.map +1 -0
  165. package/node_modules/@shennian/wire/dist/session.d.ts +15 -2
  166. package/node_modules/@shennian/wire/dist/session.d.ts.map +1 -1
  167. package/node_modules/@shennian/wire/dist/session.js +1 -1
  168. package/node_modules/@shennian/wire/dist/session.js.map +1 -1
  169. package/package.json +3 -5
  170. package/dist/scripts/wechat-rpa-confirmation.mjs +0 -5
  171. package/dist/src/agents/pi-context.d.ts +0 -42
  172. package/dist/src/agents/pi-context.js +0 -12
  173. package/dist/src/agents/pi.d.ts +0 -70
  174. package/dist/src/agents/pi.js +0 -17
  175. package/dist/src/channels/base.d.ts +0 -144
  176. package/dist/src/channels/base.js +0 -1
  177. package/dist/src/channels/registry.d.ts +0 -8
  178. package/dist/src/channels/registry.js +0 -1
  179. package/dist/src/channels/reply-split.d.ts +0 -1
  180. package/dist/src/channels/reply-split.js +0 -10
  181. package/dist/src/channels/runtime.d.ts +0 -138
  182. package/dist/src/channels/runtime.js +0 -5
  183. package/dist/src/channels/secret-registry.d.ts +0 -35
  184. package/dist/src/channels/secret-registry.js +0 -1
  185. package/dist/src/channels/websocket.d.ts +0 -55
  186. package/dist/src/channels/websocket.js +0 -8
  187. package/dist/src/channels/wechat-channel/anchor.d.ts +0 -10
  188. package/dist/src/channels/wechat-channel/anchor.js +0 -1
  189. package/dist/src/channels/wechat-channel/automation-lane.d.ts +0 -35
  190. package/dist/src/channels/wechat-channel/automation-lane.js +0 -2
  191. package/dist/src/channels/wechat-channel/client.d.ts +0 -283
  192. package/dist/src/channels/wechat-channel/client.js +0 -1
  193. package/dist/src/channels/wechat-channel/cooldown.d.ts +0 -21
  194. package/dist/src/channels/wechat-channel/cooldown.js +0 -1
  195. package/dist/src/channels/wechat-channel/core/fixture-compare.d.ts +0 -52
  196. package/dist/src/channels/wechat-channel/core/fixture-compare.js +0 -1
  197. package/dist/src/channels/wechat-channel/core/media-action-plan.d.ts +0 -3
  198. package/dist/src/channels/wechat-channel/core/media-action-plan.js +0 -1
  199. package/dist/src/channels/wechat-channel/core/schema.d.ts +0 -67
  200. package/dist/src/channels/wechat-channel/core/schema.js +0 -1
  201. package/dist/src/channels/wechat-channel/core/trace-comparator.d.ts +0 -28
  202. package/dist/src/channels/wechat-channel/core/trace-comparator.js +0 -1
  203. package/dist/src/channels/wechat-channel/fingerprint.d.ts +0 -31
  204. package/dist/src/channels/wechat-channel/fingerprint.js +0 -1
  205. package/dist/src/channels/wechat-channel/helper-assets.d.ts +0 -103
  206. package/dist/src/channels/wechat-channel/helper-assets.js +0 -1
  207. package/dist/src/channels/wechat-channel/helper-client.d.ts +0 -87
  208. package/dist/src/channels/wechat-channel/helper-client.js +0 -3
  209. package/dist/src/channels/wechat-channel/helper-protocol.d.ts +0 -122
  210. package/dist/src/channels/wechat-channel/helper-protocol.js +0 -1
  211. package/dist/src/channels/wechat-channel/human-coordination.d.ts +0 -25
  212. package/dist/src/channels/wechat-channel/human-coordination.js +0 -1
  213. package/dist/src/channels/wechat-channel/index.d.ts +0 -21
  214. package/dist/src/channels/wechat-channel/index.js +0 -1
  215. package/dist/src/channels/wechat-channel/ledger.d.ts +0 -48
  216. package/dist/src/channels/wechat-channel/ledger.js +0 -2
  217. package/dist/src/channels/wechat-channel/media-cache-resolver.d.ts +0 -42
  218. package/dist/src/channels/wechat-channel/media-cache-resolver.js +0 -1
  219. package/dist/src/channels/wechat-channel/media-resolver.d.ts +0 -186
  220. package/dist/src/channels/wechat-channel/media-resolver.js +0 -1
  221. package/dist/src/channels/wechat-channel/message-key.d.ts +0 -19
  222. package/dist/src/channels/wechat-channel/message-key.js +0 -1
  223. package/dist/src/channels/wechat-channel/observer.d.ts +0 -171
  224. package/dist/src/channels/wechat-channel/observer.js +0 -7
  225. package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +0 -96
  226. package/dist/src/channels/wechat-channel/outbound-ledger.js +0 -2
  227. package/dist/src/channels/wechat-channel/outbound-sender.d.ts +0 -74
  228. package/dist/src/channels/wechat-channel/outbound-sender.js +0 -1
  229. package/dist/src/channels/wechat-channel/pacing.d.ts +0 -3
  230. package/dist/src/channels/wechat-channel/pacing.js +0 -1
  231. package/dist/src/channels/wechat-channel/preflight.d.ts +0 -46
  232. package/dist/src/channels/wechat-channel/preflight.js +0 -1
  233. package/dist/src/channels/wechat-channel/runner.d.ts +0 -43
  234. package/dist/src/channels/wechat-channel/runner.js +0 -1
  235. package/dist/src/channels/wechat-channel/runtime.d.ts +0 -50
  236. package/dist/src/channels/wechat-channel/runtime.js +0 -1
  237. package/dist/src/channels/wechat-channel/scheduler.d.ts +0 -74
  238. package/dist/src/channels/wechat-channel/scheduler.js +0 -1
  239. package/dist/src/channels/wechat-channel/vector-store.d.ts +0 -44
  240. package/dist/src/channels/wechat-channel/vector-store.js +0 -1
  241. package/dist/src/channels/wechat-rpa/macos-flow.d.ts +0 -55
  242. package/dist/src/channels/wechat-rpa/macos-flow.js +0 -1
  243. package/dist/src/channels/wechat-rpa/macos.d.ts +0 -11
  244. package/dist/src/channels/wechat-rpa/macos.js +0 -21
  245. package/dist/src/channels/wechat-rpa/normalizer.d.ts +0 -49
  246. package/dist/src/channels/wechat-rpa/normalizer.js +0 -7
  247. package/dist/src/channels/wechat-rpa/product-channel.d.ts +0 -76
  248. package/dist/src/channels/wechat-rpa/product-channel.js +0 -16
  249. package/dist/src/channels/wechat-rpa-session-sync.d.ts +0 -26
  250. package/dist/src/channels/wechat-rpa-session-sync.js +0 -1
  251. package/dist/src/channels/wechat-rpa.d.ts +0 -104
  252. package/dist/src/channels/wechat-rpa.js +0 -6
  253. package/dist/src/channels/wecom.d.ts +0 -51
  254. package/dist/src/channels/wecom.js +0 -4
  255. package/dist/src/commands/external-attachments.d.ts +0 -9
  256. package/dist/src/commands/external-attachments.js +0 -1
  257. package/dist/src/commands/external.d.ts +0 -2
  258. package/dist/src/commands/external.js +0 -1
  259. package/dist/src/commands/helper-runtime-official-download.d.ts +0 -80
  260. package/dist/src/commands/helper-runtime-official-download.js +0 -1
  261. package/dist/src/commands/runtime.d.ts +0 -120
  262. package/dist/src/commands/runtime.js +0 -1
  263. package/dist/src/commands/wechat/command.d.ts +0 -3
  264. package/dist/src/commands/wechat/command.js +0 -1
  265. package/dist/src/commands/wechat/direct.d.ts +0 -14
  266. package/dist/src/commands/wechat/direct.js +0 -2
  267. package/dist/src/commands/wechat/doctor.d.ts +0 -2
  268. package/dist/src/commands/wechat/doctor.js +0 -1
  269. package/dist/src/commands/wechat/ipc.d.ts +0 -9
  270. package/dist/src/commands/wechat/ipc.js +0 -1
  271. package/dist/src/commands/wechat/operations.d.ts +0 -3
  272. package/dist/src/commands/wechat/operations.js +0 -4
  273. package/dist/src/commands/wechat/output.d.ts +0 -7
  274. package/dist/src/commands/wechat/output.js +0 -4
  275. package/dist/src/commands/wechat/types.d.ts +0 -142
  276. package/dist/src/commands/wechat/types.js +0 -1
  277. package/dist/src/commands/wechat/utils.d.ts +0 -16
  278. package/dist/src/commands/wechat/utils.js +0 -1
  279. package/dist/src/commands/wechat.d.ts +0 -6
  280. package/dist/src/commands/wechat.js +0 -1
  281. package/dist/src/devtools/wechat-channel-action-smoke.d.ts +0 -105
  282. package/dist/src/devtools/wechat-channel-action-smoke.js +0 -10
  283. package/dist/src/devtools/wechat-channel-download-report.d.ts +0 -111
  284. package/dist/src/devtools/wechat-channel-download-report.js +0 -2
  285. package/dist/src/devtools/wechat-channel-markdown-report.d.ts +0 -6
  286. package/dist/src/devtools/wechat-channel-markdown-report.js +0 -5
  287. package/dist/src/devtools/wechat-channel-product-steps.d.ts +0 -9
  288. package/dist/src/devtools/wechat-channel-product-steps.js +0 -40
  289. package/dist/src/session/handlers/skills.d.ts +0 -7
  290. package/dist/src/session/handlers/skills.js +0 -1
  291. package/dist/src/session/handlers/wechat-helper-runtime.d.ts +0 -33
  292. package/dist/src/session/handlers/wechat-helper-runtime.js +0 -1
  293. package/dist/src/skills/registry.d.ts +0 -16
  294. package/dist/src/skills/registry.js +0 -15
  295. package/dist/src/skills/setup.d.ts +0 -11
  296. package/dist/src/skills/setup.js +0 -1
@@ -1,186 +0,0 @@
1
- import type { ExternalMessageAttachment } from '../base.js';
2
- import type { WeChatChannelHelperTransport } from './observer.js';
3
- import { type WeChatChannelMediaCacheScanTrace } from './media-cache-resolver.js';
4
- export type WeChatChannelVisibleMediaCandidate = {
5
- messageKey: string;
6
- kind: 'image' | 'video' | 'file' | 'link' | 'card' | string;
7
- bbox?: {
8
- x: number;
9
- y: number;
10
- width: number;
11
- height: number;
12
- coordinateSpace?: string;
13
- };
14
- screenshotBbox?: {
15
- x: number;
16
- y: number;
17
- width: number;
18
- height: number;
19
- coordinateSpace?: string;
20
- };
21
- downloadActionBbox?: {
22
- x: number;
23
- y: number;
24
- width: number;
25
- height: number;
26
- coordinateSpace?: string;
27
- } | null;
28
- fileName?: string | null;
29
- mimeType?: string | null;
30
- size?: number | null;
31
- mediaStatus?: 'available' | 'not_downloaded' | 'loading' | 'metadata_only' | 'unsupported' | string | null;
32
- observedAt?: string | null;
33
- contextText?: string | null;
34
- };
35
- export type WeChatChannelMediaResolveResult = {
36
- messageKey: string;
37
- attachment: ExternalMessageAttachment;
38
- reasonCode: string;
39
- attemptReasonCodes?: string[];
40
- resolveTrace?: WeChatChannelMediaResolveTrace;
41
- };
42
- export type WeChatChannelMediaResolveTrace = {
43
- candidateKind: string;
44
- bbox?: WeChatChannelVisibleMediaCandidate['bbox'];
45
- downloadActionBbox?: WeChatChannelVisibleMediaCandidate['downloadActionBbox'];
46
- mediaStatus?: WeChatChannelVisibleMediaCandidate['mediaStatus'];
47
- actionPlan: {
48
- reasonCode: string;
49
- actions: Array<{
50
- type: string;
51
- reasonCode?: string;
52
- label?: string;
53
- target?: unknown;
54
- }>;
55
- };
56
- attempts: WeChatChannelMediaResolveAttemptTrace[];
57
- finalReasonCode?: string;
58
- attachmentValidation?: WeChatChannelMediaAttachmentValidationTrace;
59
- };
60
- export type WeChatChannelMediaResolveAttemptTrace = {
61
- phase: 'stability' | 'copy-before-download' | 'download-action' | 'copy-after-download' | 'cache-scan';
62
- stage?: WeChatChannelMediaStabilityStage;
63
- retry?: boolean;
64
- pointAttempt?: number;
65
- pointRole?: 'center' | 'file-title' | 'file-body' | 'media-top-left' | 'media-top-right' | 'media-bottom-left' | 'media-bottom-right';
66
- ok?: boolean;
67
- reasonCode?: string;
68
- rightClickPoint?: {
69
- x: number;
70
- y: number;
71
- coordinateSpace?: string;
72
- };
73
- menuSearchBounds?: WeChatChannelMenuSearchBounds;
74
- menuPickOrder?: Array<'ocr-menu'>;
75
- pickedMethod?: 'ocr-menu';
76
- pickedLabel?: string;
77
- pickedPoint?: {
78
- x: number;
79
- y: number;
80
- };
81
- ocrMenuCandidates?: WeChatChannelOcrMenuCandidateTrace[];
82
- disallowedLabels?: string[];
83
- clipboardChangeCountBefore?: number | null;
84
- clipboardChangeCountAfter?: number | null;
85
- clipboardPayload?: WeChatChannelClipboardPayloadTrace;
86
- downloadPoint?: {
87
- x: number;
88
- y: number;
89
- coordinateSpace?: string;
90
- };
91
- cacheScan?: WeChatChannelMediaCacheScanTrace;
92
- };
93
- export type WeChatChannelOcrMenuCandidateTrace = {
94
- text: string;
95
- normalizedText: string;
96
- point?: {
97
- x: number;
98
- y: number;
99
- };
100
- bbox?: {
101
- x: number;
102
- y: number;
103
- width: number;
104
- height: number;
105
- coordinateSpace?: string;
106
- };
107
- exact?: boolean;
108
- exactCopy?: boolean;
109
- fuzzy?: boolean;
110
- dangerous?: boolean;
111
- selected?: boolean;
112
- };
113
- export type WeChatChannelClipboardPayloadTrace = {
114
- changeCount?: number | null;
115
- fileUrlCount: number;
116
- filePathCount: number;
117
- hasImageData: boolean;
118
- imageDataBytes?: number;
119
- mimeType?: string;
120
- suggestedFileName?: string;
121
- fileNames?: string[];
122
- extensions?: string[];
123
- };
124
- export type WeChatChannelMediaAttachmentValidationTrace = {
125
- availability?: ExternalMessageAttachment['availability'];
126
- type?: string;
127
- name?: string;
128
- localPath?: string;
129
- mimeType?: string;
130
- extension?: string;
131
- materializationKind?: ExternalMessageAttachment['materializationKind'];
132
- isOriginal?: boolean;
133
- mimeKindMatches?: boolean;
134
- };
135
- export type WeChatChannelMediaStabilityStage = 'before-media-action' | 'after-media-action';
136
- export type WeChatChannelMediaStabilityCheck = (input: {
137
- stage: WeChatChannelMediaStabilityStage;
138
- candidate: WeChatChannelVisibleMediaCandidate;
139
- }) => Promise<{
140
- ok: true;
141
- } | {
142
- ok: false;
143
- reasonCode: string;
144
- }> | {
145
- ok: true;
146
- } | {
147
- ok: false;
148
- reasonCode: string;
149
- };
150
- type WeChatChannelMenuSearchBounds = {
151
- x: number;
152
- y: number;
153
- width: number;
154
- height: number;
155
- coordinateSpace?: string;
156
- };
157
- export declare function defaultWeChatChannelAttachmentDir(_workDir: string, runtimeId: string, bindingId: string): string;
158
- export declare function resolveVisibleWeChatChannelMedia(input: {
159
- helper: WeChatChannelHelperTransport;
160
- candidates: WeChatChannelVisibleMediaCandidate[];
161
- attachmentsDir: string;
162
- screenshot?: {
163
- mimeType: string;
164
- dataBase64: string;
165
- width: number;
166
- height: number;
167
- };
168
- windowId?: string;
169
- window?: {
170
- windowId: string;
171
- bounds?: {
172
- x: number;
173
- y: number;
174
- width: number;
175
- height: number;
176
- coordinateSpace?: string;
177
- };
178
- };
179
- traceId?: string;
180
- stabilityCheck?: WeChatChannelMediaStabilityCheck;
181
- platform?: NodeJS.Platform | string;
182
- wechatCacheRoots?: string[];
183
- }): Promise<WeChatChannelMediaResolveResult[]>;
184
- export declare function materializeLocalAttachment(candidate: WeChatChannelVisibleMediaCandidate, sourcePath: string, attachmentsDir: string, sourceAction?: string): ExternalMessageAttachment;
185
- export declare function metadataOnlyResult(candidate: WeChatChannelVisibleMediaCandidate, reasonCode: string, resolveTrace?: WeChatChannelMediaResolveTrace): WeChatChannelMediaResolveResult;
186
- export {};
@@ -1 +0,0 @@
1
- import M from"node:crypto";import p from"node:fs";import h from"node:path";import{resolveShennianPath as G}from"../../config/index.js";import{buildWeChatChannelMediaActionPlan as J}from"./core/media-action-plan.js";import{normalizeWeChatChannelMessageKind as L}from"./core/schema.js";import{findCachedWeChatInboundMedia as Z}from"./media-cache-resolver.js";const R=20*1024*1024,O=["\u5F15\u7528","\u5220\u9664","\u591A\u9009","\u8F6C\u53D1","\u6536\u85CF","\u63D0\u9192","\u7F16\u8F91","\u4FDD\u5B58","\u53E6\u5B58\u4E3A","\u6253\u5F00\u65B9\u5F0F","Quote","Delete","Forward","Favorite","Save","Save As","Save to Downloads","Open With"];function Fe(e,t,o){const n=M.createHash("sha256").update(`${t}:${o}`).digest("hex").slice(0,16);return G("wechat-rpa","attachments","inbound",n)}async function Le(e){const t=[];for(const o of e.candidates)try{const n=q(o),a=D(o,n);if(!n.actions.length){t.push(w(o,n.reasonCode,a));continue}const r=await v(e,"before-media-action",o);if(T(a,"before-media-action",r),!r.ok){t.push(w(o,r.reasonCode,a));continue}const i=ee(o);if(i==="loading"){t.push(w(o,"download_in_progress_waiting",a));continue}if(i==="pending"){const d=$({candidate:o,attachmentsDir:e.attachmentsDir,resolveTrace:a,platform:e.platform,cacheRoots:e.wechatCacheRoots});if(d.attachment){t.push(await B(e,{messageKey:o.messageKey,attachment:d.attachment,reasonCode:d.reasonCode||"edge_local_from_wechat_cache",resolveTrace:a},o,a));continue}const l=await v(e,"before-media-action",o);if(T(a,"before-media-action",l),!l.ok){t.push({...w(o,l.reasonCode,a),...d.reasonCode?{attemptReasonCodes:b([d.reasonCode,l.reasonCode])}:{}});continue}const u=await te({helper:e.helper,candidate:o,resolveTrace:a,windowId:e.windowId,traceId:e.traceId}),g=u.ok?"download_triggered_pending_next_observe":u.reasonCode||"download_action_click_failed",F=b([d.reasonCode,u.reasonCode]);t.push({...w(o,g,a),...F.length?{attemptReasonCodes:F}:{}});continue}const s=[],c=await oe({helper:e.helper,candidate:o,actionPlan:n,resolveTrace:a,attachmentsDir:e.attachmentsDir,windowId:e.windowId,window:e.window,menuSearchBounds:se(o,e.window),traceId:e.traceId});if(c.attachment){t.push(await B(e,{messageKey:o.messageKey,attachment:c.attachment,reasonCode:"edge_local",resolveTrace:a},o,a));continue}s.push(...[c.reasonCode].filter(d=>!!d));const m=$({candidate:o,attachmentsDir:e.attachmentsDir,resolveTrace:a,platform:e.platform,cacheRoots:e.wechatCacheRoots});if(m.attachment){t.push(await B(e,{messageKey:o.messageKey,attachment:m.attachment,reasonCode:m.reasonCode||"edge_local_from_wechat_cache",resolveTrace:a},o,a,s));continue}m.reasonCode&&s.push(m.reasonCode),t.push({...w(o,he([...s,c.reasonCode])||"clipboard_attachment_unavailable",a),...s.length?{attemptReasonCodes:b(s)}:{}})}catch(n){t.push(w(o,k(n),D(o,q(o))))}return t}function ee(e){if(f(e.kind)!=="video")return null;const t=String(e.mediaStatus||"").trim().toLowerCase().replace(/-/g,"_");return t==="loading"||t==="downloading"||t==="in_progress"?"loading":e.downloadActionBbox&&(t==="not_downloaded"||t==="pending_download")?"pending":null}async function te(e){const t=e.candidate.downloadActionBbox;if(!t)return{ok:!1,reasonCode:"download_action_bbox_missing"};const o={x:t.x+t.width/2,y:t.y+t.height/2,coordinateSpace:t.coordinateSpace},n=await e.helper.request("mouse.click",{x:o.x,y:o.y,coordinateSpace:o.coordinateSpace,windowId:e.windowId},e.traceId),a=n.ok===!0,r=a?"clicked_video_download_affordance":n.errorCode||"download_action_click_failed";return e.resolveTrace&&y(e.resolveTrace,{phase:"download-action",ok:a,reasonCode:a?void 0:r,downloadPoint:o}),{ok:a,reasonCode:r}}async function v(e,t,o){if(!e.stabilityCheck)return{ok:!0};const n=t==="after-media-action"?2:1;for(let a=0;a<n;a+=1)try{const r=await e.stabilityCheck({stage:t,candidate:o});if(r.ok)return r;if(r.reasonCode==="conversation_title_not_confirmed"&&a+1<n){await S(350);continue}return{ok:!1,reasonCode:r.reasonCode||"media_window_unstable"}}catch(r){const i=k(r);if(i==="conversation_title_not_confirmed"&&a+1<n){await S(350);continue}return{ok:!1,reasonCode:i}}return{ok:!1,reasonCode:"media_window_unstable"}}async function B(e,t,o,n,a=[]){const r=await v(e,"after-media-action",o);return n&&T(n,"after-media-action",r),r.ok?(n&&(n.finalReasonCode=t.reasonCode,n.attachmentValidation=z(t.attachment)),a.length?{...t,attemptReasonCodes:b(a),...n?{resolveTrace:n}:{}}:{...t,...n?{resolveTrace:n}:{}}):{...w(o,r.reasonCode,n),attemptReasonCodes:b([...a,t.reasonCode,r.reasonCode])}}async function oe(e){let t=null;try{t=await e.helper.request("clipboard.snapshot",{},e.traceId),ve(t,"clipboard.snapshot");const o=_(t.result,"changeCount"),n=W(e.actionPlan,"right-click-media",e.retry?1:0)?.target??e.candidate.bbox;if(!n)return{attachment:null,reasonCode:"media_bbox_missing"};const a=xe(e.candidate,we(e.actionPlan,e.retry)),r=Me(e.candidate,n,!!e.window?.bounds);let i;for(const[s,c]of r.entries()){s>0&&await ne(e.helper,e.traceId),e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],clipboardChangeCountBefore:o});const m=await e.helper.request("mouse.rightClick",{x:c.x,y:c.y,coordinateSpace:c.coordinateSpace,windowId:e.windowId},e.traceId);if(!m.ok){i=m.errorCode||"media_right_click_failed",e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],clipboardChangeCountBefore:o,ok:!1,reasonCode:i});continue}await S(180);const d=await ae({helper:e.helper,labels:a,point:c,windowId:e.windowId,window:e.window,menuSearchBounds:e.menuSearchBounds,traceId:e.traceId});if(e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,ok:d.ok,reasonCode:d.ok?void 0:d.reasonCode,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],pickedMethod:d.ok?"ocr-menu":void 0,pickedLabel:d.ok?d.label:void 0,pickedPoint:d.ok?d.point:void 0,ocrMenuCandidates:d.ocrMenuCandidates,disallowedLabels:O,clipboardChangeCountBefore:o}),!d.ok){i=d.reasonCode;continue}const l=await de({helper:e.helper,beforeChangeCount:o,candidate:e.candidate,traceId:e.traceId});e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,pointAttempt:s+1,pointRole:c.role,ok:!!l.result,reasonCode:l.reasonCode,rightClickPoint:c,menuSearchBounds:e.menuSearchBounds,menuPickOrder:["ocr-menu"],pickedMethod:"ocr-menu",pickedLabel:d.label,pickedPoint:d.point,ocrMenuCandidates:d.ocrMenuCandidates,disallowedLabels:O,clipboardChangeCountBefore:o,clipboardChangeCountAfter:l.lastChangeCount??_(l.result,"changeCount"),clipboardPayload:ue(l.result)});const u=le(e.candidate,l.result,e.attachmentsDir);if(u&&e.resolveTrace&&(e.resolveTrace.attachmentValidation=z(u)),u)return{attachment:u,reasonCode:l.reasonCode};if(f(e.candidate.kind)==="image"&&l.reasonCode==="clipboard_attachment_unavailable"&&s+1<r.length){i=l.reasonCode;continue}return{attachment:null,reasonCode:l.reasonCode||"clipboard_attachment_unavailable"}}return{attachment:null,reasonCode:i||"menu_ocr_copy_not_found"}}catch(o){return e.resolveTrace&&y(e.resolveTrace,{phase:e.retry?"copy-after-download":"copy-before-download",retry:!!e.retry,ok:!1,reasonCode:k(o)}),{attachment:null,reasonCode:k(o)}}finally{try{t&&await e.helper.request("clipboard.restore",t.result&&typeof t.result=="object"?t.result:{},e.traceId)}catch{}}}async function ne(e,t){try{await e.request("keyboard.shortcut",{key:"escape",modifiers:[]},t)}catch{}}async function ae(e){const t=await re(e);if(!t.ok)return t;const o=t.capture;if(!o.dataBase64||!o.width||!o.height)return{ok:!1,reasonCode:"menu_ocr_capture_failed",reason:"cannot capture menu"};const n=await e.helper.request("ocr.recognize",{mimeType:o.mimeType||"image/png",dataBase64:o.dataBase64,width:o.width,height:o.height},e.traceId);if(!n.ok)return{ok:!1,reasonCode:n.errorCode||"menu_ocr_failed",reason:n.errorSummary||"menu OCR failed"};const a=ie({blocks:n.result?.blocks??[],labels:e.labels,point:e.point,screenshot:{width:Number(o.width),height:Number(o.height)},screenBounds:o.bounds,window:t.coordinateSpace==="window"?e.window:void 0});if(!a)return{ok:!1,reasonCode:"menu_ocr_copy_not_found",reason:"copy menu text not found near attachment",ocrMenuCandidates:ce({blocks:n.result?.blocks??[],labels:e.labels,point:e.point,screenshot:{width:Number(o.width),height:Number(o.height)},screenBounds:o.bounds,window:t.coordinateSpace==="window"?e.window:void 0})};const r=await e.helper.request("mouse.click",{x:Math.round(a.point.x),y:Math.round(a.point.y),coordinateSpace:"screen",windowId:e.windowId},e.traceId);return r.ok?{ok:!0,method:"ocr-menu",label:a.text,point:a.point,ocrMenuCandidates:a.candidates}:{ok:!1,reasonCode:r.errorCode||"menu_ocr_click_failed",reason:r.errorSummary||"cannot click OCR menu item",ocrMenuCandidates:a.candidates}}async function re(e){if(e.menuSearchBounds){const o=await e.helper.request("screen.capture",{bounds:e.menuSearchBounds},e.traceId);if(o.ok&&o.result?.dataBase64&&o.result.width&&o.result.height)return{ok:!0,capture:{...o.result,bounds:o.result.bounds??e.menuSearchBounds},coordinateSpace:"screen"};if(o.errorCode&&o.errorCode!=="helper_unknown_command")return{ok:!1,reasonCode:o.errorCode||"menu_ocr_capture_failed",reason:o.errorSummary||"cannot capture menu"}}if(!e.windowId)return{ok:!1,reasonCode:"window_id_missing",reason:"window id is required for OCR menu fallback"};const t=await e.helper.request("windows.capture",{windowId:e.windowId,scope:"full-window"},e.traceId);return!t.ok||!t.result?.dataBase64||!t.result.width||!t.result.height?{ok:!1,reasonCode:t.errorCode||"menu_ocr_capture_failed",reason:t.errorSummary||"cannot capture menu"}:{ok:!0,capture:t.result,coordinateSpace:"window"}}function ie(e){const t=e.labels.map(x).filter(Boolean),o=new Set(t.filter(H)),n=[];for(const r of e.blocks){const i=Q(r.text),s=x(i),c=V(r.bbox,e.screenshot,e.window,e.screenBounds);if(!i||!s||!c||Y(s))continue;const m=t.includes(s),d=o.has(s),l=!o.size&&t.some(u=>s.includes(u)||u.includes(s));!m&&!l||c.x<e.point.x-260||c.x>e.point.x+360||c.y<e.point.y-420||c.y>e.point.y+520||n.push({text:i,normalizedText:s,point:c,...r.bbox?{bbox:r.bbox}:{},exact:m,exactCopy:d,fuzzy:l,dangerous:!1,distance:Math.hypot(c.x-e.point.x,c.y-e.point.y)})}n.sort((r,i)=>Number(i.exactCopy)-Number(r.exactCopy)||Number(i.exact)-Number(r.exact)||r.point.y-i.point.y||r.distance-i.distance);const a=n[0];return a?{text:a.text,point:a.point,candidates:n.map(r=>({text:r.text,normalizedText:r.normalizedText,point:r.point,...r.bbox?{bbox:r.bbox}:{},exact:r.exact,exactCopy:r.exactCopy,fuzzy:r.fuzzy,dangerous:r.dangerous,selected:r===a}))}:null}function ce(e){const t=e.labels.map(x).filter(Boolean),o=new Set(t.filter(H)),n=[];for(const a of e.blocks){const r=Q(a.text),i=x(r),s=V(a.bbox,e.screenshot,e.window,e.screenBounds);if(!r||!i)continue;const c=t.includes(i),m=o.has(i),d=!o.size&&t.some(g=>i.includes(g)||g.includes(i)),l=Y(i);if(!(!(s&&s.x>=e.point.x-260&&s.x<=e.point.x+360&&s.y>=e.point.y-420&&s.y<=e.point.y+520)&&!c&&!d&&!l)&&(n.push({text:r,normalizedText:i,...s?{point:s}:{},...a.bbox?{bbox:a.bbox}:{},exact:c,exactCopy:m,fuzzy:d,dangerous:l}),n.length>=24))break}return n}function se(e,t){const o=e.bbox,n=t?.bounds;if(!o||!n)return;const a=o.coordinateSpace==="screen"?o.x:n.x+o.x,r=o.coordinateSpace==="screen"?o.y:n.y+o.y;if(![a,r,o.width,o.height].every(Number.isFinite))return;const i=Math.min(640,Math.max(360,Math.ceil(o.width+260))),s=Math.min(Math.max(760,Math.ceil(o.height+620)),Math.ceil(n.height+260));return{x:Math.max(0,Math.floor(a-140)),y:Math.max(0,Math.floor(r-Math.max(360,Math.ceil(s/2)))),width:i,height:s,coordinateSpace:"screen"}}async function de(e){const t=Date.now();let o=0;const n=f(e.candidate.kind);do{const a=await e.helper.request("clipboard.readAttachment",{},e.traceId);if(!a.ok)return{reasonCode:a.errorCode||"clipboard_read_failed"};const r=e.beforeChangeCount==null||Number(a.result?.changeCount)!==Number(e.beforeChangeCount);if(r&&_e(e.candidate,a.result))return{result:a.result,lastChangeCount:_(a.result,"changeCount")};if(r&&(o+=1,o>=(n==="image"?12:3)))break;await S(n==="image"?160:120)}while(Date.now()-t<(e.timeoutMs??2500));return{reasonCode:n==="image"?"clipboard_attachment_unavailable":"clipboard_file_url_unavailable",lastChangeCount:null}}function K(e,t,o,n){const a=p.statSync(t);if(!a.isFile())throw new Error("wechat_channel_attachment_not_file");if(a.size>R)return{type:f(e.kind),name:C(e.fileName||h.basename(t)),size:a.size,mimeType:e.mimeType||P(t),availability:"unavailable-large",providerError:"attachment_too_large"};p.mkdirSync(o,{recursive:!0});const r=p.readFileSync(t),i=M.createHash("sha256").update(r).digest("hex"),s=Ce(e,t),c=be(e,t,s),m=h.extname(c)||h.extname(t)||X(s)||"",d=A(m),l=m?c.slice(0,-m.length):c,u=h.join(o,`${l}-${i.slice(0,12)}${m}`);return p.existsSync(u)||p.writeFileSync(u,r),{type:f(e.kind),name:c,mimeType:s,size:r.byteLength,...d?{extension:d}:{},localPath:u,hash:i,availability:"edge-local",...n?{sourceAction:n}:{},materializationKind:"original-file",isOriginal:!0,mimeKindMatches:!0}}function le(e,t,o){const n=I(t);return n?j(e,n,t)?K(e,n,o,"materialize-clipboard"):null:f(e.kind)!=="image"?null:me(e,t,o)}function me(e,t,o){const n=typeof t?.dataBase64=="string"?t.dataBase64.trim():"";if(!n)return null;const a=Buffer.from(n,"base64");if(!a.length)return null;if(a.byteLength>R)return{type:"image",name:C(e.fileName||t?.suggestedFileName||"wechat-image.png"),size:a.byteLength,mimeType:e.mimeType||t?.mimeType||"image/png",availability:"unavailable-large",providerError:"attachment_too_large"};p.mkdirSync(o,{recursive:!0});const r=e.mimeType||t?.mimeType||"image/png",i=X(r)||".png",s=C(e.fileName||t?.suggestedFileName||`wechat-image${i}`),c=h.extname(s)?s:`${s}${i}`,m=M.createHash("sha256").update(a).digest("hex"),d=h.extname(c)||i,l=A(d),u=d?c.slice(0,-d.length):c,g=h.join(o,`${u}-${m.slice(0,12)}${d}`);return p.existsSync(g)||p.writeFileSync(g,a),{type:"image",name:c,mimeType:r,size:a.byteLength,extension:l,localPath:g,hash:m,availability:"edge-local",sourceAction:"materialize-clipboard",materializationKind:"clipboard-image",isOriginal:!0,mimeKindMatches:!0}}function w(e,t,o){return o&&(o.finalReasonCode=t),{messageKey:e.messageKey,reasonCode:t,...o?{resolveTrace:o}:{},attachment:{type:f(e.kind),name:C(e.fileName||`${e.kind||"attachment"}`),...e.mimeType?{mimeType:e.mimeType}:{},...Number.isFinite(e.size)?{size:Number(e.size)}:{},availability:e.mediaStatus==="not_downloaded"||e.mediaStatus==="loading"?"pending-download":"metadata-only",providerError:t,materializationKind:"metadata",isOriginal:!1,mimeKindMatches:!1}}}function D(e,t){return{candidateKind:String(e.kind||"unknown"),...e.bbox?{bbox:e.bbox}:{},...e.downloadActionBbox!==void 0?{downloadActionBbox:e.downloadActionBbox}:{},...e.mediaStatus!==void 0?{mediaStatus:e.mediaStatus}:{},actionPlan:{reasonCode:t.reasonCode,actions:t.actions.map(o=>({type:o.type,...o.reasonCode?{reasonCode:o.reasonCode}:{},...o.label?{label:o.label}:{},...o.target?{target:o.target}:{}}))},attempts:[]}}function T(e,t,o,n=!1){e.attempts.push({phase:"stability",stage:t,retry:n,ok:o.ok,...o.ok?{}:{reasonCode:o.reasonCode}})}function y(e,t){e.attempts.push({...t,...t.menuPickOrder?{menuPickOrder:[...t.menuPickOrder]}:{},...t.disallowedLabels?{disallowedLabels:[...t.disallowedLabels]}:{}})}function ue(e){const t=e?.fileUrls??[],o=e?.filePaths??[],n=typeof e?.dataBase64=="string"?e.dataBase64.trim():"",a=[...o,...t].map(i=>I({filePaths:[i]})||i).map(i=>h.basename(i)).filter(Boolean),r=[...new Set(a.map(i=>A(h.extname(i||""))).filter(Boolean))];return{changeCount:_(e,"changeCount"),fileUrlCount:t.length,filePathCount:o.length,hasImageData:!!n,...n?{imageDataBytes:Buffer.from(n,"base64").byteLength}:{},...e?.mimeType?{mimeType:e.mimeType}:{},...e?.suggestedFileName?{suggestedFileName:e.suggestedFileName}:{},...a.length?{fileNames:a}:{},...r.length?{extensions:r}:{}}}function $(e){if(!fe(e.platform))return{attachment:null};if(f(e.candidate.kind)!=="video")return{attachment:null};const t=ge(e.candidate),o=Z(e.candidate,{roots:e.cacheRoots,...t!==null?{minMtimeMs:t}:{}});if(e.resolveTrace&&y(e.resolveTrace,{phase:"cache-scan",ok:o.ok,reasonCode:o.reasonCode,cacheScan:o.trace}),!o.ok)return{attachment:null,reasonCode:o.reasonCode};try{const n=K(e.candidate,o.sourcePath,e.attachmentsDir,"wechat-cache-scan");return e.resolveTrace&&(e.resolveTrace.attachmentValidation=z(n)),{attachment:n,reasonCode:"edge_local_from_wechat_cache"}}catch(n){return{attachment:null,reasonCode:k(n)}}}function z(e){if(e)return{...e.availability?{availability:e.availability}:{},...e.type?{type:e.type}:{},...e.name?{name:e.name}:{},...e.localPath?{localPath:e.localPath}:{},...e.mimeType?{mimeType:e.mimeType}:{},...e.extension?{extension:e.extension}:{},...e.materializationKind?{materializationKind:e.materializationKind}:{},...typeof e.isOriginal=="boolean"?{isOriginal:e.isOriginal}:{},...typeof e.mimeKindMatches=="boolean"?{mimeKindMatches:e.mimeKindMatches}:{}}}function he(e){const t=e.filter(o=>!!o);return t[t.length-1]}function q(e){return J({...e,kind:L(e.kind)})}function b(e){return[...new Set(e.filter(t=>!!t))]}function fe(e){return String(e||process.platform).toLowerCase()==="win32"}function ge(e){return pe(e.contextText)}function pe(e){const o=String(e||"").match(/\b(20\d{12})\b/);if(!o)return null;const n=o[1],a=Number(n.slice(0,4)),r=Number(n.slice(4,6)),i=Number(n.slice(6,8)),s=Number(n.slice(8,10)),c=Number(n.slice(10,12)),m=Number(n.slice(12,14)),d=Date.UTC(a,r-1,i,s,c,m);return Number.isFinite(d)?d:null}function W(e,t,o=0){return e.actions.filter(n=>n.type===t)[o]}function we(e,t){return W(e,"ocr-click-menu-item",t?1:0)?.label}function ye(e){const t=L(e);if(t==="image")return"image";if(t==="video-file")return"video";if(t==="file")return"file";if(t!=="unknown")return null;const o=String(e||"").toLowerCase();return o.includes("video")?"video":o.includes("image")||o.includes("photo")?"image":o.includes("file")||o.includes("document")?"file":null}function f(e){const t=ye(e);return t||"file"}function Ce(e,t){const o=f(e.kind),n=String(e.mimeType||"").trim().toLowerCase();return n&&N(n,o)?n:P(t)}function be(e,t,o){const n=f(e.kind),a=e.fileName?C(e.fileName):"";return a&&ke(a,o,n)?a:C(h.basename(t)||a||"attachment")}function ke(e,t,o){if(o==="file")return!0;const n=h.extname(e).toLowerCase();return n?E(n,o):N(t,o)}function N(e,t){return t==="image"?e.startsWith("image/"):t==="video"?e.startsWith("video/"):!0}function E(e,t){return t==="image"?[".png",".jpg",".jpeg",".gif",".webp",".heic",".tiff",".bmp"].includes(e):t==="video"?[".mp4",".mov",".m4v",".avi",".mkv",".webm"].includes(e):!0}function xe(e,t){const o=f(e.kind),n=o==="image"?["\u590D\u5236\u56FE\u7247","\u62F7\u8D1D\u56FE\u7247","\u590D\u5236\u56FE\u50CF","\u62F7\u8D1D\u56FE\u50CF","\u590D\u5236","\u62F7\u8D1D","Copy Image","Copy"]:o==="video"?["\u590D\u5236\u89C6\u9891","\u62F7\u8D1D\u89C6\u9891","\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","\u590D\u5236","\u62F7\u8D1D","Copy Video","Copy File","Copy"]:["\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","\u590D\u5236","\u62F7\u8D1D","Copy File","Copy"];return t?[t,...n.filter(a=>a!==t)]:n}function I(e){const t=e?.filePaths?.[0]||e?.fileUrls?.[0];return t?t.startsWith("file://")?decodeURIComponent(new URL(t).pathname):t:null}function _e(e,t){const o=I(t);return o?j(e,o,t):f(e.kind)==="image"&&!!t?.dataBase64}function j(e,t,o){const n=f(e.kind),a=String(o?.mimeType||e.mimeType||P(t)).toLowerCase(),r=h.extname(t).toLowerCase();return n==="image"||n==="video"?N(a,n)||E(r,n):n==="file"}function k(e){const o=(e instanceof Error?e.message:String(e)).split(":",1)[0]?.trim();return/^[a-z0-9_]+$/i.test(o||"")?o:"media_resolve_failed"}function Se(e){return{x:e.x+e.width/2,y:e.y+e.height/2,coordinateSpace:e.coordinateSpace}}function Me(e,t,o=!1){const n={...Se(t),role:"center"};if(f(e.kind)!=="file"){if(!o)return[n];const r=Math.max(18,Math.min(48,t.width*.18)),i=Math.max(18,Math.min(48,t.height*.18));return U([{x:t.x+r,y:t.y+i,coordinateSpace:t.coordinateSpace,role:"media-top-left"},{x:t.x+Math.max(r,t.width-r),y:t.y+i,coordinateSpace:t.coordinateSpace,role:"media-top-right"},{x:t.x+r,y:t.y+Math.max(i,t.height-i),coordinateSpace:t.coordinateSpace,role:"media-bottom-left"},{x:t.x+Math.max(r,t.width-r),y:t.y+Math.max(i,t.height-i),coordinateSpace:t.coordinateSpace,role:"media-bottom-right"},n])}const a=[{x:t.x+Math.min(Math.max(96,t.width*.34),Math.max(24,t.width-36)),y:t.y+Math.min(Math.max(36,t.height*.32),Math.max(12,t.height-24)),coordinateSpace:t.coordinateSpace,role:"file-title"},{x:t.x+Math.min(Math.max(128,t.width*.46),Math.max(24,t.width-36)),y:t.y+Math.min(Math.max(64,t.height*.58),Math.max(12,t.height-24)),coordinateSpace:t.coordinateSpace,role:"file-body"},n];return U(a)}function U(e){const t=new Set,o=[];for(const n of e){const a=`${Math.round(n.x)}:${Math.round(n.y)}`;t.has(a)||(t.add(a),o.push(n))}return o}function V(e,t,o,n){if(!e)return null;const a=Number(e.x),r=Number(e.y),i=Number(e.width),s=Number(e.height);if(![a,r,i,s].every(Number.isFinite))return null;const c={x:a+i/2,y:r+s/2};if(n){const l=t.width&&n.width?t.width/n.width:1,u=t.height&&n.height?t.height/n.height:l;return{x:n.x+c.x/l,y:n.y+c.y/u}}if(e.coordinateSpace==="screen"||!o?.bounds)return c;const m=t.width&&o.bounds.width?t.width/o.bounds.width:1,d=t.height&&o.bounds.height?t.height/o.bounds.height:m;return{x:o.bounds.x+c.x/m,y:o.bounds.y+c.y/d}}function x(e){return String(e||"").replace(/\s+/g,"").replace(/[.。…⋯·]/g,"").trim()}function H(e){return["\u590D\u5236","\u62F7\u8D1D","\u590D\u5236\u56FE\u7247","\u62F7\u8D1D\u56FE\u7247","\u590D\u5236\u56FE\u50CF","\u62F7\u8D1D\u56FE\u50CF","\u590D\u5236\u89C6\u9891","\u62F7\u8D1D\u89C6\u9891","\u590D\u5236\u6587\u4EF6","\u62F7\u8D1D\u6587\u4EF6","copy","copyimage","copyvideo","copyfile"].includes(e.toLowerCase())}function Y(e){return/^(引用|删除|多选|转发|收藏|提醒|编辑|另存为|保存|打开方式|delete|quote|forward|favorite|save|saveas)$/i.test(e)}function C(e){return h.basename(e||"attachment").normalize("NFKC").replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").replace(/\s+/g," ").replace(/^[ ._]+|[ ._]+$/g,"")||"attachment"}function P(e){const t=h.extname(e).toLowerCase();return t===".png"?"image/png":t===".jpg"||t===".jpeg"?"image/jpeg":t===".gif"?"image/gif":t===".webp"?"image/webp":t===".mp4"?"video/mp4":t===".mov"?"video/quicktime":t===".pdf"?"application/pdf":t===".txt"?"text/plain":"application/octet-stream"}function X(e){const t=e.toLowerCase();return t==="image/png"?".png":t==="image/jpeg"?".jpg":t==="image/gif"?".gif":t==="image/webp"?".webp":t==="video/mp4"?".mp4":t==="video/quicktime"?".mov":t==="application/pdf"?".pdf":t==="text/plain"?".txt":null}function A(e){const t=String(e||"").trim().toLowerCase();return t?t.startsWith(".")?t:`.${t}`:""}function Q(e){return typeof e=="string"?e.trim():""}function _(e,t){const o=t&&e&&typeof e=="object"?e[t]:e,n=Number(o);return Number.isFinite(n)?n:null}function S(e){return new Promise(t=>setTimeout(t,e))}function ve(e,t){if(!e.ok)throw new Error(`${e.errorCode||"helper_command_failed"}: ${e.errorSummary||t}`)}export{Fe as defaultWeChatChannelAttachmentDir,K as materializeLocalAttachment,w as metadataOnlyResult,Le as resolveVisibleWeChatChannelMedia};
@@ -1,19 +0,0 @@
1
- import type { WeChatChannelObservedMessage } from './client.js';
2
- export type WeChatChannelMessageKeyInput = Omit<WeChatChannelObservedMessage, 'stableMessageKey'> & {
3
- stableMessageKey?: string | null;
4
- };
5
- export type WeChatChannelNormalizedMessage = WeChatChannelObservedMessage & {
6
- stableKeyVersion: 1;
7
- };
8
- export declare function normalizeWeChatObservedWindowForLedger(messages: WeChatChannelMessageKeyInput[]): WeChatChannelNormalizedMessage[];
9
- export declare function buildStableWeChatMessageKey(message: WeChatChannelMessageKeyInput, windowIndex?: number, occurrence?: number): string;
10
- export declare function buildAnchorMetadata(message: WeChatChannelMessageKeyInput, windowIndex: number, occurrence: number): {
11
- stableKeyVersion: number;
12
- windowIndex: number;
13
- occurrence: number;
14
- senderRole: "unknown" | "self" | "contact" | "system";
15
- kind: string;
16
- anchorText: string;
17
- bboxBand: string | null;
18
- mediaSignature: string | null;
19
- };
@@ -1 +0,0 @@
1
- import M from"node:crypto";import{normalizeWeChatAnchorText as a}from"./anchor.js";function K(t){const n=new Map;return t.map((r,o)=>{const e=l(r,o),i=n.get(e)??0;n.set(e,i+1);const s=T(r,o,i),p=x(r.stableMessageKey)||b({base:e,occurrence:i}),y=r.anchorText||r.normalizedText||r.textExcerpt||"";return{...r,stableMessageKey:p,stableKeyVersion:1,anchorText:y,anchorMetadata:{...u(r.anchorMetadata)?r.anchorMetadata:{},...s}}})}function S(t,n=0,r=0){return x(t.stableMessageKey)||b({base:l(t,n),occurrence:r})}function T(t,n,r){return{stableKeyVersion:1,windowIndex:n,occurrence:r,senderRole:t.senderRole,kind:t.kind,anchorText:a(t.anchorText||t.normalizedText||t.textExcerpt||""),bboxBand:h(t.bbox),mediaSignature:f(t)}}function l(t,n){return JSON.stringify({senderRole:t.senderRole||"unknown",senderName:a(t.senderName||""),kind:t.kind||"text",anchorText:a(t.anchorText||t.normalizedText||t.textExcerpt||""),bboxBand:h(t.bbox),mediaSignature:f(t),neighborSignature:k(t.neighborContext),orderBand:Math.floor(n/4)})}function b(t){return`wk1_${M.createHash("sha256").update(`${t.base}|${t.occurrence}`).digest("hex").slice(0,24)}`}function x(t){return typeof t!="string"?null:t.trim()||null}function h(t){if(!u(t))return null;const n=c(t.x),r=c(t.y),o=c(t.width),e=c(t.height);return[n,r,o,e].some(i=>i===null)?null:[n,r,o,e].map(i=>Math.round((i??0)/20)*20).join(",")}function f(t){const n=u(t.mediaMetadata)?t.mediaMetadata:{},r=Array.isArray(t.visualBlocks)?t.visualBlocks:[],o=[d(n.fileName),d(n.mimeType),d(n.size),...r.map(e=>`${e.blockKind}:${e.blockId}`)].filter(Boolean);return o.length?o.join("|"):null}function k(t){if(!u(t))return null;const n=a(t.beforeText||t.previousText||t.prev),r=a(t.afterText||t.nextText||t.next);return n||r?`${n.slice(0,24)}|${r.slice(0,24)}`:null}function c(t){const n=Number(t);return Number.isFinite(n)?n:null}function d(t){return t==null?null:String(t).trim()||null}function u(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}export{T as buildAnchorMetadata,S as buildStableWeChatMessageKey,K as normalizeWeChatObservedWindowForLedger};
@@ -1,171 +0,0 @@
1
- import type { WeChatChannelHelperCommandName, WeChatChannelHelperResponse, WeChatChannelHumanActivityReasonCode } from './helper-protocol.js';
2
- import type { WeChatChannelRuntime, WeChatChannelBindingConfig } from './runtime.js';
3
- import type { WeChatChannelApiClient, WeChatChannelObservedMessage } from './client.js';
4
- import { type WeChatChannelLedger } from './ledger.js';
5
- import { type WeChatConversationListFingerprint } from './fingerprint.js';
6
- import { type WeChatChannelActivityGatePolicy, type WeChatChannelActivityGateStage } from './human-coordination.js';
7
- export type WeChatChannelHelperTransport = {
8
- request<T = unknown>(command: WeChatChannelHelperCommandName, params?: Record<string, unknown>, traceId?: string): Promise<WeChatChannelHelperResponse<T>>;
9
- };
10
- export type WeChatChannelWindowInfo = {
11
- windowId: string;
12
- appName?: string | null;
13
- title?: string | null;
14
- className?: string | null;
15
- visible?: boolean | null;
16
- minimized?: boolean | null;
17
- bounds?: {
18
- x: number;
19
- y: number;
20
- width: number;
21
- height: number;
22
- coordinateSpace?: string;
23
- };
24
- zOrder?: number | null;
25
- rootProcessId?: number | null;
26
- };
27
- export type WeChatChannelScreenPoint = {
28
- x: number;
29
- y: number;
30
- coordinateSpace: 'screen';
31
- };
32
- export type WeChatChannelForegroundMode = 'required' | 'background';
33
- export type WeChatChannelScreenshot = {
34
- mimeType: string;
35
- dataBase64?: string;
36
- width: number;
37
- height: number;
38
- windowId?: string | null;
39
- bounds?: {
40
- x: number;
41
- y: number;
42
- width: number;
43
- height: number;
44
- coordinateSpace?: string;
45
- };
46
- };
47
- export type WeChatChannelScreenshotWithData = WeChatChannelScreenshot & {
48
- dataBase64: string;
49
- };
50
- export type WeChatChannelOcrBlock = {
51
- text?: string;
52
- bbox?: {
53
- x: number;
54
- y: number;
55
- width: number;
56
- height: number;
57
- coordinateSpace?: string;
58
- };
59
- confidence?: number;
60
- };
61
- export type WeChatChannelOcrResult = {
62
- blocks?: WeChatChannelOcrBlock[];
63
- visibleConversationFingerprints?: WeChatConversationListFingerprint[];
64
- };
65
- type WeChatChannelWindowObservation = {
66
- capture: WeChatChannelScreenshot;
67
- ocr: WeChatChannelOcrResult;
68
- };
69
- export type WeChatChannelObservePipeline = 'server-observe' | 'edge-structure';
70
- export type WeChatChannelObserveApi = Pick<WeChatChannelApiClient, 'observe'> & Partial<Pick<WeChatChannelApiClient, 'structureWindow' | 'embedVisual' | 'classifyWindow'>>;
71
- export type WeChatChannelObserveActivityGuardEvent = {
72
- phase: 'snapshot' | 'lease-acquire' | 'lease-status' | 'lease-release';
73
- at: string;
74
- stage: WeChatChannelActivityGateStage;
75
- action: string;
76
- ok: boolean;
77
- reasonCode?: WeChatChannelHumanActivityReasonCode | string;
78
- waitMs?: number;
79
- };
80
- export type WeChatChannelObserveActivityGuardOptions = {
81
- policy?: Partial<WeChatChannelActivityGatePolicy>;
82
- useAutomationLease?: boolean;
83
- preflightIdleSettleTimeoutMs?: number;
84
- onEvent?: (event: WeChatChannelObserveActivityGuardEvent) => void;
85
- };
86
- export declare class WeChatChannelUserActivityAbort extends Error {
87
- readonly reasonCode: WeChatChannelHumanActivityReasonCode | string;
88
- readonly stage: WeChatChannelActivityGateStage;
89
- readonly action: string;
90
- constructor(input: {
91
- reasonCode: WeChatChannelHumanActivityReasonCode | string;
92
- stage: WeChatChannelActivityGateStage;
93
- action: string;
94
- });
95
- }
96
- export type HelperBackedObserveOptions = {
97
- runtime: WeChatChannelRuntime;
98
- binding: WeChatChannelBindingConfig;
99
- helper: WeChatChannelHelperTransport;
100
- api: WeChatChannelObserveApi;
101
- workDir?: string;
102
- attachmentsDir?: string;
103
- traceId?: string;
104
- observePipeline?: WeChatChannelObservePipeline;
105
- localLedger?: WeChatChannelLedger;
106
- vectorStorePath?: string;
107
- baselineOnly?: boolean;
108
- localLedgerTailAnchors?: unknown[];
109
- localOutboundEchoAnchors?: WeChatChannelLocalOutboundEchoAnchor[];
110
- foregroundMode?: WeChatChannelForegroundMode;
111
- mediaAnchorText?: string;
112
- activityGuard?: WeChatChannelObserveActivityGuardOptions;
113
- onObservationEvidence?: (evidence: {
114
- window: WeChatChannelWindowInfo;
115
- capture: WeChatChannelScreenshot;
116
- ocr: WeChatChannelOcrResult;
117
- }) => void;
118
- };
119
- export type WeChatChannelLocalOutboundEchoAnchor = {
120
- replyId?: string | null;
121
- idempotencyKey?: string | null;
122
- expectedEchoAnchor?: string | null;
123
- };
124
- export declare function observeWeChatChannelBindingViaHelper(options: HelperBackedObserveOptions): Promise<WeChatChannelObservedMessage[]>;
125
- export declare function selectWeChatWindowForBinding(options: HelperBackedObserveOptions, input?: {
126
- foregroundMode?: WeChatChannelForegroundMode;
127
- forceVision?: boolean;
128
- }): Promise<WeChatChannelWindowInfo>;
129
- export declare function detectWeChatMessageInputPointByServerVision(input: HelperBackedObserveOptions & {
130
- window: WeChatChannelWindowInfo;
131
- }): Promise<WeChatChannelScreenPoint>;
132
- export declare function detectWeChatSearchInputPointByServerVision(input: HelperBackedObserveOptions & {
133
- window: WeChatChannelWindowInfo;
134
- }): Promise<WeChatChannelScreenPoint>;
135
- export declare function ensureHelperPreflight(helper: WeChatChannelHelperTransport, traceId?: string): Promise<void>;
136
- export declare function ensureHelperPermissionPreflight(helper: WeChatChannelHelperTransport, traceId?: string): Promise<void>;
137
- export declare function ensureWeChatWindowReady(helper: WeChatChannelHelperTransport, traceId?: string, options?: {
138
- foreground?: WeChatChannelForegroundMode;
139
- }): Promise<WeChatChannelWindowInfo>;
140
- export declare function focusWeChatWindow(helper: WeChatChannelHelperTransport, traceId?: string): Promise<WeChatChannelWindowInfo>;
141
- export declare function focusKnownWeChatWindow(helper: WeChatChannelHelperTransport, window: WeChatChannelWindowInfo, traceId?: string): Promise<WeChatChannelWindowInfo>;
142
- export declare function focusExistingWeChatWindow(helper: WeChatChannelHelperTransport, traceId?: string): Promise<WeChatChannelWindowInfo>;
143
- export declare function openConversationInVisibleList(input: {
144
- helper: WeChatChannelHelperTransport;
145
- window: WeChatChannelWindowInfo;
146
- binding: WeChatChannelBindingConfig;
147
- traceId?: string;
148
- observation?: WeChatChannelWindowObservation;
149
- allowOcrTitleRows?: boolean;
150
- }): Promise<{
151
- opened: boolean;
152
- reason: string;
153
- }>;
154
- export declare function openConversationBySearch(input: {
155
- helper: WeChatChannelHelperTransport;
156
- window: WeChatChannelWindowInfo;
157
- binding: WeChatChannelBindingConfig;
158
- runtime?: WeChatChannelRuntime;
159
- api?: WeChatChannelObserveApi;
160
- workDir?: string;
161
- traceId?: string;
162
- searchDelayMs?: number;
163
- settleToBottom?: boolean;
164
- }): Promise<{
165
- opened: boolean;
166
- reason: string;
167
- }>;
168
- export declare function captureWeChatWindow(helper: WeChatChannelHelperTransport, windowId: string, traceId?: string, bounds?: WeChatChannelWindowInfo['bounds']): Promise<WeChatChannelScreenshotWithData>;
169
- export declare function captureAndRecognizeWeChatWindow(helper: WeChatChannelHelperTransport, windowId: string, traceId?: string, bounds?: WeChatChannelWindowInfo['bounds']): Promise<WeChatChannelWindowObservation>;
170
- export declare function recognizeWeChatScreenshot(helper: WeChatChannelHelperTransport, screenshot: WeChatChannelScreenshotWithData, traceId?: string): Promise<WeChatChannelOcrResult>;
171
- export {};
@@ -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};