@agent-wechat/cli 1.0.0-beta.8 → 1.0.0-beta.9

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
@@ -1,6 +1,6 @@
1
1
  # @agent-wechat/cli
2
2
 
3
- `wx` is the native Rust client and foreground daemon. The npm package installs a matching release executable; it does not implement the native protocol in JavaScript. The supported distribution targets are Linux x64 and ARM64 with glibc 2.36+. macOS, Windows and musl do not have a native release. Clients on other systems can use the HTTP API of a supported Linux daemon. `wx --json version` and `/v1/status` expose the runtime and account capabilities; unsupported official schemas fail explicitly.
3
+ `wx` is the native Rust client and foreground daemon. The npm package installs a matching release executable; it does not implement the native protocol in JavaScript. Linux x64/ARM64 with glibc 2.36+ is validated. The release matrix also builds macOS ARM64 and native Windows x64/ARM64 candidates; native-machine account acceptance is pending. musl remains unsupported. Official-app profile takeover is Linux-only. Clients on other systems can use the HTTP API of a supported Linux daemon. `wx --json version` and `/v1/status` expose the runtime and account capabilities; unsupported official schemas fail explicitly.
4
4
 
5
5
  ## Installation
6
6
 
@@ -51,6 +51,21 @@ wx auth login --official=/absolute/official-profile
51
51
 
52
52
  The daemon binds the stored identity, attempts saved-device login and derives verified database keys after authentication. The official app stays closed while this daemon owns the files.
53
53
 
54
+ Recall an own message using its opaque message ID and exact decimal-string
55
+ server ID from history or a verified send receipt:
56
+
57
+ ```bash
58
+ wx --account example messages recall MESSAGE_ID --server-id SERVER_ID
59
+ wx --account example operations get OPERATION_ID
60
+ ```
61
+
62
+ Use `--detach` to return the durable operation immediately. A private receipt is
63
+ written before submission; the same target uses a stable default idempotency
64
+ key. An uncertain result exits8 and must be inspected rather than automatically
65
+ resubmitted. WeChat decides eligibility, and stopping the watcher does not cancel
66
+ the recall. Recalled messages remain as placeholders; their media is unavailable
67
+ through the daemon. Raw journals, cached files and backups are retained.
68
+
54
69
  Lower-level registration and experimental profile copies are also available:
55
70
 
