@agent-wechat/agent-wechat 1.0.0-beta.13 → 1.0.0-beta.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,7 +66,7 @@ By default, `readPolicy: "on_inbound"` marks a whole thread read after its incom
66
66
 
67
67
  A whole-thread read also clears earlier unread messages in that thread, including messages the model did not receive. The daemon freezes the latest local message boundary, checks the expected version, updates local unread state and submits one native read-status notification. Server acceptance alone does not prove that a phone badge changed. A lost notification response remains `needs_review` and is never automatically resubmitted. Pending reads survive a Gateway restart and retry independently of model execution or new SSE traffic. `readPolicy: "never"` disables both local and remote marking, including previously queued reads. Crashes during an unfinished dispatch retain `needs_review`; the plugin does not automatically duplicate model turns or uncertain outgoing sends.
68
68
 
69
- The optional `readPolicy: "on_model_dispatch"` instead requires a confirmed model handoff. OpenClaw **2026.10.2** lacks `onPreparedAgentRunStart`, so its released public hooks provide a bounded compatibility path. Before dispatch, the adapter persists an immutable manifest binding the exact new message ID/version/content hash, policy hash, source and supplied asset hashes, and context roles. Text requires the exact current input and host-created message/account/session facts plus a matching `model_call_started`. Media additionally waits for the same run's `agent_end` snapshot and source-turn identity. Image bytes/MIME/length must match the frozen supplied representation; file/video/voice references must appear in the exact current body. Image count, model selection and reply delivery alone cannot confirm a model handoff. Unknown, omitted, rewritten, merged or ambiguous inputs remain unconfirmed. Host/provider history formats can prevent confirmation even when a reply was delivered; use `on_inbound` for ordinary bot read behavior.
69
+ The optional `readPolicy: "on_model_dispatch"` instead requires a confirmed model handoff. OpenClaw **2026.10.7** lacks `onPreparedAgentRunStart`, so its released public hooks provide a bounded compatibility path. Before dispatch, the adapter persists an immutable manifest binding the exact new message ID/version/content hash, policy hash, source and supplied asset hashes, and context roles. Text requires the exact current input and host-created message/account/session facts plus a matching `model_call_started`. Media additionally waits for the same run's `agent_end` snapshot and source-turn identity. Image bytes/MIME/length must match the frozen supplied representation; file/video/voice references must appear in the exact current body. Image count, model selection and reply delivery alone cannot confirm a model handoff. Unknown, omitted, rewritten, merged or ambiguous inputs remain unconfirmed. Host/provider history formats can prevent confirmation even when a reply was delivered; use `on_inbound` for ordinary bot read behavior.
70
70
 
71
71
  The model-handoff compatibility path requires the operator's explicit host permission, `plugins.entries.agent-wechat.hooks.allowConversationAccess: true`. It observes only run IDs issued by this adapter and never enables that permission itself. Without the grant, or on an unsupported host, the explicit `on_model_dispatch` policy leaves messages unread and status reports `handoffUnconfirmed`. The older `onAgentRunStart` also reports direct tools and early lifecycle phases and is never used as proof. Access and mention gates still precede model dispatch; a rejected message does not itself trigger a read.
72
72
 
