shennian 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/README.md +3 -1
  2. package/dist/publish-build-manifest.json +273 -343
  3. package/dist/src/agents/command-spec.js +2 -2
  4. package/dist/src/agents/detect.js +1 -1
  5. package/dist/src/agents/model-registry/discovery.js +2 -2
  6. package/dist/src/agents/model-registry/parsers.d.ts +1 -0
  7. package/dist/src/agents/model-registry/parsers.js +4 -4
  8. package/dist/src/agents/native-capabilities.d.ts +10 -0
  9. package/dist/src/agents/native-capabilities.js +1 -0
  10. package/dist/src/agents/platform-instructions.js +5 -5
  11. package/dist/src/agents/workbuddy.d.ts +44 -0
  12. package/dist/src/agents/workbuddy.js +3 -0
  13. package/dist/src/commands/daemon.d.ts +1 -0
  14. package/dist/src/commands/daemon.js +9 -9
  15. package/dist/src/commands/integration.d.ts +2 -0
  16. package/dist/src/commands/integration.js +1 -0
  17. package/dist/src/commands/manager.js +1 -2
  18. package/dist/src/commands/pair-browser.d.ts +43 -0
  19. package/dist/src/commands/pair-browser.js +1 -0
  20. package/dist/src/commands/pair.d.ts +2 -0
  21. package/dist/src/commands/pair.js +11 -8
  22. package/dist/src/commands/room.d.ts +13 -0
  23. package/dist/src/commands/room.js +4 -0
  24. package/dist/src/commands/upgrade.d.ts +3 -0
  25. package/dist/src/commands/upgrade.js +1 -1
  26. package/dist/src/config/index.d.ts +3 -1
  27. package/dist/src/config/index.js +2 -1
  28. package/dist/src/daemon-ipc/client.d.ts +8 -0
  29. package/dist/src/daemon-ipc/client.js +3 -0
  30. package/dist/src/daemon-ipc/paths.d.ts +7 -0
  31. package/dist/src/daemon-ipc/paths.js +1 -0
  32. package/dist/src/daemon-ipc/protocol.d.ts +30 -0
  33. package/dist/src/daemon-ipc/protocol.js +1 -0
  34. package/dist/src/daemon-ipc/secret.d.ts +3 -0
  35. package/dist/src/daemon-ipc/secret.js +3 -0
  36. package/dist/src/daemon-ipc/server.d.ts +13 -0
  37. package/dist/src/daemon-ipc/server.js +3 -0
  38. package/dist/src/index.js +2 -2
  39. package/dist/src/integrations/claude-room-plugin-lifecycle.d.ts +47 -0
  40. package/dist/src/integrations/claude-room-plugin-lifecycle.js +1 -0
  41. package/dist/src/integrations/codex-room-plugin-lifecycle.d.ts +49 -0
  42. package/dist/src/integrations/codex-room-plugin-lifecycle.js +1 -0
  43. package/dist/src/integrations/room-plugin-bundles.d.ts +23 -0
  44. package/dist/src/integrations/room-plugin-bundles.js +1 -0
  45. package/dist/src/integrations/room-plugin-lifecycle-common.d.ts +17 -0
  46. package/dist/src/integrations/room-plugin-lifecycle-common.js +1 -0
  47. package/dist/src/integrations/room-plugin-shared.d.ts +23 -0
  48. package/dist/src/integrations/room-plugin-shared.js +2 -0
  49. package/dist/src/integrations/room-session-hook.d.ts +30 -0
  50. package/dist/src/integrations/room-session-hook.js +2 -0
  51. package/dist/src/integrations/workbuddy-plugin-bundle.d.ts +15 -0
  52. package/dist/src/integrations/workbuddy-plugin-bundle.js +1 -0
  53. package/dist/src/integrations/workbuddy-plugin-lifecycle.d.ts +52 -0
  54. package/dist/src/integrations/workbuddy-plugin-lifecycle.js +2 -0
  55. package/dist/src/integrations/workbuddy-session-hook.d.ts +22 -0
  56. package/dist/src/integrations/workbuddy-session-hook.js +1 -0
  57. package/dist/src/manager/prompt.d.ts +1 -1
  58. package/dist/src/manager/prompt.js +1 -1
  59. package/dist/src/manager/retired-external-channel-compat.d.ts +78 -0
  60. package/dist/src/manager/retired-external-channel-compat.js +1 -0
  61. package/dist/src/manager/runtime.d.ts +1 -3
  62. package/dist/src/manager/runtime.js +7 -7
  63. package/dist/src/relay/client.d.ts +2 -0
  64. package/dist/src/relay/client.js +1 -1
  65. package/dist/src/room/activation-audit.d.ts +15 -0
  66. package/dist/src/room/activation-audit.js +2 -0
  67. package/dist/src/room/activation-policy.d.ts +8 -0
  68. package/dist/src/room/activation-policy.js +1 -0
  69. package/dist/src/room/activation-service.d.ts +25 -0
  70. package/dist/src/room/activation-service.js +2 -0
  71. package/dist/src/room/attachment-cache.d.ts +40 -0
  72. package/dist/src/room/attachment-cache.js +2 -0
  73. package/dist/src/room/attachment-upload.d.ts +20 -0
  74. package/dist/src/room/attachment-upload.js +1 -0
  75. package/dist/src/room/authorized-action-coordinator.d.ts +40 -0
  76. package/dist/src/room/authorized-action-coordinator.js +1 -0
  77. package/dist/src/room/authorized-action-ipc.d.ts +11 -0
  78. package/dist/src/room/authorized-action-ipc.js +1 -0
  79. package/dist/src/room/device-authorization-client.d.ts +49 -0
  80. package/dist/src/room/device-authorization-client.js +1 -0
  81. package/dist/src/room/host-session-observation-ipc.d.ts +9 -0
  82. package/dist/src/room/host-session-observation-ipc.js +1 -0
  83. package/dist/src/room/host-session-observations.d.ts +54 -0
  84. package/dist/src/room/host-session-observations.js +2 -0
  85. package/dist/src/room/invite-bootstrap.d.ts +35 -0
  86. package/dist/src/room/invite-bootstrap.js +1 -0
  87. package/dist/src/room/invocation-token-ipc.d.ts +9 -0
  88. package/dist/src/room/invocation-token-ipc.js +1 -0
  89. package/dist/src/room/invocation-token.d.ts +53 -0
  90. package/dist/src/room/invocation-token.js +1 -0
  91. package/dist/src/room/jsonl-mirror.d.ts +73 -0
  92. package/dist/src/room/jsonl-mirror.js +6 -0
  93. package/dist/src/room/managed-room-session.d.ts +143 -0
  94. package/dist/src/room/managed-room-session.js +3 -0
  95. package/dist/src/room/mirror-sync-service.d.ts +33 -0
  96. package/dist/src/room/mirror-sync-service.js +1 -0
  97. package/dist/src/room/operator-ipc.d.ts +11 -0
  98. package/dist/src/room/operator-ipc.js +1 -0
  99. package/dist/src/room/pending-authorized-actions.d.ts +69 -0
  100. package/dist/src/room/pending-authorized-actions.js +3 -0
  101. package/dist/src/room/room-action-client.d.ts +208 -0
  102. package/dist/src/room/room-action-client.js +1 -0
  103. package/dist/src/room/room-action-ipc.d.ts +33 -0
  104. package/dist/src/room/room-action-ipc.js +1 -0
  105. package/dist/src/room/room-action-schema.d.ts +3 -0
  106. package/dist/src/room/room-action-schema.js +1 -0
  107. package/dist/src/room/room-authorized-action-executor.d.ts +23 -0
  108. package/dist/src/room/room-authorized-action-executor.js +1 -0
  109. package/dist/src/room/room-binding-client.d.ts +51 -0
  110. package/dist/src/room/room-binding-client.js +1 -0
  111. package/dist/src/room/room-binding-ipc.d.ts +29 -0
  112. package/dist/src/room/room-binding-ipc.js +1 -0
  113. package/dist/src/room/session-registry-ipc.d.ts +14 -0
  114. package/dist/src/room/session-registry-ipc.js +1 -0
  115. package/dist/src/room/session-registry.d.ts +128 -0
  116. package/dist/src/room/session-registry.js +2 -0
  117. package/dist/src/room/tool-schema.d.ts +114 -0
  118. package/dist/src/room/tool-schema.js +1 -0
  119. package/dist/src/room/tool-server.d.ts +5 -0
  120. package/dist/src/room/tool-server.js +3 -0
  121. package/dist/src/session/handlers/agent-capabilities.d.ts +3 -0
  122. package/dist/src/session/handlers/agent-capabilities.js +1 -0
  123. package/dist/src/session/handlers/agent-config.js +1 -1
  124. package/dist/src/session/handlers/chat.js +2 -2
  125. package/dist/src/session/handlers/control.js +1 -1
  126. package/dist/src/session/handlers/fs.d.ts +1 -0
  127. package/dist/src/session/handlers/fs.js +1 -1
  128. package/dist/src/session/manager.d.ts +16 -6
  129. package/dist/src/session/manager.js +1 -1
  130. package/dist/src/session/types.d.ts +5 -0
  131. package/dist/src/upgrade/engine.d.ts +14 -1
  132. package/dist/src/upgrade/engine.js +2 -2
  133. package/dist/src/upgrade/scheduler.d.ts +45 -0
  134. package/dist/src/upgrade/scheduler.js +1 -0
  135. package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts +17 -0
  136. package/node_modules/@shennian/wire/dist/agent-capabilities.d.ts.map +1 -0
  137. package/node_modules/@shennian/wire/dist/agent-capabilities.js +2 -0
  138. package/node_modules/@shennian/wire/dist/agent-capabilities.js.map +1 -0
  139. package/node_modules/@shennian/wire/dist/index.d.ts +2 -1
  140. package/node_modules/@shennian/wire/dist/index.d.ts.map +1 -1
  141. package/node_modules/@shennian/wire/dist/index.js +2 -1
  142. package/node_modules/@shennian/wire/dist/index.js.map +1 -1
  143. package/node_modules/@shennian/wire/dist/machine.d.ts +1 -0
  144. package/node_modules/@shennian/wire/dist/machine.d.ts.map +1 -1
  145. package/node_modules/@shennian/wire/dist/methods.d.ts +1 -1
  146. package/node_modules/@shennian/wire/dist/methods.d.ts.map +1 -1
  147. package/node_modules/@shennian/wire/dist/room.d.ts +112 -0
  148. package/node_modules/@shennian/wire/dist/room.d.ts.map +1 -0
  149. package/node_modules/@shennian/wire/dist/room.js +4 -0
  150. package/node_modules/@shennian/wire/dist/room.js.map +1 -0
  151. package/node_modules/@shennian/wire/dist/session.d.ts +2 -2
  152. package/node_modules/@shennian/wire/dist/session.d.ts.map +1 -1
  153. package/node_modules/@shennian/wire/dist/session.js +1 -1
  154. package/node_modules/@shennian/wire/dist/session.js.map +1 -1
  155. package/package.json +3 -5
  156. package/dist/scripts/wechat-rpa-confirmation.mjs +0 -5
  157. package/dist/src/agents/pi-context.d.ts +0 -42
  158. package/dist/src/agents/pi-context.js +0 -12
  159. package/dist/src/agents/pi.d.ts +0 -70
  160. package/dist/src/agents/pi.js +0 -17
  161. package/dist/src/channels/base.d.ts +0 -144
  162. package/dist/src/channels/base.js +0 -1
  163. package/dist/src/channels/registry.d.ts +0 -8
  164. package/dist/src/channels/registry.js +0 -1
  165. package/dist/src/channels/reply-split.d.ts +0 -1
  166. package/dist/src/channels/reply-split.js +0 -10
  167. package/dist/src/channels/runtime.d.ts +0 -138
  168. package/dist/src/channels/runtime.js +0 -5
  169. package/dist/src/channels/secret-registry.d.ts +0 -35
  170. package/dist/src/channels/secret-registry.js +0 -1
  171. package/dist/src/channels/websocket.d.ts +0 -55
  172. package/dist/src/channels/websocket.js +0 -8
  173. package/dist/src/channels/wechat-channel/anchor.d.ts +0 -10
  174. package/dist/src/channels/wechat-channel/anchor.js +0 -1
  175. package/dist/src/channels/wechat-channel/automation-lane.d.ts +0 -35
  176. package/dist/src/channels/wechat-channel/automation-lane.js +0 -2
  177. package/dist/src/channels/wechat-channel/client.d.ts +0 -283
  178. package/dist/src/channels/wechat-channel/client.js +0 -1
  179. package/dist/src/channels/wechat-channel/cooldown.d.ts +0 -21
  180. package/dist/src/channels/wechat-channel/cooldown.js +0 -1
  181. package/dist/src/channels/wechat-channel/core/fixture-compare.d.ts +0 -52
  182. package/dist/src/channels/wechat-channel/core/fixture-compare.js +0 -1
  183. package/dist/src/channels/wechat-channel/core/media-action-plan.d.ts +0 -3
  184. package/dist/src/channels/wechat-channel/core/media-action-plan.js +0 -1
  185. package/dist/src/channels/wechat-channel/core/schema.d.ts +0 -67
  186. package/dist/src/channels/wechat-channel/core/schema.js +0 -1
  187. package/dist/src/channels/wechat-channel/core/trace-comparator.d.ts +0 -28
  188. package/dist/src/channels/wechat-channel/core/trace-comparator.js +0 -1
  189. package/dist/src/channels/wechat-channel/fingerprint.d.ts +0 -31
  190. package/dist/src/channels/wechat-channel/fingerprint.js +0 -1
  191. package/dist/src/channels/wechat-channel/helper-assets.d.ts +0 -103
  192. package/dist/src/channels/wechat-channel/helper-assets.js +0 -1
  193. package/dist/src/channels/wechat-channel/helper-client.d.ts +0 -87
  194. package/dist/src/channels/wechat-channel/helper-client.js +0 -3
  195. package/dist/src/channels/wechat-channel/helper-protocol.d.ts +0 -122
  196. package/dist/src/channels/wechat-channel/helper-protocol.js +0 -1
  197. package/dist/src/channels/wechat-channel/human-coordination.d.ts +0 -25
  198. package/dist/src/channels/wechat-channel/human-coordination.js +0 -1
  199. package/dist/src/channels/wechat-channel/index.d.ts +0 -21
  200. package/dist/src/channels/wechat-channel/index.js +0 -1
  201. package/dist/src/channels/wechat-channel/ledger.d.ts +0 -48
  202. package/dist/src/channels/wechat-channel/ledger.js +0 -2
  203. package/dist/src/channels/wechat-channel/media-cache-resolver.d.ts +0 -42
  204. package/dist/src/channels/wechat-channel/media-cache-resolver.js +0 -1
  205. package/dist/src/channels/wechat-channel/media-resolver.d.ts +0 -186
  206. package/dist/src/channels/wechat-channel/media-resolver.js +0 -1
  207. package/dist/src/channels/wechat-channel/message-key.d.ts +0 -19
  208. package/dist/src/channels/wechat-channel/message-key.js +0 -1
  209. package/dist/src/channels/wechat-channel/observer.d.ts +0 -171
  210. package/dist/src/channels/wechat-channel/observer.js +0 -7
  211. package/dist/src/channels/wechat-channel/outbound-ledger.d.ts +0 -96
  212. package/dist/src/channels/wechat-channel/outbound-ledger.js +0 -2
  213. package/dist/src/channels/wechat-channel/outbound-sender.d.ts +0 -74
  214. package/dist/src/channels/wechat-channel/outbound-sender.js +0 -1
  215. package/dist/src/channels/wechat-channel/pacing.d.ts +0 -3
  216. package/dist/src/channels/wechat-channel/pacing.js +0 -1
  217. package/dist/src/channels/wechat-channel/preflight.d.ts +0 -46
  218. package/dist/src/channels/wechat-channel/preflight.js +0 -1
  219. package/dist/src/channels/wechat-channel/runner.d.ts +0 -43
  220. package/dist/src/channels/wechat-channel/runner.js +0 -1
  221. package/dist/src/channels/wechat-channel/runtime.d.ts +0 -50
  222. package/dist/src/channels/wechat-channel/runtime.js +0 -1
  223. package/dist/src/channels/wechat-channel/scheduler.d.ts +0 -74
  224. package/dist/src/channels/wechat-channel/scheduler.js +0 -1
  225. package/dist/src/channels/wechat-channel/vector-store.d.ts +0 -44
  226. package/dist/src/channels/wechat-channel/vector-store.js +0 -1
  227. package/dist/src/channels/wechat-rpa/macos-flow.d.ts +0 -55
  228. package/dist/src/channels/wechat-rpa/macos-flow.js +0 -1
  229. package/dist/src/channels/wechat-rpa/macos.d.ts +0 -11
  230. package/dist/src/channels/wechat-rpa/macos.js +0 -21
  231. package/dist/src/channels/wechat-rpa/normalizer.d.ts +0 -49
  232. package/dist/src/channels/wechat-rpa/normalizer.js +0 -7
  233. package/dist/src/channels/wechat-rpa/product-channel.d.ts +0 -76
  234. package/dist/src/channels/wechat-rpa/product-channel.js +0 -16
  235. package/dist/src/channels/wechat-rpa-session-sync.d.ts +0 -26
  236. package/dist/src/channels/wechat-rpa-session-sync.js +0 -1
  237. package/dist/src/channels/wechat-rpa.d.ts +0 -104
  238. package/dist/src/channels/wechat-rpa.js +0 -6
  239. package/dist/src/channels/wecom.d.ts +0 -51
  240. package/dist/src/channels/wecom.js +0 -4
  241. package/dist/src/commands/external-attachments.d.ts +0 -9
  242. package/dist/src/commands/external-attachments.js +0 -1
  243. package/dist/src/commands/external.d.ts +0 -2
  244. package/dist/src/commands/external.js +0 -1
  245. package/dist/src/commands/helper-runtime-official-download.d.ts +0 -80
  246. package/dist/src/commands/helper-runtime-official-download.js +0 -1
  247. package/dist/src/commands/runtime.d.ts +0 -120
  248. package/dist/src/commands/runtime.js +0 -1
  249. package/dist/src/commands/wechat/command.d.ts +0 -3
  250. package/dist/src/commands/wechat/command.js +0 -1
  251. package/dist/src/commands/wechat/direct.d.ts +0 -14
  252. package/dist/src/commands/wechat/direct.js +0 -2
  253. package/dist/src/commands/wechat/doctor.d.ts +0 -2
  254. package/dist/src/commands/wechat/doctor.js +0 -1
  255. package/dist/src/commands/wechat/ipc.d.ts +0 -9
  256. package/dist/src/commands/wechat/ipc.js +0 -1
  257. package/dist/src/commands/wechat/operations.d.ts +0 -3
  258. package/dist/src/commands/wechat/operations.js +0 -4
  259. package/dist/src/commands/wechat/output.d.ts +0 -7
  260. package/dist/src/commands/wechat/output.js +0 -4
  261. package/dist/src/commands/wechat/types.d.ts +0 -142
  262. package/dist/src/commands/wechat/types.js +0 -1
  263. package/dist/src/commands/wechat/utils.d.ts +0 -16
  264. package/dist/src/commands/wechat/utils.js +0 -1
  265. package/dist/src/commands/wechat.d.ts +0 -6
  266. package/dist/src/commands/wechat.js +0 -1
  267. package/dist/src/devtools/wechat-channel-action-smoke.d.ts +0 -105
  268. package/dist/src/devtools/wechat-channel-action-smoke.js +0 -10
  269. package/dist/src/devtools/wechat-channel-download-report.d.ts +0 -111
  270. package/dist/src/devtools/wechat-channel-download-report.js +0 -2
  271. package/dist/src/devtools/wechat-channel-markdown-report.d.ts +0 -6
  272. package/dist/src/devtools/wechat-channel-markdown-report.js +0 -5
  273. package/dist/src/devtools/wechat-channel-product-steps.d.ts +0 -9
  274. package/dist/src/devtools/wechat-channel-product-steps.js +0 -40
  275. package/dist/src/session/handlers/skills.d.ts +0 -7
  276. package/dist/src/session/handlers/skills.js +0 -1
  277. package/dist/src/session/handlers/wechat-helper-runtime.d.ts +0 -33
  278. package/dist/src/session/handlers/wechat-helper-runtime.js +0 -1
  279. package/dist/src/skills/registry.d.ts +0 -16
  280. package/dist/src/skills/registry.js +0 -15
  281. package/dist/src/skills/setup.d.ts +0 -11
  282. package/dist/src/skills/setup.js +0 -1