56
71
  ```bash
@@ -88,3 +103,5 @@ Deployment examples and the deliberate release preparation sequence are in [depl
88
103
  `native-install.mjs` runs during npm installation, or through `wx-native-install` for offline/disabled-script installs. It selects the host architecture, checks the npm-bundled hash and verifies executable identity before atomic installation. `native-launcher.mjs` only runs an already installed executable.
89
104
 
90
105
  `native-check-package.mjs` is the prepack/prepublish gate. It checks version/source/target/checksum metadata; before publication it additionally requires both architecture assets to exist and match the package's manifest. A local pack smoke can use one architecture fragment; publication requires the complete matrix. These helpers belong to the existing CLI package, not additional npm packages.
106
+
107
+ Candidate platform validation and remaining profile boundaries are tracked in [the acceptance checklist](../../dev-notes/native-platform-acceptance.md). Windows executables are named `wx.exe`; the npm launcher chooses the OS/CPU-specific asset. A native ARM64 Node installation selects the native Windows ARM64 executable.
@@ -1,29 +1,53 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "1.0.0-beta.8",
3
+ "version": "1.0.0-beta.9",
4
4
  "repository": "thisnick/agent-wechat",
5
- "sourceCommit": "79280a734fae9fab54bc045b56fdffd508d5f3eb",
5
+ "sourceCommit": "6b2034a16697731d08b70d6051382469f630cc79",
6
6
  "sourceTreeDirty": false,
7
7
  "assets": [
8
8
  {
9
- "name": "wx-v1.0.0-beta.8-linux-arm64-gnu",
9
+ "name": "wx-v1.0.0-beta.9-darwin-arm64",
10
+ "platform": "darwin",
11
+ "arch": "arm64",
12
+ "rustTarget": "aarch64-apple-darwin",
13
+ "bytes": 23752464,
14
+ "sha256": "9e0ceb7aad4d00ab027630f4457e2d2f4b696226987242643e0e9c14801a2abb"
15
+ },
16
+ {
17
+ "name": "wx-v1.0.0-beta.9-linux-arm64-gnu",
10
18
  "platform": "linux",
11
19
  "arch": "arm64",
12
20
  "libc": "gnu",
13
21
  "minimumGlibc": "2.36",
14
22
  "rustTarget": "aarch64-unknown-linux-gnu",
15
- "bytes": 27093520,
16
- "sha256": "4c78ba866d3ae8c74d4404f417fff89943f7658b3c2a3d8c165cbad2279d9a14"
23
+ "bytes": 27797968,
24
+ "sha256": "0e21f34c74a5dd6ebe8375f3ffb1c66fd5cdde48b67ac2e4033af8e74acc5e0f"
17
25
  },
18
26
  {
19
- "name": "wx-v1.0.0-beta.8-linux-x64-gnu",
27
+ "name": "wx-v1.0.0-beta.9-linux-x64-gnu",
20
28
  "platform": "linux",
21
29
  "arch": "x64",
22
30
  "libc": "gnu",
23
31
  "minimumGlibc": "2.36",
24
32
  "rustTarget": "x86_64-unknown-linux-gnu",
25
- "bytes": 28757872,
26
- "sha256": "fde2920e71e0e20b926498b8c306a5064527afa5abd2b558eff9cefa0cce478e"
33
+ "bytes": 29494920,
34
+ "sha256": "dad1fd67b3f9581455c01e2d932193864e9f7c9640fdf7bea5a3bd7cd69f5147"
35
+ },
36
+ {
37
+ "name": "wx-v1.0.0-beta.9-win32-arm64.exe",
38
+ "platform": "win32",
39
+ "arch": "arm64",
40
+ "rustTarget": "aarch64-pc-windows-msvc",
41
+ "bytes": 21413888,
42
+ "sha256": "c23179ceb347e258ccf6229cbd2b92ab3eaffba6761f4a0532eafce9f1049be7"
43
+ },
44
+ {
45
+ "name": "wx-v1.0.0-beta.9-win32-x64.exe",
46
+ "platform": "win32",
47
+ "arch": "x64",
48
+ "rustTarget": "x86_64-pc-windows-msvc",
49
+ "bytes": 25868800,
50
+ "sha256": "ffd236eff7e496c82b5009e3993d33a5ed04726a5aa37407f19b38870c4c8d96"
27
51
  }
28
52
  ]
29
53
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-wechat/cli",
3
- "version": "1.0.0-beta.8",
3
+ "version": "1.0.0-beta.9",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wx": "./scripts/native-launcher.mjs",
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  // prepack checks bundled metadata; prepublishOnly additionally verifies the
3
3
  // complete, already published executable matrix before npm can be published.
4
- import { fetchBytes, manifestName, readManifest, releaseUrl, validateManifest, verifyBytes } from './native-runtime.mjs';
4
+ import { fetchBytes, targetKey, manifestName, readManifest, releaseUrl, validateManifest, verifyBytes } from './native-runtime.mjs';
5
5
  const { manifest, asset } = await readManifest();
6
6
  if (process.env.GITHUB_SHA && manifest.sourceCommit !== process.env.GITHUB_SHA) throw new Error('Native manifest source commit differs from publication commit');
7
7
  if (process.argv.includes('--publication')) {
@@ -13,7 +13,7 @@ if (process.argv.includes('--publication')) {
13
13
  validateManifest(remote, manifest.version, { requireAllTargets: true });
14
14
  if (remote.sourceCommit !== manifest.sourceCommit || remote.sourceTreeDirty === true) throw new Error('Prepared release differs from this npm package');
15
15
  for (const item of manifest.assets) {
16
- const published = remote.assets.find(candidate => candidate.arch === item.arch);
16
+ const published = remote.assets.find(candidate => targetKey(candidate) === targetKey(item));
17
17
  if (published.sha256 !== item.sha256 || published.bytes !== item.bytes) throw new Error('Prepared release differs from this npm package');
18
18
  verifyBytes(await fetchBytes(releaseUrl(manifest.version, item.name), item.bytes), item);
19
19
  }
@@ -12,20 +12,28 @@ export const releaseRepository = 'thisnick/agent-wechat';
12
12
  export const supportedTargets = Object.freeze([
13
13
  Object.freeze({ platform: 'linux', arch: 'x64', libc: 'gnu', minimumGlibc: '2.36', rustTarget: 'x86_64-unknown-linux-gnu' }),
14
14
  Object.freeze({ platform: 'linux', arch: 'arm64', libc: 'gnu', minimumGlibc: '2.36', rustTarget: 'aarch64-unknown-linux-gnu' }),
15
+ Object.freeze({ platform: 'darwin', arch: 'arm64', rustTarget: 'aarch64-apple-darwin' }),
16
+ Object.freeze({ platform: 'win32', arch: 'x64', rustTarget: 'x86_64-pc-windows-msvc' }),
17
+ Object.freeze({ platform: 'win32', arch: 'arm64', rustTarget: 'aarch64-pc-windows-msvc' }),
15
18
  ]);
16
19
  export const supportedTarget = supportedTargets[0];
17
20
  const maxBinaryBytes = 256 * 1024 * 1024;
18
21
  const allowedDownloadHosts = new Set(['github.com', 'release-assets.githubusercontent.com', 'objects.githubusercontent.com']);
19
22
 
23
+ export function targetKey(target) { return [target.platform, target.arch, target.libc].filter(Boolean).join('-'); }
24
+ export function executableName(target = targetFor()) { return target.platform === 'win32' ? 'wx.exe' : 'wx'; }
20
25
  export function targetFor({ platform = process.platform, arch = process.arch, glibc = process.report?.getReport().header.glibcVersionRuntime } = {}) {
21
- const [major, minor] = String(glibc ?? '').split('.').map(Number);
22
26
  const target = supportedTargets.find(item => item.platform === platform && item.arch === arch);
23
- if (!target || !glibc || !Number.isFinite(major) || !Number.isFinite(minor) || major < 2 || (major === 2 && minor < 36)) {
24
- throw new Error('Native wx requires Linux x64 or ARM64 with glibc 2.36 or newer. Install a supported native runtime or connect remotely to its API.');
27
+ if (!target) throw new Error(`Unsupported native wx platform: ${platform}-${arch}`);
28
+ if (platform === 'linux') {
29
+ const [major, minor] = String(glibc ?? '').split('.').map(Number);
30
+ if (!glibc || !Number.isFinite(major) || !Number.isFinite(minor) || major < 2 || (major === 2 && minor < 36)) {
31
+ throw new Error('Native wx on Linux requires glibc 2.36 or newer; musl is unsupported.');
32
+ }
25
33
  }
26
34
  return target;
27
35
  }
28
- export function assetName(version, target = targetFor()) { return `wx-v${version}-${target.platform}-${target.arch}-${target.libc}`; }
36
+ export function assetName(version, target = targetFor()) { return `wx-v${version}-${targetKey(target)}${target.platform === 'win32' ? '.exe' : ''}`; }
29
37
  export function manifestName(version) { return `wx-v${version}-checksums.json`; }
30
38
  export function releaseUrl(version, name) {
31
39
  return `https://github.com/${releaseRepository}/releases/download/v${version}/${name}`;
