@twinsearth/w2m-dsh-plugin 2.2.3 → 2.2.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.
@@ -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.2.3"
8
+ "version": "2.2.5"
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.2.3",
15
+ "version": "2.2.5",
16
16
  "author": {
17
17
  "name": "TwinsEarth"
18
18
  },
@@ -26,5 +26,5 @@
26
26
  ]
27
27
  }
28
28
  ],
29
- "version": "2.2.3"
29
+ "version": "2.2.5"
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.2.3",
4
+ "version": "2.2.5",
5
5
  "author": {
6
6
  "name": "TwinsEarth"
7
7
  },
package/CHANGELOG.md CHANGED
@@ -4,9 +4,38 @@ All notable changes to this project are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.2.5] - 2026-11-12
8
+
9
+ - DSH 0.2.2-rc.2 compatibility, measured rather than assumed: the packed artifact mounts and boots in
10
+ the rc.2 runtime (`@deepseek-ai/dsh@0.2.2-rc.2`) with every host entry active, all `w2m_*` tools
11
+ registered, the browser half composed into `__DSH_BOOT__` and activated, the real page booting in a
12
+ browser, and the Node-execution menu opening and taking temporary execution from the composer.
13
+ - The compatibility gate now pins that host: `DSH_HOST_VERSION` moves from `0.2.0-rc.2` to
14
+ `0.2.2-rc.2`, with the Cordis versions that release carries (`@deepseek-ai/cordis@4.1.0`,
15
+ `@deepseek-ai/cordis-plugin-loader@1.1.0`) and the pnpm the runtime bundles (`11.28.5`). The gate is
16
+ what turns "the host moved" into a measurement instead of a surprise.
17
+ - `package.json#engines.dsh` is declared for the first time: `>=0.2.0 <0.3.0`. The requirement is read
18
+ before any plugin code loads, so a host outside the line is refused with a named requirement instead
19
+ of failing later. Prereleases participate in the range (DSH evaluates it with `includePrerelease`),
20
+ which is why `0.2.2-rc.2` and `0.2.2-rc.1` both satisfy it; declaring `engines.dsh` also means the
21
+ old `@deepseek-ai/dsh-*` peer fallback no longer decides compatibility for this package.
22
+ - Reviewed the two rc.2 changes an extension could depend on, and neither needs this package to move:
23
+ tool failures now carry structured identity (`ToolGuardDenial.info`, `ToolContextUnavailableError`,
24
+ approval and context error codes) but this package registers no `tools` guards and already returns a
25
+ named refusal reason, so the change is additive from here; and plugins can register MCP servers for
26
+ their own lifetime through `ctx.mcpManager`, which this package deliberately does **not** do — its
27
+ bundled `w2m-mcp` server mirrors the same `w2m_*` tools for codex/Claude hosts, so mounting it inside
28
+ DSH would register every tool twice.
7
29
  - `w2m_intent`: structured intents mapped onto allow-listed commands; unknown actions, parameters and types
8
30
  are refused by name (the fleet does not invent commands).
9
31
 
32
+ ## [2.2.4] - 2026-11-05
33
+
34
+ - Fixes the remote desktop `HTTP 404`: a default desktop profile leaves `stateDir` empty, and
35
+ the remote-view route registration returned not-mounted in that case. The host now resolves
36
+ the same `~/.dsh/xclient` directory the agent uses, so `/api/w2m/remote/config|start|frame|stop`
37
+ are mounted and the settings toggle works without configuring `stateDir` by hand.
38
+ - Remote-view route coverage now includes the default-stateDir mount path.
10
39
  ## [2.2.3] - 2026-11-05
11
40
 
12
41
  - Remote desktop (view-only) now reaches 1 frame per second in a fleet. A machine opts in by
package/README.md CHANGED
@@ -93,7 +93,7 @@ w2m-mcp --help
93
93
  # 复制进你自己的 codex/mcp-servers.toml
94
94
  [mcp_servers.w2m]
95
95
  command = "npx"