@@ -1,48 +0,0 @@
1
- import type { WeChatChannelObservedMessage } from './client.js';
2
- import type { WeChatChannelCooldownState } from './cooldown.js';
3
- import type { WeChatChannelVectorReference } from './vector-store.js';
4
- export type WeChatChannelLedger = {
5
- version: 1;
6
- runtimeId: string;
7
- bindings: Record<string, WeChatChannelBindingLedger>;
8
- };
9
- export type WeChatChannelBindingLedger = {
10
- bindingId: string;
11
- baselineEstablished: boolean;
12
- disabledSince?: string | null;
13
- revision: number;
14
- recent: WeChatChannelObservedMessage[];
15
- pendingSendKeys: string[];
16
- attachmentStates?: Record<string, WeChatChannelAttachmentState>;
17
- vectorReferences?: Record<string, WeChatChannelVectorReference[]>;
18
- cooldown?: WeChatChannelCooldownState;
19
- };
20
- export type WeChatChannelAttachmentState = {
21
- stableMessageKey: string;
22
- kind: string;
23
- availability: string;
24
- deliveryStatus?: string;
25
- localPath?: string;
26
- url?: string;
27
- name?: string;
28
- providerError?: string;
29
- reasonCode?: string;
30
- };
31
- export declare function loadWeChatChannelLedger(filePath: string, runtimeId: string): WeChatChannelLedger;
32
- export declare function saveWeChatChannelLedger(filePath: string, ledger: WeChatChannelLedger): void;
33
- export declare function updateWeChatChannelBindingLedger(input: {
34
- ledger: WeChatChannelLedger;
35
- bindingId: string;
36
- observedMessages: WeChatChannelObservedMessage[];
37
- baselineOnly?: boolean;
38
- vectorReferences?: WeChatChannelVectorReference[];
39
- }): {
40
- binding: WeChatChannelBindingLedger;
41
- newMessages: WeChatChannelObservedMessage[];
42
- };
43
- export declare function markWeChatChannelBindingDisabled(input: {
44
- ledger: WeChatChannelLedger;
45
- bindingId: string;
46
- disabledAt?: Date;
47
- }): WeChatChannelBindingLedger;
48
- export declare function filterDeliverableWeChatMessages(previous: WeChatChannelObservedMessage[], current: WeChatChannelObservedMessage[]): WeChatChannelObservedMessage[];
@@ -1,2 +0,0 @@
1
- import y from"node:fs";import m from"node:path";import{WECHAT_CHANNEL_RECENT_MESSAGE_WINDOW as R}from"./runtime.js";import{filterNewWeChatMessagesByAnchor as C,isLikelySameWeChatMessage as p}from"./anchor.js";import{normalizeWeChatObservedWindowForLedger as B}from"./message-key.js";function J(e,t){try{const n=JSON.parse(y.readFileSync(e,"utf8"));if(n?.version===1&&n.runtimeId===t&&n.bindings&&typeof n.bindings=="object")return n}catch{}return{version:1,runtimeId:t,bindings:{}}}function $(e,t){y.mkdirSync(m.dirname(e),{recursive:!0}),y.writeFileSync(e,JSON.stringify(t,null,2))}function G(e){const t=e.ledger.bindings[e.bindingId],n=B(e.observedMessages).map(E),r=L(t?.recent??[],n).slice(-R),s=e.baselineOnly||!t?.baselineEstablished||!!t?.disabledSince?[]:x(t?.recent??[],r),l={bindingId:e.bindingId,baselineEstablished:!0,disabledSince:null,revision:(t?.revision??0)+(s.length>0?1:0),recent:r,pendingSendKeys:t?.pendingSendKeys??[],attachmentStates:W(r,t?.attachmentStates),vectorReferences:I(r,t?.vectorReferences,e.vectorReferences),cooldown:t?.cooldown};return e.ledger.bindings[e.bindingId]=l,{binding:l,newMessages:s}}function E(e){return Array.isArray(e.visualBlocks)?{...e,visualBlocks:e.visualBlocks.map(t=>{const{vectorBase64:n,...r}=t;return r})}:e}function U(e){const t=e.ledger.bindings[e.bindingId],n={bindingId:e.bindingId,baselineEstablished:!1,disabledSince:(e.disabledAt??new Date).toISOString(),revision:t?.revision??0,recent:t?.recent??[],pendingSendKeys:t?.pendingSendKeys??[],attachmentStates:t?.attachmentStates,vectorReferences:t?.vectorReferences,cooldown:t?.cooldown};return e.ledger.bindings[e.bindingId]=n,n}function I(e,t,n){const r=new Map;for(const s of n??[]){const l=o(s.stableMessageKey);if(!l)continue;const c=r.get(l)??[];c.push(s),r.set(l,c)}const i={};for(const s of e){const l=r.get(s.stableMessageKey)??N(s)??t?.[s.stableMessageKey];l?.length&&(i[s.stableMessageKey]=l)}return Object.keys(i).length?i:void 0}function N(e){const n=(Array.isArray(e.visualBlocks)?e.visualBlocks:[]).flatMap(r=>{const i=o(r.vectorStoreKey),s=o(r.blockId),l=o(r.blockKind)||"visual",c=o(r.modelVersion)||o(r.model)||"server-visual-embedding",u=Number(r.dims);return!i||!s||!Number.isFinite(u)||u<1?[]:[{stableMessageKey:e.stableMessageKey,blockId:s,blockKind:l,vectorStoreKey:i,model:c,...r.modelVersion!==void 0?{modelVersion:r.modelVersion}:{},dims:Math.round(u),...o(r.signature)?{signature:o(r.signature)}:{},...r.bbox!==void 0?{bbox:r.bbox}:{},observedAt:e.observedAt||new Date(0).toISOString()}]});return n.length?n:void 0}function x(e,t){const n=C({previous:e,current:t}),r=new Set(n.map(a=>a.stableMessageKey)),i=new Set(t.map(a=>a.stableMessageKey)),s=[],l=t.filter(a=>{if(r.has(a.stableMessageKey))return!0;const S=e.find(g=>g.stableMessageKey===a.stableMessageKey)??e.find(g=>!i.has(g.stableMessageKey)&&p(g,a));return S?T(S,a):!1}),c=new Set(l.map(a=>a.stableMessageKey)),u=l.filter(a=>!(a.senderRole==="self"||a.isBaseline===!0||v(a.deliveryStatus)||b(a)&&!d(a))),w=new Set(u.map(a=>a.stableMessageKey));for(const a of t)s.push({stableMessageKey:a.stableMessageKey,kind:a.kind||null,senderRole:a.senderRole||null,anchorText:(a.anchorText||a.normalizedText||a.textExcerpt||"").slice(0,40),isNewByAnchor:r.has(a.stableMessageKey),isCandidate:c.has(a.stableMessageKey),delivered:w.has(a.stableMessageKey),isBaseline:a.isBaseline===!0,deliveryStatus:a.deliveryStatus??null,hasAttachmentCandidate:b(a),hasAgentReadableAttachment:d(a),dropReason:O(a,c.has(a.stableMessageKey))});return P(s),u}function O(e,t){return t?e.senderRole==="self"?"sender-self":e.isBaseline===!0?"baseline":v(e.deliveryStatus)?`status:${M(e.deliveryStatus)}`:b(e)&&!d(e)?"attachment-not-readable":null:"not-new-and-no-media-upgrade"}function P(e){const t=process.env.SHENNIAN_WECHAT_DELIVERABILITY_TRACE;if(t)try{const n=JSON.stringify({at:new Date().toISOString(),messages:e})+`
2
- `;t==="1"||t==="stderr"?process.stderr.write(`[wechat-deliverability] ${n}`):(y.mkdirSync(m.dirname(t),{recursive:!0}),y.appendFileSync(t,n))}catch{}}function W(e,t){const n={};for(const r of e){const i=k(r),s=t?.[r.stableMessageKey];if(!i&&s){n[r.stableMessageKey]=s;continue}i&&(n[r.stableMessageKey]=D(s,i))}return Object.keys(n).length?n:void 0}function k(e){const t=h(e.mediaMetadata);if(!t.length&&!b(e)&&!v(e.deliveryStatus))return null;const n=A(e.mediaMetadata)??t[0]??{},r=M(e.deliveryStatus),i=o(n.availability)||o(e.mediaMetadata?.availability)||(r==="needs-review"?"needs-review":"metadata-only");return{stableMessageKey:e.stableMessageKey,kind:e.kind||o(n.type)||"unknown",availability:i,...r?{deliveryStatus:r}:{},...o(n.localPath)?{localPath:o(n.localPath)}:{},...o(n.url)?{url:o(n.url)}:{},...o(n.name)||o(n.fileName)?{name:o(n.name)||o(n.fileName)}:{},...o(n.providerError)?{providerError:o(n.providerError)}:{},...o(n.reasonCode)||o(e.mediaMetadata?.edgeResolveReasonCode)?{reasonCode:o(n.reasonCode)||o(e.mediaMetadata?.edgeResolveReasonCode)}:{}}}function D(e,t){return!e||K(t)?t:K(e)?e:t}function K(e){return e.availability==="edge-local"&&!!e.localPath||e.availability==="server-url"&&!!e.url}function v(e){const t=M(e);return t==="suppressed"||t==="pending"||t==="needs-review"||t==="manual-review"}function L(e,t){const n=new Set(t.map(r=>r.stableMessageKey));return t.map(r=>{if(d(r))return r;const i=e.find(s=>s.stableMessageKey===r.stableMessageKey&&d(s))??e.find(s=>!n.has(s.stableMessageKey)&&p(s,r)&&d(s));return i?{...r,mediaMetadata:V(r.mediaMetadata,i.mediaMetadata)}:r})}function T(e,t){return b(e)&&!d(e)&&d(t)}function b(e){return h(e.mediaMetadata).length>0||/image|photo|video|file|document/i.test(e.kind||"")}function d(e){return h(e.mediaMetadata).some(t=>{const n=typeof t.localPath=="string"?t.localPath.trim():"",r=typeof t.url=="string"?t.url.trim():"",i=typeof t.availability=="string"?t.availability:"";return i==="edge-local"&&!!n||i==="server-url"&&!!r})}function V(e,t){const n=f(e)?{...e}:{},r=f(t)?t:{},i=A(r);return i?{...n,availability:i.availability,mediaStatus:"downloaded",attachment:{...f(n.attachment)?n.attachment:{},...i}}:e}function A(e){return h(e).find(t=>{const n=typeof t.availability=="string"?t.availability:"",r=typeof t.localPath=="string"?t.localPath.trim():"",i=typeof t.url=="string"?t.url.trim():"";return n==="edge-local"&&!!r||n==="server-url"&&!!i})??null}function h(e){return f(e)?Array.isArray(e.attachments)?e.attachments.filter(f):f(e.attachment)?[e.attachment]:e.localPath||e.url||e.name||e.fileName||e.availability?[e]:[]:[]}function f(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function M(e){return String(e??"").trim().toLowerCase().replace(/_/g,"-")}function o(e){return typeof e=="string"?e.trim():""}export{x as filterDeliverableWeChatMessages,J as loadWeChatChannelLedger,U as markWeChatChannelBindingDisabled,$ as saveWeChatChannelLedger,G as updateWeChatChannelBindingLedger};
@@ -1,42 +0,0 @@
1
- type CacheCandidate = {
2
- kind: string;
3
- fileName?: string | null;
4
- mimeType?: string | null;
5
- size?: number | null;
6
- };
7
- export type WeChatChannelMediaCacheScanTrace = {
8
- strategy: 'token' | 'recent-unique' | 'none';
9
- roots: string[];
10
- extensionCandidates: string[];
11
- tokens: string[];
12
- hasTimeAnchor?: boolean;
13
- scannedFileCount: number;
14
- matchedFileCount: number;
15
- minMtimeMs?: number;
16
- maxAgeMs: number;
17
- selected?: {
18
- path: string;
19
- name: string;
20
- size: number;
21
- mtimeMs: number;
22
- score?: number;
23
- };
24
- };
25
- export type WeChatChannelMediaCacheLookupResult = {
26
- ok: true;
27
- sourcePath: string;
28
- reasonCode: 'wechat_cache_token_match' | 'wechat_cache_recent_unique_match';
29
- trace: WeChatChannelMediaCacheScanTrace;
30
- } | {
31
- ok: false;
32
- reasonCode: 'wechat_cache_scan_unavailable' | 'wechat_cache_lookup_token_missing' | 'wechat_cache_file_not_found' | 'wechat_cache_recent_match_ambiguous';
33
- trace: WeChatChannelMediaCacheScanTrace;
34
- };
35
- export declare function findCachedWeChatInboundMedia(candidate: CacheCandidate, options?: {
36
- roots?: string[];
37
- minMtimeMs?: number;
38
- nowMs?: number;
39
- maxAgeMs?: number;
40
- maxFiles?: number;
41
- }): WeChatChannelMediaCacheLookupResult;
42
- export {};
@@ -1 +0,0 @@
1
- import p from"node:fs";import F from"node:os";import h from"node:path";const b=5e3,N=336*60*60*1e3,x=5e3,v=new Set([".apng",".avif",".bmp",".gif",".heic",".heif",".jpeg",".jpg",".png",".tif",".tiff",".webp"]),S=new Set([".3g2",".3gp",".avi",".m4v",".mkv",".mov",".mp4",".mpeg",".mpg",".webm",".wmv"]),w=/^(attachment|document|file|image|img|photo|pic|picture|video|vid|wechat|weixin|wx|copy|download|mp4|mov|m4v|png|jpg|jpeg|gif|webp|txt|pdf)$/i;function $(e,t={}){const n=k(t.roots),r=Number.isFinite(Number(t.maxAgeMs))?Number(t.maxAgeMs):N,s=Number.isFinite(Number(t.minMtimeMs))?Number(t.minMtimeMs)-x:void 0,i=y(e),a=E(e),c=s!==void 0,o=()=>({strategy:"none",roots:n,extensionCandidates:i,tokens:a,...c?{hasTimeAnchor:c}:{},scannedFileCount:0,matchedFileCount:0,...s!==void 0?{minMtimeMs:s}:{},maxAgeMs:r});if(!n.length||!i.length)return{ok:!1,reasonCode:"wechat_cache_scan_unavailable",trace:o()};const m=z(n,{maxFiles:t.maxFiles,maxAgeMs:r,nowMs:t.nowMs}).filter(l=>i.includes(h.extname(l.name).toLowerCase()));if(a.length){const l=m.map(g=>({...g,score:L(g,a,e)})).filter(g=>g.score>0).sort((g,d)=>d.score-g.score||d.mtimeMs-g.mtimeMs),f=l[0];if(f)return{ok:!0,sourcePath:f.path,reasonCode:"wechat_cache_token_match",trace:{...o(),strategy:"token",scannedFileCount:m.length,matchedFileCount:l.length,selected:_(f)}}}const u=c?T(e,m,s):[];if(u.length===1){const l=u[0];return{ok:!0,sourcePath:l.path,reasonCode:"wechat_cache_recent_unique_match",trace:{...o(),strategy:"recent-unique",scannedFileCount:m.length,matchedFileCount:u.length,selected:_(l)}}}return u.length>1?{ok:!1,reasonCode:"wechat_cache_recent_match_ambiguous",trace:{...o(),strategy:"recent-unique",scannedFileCount:m.length,matchedFileCount:u.length}}:{ok:!1,reasonCode:a.length||s!==void 0?"wechat_cache_file_not_found":"wechat_cache_lookup_token_missing",trace:{...o(),scannedFileCount:m.length,matchedFileCount:0}}}function k(e){if(Array.isArray(e)&&e.length)return e.map(n=>String(n||"").trim()).filter(Boolean);if(process.platform!=="win32")return[];const t=F.homedir();return t?[h.join(t,"Documents","xwechat_files"),h.join(t,"Documents","WeChat Files")]:[]}function y(e){const t=D(h.extname(String(e.fileName||"")));if(t)return[t];const n=String(e.mimeType||"").toLowerCase();if(n==="image/png")return[".png"];if(n==="image/jpeg")return[".jpg",".jpeg"];if(n==="image/gif")return[".gif"];if(n==="image/webp")return[".webp"];if(n==="video/mp4")return[".mp4"];if(n==="video/quicktime")return[".mov"];const r=C(e);return r==="image"?[...v]:r==="video"?[...S]:[]}function E(e){const t=[e.fileName].map(r=>M(r)).filter(Boolean),n=new Set;for(const r of t){for(const s of r.split(/[^a-z0-9]+/i))s.length>=4&&!w.test(s)&&n.add(s.toLowerCase());r.length>=8&&!w.test(r)&&n.add(r.toLowerCase())}return[...n]}function z(e,t){const n=Number.isFinite(Number(t.maxFiles))?Math.max(1,Number(t.maxFiles)):b,s=(Number.isFinite(Number(t.nowMs))?Number(t.nowMs):Date.now())-t.maxAgeMs,i=[],a=e.map(o=>h.resolve(o)),c=new Set;for(;a.length&&i.length<n;){const o=a.pop();if(!o||c.has(o))continue;c.add(o);let m;try{m=p.readdirSync(o,{withFileTypes:!0})}catch{continue}for(const u of m){const l=h.join(o,u.name);if(u.isDirectory()){A(o,u.name)&&a.push(l);continue}if(!u.isFile())continue;let f;try{f=p.statSync(l)}catch{continue}if(!(f.mtimeMs<s||f.size<=0)&&(i.push({path:l,name:u.name,size:f.size,mtimeMs:f.mtimeMs}),i.length>=n))break}}return i.sort((o,m)=>m.mtimeMs-o.mtimeMs)}function A(e,t){const n=t.toLowerCase(),r=e.toLowerCase();return/^(cache|temp|tmp|rwtemp|filestorage|msgattach|msg|image|video|file|[0-9-]+)$/i.test(n)||r.includes("xwechat_files")||r.includes("wechat files")}function L(e,t,n){const r=M(e.name),s=t.reduce((c,o)=>c+(r.includes(o)?Math.min(20,o.length):0),0),i=Number(n.size),a=Number.isFinite(i)&&i>0&&Math.abs(e.size-i)<=Math.max(8,i*.02)?12:0;return s+a}function T(e,t,n){if(C(e)!=="video"||n===void 0)return[];const r=t.filter(i=>i.mtimeMs>=n),s=new Map;for(const i of r){const a=h.basename(i.name,h.extname(i.name)).replace(/_raw$/i,""),c=s.get(a)??[];c.push(i),s.set(a,c)}return[...s.values()].map(i=>i.sort((a,c)=>Number(/_raw\./i.test(c.name))-Number(/_raw\./i.test(a.name))||c.mtimeMs-a.mtimeMs)[0])}function _(e){return{path:e.path,name:e.name,size:e.size,mtimeMs:e.mtimeMs,...Number.isFinite(e.score)?{score:e.score}:{}}}function C(e){const t=String(e.kind||"").toLowerCase().replace(/_/g,"-");return t.includes("image")||t.includes("photo")?"image":t.includes("video")?"video":"file"}function M(e){return j(String(e||"").trim()).toLowerCase().replace(/\.[a-z0-9]{1,8}$/i,"").replace(/[^a-z0-9]+/gi," ").trim()}function j(e){return e.replace(/\\/g,"/").split("/").filter(Boolean).pop()||""}function D(e){const t=String(e||"").trim().toLowerCase();return t.startsWith(".")?t:t?`.${t}`:""}export{$ as findCachedWeChatInboundMedia};
@@ -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 {};