@@ -38,17 +46,17 @@ export function validateManifest(manifest, version, { target = targetFor(), requ
38
46
  }
39
47
  const seen = new Set();
40
48
  for (const asset of manifest.assets) {
41
- const expected = supportedTargets.find(item => item.arch === asset.arch);
42
- if (!expected || seen.has(asset.arch) || Object.entries(expected).some(([key, value]) => asset[key] !== value)
49
+ const expected = supportedTargets.find(item => targetKey(item) === targetKey(asset));
50
+ if (!expected || seen.has(targetKey(asset)) || Object.entries(expected).some(([key, value]) => asset[key] !== value)
43
51
  || asset.name !== assetName(version, expected) || !/^[a-f0-9]{64}$/.test(asset.sha256 ?? '')
44
52
  || !Number.isSafeInteger(asset.bytes) || asset.bytes < 1 || asset.bytes > maxBinaryBytes) {
45
53
  throw new Error('Invalid native release asset, duplicate or unsupported target');
46
54
  }
47
- seen.add(asset.arch);
55
+ seen.add(targetKey(asset));
48
56
  }
49
57
  if (requireAllTargets && seen.size !== supportedTargets.length) throw new Error('Native publication requires every supported target');
50
- const asset = manifest.assets.find(item => item.arch === target.arch);
51
- if (!asset) throw new Error(`Native manifest has no asset for ${target.arch}`);
58
+ const asset = manifest.assets.find(item => targetKey(item) === targetKey(target));
59
+ if (!asset) throw new Error(`Native manifest has no asset for ${targetKey(target)}`);
52
60
  return asset;
53
61
  }
54
62
  export async function readManifest(root = packageRoot) {
@@ -112,7 +120,7 @@ export async function inspectBinary(path, version) {
112
120
  }
113
121
  return value;
114
122
  }
115
- export function installPath(root, version, target = targetFor()) { return join(root, 'native', version, `${target.platform}-${target.arch}-${target.libc}`, 'wx'); }
123
+ export function installPath(root, version, target = targetFor()) { return join(root, 'native', version, targetKey(target), executableName(target)); }
116
124
  export async function installNative({ root = packageRoot, artifactDir, fetchOptions, downloadUrl, inspect = inspectBinary } = {}) {
117
125
  targetFor();
118
126
  const { version, asset } = await readManifest(root);
@@ -135,7 +143,7 @@ export async function installNative({ root = packageRoot, artifactDir, fetchOpti
135
143
  verifyBytes(bytes, asset);
136
144
  const destination = installPath(root, version);
137
145
  await mkdir(dirname(destination), { recursive: true, mode: 0o755 });
138
- const temporary = `${destination}.${process.pid}.${createHash('sha256').update(randomUUID()).digest('hex').slice(0, 16)}.tmp`;
146
+ const temporary = `${destination}.${process.pid}.${createHash('sha256').update(randomUUID()).digest('hex').slice(0, 16)}.tmp${process.platform === 'win32' ? '.exe' : ''}`;
139
147
  try {
140
148
  await writeFile(temporary, bytes, { flag: 'wx', mode: 0o755 });
141
149
  await chmod(temporary, 0o755);
@@ -166,7 +174,11 @@ export function runNative(path, args, { spawnImpl = spawn, processObject = proce
166
174
  const child = spawnImpl(path, args, { stdio: 'inherit', shell: false, windowsHide: true });
167
175
  const handlers = new Map();
168
176
  for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP']) {
169
- const handler = () => { if (!child.killed) child.kill(signal); };
177
+ const handler = () => {
178
+ // Windows broadcasts console Ctrl+C to both processes; Node's kill(SIGINT)
179
+ // would terminate the child before Rust can finish graceful shutdown.
180
+ if (!child.killed && !(process.platform === 'win32' && signal === 'SIGINT')) child.kill(signal);
181
+ };
170
182
  handlers.set(signal, handler);
171
183
  processObject.on(signal, handler);
172
184
  }