96
- args = ["-y", "@twinsearth/w2m-dsh-plugin@2.2.3", "w2m-mcp"]
96
+ args = ["-y", "@twinsearth/w2m-dsh-plugin@2.2.5", "w2m-mcp"]
97
97
  ```
98
98
 
99
99
  ### 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.2.3", "w2m-mcp"]
15
+ args = ["-y", "-p", "@twinsearth/w2m-dsh-plugin@2.2.5", "w2m-mcp"]
16
16
  startup_timeout_sec = 20
17
17
  tool_timeout_sec = 60
@@ -0,0 +1,32 @@
1
+ {
2
+ "version": "2.2.4",
3
+ "case": "RELEASE-2240",
4
+ "kind": "positive",
5
+ "machines": [
6
+ "b53a37f4-1464-4512-9259-33a7df091e3e"
7
+ ],
8
+ "executed_at": "2026-11-05T15:10:00.000Z",
9
+ "executor": "lead",
10
+ "task_id": "pre-release-2240",
11
+ "requirement": "v2.2.4: remote-view host routes mount on a default desktop profile whose stateDir is unset, so the settings toggle and /api/w2m/remote/{config,start,frame,stop} no longer return HTTP 404",
12
+ "commands": [
13
+ ["node", "--test", "--test-force-exit", "test/remote-view-route.test.mjs", "test/view-consent.test.mjs", "test/view-frame-channel.test.mjs", "test/relay-target.test.mjs", "test/client-bundle.test.mjs"],
14
+ ["node", "scripts/check-entrypoints.mjs"],
15
+ ["node", "--test", "--test-force-exit", "test/loader-entry.test.mjs"]
16
+ ],
17
+ "result": {
18
+ "outcome": "ok",
19
+ "assertions": {
20
+ "remote_view": "test/remote-view-route.test.mjs 4/4: default-stateDir mount, P2P session, P2P refusal, and relay refresh",
21
+ "consent": "test/view-consent.test.mjs 4/4",
22
+ "p2p": "test/view-frame-channel.test.mjs 4/4",
23
+ "relay": "test/relay-target.test.mjs 3/3",
24
+ "client": "test/client-bundle.test.mjs 36/36",
25
+ "entrypoints": "node scripts/check-entrypoints.mjs: all entry points PASS",
26
+ "loader": "test/loader-entry.test.mjs 10/10 against the packed 2.2.4 artifact in the real DSH 0.2.2-rc.1 Loader and Edge page",
27
+ "root_cause": "registerRemoteViewRoutes returned { mounted: false, reason: 'stateDir is not configured' } when cfg.stateDir was empty; no /api/w2m/remote/* route existed",
28
+ "fix": "resolveStateDir(null, '') resolves ~/.dsh/xclient, matching the agent's default state directory",
29
+ "scope": "code and tests only; no profile was edited by the tests; npm publish is separate"
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "version": "2.2.5",
3
+ "case": "RELEASE-2250",
4
+ "kind": "positive",
5
+ "machines": ["b53a37f4-1464-4512-9259-33a7df091e3e"],
6
+ "executed_at": "2026-11-12T12:43:04Z",
7
+ "executor": "lead",
8
+ "task_id": "pre-release-2250",
9
+ "requirement": "v2.2.5: the packed artifact mounts and boots in DSH 0.2.2-rc.2 (host entries active, all w2m_* tools registered, browser half composed and activated, real page boots, composer menus usable), and package.json#engines.dsh declares the supported host range before any plugin code loads",
10
+ "commands": [
11
+ ["node", "scripts/pack.mjs"],
12
+ ["node", "test/helpers/dsh-loader-driver.mjs", "<harnessRoot>", "<dshHome>", "w2mrc2", "[\"--port\",\"0\",\"--no-open\"]", "<overlay>"],
13
+ ["node", "--test", "--test-force-exit", "test/loader-entry.test.mjs"],
14
+ ["node", "--test", "--test-force-exit", "test/installed-version.test.mjs", "test/evidence.test.mjs", "test/claims.test.mjs", "test/agent-plugins.test.mjs"],
15
+ ["node", "scripts/preflight.mjs"]
16
+ ],
17
+ "result": {
18
+ "outcome": "ok",
19
+ "assertions": {
20
+ "host": "DSH 0.2.2-rc.2 (@deepseek-ai/dsh@0.2.2-rc.2 installed from npm; cordis 4.1.0, cordis-plugin-loader 1.1.0, cordis-plugin-group 1.1.0 resolved by that tree)",
21
+ "loader": "drive the packed 2.2.5 artifact through the real Loader in a web profile: 177 entries active, 0 failed fibers, the w2m row active, 23 tools registered through the tools service projection",
22
+ "client_host_half": "the real clientModules registry accepted the package's dsh.client declaration and composed a boot-graph row for @twinsearth/w2m-dsh-plugin from the shipped lib/client.js",
23
+ "client_activation": "the real client module system plus a real Cordis fiber activated the entry (state active, no error) and it took 16 composer/sidebar/settings seats",
24
+ "client_page": "the profile's Web app booted in headless Edge against the real server: the package stylesheet arrived, the boot overlay was dismissed, and no entry reported a boot failure",
25
+ "composer_control": "the Node-execution menu opened from the composer with three options, and selecting temporary execution updated the control to 'Node-execution: temporary 24h, 24h left' with data-on=true and no error note",
26
+ "routes": "w2m_status reports target_selection.attached=true and the live connection registry holds 25 fetch routes, including /api/w2m/target, /api/w2m/capability and the four /api/w2m/remote/* routes",
27
+ "engines_dsh": "package.json#engines.dsh is '>=0.2.0 <0.3.0'; DSH evaluates it with includePrerelease, so 0.2.2-rc.1 and 0.2.2-rc.2 both satisfy it, and the packed tarball installed into the rc.2 profile without a compatibility refusal",
28
+ "compat_gate": "compat.yml pins DSH_HOST_VERSION 0.2.2-rc.2 with cordis 4.1.0 / cordis-plugin-loader 1.1.0 / pnpm 11.28.5; the pin is the release gate's measurement of this host",
29
+ "not_adopted": "rc.2 lets a plugin register MCP servers through ctx.mcpManager; this package does not, because its bundled w2m-mcp server mirrors the same w2m_* tools for codex and Claude hosts, so mounting it inside DSH would register every tool twice",
30
+ "artifact": "scripts/pack.mjs packs dist/twinsearth-w2m-dsh-plugin-2.2.5.tgz deterministically from this tree; the published sha256 is the one release.yml writes into dist/SHA256SUMS beside the tarball, so the artifact digest is not restated here -- a record that named its own tarball's hash would be inside the tarball it describes",
31
+ "scope": "code, tests, manifests and docs; the probe profile and the rc.2 runtime live under a temporary directory, and publishing is a separate workflow run"
32
+ }
33
+ }
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twinsearth/w2m-dsh-plugin",
3
- "version": "2.2.3",
3
+ "version": "2.2.5",
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": {
@@ -58,7 +58,8 @@
58
58
  "locale"
59
59
  ],
60
60
  "engines": {
61
- "node": ">=20.19.0"
61
+ "node": ">=20.19.0",
62
+ "dsh": ">=0.2.0 <0.3.0"
62
63
  },
63
64
  "license": "MIT",
64
65
  "scripts": {
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.2.3",
4
+ "version": "2.2.5",
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": [
@@ -12,6 +12,7 @@ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
12
12
  import { dirname, join } from 'node:path';
13
13
  import { captureHostScreen } from './capture-route.mjs';
14
14
  import { createViewSide, openViewFrame } from '../agent/view/session-key.mjs';
15
+ import { resolveStateDir } from '../util/cli.mjs';
15
16
 
16
17
  export const REMOTE_CONFIG_PATH = '/api/w2m/remote/config';
17
18
  export const REMOTE_FRAME_PATH = '/api/w2m/remote/frame';
@@ -43,8 +44,13 @@ function payloadJson(payload) {
43
44
  export function registerRemoteViewRoutes(ctx, deps = {}) {
44
45
  const status = { mounted: false, reason: 'the host has no Connection service', configPath: null };
45
46
  if (typeof ctx?.inject !== 'function') return status;
46
- if (typeof deps.stateDir !== 'string' || deps.stateDir === '') { status.reason = 'stateDir is not configured'; return status; }
47
- const file = join(deps.stateDir, 'remote-view.json');
47
+ // stateDir is unset on a default desktop profile. That must not silently remove the
48
+ // remote-view routes: the settings toggle and every /api/w2m/remote/* call would 404.
49
+ // Resolve the same default the agent uses so consent lives beside device.json.
50
+ const stateDir = typeof deps.stateDir === 'string' && deps.stateDir !== ''
51
+ ? deps.stateDir
52
+ : resolveStateDir(null, '');
53
+ const file = join(stateDir, 'remote-view.json');
48
54
  const capture = deps.capture ?? captureHostScreen;
49
55
  const platform = deps.platform ?? process.platform;
50
56
  const p2p = deps.p2p ?? null;
@@ -296,7 +296,7 @@ const MAX_STAGES = 16;
296
296
  * `package.json` during `scripts/pack.mjs` rather than hand-maintained, and `W2M_PLUGIN_VERSION`
297
297
  * overrides it at runtime for tests and packagers.
298
298
  */
299
- const PLUGIN_VERSION = '2.2.3';
299
+ const PLUGIN_VERSION = '2.2.5';
300
300
 
301
301
  /** How long any single HTTP call may take before it is aborted, in milliseconds. */
302
302
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;