@agent-wechat/agent-wechat 1.0.0-beta.4 → 1.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ var nativeConfigSchema = {
22
22
  }
23
23
  }] },
24
24
  consumerStateDir: { type: "string" },
25
- readPolicy: { type: "string", enum: ["never", "on_model_dispatch"] },
25
+ readPolicy: { type: "string", enum: ["never", "on_inbound", "on_model_dispatch"] },
26
26
  gatewayFacade: { type: "object", additionalProperties: false, required: ["enabled"], properties: { enabled: { type: "boolean" }, prefix: { type: "string" } } }
27
27
  }
28
28
  };
@@ -734,7 +734,7 @@ function collectWeChatStatusIssues(accounts) {
734
734
  accountId: snapshot.accountId,
735
735
  kind: "runtime",
736
736
  message: "Prepared model handoff was not confirmed by this OpenClaw host; automatic read state remains unchanged.",
737
- fix: "Use a compatible prepared-run SDK hook, or select native.readPolicy=never while retaining explicit local read control."
737
+ fix: "Select native.readPolicy=on_inbound to mark successfully handled conversations read without model hooks, or use a compatible prepared-run SDK hook."
738
738
  });
739
739
  }
740
740
  if ((snapshot.needsReview ?? 0) > 0) {
@@ -1573,7 +1573,7 @@ function nativeWasMentioned(message) {
1573
1573
  return message.mentions?.state === "known" && message.mentions.self === true;
1574
1574
  }
1575
1575
  async function projectNativeRead(client, accountId, state) {
1576
- const pending2 = state.items().filter((value) => value.readPending && value.runId);
1576
+ const pending2 = state.items().filter((value) => value.readPending);
1577
1577
  const threads = [...new Set(pending2.map((item) => item.message.threadId))];
1578
1578
  for (const threadId of threads) {
1579
1579
  for (let attempt = 0; attempt < 2; attempt++) {
@@ -1604,6 +1604,7 @@ async function projectNativeRead(client, accountId, state) {
1604
1604
  }
1605
1605
  async function dispatchNativeMessage(params) {
1606
1606
  const { client, state, account, message, cfg, core } = params;
1607
+ const readPolicy = account.native?.readPolicy ?? "on_inbound";
1607
1608
  const custody = state.get(message.id);
1608
1609
  if (!custody || custody.state !== "received") return "needs_review";
1609
1610
  if (custody.origin !== "live" || message.direction !== "incoming" || ![1, 3, 34, 43, 47, 49].includes(message.type) || message.type === 1 && !message.body || !message.senderId) {
@@ -1698,7 +1699,7 @@ async function dispatchNativeMessage(params) {
1698
1699
  assets: preparedMedia.suppliedAssets ?? []
1699
1700
  });
1700
1701
  state.update(message.id, { state: "dispatching", dispatchManifest });
1701
- const callback = message.type === 1 || preparedMedia.attachment?.status === "ready" && preparedMedia.suppliedAssets?.length ? state.preparedCallback([message.id], account.native?.readPolicy ?? "on_model_dispatch") : void 0;
1702
+ const callback = readPolicy !== "on_inbound" && (message.type === 1 || preparedMedia.attachment?.status === "ready" && preparedMedia.suppliedAssets?.length) ? state.preparedCallback([message.id], readPolicy) : void 0;
1702
1703
  if (callback) trackNativePreparedInput(dispatchManifest, callback);
1703
1704
  let failed = false;
1704
1705
  let delivery = 0;
@@ -1732,8 +1733,12 @@ async function dispatchNativeMessage(params) {
1732
1733
  // and media-snapshot bridge; unsupported or ambiguous handoffs leave reads unchanged.
1733
1734
  replyOptions: { runId: dispatchManifest.runId, onModelSelected, onPreparedAgentRunStart: callback }
1734
1735
  });
1735
- const prepared = Boolean(state.get(message.id)?.runId);
1736
- state.update(message.id, { state: failed ? "needs_review" : "completed", handoffUnconfirmed: !prepared });
1736
+ const readPending = readPolicy === "on_inbound" && !failed && ingress.ingress.admission === "dispatch" ? true : state.get(message.id)?.readPending;
1737
+ state.update(message.id, {
1738
+ state: failed ? "needs_review" : "completed",
1739
+ readPending,
1740
+ handoffUnconfirmed: readPolicy === "on_model_dispatch" && !state.get(message.id)?.runId
1741
+ });
1737
1742
  return failed ? "needs_review" : "completed";
1738
1743
  } catch {
1739
1744
  state.update(message.id, { state: "needs_review" });
@@ -1767,9 +1772,12 @@ async function startNativeMonitor(opts) {
1767
1772
  const core = getWeChatRuntime();
1768
1773
  let backoff = 250;
1769
1774
  let readTask;
1770
- const flushRead = () => readTask ??= projectNativeRead(host2.client, native.accountId, state).finally(() => {
1771
- readTask = void 0;
1772
- });
1775
+ const flushRead = () => {
1776
+ if (native.readPolicy === "never") return Promise.resolve();
1777
+ return readTask ??= projectNativeRead(host2.client, native.accountId, state).finally(() => {
1778
+ readTask = void 0;
1779
+ });
1780
+ };
1773
1781
  const process2 = async () => {
1774
1782
  const cfg = core.config.current();
1775
1783
  const account = resolveWeChatAccount(cfg, opts.account.accountId) ?? opts.account;
@@ -1788,10 +1796,10 @@ async function startNativeMonitor(opts) {
1788
1796
  try {
1789
1797
  await flushRead();
1790
1798
  } catch {
1791
- opts.log?.error?.("Native read projection is pending; prepared thread receipt retained for retry");
1799
+ opts.log?.error?.("Native read projection is pending; thread read receipt retained for retry");
1792
1800
  }
1793
1801
  const needsReview = state.items().filter((value) => value.state === "needs_review" || value.phoneReadState === "needs_review" || value.phoneReadState === "rejected").length;
1794
- const handoffUnconfirmed = native.readPolicy !== "never" && state.items().some((value) => value.handoffUnconfirmed);
1802
+ const handoffUnconfirmed = native.readPolicy === "on_model_dispatch" && state.items().some((value) => value.handoffUnconfirmed);
1795
1803
  const accountStatus = await host2.client.account(native.accountId);
1796
1804
  opts.setStatus({
1797
1805
  accountId: account.accountId,
@@ -1807,9 +1815,9 @@ async function startNativeMonitor(opts) {
1807
1815
  await flushRead();
1808
1816
  if (!opts.abortSignal.aborted) opts.setStatus({
1809
1817
  accountId: opts.account.accountId,
1810
- handoffUnconfirmed: native.readPolicy !== "never" && state.items().some((value) => value.handoffUnconfirmed)
1818
+ handoffUnconfirmed: native.readPolicy === "on_model_dispatch" && state.items().some((value) => value.handoffUnconfirmed)
1811
1819
  });
1812
- }, () => opts.log?.error?.("Native read projection remains pending; prepared thread receipts retained"));
1820
+ }, () => opts.log?.error?.("Native read projection remains pending; thread read receipts retained"));
1813
1821
  try {
1814
1822
  while (!opts.abortSignal.aborted) {
1815
1823
  try {
@@ -2361,7 +2369,8 @@ var plugin = {
2361
2369
  api.registerChannel({ plugin: wechatPlugin });
2362
2370
  const stopFacade = selected?.native ? registerNativeFacade(api, selected.native) : () => {
2363
2371
  };
2364
- const stopPreparedBoundary = registerNativePreparedBoundary(api);
2372
+ const stopPreparedBoundary = selected?.native?.readPolicy && selected.native.readPolicy !== "on_inbound" ? registerNativePreparedBoundary(api) : () => {
2373
+ };
2365
2374
  api.registerService({
2366
2375
  id: "agent-wechat-native",
2367
2376
  reload: { configPrefixes: ["plugins.entries.agent-wechat.config", "channels.agent-wechat", "secrets"] },
@@ -95,6 +95,7 @@
95
95
  "type": "string",
96
96
  "enum": [
97
97
  "never",
98
+ "on_inbound",
98
99
  "on_model_dispatch"
99
100
  ]
100
101
  },
@@ -274,6 +275,7 @@
274
275
  "type": "string",
275
276
  "enum": [
276
277
  "never",
278
+ "on_inbound",
277
279
  "on_model_dispatch"
278
280
  ]
279
281
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-wechat/agent-wechat",
3
- "version": "1.0.0-beta.4",
3
+ "version": "1.0.0-beta.5",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -183,6 +183,7 @@
183
183
  "type": "string",
184
184
  "enum": [
185
185
  "never",
186
+ "on_inbound",
186
187
  "on_model_dispatch"
187
188
  ]
188
189
  },