@omercnet/paseo-shared-browser 3.0.0-next.284.1 → 3.0.0-next.292.1
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/OVERVIEW.md +1 -1
- package/README.md +4 -2
- package/client/browser-chrome.tsx +1 -1
- package/client/browser-compose-controls.test.tsx +1 -1
- package/client/browser-compose-controls.tsx +1 -1
- package/client/browser-control-button.tsx +1 -1
- package/client/browser-control-dialog.tsx +1 -1
- package/client/browser-panel-state.test.ts +23 -0
- package/client/browser-panel-state.ts +14 -0
- package/client/browser-resolution-picker.tsx +1 -1
- package/client/browser-toolbar-menu.tsx +1 -1
- package/client/browser-viewer-recovery.test.ts +24 -0
- package/client/browser-viewer-recovery.ts +20 -0
- package/client/browser.tsx +57 -7
- package/index.client.tsx +0 -1
- package/npm-shrinkwrap.json +20 -20
- package/package.json +3 -3
- package/paseo-plugin.json +1 -1
package/OVERVIEW.md
CHANGED
|
@@ -13,7 +13,7 @@ New agents whose provider accepts external MCP servers receive a local MCP serve
|
|
|
13
13
|
|
|
14
14
|
## Setup
|
|
15
15
|
|
|
16
|
-
- Paseo ^0.
|
|
16
|
+
- Paseo ^0.13.0, and Node.js 24 or newer on the daemon host.
|
|
17
17
|
- Chromium is downloaded when the plugin is installed and stored in the Paseo data directory. On Linux ARM64 nothing is downloaded, and you install a non-Snap Chromium at `/usr/bin/chromium` first. `PASEO_SHARED_BROWSER_CHROMIUM_EXECUTABLE` points the plugin at a different Chromium.
|
|
18
18
|
|
|
19
19
|
## Limits
|
package/README.md
CHANGED
|
@@ -183,7 +183,9 @@ User-supplied `AGENT_BROWSER_*` variables are deliberately ignored.
|
|
|
183
183
|
within the pane, scroll long lists, and dismiss with an outside press, Escape or native Back.
|
|
184
184
|
- The monitor menu offers **Fit to panel** (default) and **Actual size (100%)**. Actual size
|
|
185
185
|
uses browser layout pixels, not the larger JPEG dimensions of sharper phone captures.
|
|
186
|
-
This choice affects only the current viewer, without resizing the shared browser.
|
|
186
|
+
This choice affects only the current viewer, without resizing the shared browser. Each
|
|
187
|
+
Shared Browser tab remembers its choice and its selected browser page across app reloads;
|
|
188
|
+
a remembered page that no longer exists falls back to the default page.
|
|
187
189
|
Desktop local scrollbars reveal overflow while wheel events on a controlled frame go to
|
|
188
190
|
the remote page. Phone viewers can pan while observing; controlling sends swipes to the
|
|
189
191
|
page instead. Fitting images stay centered without empty scroll ranges; a scrollbar on
|
|
@@ -422,7 +424,7 @@ runs the actual Paseo compiler on both plugin entries.
|
|
|
422
424
|
Release Please maintains the version, changelog, component tag, and GitHub release from
|
|
423
425
|
Conventional Commits in the monorepo.
|
|
424
426
|
|
|
425
|
-
Both the Paseo daemon and app must satisfy `^0.
|
|
427
|
+
Both the Paseo daemon and app must satisfy `^0.13.0`. Encoded video is opt-in on the daemon and
|
|
426
428
|
requires WebCodecs in a web client; JPEG is always available. The client surface uses React
|
|
427
429
|
Native primitives and works in desktop, web, iOS, and Android Paseo clients.
|
|
428
430
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Public themed panel controls and notices. Leaves own only focus/hover styling, never browser authority. */
|
|
2
2
|
import type { PluginWorkspacePanelProps } from "@getpaseo/plugin/client";
|
|
3
|
-
import { Icon, TextInput } from "@getpaseo/plugin/client/
|
|
3
|
+
import { Icon, TextInput } from "@getpaseo/plugin/client/ui";
|
|
4
4
|
import { type ReactNode, useCallback, useState } from "react";
|
|
5
5
|
import {
|
|
6
6
|
ActivityIndicator,
|
|
@@ -33,7 +33,7 @@ vi.mock("react", () => ({
|
|
|
33
33
|
hooks.effects.push(effect);
|
|
34
34
|
},
|
|
35
35
|
}));
|
|
36
|
-
vi.mock("@getpaseo/plugin/client/
|
|
36
|
+
vi.mock("@getpaseo/plugin/client/ui", () => {
|
|
37
37
|
const Modal = Object.assign(() => null, { Content: () => null });
|
|
38
38
|
return { Modal, TextInput: () => null };
|
|
39
39
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Explicit Compose draft UI, with original control/document ownership pinned until Done. */
|
|
2
2
|
import type { PluginWorkspacePanelProps } from "@getpaseo/plugin/client";
|
|
3
|
-
import { Modal, TextInput } from "@getpaseo/plugin/client/
|
|
3
|
+
import { Modal, TextInput } from "@getpaseo/plugin/client/ui";
|
|
4
4
|
import { useEffect, useRef, useState } from "react";
|
|
5
5
|
import { Text, View } from "react-native";
|
|
6
6
|
import { ControlButton } from "./browser-chrome";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginWorkspacePanelProps } from "@getpaseo/plugin/client";
|
|
2
|
-
import { Icon } from "@getpaseo/plugin/client/
|
|
2
|
+
import { Icon } from "@getpaseo/plugin/client/ui";
|
|
3
3
|
import { useCallback, useState } from "react";
|
|
4
4
|
import { Pressable, Text, type TextStyle, type ViewStyle } from "react-native";
|
|
5
5
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Confirm a one-time control request before the selected tab action continues. */
|
|
2
2
|
import type { PluginWorkspacePanelProps } from "@getpaseo/plugin/client";
|
|
3
|
-
import { Icon, Modal } from "@getpaseo/plugin/client/
|
|
3
|
+
import { Icon, Modal } from "@getpaseo/plugin/client/ui";
|
|
4
4
|
import type { BrowserState } from "../shared/browser";
|
|
5
5
|
import { ControlButton } from "./browser-chrome";
|
|
6
6
|
import type { ControlRequest } from "./browser-control-request";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { browserPanelStateSchema, DEFAULT_BROWSER_PANEL_STATE } from "./browser-panel-state";
|
|
3
|
+
|
|
4
|
+
describe("persisted browser panel state", () => {
|
|
5
|
+
it("round-trips a remembered tab and display mode", () => {
|
|
6
|
+
const state = { scaleMode: "actual", selectedTabId: "page-2" };
|
|
7
|
+
expect(browserPanelStateSchema.parse(state)).toEqual(state);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("accepts its own default", () => {
|
|
11
|
+
expect(browserPanelStateSchema.safeParse(DEFAULT_BROWSER_PANEL_STATE).success).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("rejects state that a newer or older plugin version could have written", () => {
|
|
15
|
+
expect(browserPanelStateSchema.safeParse(undefined).success).toBe(false);
|
|
16
|
+
expect(
|
|
17
|
+
browserPanelStateSchema.safeParse({ scaleMode: "zoom", selectedTabId: null }).success,
|
|
18
|
+
).toBe(false);
|
|
19
|
+
expect(browserPanelStateSchema.safeParse({ scaleMode: "fit", selectedTabId: 3 }).success).toBe(
|
|
20
|
+
false,
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Per-tab state Paseo persists across tab restoration and app reloads. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { browserTabIdSchema } from "../shared/browser";
|
|
4
|
+
|
|
5
|
+
export const browserPanelStateSchema = z.object({
|
|
6
|
+
scaleMode: z.enum(["fit", "actual"]),
|
|
7
|
+
selectedTabId: browserTabIdSchema.nullable(),
|
|
8
|
+
});
|
|
9
|
+
export type BrowserPanelState = z.infer<typeof browserPanelStateSchema>;
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_BROWSER_PANEL_STATE: BrowserPanelState = {
|
|
12
|
+
scaleMode: "fit",
|
|
13
|
+
selectedTabId: null,
|
|
14
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Grouped resolution choices with independent host favorites and capture quality. */
|
|
2
2
|
import type { PluginHostProps } from "@getpaseo/plugin/client";
|
|
3
|
-
import { Icon } from "@getpaseo/plugin/client/
|
|
3
|
+
import { Icon } from "@getpaseo/plugin/client/ui";
|
|
4
4
|
import { Pressable, StyleSheet, Text, View } from "react-native";
|
|
5
5
|
import type { BrowserDisplayPreferences } from "../shared/browser-display-preferences";
|
|
6
6
|
import type { DevicePresetId } from "../shared/device-presets";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* host internals. Placement stays inside the pane, including compact clients.
|
|
5
5
|
*/
|
|
6
6
|
import type { PluginHostProps } from "@getpaseo/plugin/client";
|
|
7
|
-
import { Icon } from "@getpaseo/plugin/client/
|
|
7
|
+
import { Icon } from "@getpaseo/plugin/client/ui";
|
|
8
8
|
import {
|
|
9
9
|
type ReactNode,
|
|
10
10
|
type RefObject,
|
|
@@ -3,6 +3,7 @@ import { describe, expect, it } from "vitest";
|
|
|
3
3
|
import {
|
|
4
4
|
createBrowserViewerRecovery,
|
|
5
5
|
isBrowserClosedError,
|
|
6
|
+
isBrowserTabUnavailableError,
|
|
6
7
|
isExpiredBrowserViewerError,
|
|
7
8
|
} from "./browser-viewer-recovery";
|
|
8
9
|
|
|
@@ -109,3 +110,26 @@ it("the actual capture query observer discards old token errors when its token k
|
|
|
109
110
|
client.clear();
|
|
110
111
|
}
|
|
111
112
|
});
|
|
113
|
+
|
|
114
|
+
describe("remembered tab recovery", () => {
|
|
115
|
+
it("recognizes only the unavailable-tab rejection", () => {
|
|
116
|
+
const unavailable = Object.assign(
|
|
117
|
+
new Error(
|
|
118
|
+
"Request failed: Workspace runtime identity failed: Browser tab is no longer available requestType=plugin.rpc.invoke.request code=handler_error",
|
|
119
|
+
),
|
|
120
|
+
{ code: "handler_error" },
|
|
121
|
+
);
|
|
122
|
+
expect(isBrowserTabUnavailableError(unavailable)).toBe(true);
|
|
123
|
+
expect(isBrowserTabUnavailableError(new Error("Browser tab is no longer available"))).toBe(
|
|
124
|
+
true,
|
|
125
|
+
);
|
|
126
|
+
expect(isBrowserTabUnavailableError(expired)).toBe(false);
|
|
127
|
+
expect(isBrowserTabUnavailableError(new Error("Browser is closed"))).toBe(false);
|
|
128
|
+
expect(
|
|
129
|
+
isBrowserTabUnavailableError(
|
|
130
|
+
new Error("Could not parse: Browser tab is no longer available"),
|
|
131
|
+
),
|
|
132
|
+
).toBe(false);
|
|
133
|
+
expect(isBrowserTabUnavailableError(null)).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
*/
|
|
6
6
|
const VIEWER_EXPIRED_MESSAGE = "Viewer token is invalid or expired";
|
|
7
7
|
const BROWSER_CLOSED_MESSAGE = "Browser is closed";
|
|
8
|
+
const BROWSER_TAB_UNAVAILABLE_MESSAGE = "Browser tab is no longer available";
|
|
9
|
+
// The supervisor wraps runtime rejections as "Workspace runtime <operation> failed: <message>".
|
|
10
|
+
const UNAVAILABLE_TAB_PATTERN = new RegExp(
|
|
11
|
+
`^(?:Workspace runtime \\w+ failed: )?${BROWSER_TAB_UNAVAILABLE_MESSAGE}(?: requestType=|$)`,
|
|
12
|
+
);
|
|
8
13
|
|
|
9
14
|
/** Recognize the server's explicit close fence without confusing it with a transport failure. */
|
|
10
15
|
export function isBrowserClosedError(error: unknown): boolean {
|
|
@@ -76,3 +81,18 @@ export function createBrowserViewerRecovery() {
|
|
|
76
81
|
return true;
|
|
77
82
|
};
|
|
78
83
|
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A remembered tab can outlive its page; the server then rejects attaching to it. The runtime
|
|
87
|
+
* wraps that rejection ("Workspace runtime identity failed: ..."), so match the phrase.
|
|
88
|
+
*/
|
|
89
|
+
export function isBrowserTabUnavailableError(error: unknown): boolean {
|
|
90
|
+
if (!error || typeof error !== "object") return false;
|
|
91
|
+
const value = error as { message?: unknown; code?: unknown };
|
|
92
|
+
if (typeof value.message !== "string") return false;
|
|
93
|
+
if (value.code !== undefined && value.code !== "handler_error") return false;
|
|
94
|
+
const message = value.message.startsWith("Request failed: ")
|
|
95
|
+
? value.message.slice("Request failed: ".length)
|
|
96
|
+
: value.message;
|
|
97
|
+
return UNAVAILABLE_TAB_PATTERN.test(message);
|
|
98
|
+
}
|
package/client/browser.tsx
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* presentation models live in focused counterpart hooks; this module never
|
|
5
5
|
* replays published mutations or substitutes visible pixels for input authority.
|
|
6
6
|
*/
|
|
7
|
-
import { type PluginWorkspacePanelProps, useRpc } from "@getpaseo/plugin/client";
|
|
8
|
-
import { Icon, Modal } from "@getpaseo/plugin/client/
|
|
7
|
+
import { type PluginWorkspacePanelProps, useRpc, useTabState } from "@getpaseo/plugin/client";
|
|
8
|
+
import { Icon, Modal } from "@getpaseo/plugin/client/ui";
|
|
9
9
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
10
10
|
import {
|
|
11
11
|
type ReactNode,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
type CaptureDensityMode,
|
|
54
54
|
getAutomaticCaptureDensity,
|
|
55
55
|
} from "./browser-auto-capture-density";
|
|
56
|
-
import {
|
|
56
|
+
import { getBrowserCanvasLayout } from "./browser-canvas-layout";
|
|
57
57
|
import { BrowserCanvasViewport } from "./browser-canvas-viewport";
|
|
58
58
|
import {
|
|
59
59
|
CanvasPlaceholder,
|
|
@@ -75,6 +75,7 @@ import { type EmulationSelection, matchingResolutionPresetId } from "./browser-e
|
|
|
75
75
|
import { getFillViewportResolution } from "./browser-fill-viewport";
|
|
76
76
|
import type { FrameCandidate } from "./browser-frame-buffer";
|
|
77
77
|
import { BrowserFrameImage } from "./browser-frame-image";
|
|
78
|
+
import { browserPanelStateSchema, DEFAULT_BROWSER_PANEL_STATE } from "./browser-panel-state";
|
|
78
79
|
import { createStyles, DIMENSION, SPACE } from "./browser-panel-styles";
|
|
79
80
|
import { BrowserResolutionPicker } from "./browser-resolution-picker";
|
|
80
81
|
import { BrowserTabs } from "./browser-tabs";
|
|
@@ -86,7 +87,11 @@ import {
|
|
|
86
87
|
} from "./browser-toolbar-menu";
|
|
87
88
|
import { isFrameCurrent, isVideoSourceCurrent } from "./browser-video-currency";
|
|
88
89
|
import { BrowserVideoSurface } from "./browser-video-surface";
|
|
89
|
-
import {
|
|
90
|
+
import {
|
|
91
|
+
isBrowserClosedError,
|
|
92
|
+
isBrowserTabUnavailableError,
|
|
93
|
+
isExpiredBrowserViewerError,
|
|
94
|
+
} from "./browser-viewer-recovery";
|
|
90
95
|
import { createFrameLifecycle } from "./frame-lifecycle";
|
|
91
96
|
import { useBrowserAutoCaptureDensity } from "./use-browser-auto-capture-density";
|
|
92
97
|
import { useBrowserCanvasInput } from "./use-browser-canvas-input";
|
|
@@ -188,6 +193,7 @@ export function SharedBrowserPanel({
|
|
|
188
193
|
host,
|
|
189
194
|
layout,
|
|
190
195
|
workspaceId,
|
|
196
|
+
tab,
|
|
191
197
|
}: PluginWorkspacePanelProps) {
|
|
192
198
|
const queryClient = useQueryClient();
|
|
193
199
|
const styles = useMemo(() => createStyles(theme, layout.compact), [theme, layout.compact]);
|
|
@@ -245,7 +251,38 @@ export function SharedBrowserPanel({
|
|
|
245
251
|
const [operationError, setOperationError] = useState<string | null>(null);
|
|
246
252
|
const [reconnecting, setReconnecting] = useState(false);
|
|
247
253
|
const [browserClosed, setBrowserClosed] = useState(false);
|
|
248
|
-
const [
|
|
254
|
+
const [panelState, writePanelState] = useTabState(
|
|
255
|
+
tab,
|
|
256
|
+
browserPanelStateSchema,
|
|
257
|
+
DEFAULT_BROWSER_PANEL_STATE,
|
|
258
|
+
);
|
|
259
|
+
// Writes replace the whole persisted value; merge into the latest one so two
|
|
260
|
+
// updates in the same tick (e.g. Fill viewport) cannot drop each other.
|
|
261
|
+
const panelStateRef = useRef(panelState);
|
|
262
|
+
panelStateRef.current = panelState;
|
|
263
|
+
const updatePanelState = useCallback(
|
|
264
|
+
(patch: Partial<typeof panelState>) => {
|
|
265
|
+
const next = { ...panelStateRef.current, ...patch };
|
|
266
|
+
if (
|
|
267
|
+
next.scaleMode === panelStateRef.current.scaleMode &&
|
|
268
|
+
next.selectedTabId === panelStateRef.current.selectedTabId
|
|
269
|
+
) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
panelStateRef.current = next;
|
|
273
|
+
writePanelState(next);
|
|
274
|
+
},
|
|
275
|
+
[writePanelState],
|
|
276
|
+
);
|
|
277
|
+
const { selectedTabId, scaleMode } = panelState;
|
|
278
|
+
const setSelectedTabId = useCallback(
|
|
279
|
+
(tabId: string | null) => updatePanelState({ selectedTabId: tabId }),
|
|
280
|
+
[updatePanelState],
|
|
281
|
+
);
|
|
282
|
+
const setScaleMode = useCallback(
|
|
283
|
+
(mode: typeof scaleMode) => updatePanelState({ scaleMode: mode }),
|
|
284
|
+
[updatePanelState],
|
|
285
|
+
);
|
|
249
286
|
const selectedTabIdRef = useRef(selectedTabId);
|
|
250
287
|
selectedTabIdRef.current = selectedTabId;
|
|
251
288
|
const [tabMutationPending, setTabMutationPending] = useState(false);
|
|
@@ -268,7 +305,6 @@ export function SharedBrowserPanel({
|
|
|
268
305
|
const [keysSubmenuOpen, setKeysSubmenuOpen] = useState(false);
|
|
269
306
|
const keysAnchorRef = useRef<View | null>(null);
|
|
270
307
|
const [toolbarMenu, setToolbarMenu] = useState<"display" | "actions" | null>(null);
|
|
271
|
-
const [scaleMode, setScaleMode] = useState<BrowserCanvasDisplayMode>("fit");
|
|
272
308
|
const paneRef = useRef<View | null>(null);
|
|
273
309
|
const displayAnchorRef = useRef<View | null>(null);
|
|
274
310
|
const actionsAnchorRef = useRef<View | null>(null);
|
|
@@ -426,6 +462,12 @@ export function SharedBrowserPanel({
|
|
|
426
462
|
if (isBrowserClosedError(attachQuery.error)) setBrowserClosed(true);
|
|
427
463
|
}, [attachQuery.error]);
|
|
428
464
|
|
|
465
|
+
// A restored selection can name a page that no longer exists; without the
|
|
466
|
+
// attach there is no viewer to list tabs with, so fall back to the default page.
|
|
467
|
+
useEffect(() => {
|
|
468
|
+
if (selectedTabId && isBrowserTabUnavailableError(attachQuery.error)) setSelectedTabId(null);
|
|
469
|
+
}, [attachQuery.error, selectedTabId, setSelectedTabId]);
|
|
470
|
+
|
|
429
471
|
useEffect(() => {
|
|
430
472
|
if (!closedView) return;
|
|
431
473
|
setControlRequest(null);
|
|
@@ -457,13 +499,21 @@ export function SharedBrowserPanel({
|
|
|
457
499
|
setOperationError(null);
|
|
458
500
|
setRuntimeNotice(null);
|
|
459
501
|
setBrowserClosed(false);
|
|
460
|
-
setSelectedTabId(null);
|
|
461
502
|
setTabCloseConfirmationOpen(false);
|
|
462
503
|
setControlRequest(null);
|
|
463
504
|
setPendingControlAction(null);
|
|
464
505
|
setCloseConfirmationOpen(false);
|
|
465
506
|
}, [reset, workspaceId, host.id, inputLifecycle]);
|
|
466
507
|
|
|
508
|
+
// The remembered tab belongs to this host and workspace. Keep it on mount,
|
|
509
|
+
// where it was just restored, and clear it only when the scope really changes.
|
|
510
|
+
const selectionScopeRef = useRef(panelScope);
|
|
511
|
+
useEffect(() => {
|
|
512
|
+
if (selectionScopeRef.current === panelScope) return;
|
|
513
|
+
selectionScopeRef.current = panelScope;
|
|
514
|
+
setSelectedTabId(null);
|
|
515
|
+
}, [panelScope, setSelectedTabId]);
|
|
516
|
+
|
|
467
517
|
useEffect(() => {
|
|
468
518
|
// A tab selection changes the viewer's page and frame authority, even
|
|
469
519
|
// though the underlying Chromium process and saved profile stay shared.
|
package/index.client.tsx
CHANGED
package/npm-shrinkwrap.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"name": "@omercnet/paseo-shared-browser",
|
|
9
9
|
"version": "3.0.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@getpaseo/plugin": "0.13.0
|
|
11
|
+
"@getpaseo/plugin": "0.13.0",
|
|
12
12
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
13
13
|
"agent-browser": "0.39.1",
|
|
14
14
|
"esbuild": "0.28.2",
|
|
@@ -441,29 +441,29 @@
|
|
|
441
441
|
}
|
|
442
442
|
},
|
|
443
443
|
"node_modules/@getpaseo/client": {
|
|
444
|
-
"version": "0.13.0
|
|
445
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/client/-/client-0.13.0
|
|
446
|
-
"integrity": "sha512-
|
|
444
|
+
"version": "0.13.0",
|
|
445
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/client/-/client-0.13.0.tgz",
|
|
446
|
+
"integrity": "sha512-379gl/OHIowATqKBZugupxX6HaOPWQhkOeVnlMQNWnZ5oKbyfCTEPGSkzA8Kotvv1Uue2u+j8z2WnLXyZ9ChYQ==",
|
|
447
447
|
"peer": true,
|
|
448
448
|
"dependencies": {
|
|
449
|
-
"@getpaseo/protocol": "0.13.0
|
|
450
|
-
"@getpaseo/relay": "0.13.0
|
|
449
|
+
"@getpaseo/protocol": "0.13.0",
|
|
450
|
+
"@getpaseo/relay": "0.13.0",
|
|
451
451
|
"ws": "^8.20.0",
|
|
452
452
|
"zod": "^4.4.3"
|
|
453
453
|
}
|
|
454
454
|
},
|
|
455
455
|
"node_modules/@getpaseo/plugin": {
|
|
456
|
-
"version": "0.13.0
|
|
457
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/plugin/-/plugin-0.13.0
|
|
458
|
-
"integrity": "sha512-
|
|
456
|
+
"version": "0.13.0",
|
|
457
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/plugin/-/plugin-0.13.0.tgz",
|
|
458
|
+
"integrity": "sha512-8aGH0lf5kF9yjaM0dVsm8Awu5eB2jHhmbX9ljgf6+jttNWX3XRbRNeylg3whPoKORGrJNlpuLx3XvJMC5KSCaQ==",
|
|
459
459
|
"dependencies": {
|
|
460
460
|
"@agentclientprotocol/sdk": "^1.4.0",
|
|
461
461
|
"i18next": "^26.3.0",
|
|
462
462
|
"use-sync-external-store": "^1.6.0"
|
|
463
463
|
},
|
|
464
464
|
"peerDependencies": {
|
|
465
|
-
"@getpaseo/client": "0.13.0
|
|
466
|
-
"@getpaseo/protocol": "0.13.0
|
|
465
|
+
"@getpaseo/client": "0.13.0",
|
|
466
|
+
"@getpaseo/protocol": "0.13.0",
|
|
467
467
|
"react": ">=19.1.0 <20",
|
|
468
468
|
"react-native": ">=0.81.5",
|
|
469
469
|
"zod": "^4.4.3"
|
|
@@ -475,9 +475,9 @@
|
|
|
475
475
|
}
|
|
476
476
|
},
|
|
477
477
|
"node_modules/@getpaseo/protocol": {
|
|
478
|
-
"version": "0.13.0
|
|
479
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/protocol/-/protocol-0.13.0
|
|
480
|
-
"integrity": "sha512-
|
|
478
|
+
"version": "0.13.0",
|
|
479
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/protocol/-/protocol-0.13.0.tgz",
|
|
480
|
+
"integrity": "sha512-g5Hp6QP5hV7KTCrSRBVye2+qhptwnhhLXRn6PHaS1L8PgmeRh5LvrE8PZq3HRq8B1WxflVDuV2WRB2Z3FNcvJA==",
|
|
481
481
|
"peer": true,
|
|
482
482
|
"dependencies": {
|
|
483
483
|
"semver": "^7.8.5",
|
|
@@ -485,9 +485,9 @@
|
|
|
485
485
|
}
|
|
486
486
|
},
|
|
487
487
|
"node_modules/@getpaseo/relay": {
|
|
488
|
-
"version": "0.13.0
|
|
489
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/relay/-/relay-0.13.0
|
|
490
|
-
"integrity": "sha512-
|
|
488
|
+
"version": "0.13.0",
|
|
489
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/relay/-/relay-0.13.0.tgz",
|
|
490
|
+
"integrity": "sha512-Yd/RR+2hStTEtmkutwE21drjVmgz+RnQWyjmoh1++dPysp2oNsrimurnbfN0yoBJ5xXWlyuvn8Sr7CziTpkv7Q==",
|
|
491
491
|
"peer": true,
|
|
492
492
|
"dependencies": {
|
|
493
493
|
"@noble/ciphers": "^2.4.0",
|
|
@@ -1229,9 +1229,9 @@
|
|
|
1229
1229
|
}
|
|
1230
1230
|
},
|
|
1231
1231
|
"node_modules/i18next": {
|
|
1232
|
-
"version": "26.5.
|
|
1233
|
-
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.
|
|
1234
|
-
"integrity": "sha512-
|
|
1232
|
+
"version": "26.5.8",
|
|
1233
|
+
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.8.tgz",
|
|
1234
|
+
"integrity": "sha512-EQx2RyhwINMekbykhZpAJQ2ILeJqnYOpRjWEkSVv45pR8yeVbb0thr2zxQ+dOo365OIb7h06BKPtt16WE8Wliw==",
|
|
1235
1235
|
"funding": [
|
|
1236
1236
|
{
|
|
1237
1237
|
"type": "individual",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omercnet/paseo-shared-browser",
|
|
3
|
-
"version": "3.0.0-next.
|
|
3
|
+
"version": "3.0.0-next.292.1",
|
|
4
4
|
"description": "One real Chromium session per Paseo workspace, shared live across every connected client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"browser",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"test:video": "vitest run tests/video.smoke.test.ts --testTimeout=30000"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@getpaseo/plugin": "0.13.0
|
|
57
|
+
"@getpaseo/plugin": "0.13.0",
|
|
58
58
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
59
59
|
"agent-browser": "0.39.1",
|
|
60
60
|
"esbuild": "0.28.2",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@biomejs/biome": "^2.5.10",
|
|
65
|
-
"@getpaseo/server": "0.13.0
|
|
65
|
+
"@getpaseo/server": "0.13.0",
|
|
66
66
|
"@tanstack/react-query": "^5.102.3",
|
|
67
67
|
"@types/node": "^24.10.1",
|
|
68
68
|
"@types/react": "^19.2.18",
|
package/paseo-plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "shared-browser",
|
|
3
3
|
"description": "One real Chromium session per Paseo workspace, shared live across every connected client.",
|
|
4
|
-
"requirements": { "paseo": "^0.
|
|
4
|
+
"requirements": { "paseo": "^0.13.0" },
|
|
5
5
|
"build": [["node", "scripts/prepare-dependencies.mjs"], ["npm", "run", "prepare:runtime"]]
|
|
6
6
|
}
|