@rrwebcloud/openclaw-session-recording 2026.3.28-1 → 2026.3.28

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.
Files changed (3) hide show
  1. package/README.md +0 -2
  2. package/index.ts +15 -83
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -21,8 +21,6 @@ plugins:
21
21
 
22
22
  ## Notes
23
23
 
24
- - OpenClaw `2026.3.24+` uses the full automatic browser-runtime integration path
25
- - OpenClaw `2026.3.13` loads in legacy compatibility mode and reports clear next steps instead of failing on install
26
24
  - `serverUrl` defaults to `https://api.rrwebcloud.com`
27
25
  - `secretKey` is not required for the bundled browser flow
28
26
  - the plugin targets managed Chromium browser profiles such as `openclaw`
package/index.ts CHANGED
@@ -2,6 +2,12 @@ import crypto from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { Type } from "@sinclair/typebox";
5
+ import {
6
+ clearManagedBrowserReplayContextsForSession,
7
+ registerManagedBrowserExtensions,
8
+ setManagedBrowserReplayContext,
9
+ unregisterManagedBrowserExtensions,
10
+ } from "openclaw/plugin-sdk/browser-runtime";
5
11
  import { readJsonFileWithFallback, writeJsonFileAtomically } from "openclaw/plugin-sdk/json-store";