@@ -203,6 +203,6 @@ Set `native.gatewayFacade: {"enabled": true}` to register `/plugins/agent-wechat
203
203
 
204
204
  The actual Gateway authenticates requests before the proxy runs. Its bearer is never forwarded to the daemon; the plugin uses its private daemon token reference. Routes are restricted to the configured account, with no daemon-wide token/account administration. Binary bodies, byte ranges, status codes and SSE are preserved within explicit size limits. Client disconnect/plugin shutdown closes upstream streaming work without cancelling durable sends.
205
205
 
206
- `scripts/native-gateway-smoke.mjs` tests the built plugin on an isolated OpenClaw **2026.10.2** Gateway with synthetic loopback data: auth rejection, separate credentials, account boundaries, Range206, SSE and cancellation. This transport test is separate from the local model-boundary test above; neither uses an external model provider or a real WeChat account.
206
+ `scripts/native-gateway-smoke.mjs` tests the built plugin on an isolated OpenClaw **2026.10.7** Gateway with synthetic loopback data: auth rejection, separate credentials, account boundaries, Range206, SSE and cancellation. This transport test is separate from the local model-boundary test above; neither uses an external model provider or a real WeChat account.
207
207
 
208
208
  See [native deployment examples](../../deploy/native/README.md) and [native CLI installation](../cli/README.md).
package/dist/index.js CHANGED
@@ -192,7 +192,7 @@ var NativeWeChatClient = class {
192
192
  if (typeof options.token !== "string" || !options.token || /[\r\n]/.test(options.token))
193
193
  throw new Error("Native API bearer token is required");
194
194
  this.token = options.token;
195
- this.fetchImpl = options.fetch ?? fetch;
195
+ this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
196
196
  this.timeoutMs = options.timeoutMs ?? 3e4;
197
197
  this.mediaTimeoutMs = options.mediaTimeoutMs ?? 60 * 6e4;
198
198
  if (!Number.isInteger(this.mediaTimeoutMs) || this.mediaTimeoutMs < 1 || this.mediaTimeoutMs > 60 * 6e4)
@@ -279,9 +279,22 @@ var NativeWeChatClient = class {
279
279
  throw new Error("Account ID or alias is required");
280
280
  return this.request("v1/accounts", { method: "POST", body: JSON.stringify(body) });
281
281
  }
282
+ removeAccount(accountId, confirmAccountId) {
283
+ if (accountId !== confirmAccountId)
284
+ throw new Error("Account confirmation does not match");
285
+ return this.request(`v1/accounts/${id(accountId)}`, { method: "DELETE", body: JSON.stringify({ confirmAccountId }) });
286
+ }
282
287
  updateAccount(accountId, options) {
283
288
  return this.request(`v1/accounts/${id(accountId)}`, { method: "PATCH", body: JSON.stringify(options) });
284
289
  }
290
+ accountSettings(accountId, signal) {
291
+ return this.request(`v1/accounts/${id(accountId)}/settings`, { signal });
292
+ }
293
+ updateAccountSettings(accountId, settings, signal) {
294
+ if (!Number.isSafeInteger(settings.autoDownloadMaxBytes) || settings.autoDownloadMaxBytes < 0 || settings.autoDownloadMaxBytes > NATIVE_MAX_SOURCE_BYTES)
295
+ throw new Error("Invalid automatic download limit");
296
+ return this.request(`v1/accounts/${id(accountId)}/settings`, { method: "PATCH", body: JSON.stringify(settings), signal });
297
+ }
285
298
  capabilities(accountId) {
286
299
  return this.request(`v1/accounts/${id(accountId)}/capabilities`);
287
300
  }
@@ -629,7 +642,7 @@ var NativeWeChatClient = class {
629
642
  ack(accountId, consumerId, cursor) {
630
643
  return this.request(`v1/accounts/${id(accountId)}/consumers/${id(consumerId)}/ack`, { method: "POST", body: JSON.stringify({ cursor: decimal(cursor) }) });
631
644
  }
632
- async *watch(accountId, after = "0", signal) {
645
+ async *watch(accountId, after = "0", signal, options = {}) {
633
646
  const connection = new AbortController();
634
647
  const streamSignal = signal ? AbortSignal.any([signal, connection.signal]) : connection.signal;
635
648
  const bounded = async (work, milliseconds, reason) => {
@@ -671,6 +684,7 @@ var NativeWeChatClient = class {
671
684
  const { value, done } = await bounded(() => activeReader.read(), this.streamIdleTimeoutMs, "Native SSE idle timeout");
672
685
  if (done)
673
686
  break;
687
+ options.onActivity?.();
674
688
  buffer += decoder.decode(value, { stream: true });
675
689
  if (buffer.length > 1024 * 1024)
676
690
  throw new Error("Native SSE frame exceeds its bound");
@@ -2397,7 +2411,7 @@ function nativeDispatchManifest(params) {
2397
2411
  }))) } : {},
2398
2412
  assets,
2399
2413
  policySha256: digest(JSON.stringify(params.policy ?? null)),
2400
- // Exact released 2026.10.2 source-turn identity. Requiring it in the later
2414
+ // Exact source-turn identity of OpenClaw 2026.10.2 through 2026.10.7. Requiring it in the later
2401
2415
  // snapshot prevents an identical older image/body from proving this input.
2402
2416
  hostSourceTurnId: `channel-user:v1:${digest(JSON.stringify(["agent-wechat", params.channelAccountId, `wechat:${params.message.threadId}`, messageSid]))}`
2403
2417
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-wechat/agent-wechat",
3
- "version": "1.0.0-beta.13",
3
+ "version": "1.0.0-beta.15",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -9,9 +9,9 @@
9
9
  "devDependencies": {
10
10
  "@types/node": "^22",
11
11
  "esbuild": "^0.25.0",
12
- "openclaw": "2026.10.2",
12
+ "openclaw": "2026.10.7",
13
13
  "typescript": "^5.4.5",
14
- "@agent-wechat/shared": "1.0.0-beta.2"
14
+ "@agent-wechat/shared": "1.0.0-beta.3"
15
15
  },
16
16
  "openclaw": {
17
17
  "extensions": [