@qping/plugin-bus 0.9.0 → 0.11.0

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.
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * v3 Node SDK bootstrap entry. Reads the bootstrap line from stdin (pipePath\ttoken), connects to
3
- * the named pipe, completes bus.handshake (presenting the token and receiving bound identity),
4
- * and starts a HandlerRouter stamped with that identity.
3
+ * the named pipe, completes bus.handshake by presenting the token, and starts a HandlerRouter.
5
4
  *
6
5
  * This mirrors the C# NodeProcessController's spawn contract: the host writes one line to the
7
6
  * Node process's stdin — "<pipePath>\t<token>" — then waits for the Node side to connect the pipe
@@ -25,11 +24,7 @@ export interface PluginRuntime {
25
24
  */
26
25
  export declare function runPlugin(handlers: PluginHandlers): Promise<PluginRuntime>;
27
26
  /**
28
- * Sends bus.handshake with the bootstrap token and waits for the host response that binds
29
- * plugin/session/endpoint identity. Rejects on HandshakeFailed / ProtocolMismatch / timeout.
27
+ * Sends bus.handshake with the bootstrap token and waits for host acknowledgement.
28
+ * Protocol compatibility has already been checked from the manifest before process startup.
30
29
  */
31
- export declare function completeHandshake(transport: NodeTransport, token: string, timeoutMs?: number): Promise<{
32
- pluginId: string;
33
- sessionId: string;
34
- endpointId: string;
35
- }>;
30
+ export declare function completeHandshake(transport: NodeTransport, token: string, timeoutMs?: number): Promise<void>;
@@ -139,10 +139,6 @@ var ErrorCode = {
139
139
  RateLimited: "RateLimited"
140
140
  };
141
141
  var ProtocolVersion = "3.0";
142
- var EndpointIds = {
143
- NodeMain: "node-main",
144
- Host: "host"
145
- };
146
142
  var Routes = {
147
143
  Bus: {
148
144
  Handshake: "bus.handshake",
@@ -294,20 +290,11 @@ function deadlineFromTimeoutMs(timeoutMs) {
294
290
  var HandlerRouter = class {
295
291
  handlers = /* @__PURE__ */ new Map();
296
292
  pendingHostCalls = /* @__PURE__ */ new Map();
297
- pluginId = "p";
298
- sessionId = "s";
299
- endpointId = EndpointIds.NodeMain;
300
293
  /** Injected transport send fn; tests can override `router.send` directly. */
301
294
  send;
302
295
  constructor(deps) {
303
296
  this.send = deps.send;
304
297
  }
305
- /** Sets the bound identity stamped on outbound messages (after handshake). */
306
- setIdentity(ids) {
307
- this.pluginId = ids.pluginId;
308
- this.sessionId = ids.sessionId;
309
- this.endpointId = ids.endpointId;
310
- }
311
298
  handle(route, handler) {
312
299
  this.handlers.set(route, handler);
313
300
  }
@@ -351,9 +338,9 @@ var HandlerRouter = class {
351
338
  version: ProtocolVersion,
352
339
  id,
353
340
  traceId: id,
354
- sessionId: this.sessionId,
355
- pluginId: this.pluginId,
356
- endpointId: this.endpointId,
341
+ sessionId: "",
342
+ pluginId: "",
343
+ endpointId: "",
357
344
  kind: MessageKind.Request,
358
345
  route,
359
346
  timeoutMs: effectiveTimeoutMs,
@@ -397,9 +384,9 @@ var HandlerRouter = class {
397
384
  id: randomBytesHex(),
398
385
  correlationId: req.id,
399
386
  traceId: req.traceId,
400
- sessionId: req.sessionId,
401
- pluginId: req.pluginId,
402
- endpointId: this.endpointId,
387
+ sessionId: "",
388
+ pluginId: "",
389
+ endpointId: "",
403
390
  kind: MessageKind.Response,
404
391
  route: req.route,
405
392
  payload
@@ -418,29 +405,16 @@ function randomBytesHex() {
418
405
  }
419
406
 
420
407
  // src/bootstrap.ts
421
- var SUPPORTED_VERSIONS = [ProtocolVersion];
422
408
  async function runPlugin(handlers) {
423
409
  const { pipePath, token } = await readBootstrapLine();
424
410
  const transport = new NodeTransport();
425
411
  await transport.connect(pipePath);
426
- const identity = await completeHandshake(transport, token);
412
+ await completeHandshake(transport, token);
427
413
  const router = new HandlerRouter({ send: (env) => transport.send(env) });
428
- router.setIdentity(identity);
429
- const HOST_LOST_MS = 15e3;
430
- let lastPingAt = Date.now();
431
- const watchdog = setInterval(() => {
432
- if (Date.now() - lastPingAt > HOST_LOST_MS) {
433
- clearInterval(watchdog);
434
- process.exit(1);
435
- }
436
- }, 1e3);
437
- watchdog.unref?.();
438
414
  transport.onDisconnect(() => {
439
- clearInterval(watchdog);
440
415
  process.exit(1);
441
416
  });
442
417
  transport.onMessage((env) => {
443
- if (env.route === Routes.Bus.Ping) lastPingAt = Date.now();
444
418
  router.dispatch(env);
445
419
  });
446
420
  for (const [route, handler] of Object.entries(handlers)) {
@@ -450,7 +424,6 @@ async function runPlugin(handlers) {
450
424
  transport,
451
425
  router,
452
426
  close: async () => {
453
- clearInterval(watchdog);
454
427
  await transport.close();
455
428
  }
456
429
  };
@@ -479,15 +452,11 @@ async function completeHandshake(transport, token, timeoutMs = 1e4) {
479
452
  traceId: id,
480
453
  sessionId: "",
481
454
  pluginId: "",
482
- endpointId: EndpointIds.NodeMain,
455
+ endpointId: "",
483
456
  kind: MessageKind.Request,
484
457
  route: Routes.Bus.Handshake,
485
458
  timeoutMs,
486
- payload: {
487
- version: ProtocolVersion,
488
- supportedVersions: SUPPORTED_VERSIONS,
489
- token
490
- }
459
+ payload: { token }
491
460
  };
492
461
  return new Promise((resolve, reject) => {
493
462
  const timer = setTimeout(() => {
@@ -502,15 +471,7 @@ async function completeHandshake(transport, token, timeoutMs = 1e4) {
502
471
  reject(new Error(`${env.error.code}: ${env.error.message}`));
503
472
  return;
504
473
  }
505
- const p = env.payload ?? {};
506
- const pluginId = String(p.pluginId ?? "");
507
- const sessionId = String(p.sessionId ?? "");
508
- const endpointId = String(p.endpointId ?? EndpointIds.NodeMain);
509
- if (!pluginId || !sessionId) {
510
- reject(new Error("bus.handshake success response missing bound identity"));
511
- return;
512
- }
513
- resolve({ pluginId, sessionId, endpointId });
474
+ resolve();
514
475
  });
515
476
  transport.send(req);
516
477
  });
package/dist/node.mjs CHANGED
@@ -139,10 +139,6 @@ var ErrorCode = {
139
139
  RateLimited: "RateLimited"
140
140
  };
141
141
  var ProtocolVersion = "3.0";
142
- var EndpointIds = {
143
- NodeMain: "node-main",
144
- Host: "host"
145
- };
146
142
  var Routes = {
147
143
  Bus: {
148
144
  Handshake: "bus.handshake",
@@ -303,20 +299,11 @@ function deadlineFromTimeoutMs(timeoutMs) {
303
299
  var HandlerRouter = class {
304
300
  handlers = /* @__PURE__ */ new Map();
305
301
  pendingHostCalls = /* @__PURE__ */ new Map();
306
- pluginId = "p";
307
- sessionId = "s";
308
- endpointId = EndpointIds.NodeMain;
309
302
  /** Injected transport send fn; tests can override `router.send` directly. */
310
303
  send;
311
304
  constructor(deps) {
312
305
  this.send = deps.send;
313
306
  }
314
- /** Sets the bound identity stamped on outbound messages (after handshake). */
315
- setIdentity(ids) {
316
- this.pluginId = ids.pluginId;
317
- this.sessionId = ids.sessionId;
318
- this.endpointId = ids.endpointId;
319
- }
320
307
  handle(route, handler) {
321
308
  this.handlers.set(route, handler);
322
309
  }
@@ -360,9 +347,9 @@ var HandlerRouter = class {
360
347
  version: ProtocolVersion,
361
348
  id,
362
349
  traceId: id,
363
- sessionId: this.sessionId,
364
- pluginId: this.pluginId,
365
- endpointId: this.endpointId,
350
+ sessionId: "",
351
+ pluginId: "",
352
+ endpointId: "",
366
353
  kind: MessageKind.Request,
367
354
  route,
368
355
  timeoutMs: effectiveTimeoutMs,
@@ -406,9 +393,9 @@ var HandlerRouter = class {
406
393
  id: randomBytesHex(),
407
394
  correlationId: req.id,
408
395
  traceId: req.traceId,
409
- sessionId: req.sessionId,
410
- pluginId: req.pluginId,
411
- endpointId: this.endpointId,
396
+ sessionId: "",
397
+ pluginId: "",
398
+ endpointId: "",
412
399
  kind: MessageKind.Response,
413
400
  route: req.route,
414
401
  payload
@@ -427,29 +414,16 @@ function randomBytesHex() {
427
414
  }
428
415
 
429
416
  // src/bootstrap.ts
430
- var SUPPORTED_VERSIONS = [ProtocolVersion];
431
417
  async function runPlugin(handlers) {
432
418
  const { pipePath, token } = await readBootstrapLine();
433
419
  const transport = new NodeTransport();
434
420
  await transport.connect(pipePath);
435
- const identity = await completeHandshake(transport, token);
421
+ await completeHandshake(transport, token);
436
422
  const router = new HandlerRouter({ send: (env) => transport.send(env) });
437
- router.setIdentity(identity);
438
- const HOST_LOST_MS = 15e3;
439
- let lastPingAt = Date.now();
440
- const watchdog = setInterval(() => {
441
- if (Date.now() - lastPingAt > HOST_LOST_MS) {
442
- clearInterval(watchdog);
443
- process.exit(1);
444
- }
445
- }, 1e3);
446
- watchdog.unref?.();
447
423
  transport.onDisconnect(() => {
448
- clearInterval(watchdog);
449
424
  process.exit(1);
450
425
  });
451
426
  transport.onMessage((env) => {
452
- if (env.route === Routes.Bus.Ping) lastPingAt = Date.now();
453
427
  router.dispatch(env);
454
428
  });
455
429
  for (const [route, handler] of Object.entries(handlers)) {
@@ -459,7 +433,6 @@ async function runPlugin(handlers) {
459
433
  transport,
460
434
  router,
461
435
  close: async () => {
462
- clearInterval(watchdog);
463
436
  await transport.close();
464
437
  }
465
438
  };
@@ -488,15 +461,11 @@ async function completeHandshake(transport, token, timeoutMs = 1e4) {
488
461
  traceId: id,
489
462
  sessionId: "",
490
463
  pluginId: "",
491
- endpointId: EndpointIds.NodeMain,
464
+ endpointId: "",
492
465
  kind: MessageKind.Request,
493
466
  route: Routes.Bus.Handshake,
494
467
  timeoutMs,
495
- payload: {
496
- version: ProtocolVersion,
497
- supportedVersions: SUPPORTED_VERSIONS,
498
- token
499
- }
468
+ payload: { token }
500
469
  };
501
470
  return new Promise((resolve, reject) => {
502
471
  const timer = setTimeout(() => {
@@ -511,15 +480,7 @@ async function completeHandshake(transport, token, timeoutMs = 1e4) {
511
480
  reject(new Error(`${env.error.code}: ${env.error.message}`));
512
481
  return;
513
482
  }
514
- const p = env.payload ?? {};
515
- const pluginId = String(p.pluginId ?? "");
516
- const sessionId = String(p.sessionId ?? "");
517
- const endpointId = String(p.endpointId ?? EndpointIds.NodeMain);
518
- if (!pluginId || !sessionId) {
519
- reject(new Error("bus.handshake success response missing bound identity"));
520
- return;
521
- }
522
- resolve({ pluginId, sessionId, endpointId });
483
+ resolve();
523
484
  });
524
485
  transport.send(req);
525
486
  });
@@ -691,7 +652,7 @@ var Plugin = class {
691
652
  traceId: crypto.randomUUID().replace(/-/g, "").slice(0, 32),
692
653
  sessionId: "",
693
654
  pluginId: "",
694
- endpointId: EndpointIds.NodeMain,
655
+ endpointId: "",
695
656
  kind: MessageKind.Event,
696
657
  route,
697
658
  payload
package/dist/router.d.ts CHANGED
@@ -15,20 +15,11 @@ export declare function resolveHostCallTimeoutMs(explicit?: number): number;
15
15
  export declare class HandlerRouter {
16
16
  private handlers;
17
17
  private pendingHostCalls;
18
- private pluginId;
19
- private sessionId;
20
- private endpointId;
21
18
  /** Injected transport send fn; tests can override `router.send` directly. */
22
19
  send: Sender;
23
20
  constructor(deps: {
24
21
  send: Sender;
25
22
  });
26
- /** Sets the bound identity stamped on outbound messages (after handshake). */
27
- setIdentity(ids: {
28
- pluginId: string;
29
- sessionId: string;
30
- endpointId: string;
31
- }): void;
32
23
  handle(route: string, handler: Handler): void;
33
24
  /** Dispatches an inbound request/response. Returns once handled. */
34
25
  dispatch(env: Envelope): Promise<void>;
@@ -2,8 +2,8 @@
2
2
  * v3 Web SDK: speaks protocol envelopes over chrome.webview.postMessage.
3
3
  * Host stamps identity; the page does not supply plugin/entry/session ids.
4
4
  *
5
- * Connections start with bus.handshake. Subsequent plugin.call.* envelopes use the
6
- * negotiated version. call("refresh") is sent as plugin.call.refresh.
5
+ * Connections start with a payload-free bus.handshake readiness signal. The host validates the
6
+ * plugin manifest version before loading the page. call("refresh") is sent as plugin.call.refresh.
7
7
  */
8
8
  import { mytoolsI18n } from "./i18n.ts";
9
9
  import type { MyToolsThemePayload } from "./webTypes.ts";
@@ -2494,19 +2494,11 @@ function applyHostSideEffects(env) {
2494
2494
  mytoolsTheme.apply(payload);
2495
2495
  }
2496
2496
  }
2497
- function negotiatedVersionFrom(payload) {
2498
- if (payload && typeof payload === "object" && "negotiatedVersion" in payload) {
2499
- const value = payload.negotiatedVersion;
2500
- if (typeof value === "string" && value.length > 0) return value;
2501
- }
2502
- return ProtocolVersion;
2503
- }
2504
2497
  function createWebBusClient(options) {
2505
2498
  const pending = /* @__PURE__ */ new Map();
2506
2499
  const eventHandlers = /* @__PURE__ */ new Set();
2507
2500
  const lastByRoute = /* @__PURE__ */ new Map();
2508
2501
  const defaultTimeout = options?.timeoutMs ?? 3e4;
2509
- let wireVersion = ProtocolVersion;
2510
2502
  let handshakeError = null;
2511
2503
  const onMessage = (event) => {
2512
2504
  const env = parseMessage(event.data);
@@ -2531,9 +2523,7 @@ function createWebBusClient(options) {
2531
2523
  let handshakeDone = Promise.resolve();
2532
2524
  if (hasWebView()) {
2533
2525
  window.chrome.webview.addEventListener("message", onMessage);
2534
- handshakeDone = handshake(HandshakeTimeoutMs).then((version) => {
2535
- wireVersion = version;
2536
- }).catch((err) => {
2526
+ handshakeDone = signalPageReady(HandshakeTimeoutMs).catch((err) => {
2537
2527
  handshakeError = err instanceof Error ? err : new Error(String(err));
2538
2528
  throw handshakeError;
2539
2529
  });
@@ -2564,7 +2554,7 @@ function createWebBusClient(options) {
2564
2554
  }
2565
2555
  });
2566
2556
  post({
2567
- version: wireVersion,
2557
+ version: ProtocolVersion,
2568
2558
  id,
2569
2559
  traceId: id,
2570
2560
  sessionId: "",
@@ -2602,7 +2592,7 @@ function createWebBusClient(options) {
2602
2592
  }
2603
2593
  };
2604
2594
  }
2605
- function handshake(timeoutMs) {
2595
+ function signalPageReady(timeoutMs) {
2606
2596
  const id = randomId();
2607
2597
  return new Promise((resolve, reject) => {
2608
2598
  const timer = window.setTimeout(() => {
@@ -2616,7 +2606,7 @@ function handshake(timeoutMs) {
2616
2606
  if (env.error) {
2617
2607
  reject(new Error(`${env.error.code}: ${env.error.message}`));
2618
2608
  } else {
2619
- resolve(negotiatedVersionFrom(env.payload));
2609
+ resolve();
2620
2610
  }
2621
2611
  };
2622
2612
  const cleanup = () => {
@@ -2633,8 +2623,7 @@ function handshake(timeoutMs) {
2633
2623
  endpointId: "web",
2634
2624
  kind: MessageKind.Request,
2635
2625
  route: Routes.Bus.Handshake,
2636
- timeoutMs,
2637
- payload: { version: ProtocolVersion, supportedVersions: [ProtocolVersion] }
2626
+ timeoutMs
2638
2627
  });
2639
2628
  });
2640
2629
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qping/plugin-bus",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "v3 message-bus runtime for MyTools plugins (named-pipe transport).",
5
5
  "type": "module",
6
6
  "files": [
package/src/bootstrap.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * v3 Node SDK bootstrap entry. Reads the bootstrap line from stdin (pipePath\ttoken), connects to
3
- * the named pipe, completes bus.handshake (presenting the token and receiving bound identity),
4
- * and starts a HandlerRouter stamped with that identity.
3
+ * the named pipe, completes bus.handshake by presenting the token, and starts a HandlerRouter.
5
4
  *
6
5
  * This mirrors the C# NodeProcessController's spawn contract: the host writes one line to the
7
6
  * Node process's stdin — "<pipePath>\t<token>" — then waits for the Node side to connect the pipe
@@ -14,7 +13,6 @@ import { NodeTransport } from "./transport.ts";
14
13
  import { HandlerRouter } from "./router.ts";
15
14
  import {
16
15
  type Envelope,
17
- EndpointIds,
18
16
  MessageKind,
19
17
  ProtocolVersion,
20
18
  Routes,
@@ -30,8 +28,6 @@ export interface PluginRuntime {
30
28
  close(): Promise<void>;
31
29
  }
32
30
 
33
- const SUPPORTED_VERSIONS = [ProtocolVersion];
34
-
35
31
  /**
36
32
  * Connects to the host pipe (reading the bootstrap line from stdin), completes handshake, and
37
33
  * returns a runtime whose router dispatches inbound plugin.call.* requests to the given handlers.
@@ -42,29 +38,14 @@ export async function runPlugin(handlers: PluginHandlers): Promise<PluginRuntime
42
38
  const transport = new NodeTransport();
43
39
  await transport.connect(pipePath);
44
40
 
45
- const identity = await completeHandshake(transport, token);
41
+ await completeHandshake(transport, token);
46
42
  const router = new HandlerRouter({ send: (env: Envelope) => transport.send(env) });
47
- router.setIdentity(identity);
48
-
49
- // Passive host-liveness watchdog: exit if Host stops sending bus.ping (orphan process).
50
- // Threshold is well above the host ping interval (~2s) to tolerate brief host stalls.
51
- const HOST_LOST_MS = 15_000;
52
- let lastPingAt = Date.now();
53
- const watchdog = setInterval(() => {
54
- if (Date.now() - lastPingAt > HOST_LOST_MS) {
55
- clearInterval(watchdog);
56
- process.exit(1);
57
- }
58
- }, 1_000);
59
- watchdog.unref?.();
60
43
 
61
44
  transport.onDisconnect(() => {
62
- clearInterval(watchdog);
63
45
  process.exit(1);
64
46
  });
65
47
 
66
48
  transport.onMessage((env) => {
67
- if (env.route === Routes.Bus.Ping) lastPingAt = Date.now();
68
49
  router.dispatch(env);
69
50
  });
70
51
 
@@ -76,7 +57,6 @@ export async function runPlugin(handlers: PluginHandlers): Promise<PluginRuntime
76
57
  transport,
77
58
  router,
78
59
  close: async () => {
79
- clearInterval(watchdog);
80
60
  await transport.close();
81
61
  },
82
62
  };
@@ -101,14 +81,14 @@ async function readBootstrapLine(): Promise<{ pipePath: string; token: string }>
101
81
  }
102
82
 
103
83
  /**
104
- * Sends bus.handshake with the bootstrap token and waits for the host response that binds
105
- * plugin/session/endpoint identity. Rejects on HandshakeFailed / ProtocolMismatch / timeout.
84
+ * Sends bus.handshake with the bootstrap token and waits for host acknowledgement.
85
+ * Protocol compatibility has already been checked from the manifest before process startup.
106
86
  */
107
87
  export async function completeHandshake(
108
88
  transport: NodeTransport,
109
89
  token: string,
110
90
  timeoutMs = 10000,
111
- ): Promise<{ pluginId: string; sessionId: string; endpointId: string }> {
91
+ ): Promise<void> {
112
92
  const id = randomBytes(16).toString("hex");
113
93
  const req: Envelope = {
114
94
  version: ProtocolVersion,
@@ -116,15 +96,11 @@ export async function completeHandshake(
116
96
  traceId: id,
117
97
  sessionId: "",
118
98
  pluginId: "",
119
- endpointId: EndpointIds.NodeMain,
99
+ endpointId: "",
120
100
  kind: MessageKind.Request,
121
101
  route: Routes.Bus.Handshake,
122
102
  timeoutMs,
123
- payload: {
124
- version: ProtocolVersion,
125
- supportedVersions: SUPPORTED_VERSIONS,
126
- token,
127
- },
103
+ payload: { token },
128
104
  };
129
105
 
130
106
  return new Promise((resolve, reject) => {
@@ -141,15 +117,7 @@ export async function completeHandshake(
141
117
  reject(new Error(`${env.error.code}: ${env.error.message}`));
142
118
  return;
143
119
  }
144
- const p = (env.payload ?? {}) as Record<string, unknown>;
145
- const pluginId = String(p.pluginId ?? "");
146
- const sessionId = String(p.sessionId ?? "");
147
- const endpointId = String(p.endpointId ?? EndpointIds.NodeMain);
148
- if (!pluginId || !sessionId) {
149
- reject(new Error("bus.handshake success response missing bound identity"));
150
- return;
151
- }
152
- resolve({ pluginId, sessionId, endpointId });
120
+ resolve();
153
121
  });
154
122
 
155
123
  transport.send(req);
package/src/node.ts CHANGED
@@ -14,7 +14,6 @@ import { runPlugin, type PluginRuntime } from "./bootstrap.ts";
14
14
  import { asHostEnv, type PluginHostEnv, type PluginTheme } from "./hostEnv.ts";
15
15
  import { toActionManifest, type ActionDefinition, type ActionOutcome } from "./actions.ts";
16
16
  import {
17
- EndpointIds,
18
17
  MessageKind,
19
18
  ProtocolVersion,
20
19
  Routes,
@@ -153,7 +152,7 @@ export class Plugin {
153
152
  traceId: crypto.randomUUID().replace(/-/g, "").slice(0, 32),
154
153
  sessionId: "",
155
154
  pluginId: "",
156
- endpointId: EndpointIds.NodeMain,
155
+ endpointId: "",
157
156
  kind: MessageKind.Event,
158
157
  route,
159
158
  payload,
package/src/router.ts CHANGED
@@ -9,7 +9,6 @@ import { randomBytes } from "node:crypto";
9
9
  import {
10
10
  type Envelope,
11
11
  type BusError,
12
- EndpointIds,
13
12
  ErrorCode,
14
13
  MessageKind,
15
14
  ProtocolVersion,
@@ -61,10 +60,6 @@ function deadlineFromTimeoutMs(timeoutMs: number | null | undefined): number | n
61
60
  export class HandlerRouter {
62
61
  private handlers = new Map<string, Handler>();
63
62
  private pendingHostCalls = new Map<string, PendingHostCall>();
64
- private pluginId = "p";
65
- private sessionId = "s";
66
- private endpointId: string = EndpointIds.NodeMain;
67
-
68
63
  /** Injected transport send fn; tests can override `router.send` directly. */
69
64
  send: Sender;
70
65
 
@@ -72,13 +67,6 @@ export class HandlerRouter {
72
67
  this.send = deps.send;
73
68
  }
74
69
 
75
- /** Sets the bound identity stamped on outbound messages (after handshake). */
76
- setIdentity(ids: { pluginId: string; sessionId: string; endpointId: string }): void {
77
- this.pluginId = ids.pluginId;
78
- this.sessionId = ids.sessionId;
79
- this.endpointId = ids.endpointId;
80
- }
81
-
82
70
  handle(route: string, handler: Handler): void {
83
71
  this.handlers.set(route, handler);
84
72
  }
@@ -129,9 +117,9 @@ export class HandlerRouter {
129
117
  version: ProtocolVersion,
130
118
  id,
131
119
  traceId: id,
132
- sessionId: this.sessionId,
133
- pluginId: this.pluginId,
134
- endpointId: this.endpointId,
120
+ sessionId: "",
121
+ pluginId: "",
122
+ endpointId: "",
135
123
  kind: MessageKind.Request,
136
124
  route,
137
125
  timeoutMs: effectiveTimeoutMs,
@@ -171,9 +159,9 @@ export class HandlerRouter {
171
159
  id: randomBytesHex(),
172
160
  correlationId: req.id,
173
161
  traceId: req.traceId,
174
- sessionId: req.sessionId,
175
- pluginId: req.pluginId,
176
- endpointId: this.endpointId,
162
+ sessionId: "",
163
+ pluginId: "",
164
+ endpointId: "",
177
165
  kind: MessageKind.Response,
178
166
  route: req.route,
179
167
  payload,
package/src/webClient.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  * v3 Web SDK: speaks protocol envelopes over chrome.webview.postMessage.
3
3
  * Host stamps identity; the page does not supply plugin/entry/session ids.
4
4
  *
5
- * Connections start with bus.handshake. Subsequent plugin.call.* envelopes use the
6
- * negotiated version. call("refresh") is sent as plugin.call.refresh.
5
+ * Connections start with a payload-free bus.handshake readiness signal. The host validates the
6
+ * plugin manifest version before loading the page. call("refresh") is sent as plugin.call.refresh.
7
7
  */
8
8
 
9
9
  import { mytoolsI18n } from "./i18n.ts";
@@ -116,14 +116,6 @@ function applyHostSideEffects(env: Envelope): void {
116
116
  }
117
117
  }
118
118
 
119
- function negotiatedVersionFrom(payload: unknown): string {
120
- if (payload && typeof payload === "object" && "negotiatedVersion" in payload) {
121
- const value = (payload as { negotiatedVersion?: unknown }).negotiatedVersion;
122
- if (typeof value === "string" && value.length > 0) return value;
123
- }
124
- return ProtocolVersion;
125
- }
126
-
127
119
  /**
128
120
  * Creates a Web bus client. Registers the message listener immediately so host
129
121
  * events that arrive before `on()` are buffered and replayed.
@@ -138,7 +130,6 @@ export function createWebBusClient(options?: {
138
130
  const eventHandlers = new Set<(env: Envelope) => void>();
139
131
  const lastByRoute = new Map<string, Envelope>();
140
132
  const defaultTimeout = options?.timeoutMs ?? 30_000;
141
- let wireVersion = ProtocolVersion;
142
133
  let handshakeError: Error | null = null;
143
134
 
144
135
  const onMessage = (event: MessageEvent) => {
@@ -165,10 +156,7 @@ export function createWebBusClient(options?: {
165
156
  let handshakeDone: Promise<void> = Promise.resolve();
166
157
  if (hasWebView()) {
167
158
  (window as any).chrome.webview.addEventListener("message", onMessage);
168
- handshakeDone = handshake(HandshakeTimeoutMs)
169
- .then((version) => {
170
- wireVersion = version;
171
- })
159
+ handshakeDone = signalPageReady(HandshakeTimeoutMs)
172
160
  .catch((err: unknown) => {
173
161
  handshakeError = err instanceof Error ? err : new Error(String(err));
174
162
  throw handshakeError;
@@ -203,7 +191,7 @@ export function createWebBusClient(options?: {
203
191
  },
204
192
  });
205
193
  post({
206
- version: wireVersion,
194
+ version: ProtocolVersion,
207
195
  id,
208
196
  traceId: id,
209
197
  sessionId: "",
@@ -245,7 +233,7 @@ export function createWebBusClient(options?: {
245
233
  };
246
234
  }
247
235
 
248
- function handshake(timeoutMs: number): Promise<string> {
236
+ function signalPageReady(timeoutMs: number): Promise<void> {
249
237
  const id = randomId();
250
238
  return new Promise((resolve, reject) => {
251
239
  const timer = window.setTimeout(() => {
@@ -260,7 +248,7 @@ function handshake(timeoutMs: number): Promise<string> {
260
248
  if (env.error) {
261
249
  reject(new Error(`${env.error.code}: ${env.error.message}`));
262
250
  } else {
263
- resolve(negotiatedVersionFrom(env.payload));
251
+ resolve();
264
252
  }
265
253
  };
266
254
 
@@ -280,7 +268,6 @@ function handshake(timeoutMs: number): Promise<string> {
280
268
  kind: MessageKind.Request,
281
269
  route: Routes.Bus.Handshake,
282
270
  timeoutMs,
283
- payload: { version: ProtocolVersion, supportedVersions: [ProtocolVersion] },
284
271
  });
285
272
  });
286
273
  }