@twinsearth/w2m-dsh-plugin 2.1.10 → 2.1.11

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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "The w2m fleet plugins: one account, many machines, any of Windows, macOS or Linux.",
8
- "version": "2.1.10"
8
+ "version": "2.1.11"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "w2m-fleet",
13
13
  "source": "./",
14
14
  "description": "Read fleet state and dispatch commands across the machines registered to one account. Read-only MCP surface: the five exposed tools cannot change anything.",
15
- "version": "2.1.10",
15
+ "version": "2.1.11",
16
16
  "author": {
17
17
  "name": "TwinsEarth"
18
18
  },
@@ -26,5 +26,5 @@
26
26
  ]
27
27
  }
28
28
  ],
29
- "version": "2.1.10"
29
+ "version": "2.1.11"
30
30
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "w2m-fleet",
3
3
  "description": "Drive the same project on online Windows, macOS and Linux machines from one account: read fleet state, dispatch commands and read results. The MCP surface is deliberately read-only.",
4
- "version": "2.1.10",
4
+ "version": "2.1.11",
5
5
  "author": {
6
6
  "name": "TwinsEarth"
7
7
  },
package/CHANGELOG.md CHANGED
@@ -7,6 +7,11 @@ All notable changes to this project are documented here.
7
7
  - `w2m_intent`: structured intents mapped onto allow-listed commands; unknown actions, parameters and types
8
8
  are refused by name (the fleet does not invent commands).
9
9
 
10
+ ## [2.1.11] - 2026-11-01
11
+
12
+ - Account switch: refresh the account profile when `getDeviceIdentity()` has no userId. After a DeepSeek account switch the host clears its cached profile, so the identity read returns no userId until someone calls `getProfile()`; the plugin then derived no new fleet key and kept the previous account's token. It now fetches the profile once, derives the new key, detects the fleet mismatch and re-pairs. This is the remaining half of the v2.1.10 account-switch fix.
13
+ - Tests: a stale-profile service yields the switched account's fleet key in test/chatops-account.test.mjs.
14
+
10
15
  ## [2.1.10] - 2026-11-01
11
16
 
12
17
  - Fleet binding: a DeepSeek account switch now re-pairs the machine instead of leaving it in the previous account's fleet. Startup compares the relay's fleet_id with the fleet id derived from the signed-in account, and a 60s watcher covers a switch without a process restart. A stored token is only valid for the account that minted it; it is no longer treated as proof of the current account.
package/README.md CHANGED
@@ -92,7 +92,7 @@ w2m-mcp --help
92
92
  # 复制进你自己的 codex/mcp-servers.toml
93
93
  [mcp_servers.w2m]
94
94
  command = "npx"
95
- args = ["-y", "@twinsearth/w2m-dsh-plugin@2.1.10", "w2m-mcp"]
95
+ args = ["-y", "@twinsearth/w2m-dsh-plugin@2.1.11", "w2m-mcp"]
96
96
  ```
97
97
 
98
98
  ### 5. 验证过的 release tarball(离线)
@@ -12,6 +12,6 @@
12
12
 
13
13
  [mcp_servers.w2m-fleet]
14
14
  command = "npx"
15
- args = ["-y", "-p", "@twinsearth/w2m-dsh-plugin@2.1.10", "w2m-mcp"]
15
+ args = ["-y", "-p", "@twinsearth/w2m-dsh-plugin@2.1.11", "w2m-mcp"]
16
16
  startup_timeout_sec = 20
17
17
  tool_timeout_sec = 60
@@ -0,0 +1,20 @@
1
+ {
2
+ "version": "2.1.11",
3
+ "case": "ACCOUNT-SWITCH-PROFILE-21110",
4
+ "kind": "positive",
5
+ "machines": [
6
+ "1bef9935-8c13-4dd9-9043-4e025320723f"
7
+ ],
8
+ "executed_at": "2026-10-31T19:11:34.238Z",
9
+ "executor": "lead",
10
+ "task_id": "account-switch-profile-21110-1793473894239",
11
+ "requirement": "After a DeepSeek account switch the plugin must refresh the cleared profile, derive the new fleet key and re-pair instead of keeping the previous fleet token",
12
+ "result": {
13
+ "outcome": "ok",
14
+ "assertions": {
15
+ "refresh": "identify() calls getProfile when getDeviceIdentity has no userId",
16
+ "key": "the switched account yields a different fleetKey",
17
+ "rebind": "the v2.1.10 fleet mismatch check then re-pairs"
18
+ }
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twinsearth/w2m-dsh-plugin",
3
- "version": "2.1.10",
3
+ "version": "2.1.11",
4
4
  "description": "Run one project across your own Windows and macOS machines from a single DeepSeek account, through 11 w2m_* tools. Four coordination modes (replicate, split, broadcast, pipeline) and six aggregate verdicts (consistent, divergent, divergent-platform, failed, partial, unverifiable). P2P hole punching by default, with a bundled relay, STUN responder and ledger fallback, so the fleet needs no third-party service. Joining needs a pairing code plus autoStartAgent: true; installing alone does not join.",
5
5
  "type": "module",
6
6
  "exports": {
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "twinsearth-w2m-dsh",
4
- "version": "2.1.10",
4
+ "version": "2.1.11",
5
5
  "description": "Run one project across your own Windows and macOS machines from a single DeepSeek account, through 12 w2m_* tools. Four coordination modes (replicate, split, broadcast, pipeline) and six aggregate verdicts (consistent, divergent, divergent-platform, failed, partial, unverifiable). P2P hole punching by default, with a bundled relay, STUN responder and ledger fallback, so the fleet needs no third-party service. Joining needs a pairing code plus autoStartAgent: true; installing alone does not join.",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -300,6 +300,23 @@ export function createAccountIdentity(options = {}) {
300
300
  let identity;
301
301
  try {
302
302
  identity = await service.getDeviceIdentity();
303
+ /**
304
+ * A switched account is invisible until the profile is fetched.
305
+ *
306
+ * `getDeviceIdentity()` reads `getPlatformSession().userId`, and that is only populated
307
+ * from a profile already cached for the current grant. After credentials/record-updated
308
+ * the old profile is discarded and the session's userId is null until someone calls
309
+ * `getProfile()`. A machine that was paired before the switch therefore derived no new
310
+ * fleet key and kept its old token -- the reported "still in the previous account's
311
+ * fleet" state. Fetch the profile once when the identity is missing; the second read then
312
+ * sees the new account.
313
+ */
314
+ if ((identity?.userId == null) && typeof service.getProfile === 'function') {
315
+ try {
316
+ await service.getProfile();
317
+ identity = await service.getDeviceIdentity();
318
+ } catch { /* keep the signed-out answer if the profile cannot be read */ }
319
+ }
303
320
  } catch (error) {
304
321
  return { ok: false, reason: 'identity_read_failed', detail: error instanceof Error ? error.message : String(error) };
305
322
  }
@@ -293,7 +293,7 @@ const MAX_STAGES = 16;
293
293
  * `package.json` during `scripts/pack.mjs` rather than hand-maintained, and `W2M_PLUGIN_VERSION`
294
294
  * overrides it at runtime for tests and packagers.
295
295
  */
296
- const PLUGIN_VERSION = '2.1.10';
296
+ const PLUGIN_VERSION = '2.1.11';
297
297
 
298
298
  /** How long any single HTTP call may take before it is aborted, in milliseconds. */
299
299
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;