6
12
  import { definePluginEntry, type OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
7
13
  import { type AnyAgentTool, type OpenClawConfig } from "openclaw/plugin-sdk/plugin-entry";
@@ -39,28 +45,6 @@ type ReplayStateStore = {
39
45
 
40
46
  const RRWEB_PLUGIN_ID = "rrweb-replay";
41
47
  const DEFAULT_RRWEB_API_BASE_URL = "https://api.rrwebcloud.com";
42
- const LEGACY_BROWSER_RUNTIME_REASON =
43
- "This OpenClaw host does not export plugin-sdk/browser-runtime. Automatic rrweb extension wiring requires OpenClaw >=2026.3.24. On legacy hosts, install/configure the rrweb browser addon separately or upgrade OpenClaw.";
44
-
45
- type BrowserRuntimeCompat = {
46
- clearManagedBrowserReplayContextsForSession: (sessionKey: string) => void;
47
- registerManagedBrowserExtensions: (params: {
48
- sourceId: string;
49
- profiles: string[];
50
- extensionPaths: string[];
51
- }) => void;
52
- setManagedBrowserReplayContext: (params: {
53
- cdpUrl: string;
54
- profile: string;
55
- sessionKey?: string;
56
- sessionId?: string;
57
- replaySessionId: string;
58
- replayServerUrl?: string;
59
- replayUrl?: string;
60
- updatedAt: string;
61
- }) => void;
62
- unregisterManagedBrowserExtensions: (sourceId: string) => void;
63
- };
64
48
 
65
49
  const rrwebReplayConfigSchema = {
66
50
  parse(value: unknown): RrwebReplayConfig {
@@ -226,17 +210,10 @@ function buildReplaySessionState(params: {
226
210
  function describeReplayAvailability(params: {
227
211
  config: RrwebReplayConfig;
228
212
  extensionDir: string | null;
229
- browserRuntimeAvailable: boolean;
230
213
  }): { enabled: boolean; reason?: string } {
231
214
  if (!params.config.enabled) {
232
215
  return { enabled: false, reason: "Plugin disabled in rrweb-replay config." };
233
216
  }
234
- if (!params.browserRuntimeAvailable) {
235
- return {
236
- enabled: false,
237
- reason: LEGACY_BROWSER_RUNTIME_REASON,
238
- };
239
- }
240
217
  if (!params.extensionDir) {
241
218
  return {
242
219
  enabled: false,
@@ -257,23 +234,6 @@ function describeReplayAvailability(params: {
257
234
  return { enabled: true };
258
235
  }
259
236
 
260
- async function loadBrowserRuntimeCompat(): Promise<BrowserRuntimeCompat | null> {
261
- try {
262
- const mod = (await import("openclaw/plugin-sdk/browser-runtime")) as BrowserRuntimeCompat;
263
- if (
264
- typeof mod.registerManagedBrowserExtensions === "function" &&
265
- typeof mod.unregisterManagedBrowserExtensions === "function" &&
266
- typeof mod.setManagedBrowserReplayContext === "function" &&
267
- typeof mod.clearManagedBrowserReplayContextsForSession === "function"
268
- ) {
269
- return mod;
270
- }
271
- } catch {
272
- // Legacy OpenClaw hosts do not expose plugin-sdk/browser-runtime.
273
- }
274
- return null;
275
- }
276
-
277
237
  function resolveBrowserProfileForReplay(params: {
278
238
  config: OpenClawConfig;
279
239
  preferredProfile?: string;
@@ -393,7 +353,6 @@ async function markReplaySessionEnded(params: {
393
353
  async function armReplayContext(params: {
394
354
  api: OpenClawPluginApi;
395
355
  pluginConfig: RrwebReplayConfig;
396
- browserRuntime: BrowserRuntimeCompat | null;
397
356
  sessionKey?: string;
398
357
  sessionId?: string;
399
358
  preferredProfile?: string;
@@ -414,10 +373,10 @@ async function armReplayContext(params: {
414
373
  config: params.api.config,
415
374
  preferredProfile: params.preferredProfile ?? replayEntry.currentProfile,
416
375
  });
417
- if (!params.browserRuntime || !profile || !profile.cdpUrl) {
376
+ if (!profile || !profile.cdpUrl) {
418
377
  return replayEntry;
419
378
  }
420
- params.browserRuntime.setManagedBrowserReplayContext({
379
+ setManagedBrowserReplayContext({
421
380
  cdpUrl: profile.cdpUrl,
422
381
  profile: profile.name,
423
382
  sessionKey: params.sessionKey,
@@ -446,7 +405,6 @@ function createReplaySessionInfoTool(params: {
446
405
  api: OpenClawPluginApi;
447
406
  pluginConfig: RrwebReplayConfig;
448
407
  extensionDir: string | null;
449
- browserRuntimePromise: Promise<BrowserRuntimeCompat | null>;
450
408
  context: {
451
409
  sessionKey?: string;
452
410
  sessionId?: string;
@@ -471,13 +429,11 @@ function createReplaySessionInfoTool(params: {
471
429
  ),
472
430
  }),
473
431
  execute: async (_id, rawParams) => {
474
- const browserRuntime = await params.browserRuntimePromise;
475
432
  const toolParams =
476
433
  rawParams && typeof rawParams === "object" ? (rawParams as Record<string, unknown>) : null;
477
434
  const availability = describeReplayAvailability({
478
435
  config: params.pluginConfig,
479
436
  extensionDir: params.extensionDir,
480
- browserRuntimeAvailable: Boolean(browserRuntime),
481
437
  });
482
438
  const activate = toolParams?.activate === true;
483
439
  const preferredProfile = toolParams
@@ -506,7 +462,6 @@ function createReplaySessionInfoTool(params: {
506
462
  entry = await armReplayContext({
507
463
  api: params.api,
508
464
  pluginConfig: params.pluginConfig,
509
- browserRuntime,
510
465
  sessionKey: params.context.sessionKey,
511
466
  sessionId: params.context.sessionId,
512
467
  preferredProfile,
@@ -524,7 +479,6 @@ function createReplaySessionInfoTool(params: {
524
479
  enabled: availability.enabled,
525
480
  reason: availability.reason ?? entry.reason ?? null,
526
481
  activated: activate && availability.enabled,
527
- compatibilityMode: browserRuntime ? "modern" : "legacy",
528
482
  });
529
483
  },
530
484
  };
@@ -539,27 +493,22 @@ export default definePluginEntry({
539
493
  const pluginConfig = rrwebReplayConfigSchema.parse(api.pluginConfig);
540
494
  const extensionDir = resolveExtensionDirectory({ config: pluginConfig, api });
541
495
  const serviceSourceId = `${RRWEB_PLUGIN_ID}:${api.source}`;
542
- const browserRuntimePromise = loadBrowserRuntimeCompat();
496
+ const availability = describeReplayAvailability({ config: pluginConfig, extensionDir });
543
497
 
544
498
  api.registerService({
545
499
  id: "rrweb-replay-browser-extension",
546
500
  async start(ctx) {
547
- const browserRuntime = await browserRuntimePromise;
548
501
  if (!pluginConfig.enabled) {
549
502
  ctx.logger.info("[rrweb-replay] disabled; not registering browser extension");
550
503
  return;
551
504
  }
552
- if (!browserRuntime) {
553
- ctx.logger.warn(`[rrweb-replay] ${LEGACY_BROWSER_RUNTIME_REASON}`);
554
- return;
555
- }
556
505
  if (!extensionDir) {
557
506
  ctx.logger.warn(
558
507
  "[rrweb-replay] extension directory missing; replay browser extension was not registered",
559
508
  );
560
509
  return;
561
510
  }
562
- browserRuntime.registerManagedBrowserExtensions({
511
+ registerManagedBrowserExtensions({
563
512
  sourceId: serviceSourceId,
564
513
  profiles: pluginConfig.browserProfiles,
565
514
  extensionPaths: [extensionDir],
@@ -569,18 +518,11 @@ export default definePluginEntry({
569
518
  );
570
519
  },
571
520
  async stop() {
572
- const browserRuntime = await browserRuntimePromise;
573
- browserRuntime?.unregisterManagedBrowserExtensions(serviceSourceId);
521
+ unregisterManagedBrowserExtensions(serviceSourceId);
574
522
  },
575
523
  });
576
524
 
577
525
  api.on("session_start", async (event, ctx) => {
578
- const browserRuntime = await browserRuntimePromise;
579
- const availability = describeReplayAvailability({
580
- config: pluginConfig,
581
- extensionDir,
582
- browserRuntimeAvailable: Boolean(browserRuntime),
583
- });
584
526
  await upsertReplaySession({
585
527
  api,
586
528
  config: pluginConfig,
@@ -594,9 +536,8 @@ export default definePluginEntry({
594
536
  });
595
537
 
596
538
  api.on("before_reset", async (_event, ctx) => {
597
- const browserRuntime = await browserRuntimePromise;
598
- if (ctx.sessionKey && browserRuntime) {
599
- browserRuntime.clearManagedBrowserReplayContextsForSession(ctx.sessionKey);
539
+ if (ctx.sessionKey) {
540
+ clearManagedBrowserReplayContextsForSession(ctx.sessionKey);
600
541
  }
601
542
  await markReplaySessionEnded({
602
543
  api,
@@ -606,9 +547,8 @@ export default definePluginEntry({
606
547
  });
607
548
 
608
549
  api.on("session_end", async (_event, ctx) => {
609
- const browserRuntime = await browserRuntimePromise;
610
- if (ctx.sessionKey && browserRuntime) {
611
- browserRuntime.clearManagedBrowserReplayContextsForSession(ctx.sessionKey);
550
+ if (ctx.sessionKey) {
551
+ clearManagedBrowserReplayContextsForSession(ctx.sessionKey);
612
552
  }
613
553
  await markReplaySessionEnded({
614
554
  api,
@@ -618,12 +558,6 @@ export default definePluginEntry({
618
558
  });
619
559
 
620
560
  api.on("before_tool_call", async (event, ctx) => {
621
- const browserRuntime = await browserRuntimePromise;
622
- const availability = describeReplayAvailability({
623
- config: pluginConfig,
624
- extensionDir,
625
- browserRuntimeAvailable: Boolean(browserRuntime),
626
- });
627
561
  if (event.toolName !== "browser" || pluginConfig.recordingPolicy !== "browser-only") {
628
562
  return;
629
563
  }
@@ -637,7 +571,6 @@ export default definePluginEntry({
637
571
  await armReplayContext({
638
572
  api,
639
573
  pluginConfig,
640
- browserRuntime,
641
574
  sessionKey: ctx.sessionKey,
642
575
  sessionId: ctx.sessionId,
643
576
  preferredProfile: rawProfile,
@@ -650,7 +583,6 @@ export default definePluginEntry({
650
583
  api,
651
584
  pluginConfig,
652
585
  extensionDir,
653
- browserRuntimePromise,
654
586
  context: {
655
587
  sessionKey: context.sessionKey,
656
588
  sessionId: context.sessionId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rrwebcloud/openclaw-session-recording",
3
- "version": "2026.3.28-1",
3
+ "version": "2026.3.28",
4
4
  "description": "OpenClaw rrweb replay plugin",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,7 +19,7 @@
19
19
  "openclaw": "workspace:*"
20
20
  },
21
21
  "peerDependencies": {
22
- "openclaw": ">=2026.3.13"
22
+ "openclaw": ">=2026.3.24"
23
23
  },
24
24
  "peerDependenciesMeta": {
25
25
  "openclaw": {
@@ -35,7 +35,7 @@
35
35
  "npmSpec": "@rrwebcloud/openclaw-session-recording",
36
36
  "localPath": "extensions/rrweb-replay",
37
37
  "defaultChoice": "npm",
38
- "minHostVersion": ">=2026.3.13"
38
+ "minHostVersion": ">=2026.3.24"
39
39
  },
40
40
  "release": {
41
41
  "publishToNpm": true