@omercnet/paseo-shared-browser 3.0.0 → 4.0.0-next.313.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 +126 -47
- 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 || ^0.14.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 || ^0.14.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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omercnet/paseo-shared-browser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@omercnet/paseo-shared-browser",
|
|
9
|
-
"version": "
|
|
9
|
+
"version": "4.0.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@getpaseo/plugin": "0.
|
|
11
|
+
"@getpaseo/plugin": "0.14.0-beta.1",
|
|
12
12
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
13
13
|
"agent-browser": "0.39.1",
|
|
14
14
|
"esbuild": "0.28.2",
|
|
@@ -441,28 +441,30 @@
|
|
|
441
441
|
}
|
|
442
442
|
},
|
|
443
443
|
"node_modules/@getpaseo/client": {
|
|
444
|
-
"version": "0.
|
|
445
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/client/-/client-0.
|
|
446
|
-
"integrity": "sha512-
|
|
444
|
+
"version": "0.14.0-beta.1",
|
|
445
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/client/-/client-0.14.0-beta.1.tgz",
|
|
446
|
+
"integrity": "sha512-uG7ClWxBljs9g/q2XInPqETMrDeU8kkCSD/pr+lgyqqSq/l8F/oQ9EMS/TH9tLRqKIwWEdUl9+r4AnpPVxA5iQ==",
|
|
447
447
|
"peer": true,
|
|
448
448
|
"dependencies": {
|
|
449
|
-
"@getpaseo/protocol": "0.
|
|
450
|
-
"@getpaseo/relay": "0.
|
|
449
|
+
"@getpaseo/protocol": "0.14.0-beta.1",
|
|
450
|
+
"@getpaseo/relay": "0.14.0-beta.1",
|
|
451
|
+
"ws": "^8.20.0",
|
|
451
452
|
"zod": "^4.4.3"
|
|
452
453
|
}
|
|
453
454
|
},
|
|
454
455
|
"node_modules/@getpaseo/plugin": {
|
|
455
|
-
"version": "0.
|
|
456
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/plugin/-/plugin-0.
|
|
457
|
-
"integrity": "sha512-
|
|
456
|
+
"version": "0.14.0-beta.1",
|
|
457
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/plugin/-/plugin-0.14.0-beta.1.tgz",
|
|
458
|
+
"integrity": "sha512-AAYp3xaX6l5W0oOqCGyfJKL/IeguhTKGEEN4WlISuC1+B7GGu+adUPESOPkhs/4THfzk0TZjuAQBImGhYDrXuw==",
|
|
458
459
|
"dependencies": {
|
|
459
460
|
"@agentclientprotocol/sdk": "^1.4.0",
|
|
461
|
+
"i18next": "^26.3.0",
|
|
460
462
|
"use-sync-external-store": "^1.6.0"
|
|
461
463
|
},
|
|
462
464
|
"peerDependencies": {
|
|
463
|
-
"@getpaseo/client": "0.
|
|
464
|
-
"@getpaseo/protocol": "0.
|
|
465
|
-
"react": "
|
|
465
|
+
"@getpaseo/client": "0.14.0-beta.1",
|
|
466
|
+
"@getpaseo/protocol": "0.14.0-beta.1",
|
|
467
|
+
"react": ">=19.1.0 <20",
|
|
466
468
|
"react-native": ">=0.81.5",
|
|
467
469
|
"zod": "^4.4.3"
|
|
468
470
|
},
|
|
@@ -473,9 +475,9 @@
|
|
|
473
475
|
}
|
|
474
476
|
},
|
|
475
477
|
"node_modules/@getpaseo/protocol": {
|
|
476
|
-
"version": "0.
|
|
477
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/protocol/-/protocol-0.
|
|
478
|
-
"integrity": "sha512-
|
|
478
|
+
"version": "0.14.0-beta.1",
|
|
479
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/protocol/-/protocol-0.14.0-beta.1.tgz",
|
|
480
|
+
"integrity": "sha512-qkZCmLlL5EQ1PkN0Jy8JLIfyqoj34UC2HdJIicERQ/OdrYGQ3krpOfIpYJ3c3BU27GcDL/E4aoA0GbuEVR4qUw==",
|
|
479
481
|
"peer": true,
|
|
480
482
|
"dependencies": {
|
|
481
483
|
"semver": "^7.8.5",
|
|
@@ -483,11 +485,14 @@
|
|
|
483
485
|
}
|
|
484
486
|
},
|
|
485
487
|
"node_modules/@getpaseo/relay": {
|
|
486
|
-
"version": "0.
|
|
487
|
-
"resolved": "https://registry.npmjs.org/@getpaseo/relay/-/relay-0.
|
|
488
|
-
"integrity": "sha512-
|
|
488
|
+
"version": "0.14.0-beta.1",
|
|
489
|
+
"resolved": "https://registry.npmjs.org/@getpaseo/relay/-/relay-0.14.0-beta.1.tgz",
|
|
490
|
+
"integrity": "sha512-JgFNDsOX5WGgyBreyxsJ98Mwzi6Q+BUDIn8m+/lSUYpMqQyr2KeX0hKQqoDXv4rA0FhHgi5U/GG4LG2BGZx0PA==",
|
|
489
491
|
"peer": true,
|
|
490
492
|
"dependencies": {
|
|
493
|
+
"@noble/ciphers": "^2.4.0",
|
|
494
|
+
"@noble/curves": "^2.4.0",
|
|
495
|
+
"@noble/hashes": "^2.4.0",
|
|
491
496
|
"base64-js": "^1.5.1",
|
|
492
497
|
"tweetnacl": "^1.0.3",
|
|
493
498
|
"ws": "^8.14.2"
|
|
@@ -545,6 +550,48 @@
|
|
|
545
550
|
}
|
|
546
551
|
}
|
|
547
552
|
},
|
|
553
|
+
"node_modules/@noble/ciphers": {
|
|
554
|
+
"version": "2.4.0",
|
|
555
|
+
"resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.4.0.tgz",
|
|
556
|
+
"integrity": "sha512-AnjFn0Jv92laAkvMrghlFZq4qQCIN/4DxFV/eooqtC2YTjB7kBeLMS2T9KJX4Dn+ZVXLOwK0lSgqDtx9gvxtiw==",
|
|
557
|
+
"license": "MIT",
|
|
558
|
+
"peer": true,
|
|
559
|
+
"engines": {
|
|
560
|
+
"node": ">= 20.19.0"
|
|
561
|
+
},
|
|
562
|
+
"funding": {
|
|
563
|
+
"url": "https://paulmillr.com/funding/"
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
"node_modules/@noble/curves": {
|
|
567
|
+
"version": "2.4.0",
|
|
568
|
+
"resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.4.0.tgz",
|
|
569
|
+
"integrity": "sha512-P4/62zrgfH33CneE3Dn4WhJVA22YUU0eR51wKIan4NVRvwsA0YnPTwWGpNbpuacSujmSFLvyzpyuR30+fbq2Ew==",
|
|
570
|
+
"license": "MIT",
|
|
571
|
+
"peer": true,
|
|
572
|
+
"dependencies": {
|
|
573
|
+
"@noble/hashes": "2.4.0"
|
|
574
|
+
},
|
|
575
|
+
"engines": {
|
|
576
|
+
"node": ">= 20.19.0"
|
|
577
|
+
},
|
|
578
|
+
"funding": {
|
|
579
|
+
"url": "https://paulmillr.com/funding/"
|
|
580
|
+
}
|
|
581
|
+
},
|
|
582
|
+
"node_modules/@noble/hashes": {
|
|
583
|
+
"version": "2.4.0",
|
|
584
|
+
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz",
|
|
585
|
+
"integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==",
|
|
586
|
+
"license": "MIT",
|
|
587
|
+
"peer": true,
|
|
588
|
+
"engines": {
|
|
589
|
+
"node": ">= 20.19.0"
|
|
590
|
+
},
|
|
591
|
+
"funding": {
|
|
592
|
+
"url": "https://paulmillr.com/funding/"
|
|
593
|
+
}
|
|
594
|
+
},
|
|
548
595
|
"node_modules/accepts": {
|
|
549
596
|
"version": "2.0.0",
|
|
550
597
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
|
|
@@ -627,18 +674,18 @@
|
|
|
627
674
|
"peer": true
|
|
628
675
|
},
|
|
629
676
|
"node_modules/body-parser": {
|
|
630
|
-
"version": "2.
|
|
631
|
-
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.
|
|
632
|
-
"integrity": "sha512-
|
|
677
|
+
"version": "2.4.0",
|
|
678
|
+
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.4.0.tgz",
|
|
679
|
+
"integrity": "sha512-Ifk1KcLrxaGt1occQagQNFNNOqRt1LFuehEnHHzB8Z6cRgIxRU1TBaiIsUiCdA+gy5PL7Y1IX31DNKkRmxtXjQ==",
|
|
633
680
|
"license": "MIT",
|
|
634
681
|
"dependencies": {
|
|
635
682
|
"bytes": "^3.1.2",
|
|
636
|
-
"content-type": "^2.
|
|
683
|
+
"content-type": "^2.1.0",
|
|
637
684
|
"debug": "^4.4.3",
|
|
638
685
|
"http-errors": "^2.0.1",
|
|
639
|
-
"iconv-lite": "^0.7.
|
|
686
|
+
"iconv-lite": "^0.7.3",
|
|
640
687
|
"on-finished": "^2.4.1",
|
|
641
|
-
"qs": "^6.
|
|
688
|
+
"qs": "^6.16.1",
|
|
642
689
|
"raw-body": "^3.0.2",
|
|
643
690
|
"type-is": "^2.1.0"
|
|
644
691
|
},
|
|
@@ -1016,9 +1063,9 @@
|
|
|
1016
1063
|
"license": "MIT"
|
|
1017
1064
|
},
|
|
1018
1065
|
"node_modules/fast-uri": {
|
|
1019
|
-
"version": "3.1.
|
|
1020
|
-
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.
|
|
1021
|
-
"integrity": "sha512-
|
|
1066
|
+
"version": "3.1.9",
|
|
1067
|
+
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz",
|
|
1068
|
+
"integrity": "sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==",
|
|
1022
1069
|
"funding": [
|
|
1023
1070
|
{
|
|
1024
1071
|
"type": "github",
|
|
@@ -1153,9 +1200,9 @@
|
|
|
1153
1200
|
}
|
|
1154
1201
|
},
|
|
1155
1202
|
"node_modules/hono": {
|
|
1156
|
-
"version": "4.13.
|
|
1157
|
-
"resolved": "https://registry.npmjs.org/hono/-/hono-4.13.
|
|
1158
|
-
"integrity": "sha512-
|
|
1203
|
+
"version": "4.13.14",
|
|
1204
|
+
"resolved": "https://registry.npmjs.org/hono/-/hono-4.13.14.tgz",
|
|
1205
|
+
"integrity": "sha512-yhRLQ21U6qa9Hsu2N7Qcbh8tE+WKEcoErjIo56LeSGiGXGp9sA7UpE86Ui9uexb61KakiGwuHMn2QdV7w6i6kQ==",
|
|
1159
1206
|
"license": "MIT",
|
|
1160
1207
|
"engines": {
|
|
1161
1208
|
"node": ">=16.9.0"
|
|
@@ -1181,6 +1228,34 @@
|
|
|
1181
1228
|
"url": "https://opencollective.com/express"
|
|
1182
1229
|
}
|
|
1183
1230
|
},
|
|
1231
|
+
"node_modules/i18next": {
|
|
1232
|
+
"version": "26.5.11",
|
|
1233
|
+
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.11.tgz",
|
|
1234
|
+
"integrity": "sha512-Wc0klBPKxqZ2tL2qdAnF8xvvnWgr1IMGSY2ikTiAvaFVbz7xiFARtkoU4RidBDw1SyziGROp0qxu6qnJ7l2Wug==",
|
|
1235
|
+
"funding": [
|
|
1236
|
+
{
|
|
1237
|
+
"type": "individual",
|
|
1238
|
+
"url": "https://www.locize.com/i18next"
|
|
1239
|
+
},
|
|
1240
|
+
{
|
|
1241
|
+
"type": "individual",
|
|
1242
|
+
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
|
1243
|
+
},
|
|
1244
|
+
{
|
|
1245
|
+
"type": "individual",
|
|
1246
|
+
"url": "https://www.locize.com"
|
|
1247
|
+
}
|
|
1248
|
+
],
|
|
1249
|
+
"license": "MIT",
|
|
1250
|
+
"peerDependencies": {
|
|
1251
|
+
"typescript": "^5 || ^6 || ^7"
|
|
1252
|
+
},
|
|
1253
|
+
"peerDependenciesMeta": {
|
|
1254
|
+
"typescript": {
|
|
1255
|
+
"optional": true
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1184
1259
|
"node_modules/iconv-lite": {
|
|
1185
1260
|
"version": "0.7.3",
|
|
1186
1261
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz",
|
|
@@ -1204,9 +1279,9 @@
|
|
|
1204
1279
|
"license": "ISC"
|
|
1205
1280
|
},
|
|
1206
1281
|
"node_modules/ip-address": {
|
|
1207
|
-
"version": "10.7.
|
|
1208
|
-
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.
|
|
1209
|
-
"integrity": "sha512-
|
|
1282
|
+
"version": "10.7.5",
|
|
1283
|
+
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.5.tgz",
|
|
1284
|
+
"integrity": "sha512-t2v0rkILYv9WXmSL7TpAaU3HXgaFYOPUcH3QHgwQ++gpJuH3bqyMy4Fvt/DJCTKwzH3Cf+bAp5W/mFL39KPLzA==",
|
|
1210
1285
|
"license": "MIT",
|
|
1211
1286
|
"engines": {
|
|
1212
1287
|
"node": ">= 12"
|
|
@@ -1234,9 +1309,9 @@
|
|
|
1234
1309
|
"license": "ISC"
|
|
1235
1310
|
},
|
|
1236
1311
|
"node_modules/jose": {
|
|
1237
|
-
"version": "6.2.
|
|
1238
|
-
"resolved": "https://registry.npmjs.org/jose/-/jose-6.2.
|
|
1239
|
-
"integrity": "sha512-
|
|
1312
|
+
"version": "6.2.13",
|
|
1313
|
+
"resolved": "https://registry.npmjs.org/jose/-/jose-6.2.13.tgz",
|
|
1314
|
+
"integrity": "sha512-7TIg10ZE1x82YediN+lcrPNvGMKge9yFHQD+Qho/b8y2adfugU3AsvvHfxV0fzyFllT6l9xCjf4RWY9g/Z9PJQ==",
|
|
1240
1315
|
"license": "MIT",
|
|
1241
1316
|
"funding": {
|
|
1242
1317
|
"url": "https://github.com/sponsors/panva"
|
|
@@ -1370,15 +1445,19 @@
|
|
|
1370
1445
|
}
|
|
1371
1446
|
},
|
|
1372
1447
|
"node_modules/on-finished": {
|
|
1373
|
-
"version": "2.4.
|
|
1374
|
-
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.
|
|
1375
|
-
"integrity": "sha512-
|
|
1448
|
+
"version": "2.4.2",
|
|
1449
|
+
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.2.tgz",
|
|
1450
|
+
"integrity": "sha512-ATWUv387i+nLD49EiDoOft5scf32Vsdz3ktrQJG9bi7jRFmaXTssvyvj1EmeKVVgvesbqUtvQQvaS2TpTukAZQ==",
|
|
1376
1451
|
"license": "MIT",
|
|
1377
1452
|
"dependencies": {
|
|
1378
1453
|
"ee-first": "1.1.1"
|
|
1379
1454
|
},
|
|
1380
1455
|
"engines": {
|
|
1381
1456
|
"node": ">= 0.8"
|
|
1457
|
+
},
|
|
1458
|
+
"funding": {
|
|
1459
|
+
"type": "opencollective",
|
|
1460
|
+
"url": "https://opencollective.com/express"
|
|
1382
1461
|
}
|
|
1383
1462
|
},
|
|
1384
1463
|
"node_modules/once": {
|
|
@@ -1445,9 +1524,9 @@
|
|
|
1445
1524
|
}
|
|
1446
1525
|
},
|
|
1447
1526
|
"node_modules/qs": {
|
|
1448
|
-
"version": "6.
|
|
1449
|
-
"resolved": "https://registry.npmjs.org/qs/-/qs-6.
|
|
1450
|
-
"integrity": "sha512-
|
|
1527
|
+
"version": "6.17.0",
|
|
1528
|
+
"resolved": "https://registry.npmjs.org/qs/-/qs-6.17.0.tgz",
|
|
1529
|
+
"integrity": "sha512-5LK5BZ2XDHMvcUJaf0CQ5HL3aVgKbpklvByC7qLSxYkfE8COEEbJg5xCHWCTqzqi0Gs4Jn5Mv5v3R38W6edscA==",
|
|
1451
1530
|
"license": "BSD-3-Clause",
|
|
1452
1531
|
"dependencies": {
|
|
1453
1532
|
"es-define-property": "^1.0.1",
|
|
@@ -1489,9 +1568,9 @@
|
|
|
1489
1568
|
}
|
|
1490
1569
|
},
|
|
1491
1570
|
"node_modules/react": {
|
|
1492
|
-
"version": "19.1
|
|
1493
|
-
"resolved": "https://registry.npmjs.org/react/-/react-19.1.
|
|
1494
|
-
"integrity": "sha512-
|
|
1571
|
+
"version": "19.3.1",
|
|
1572
|
+
"resolved": "https://registry.npmjs.org/react/-/react-19.3.1.tgz",
|
|
1573
|
+
"integrity": "sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==",
|
|
1495
1574
|
"license": "MIT",
|
|
1496
1575
|
"peer": true,
|
|
1497
1576
|
"engines": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omercnet/paseo-shared-browser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-next.313.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.
|
|
57
|
+
"@getpaseo/plugin": "0.14.0-beta.1",
|
|
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.
|
|
65
|
+
"@getpaseo/server": "0.14.0-beta.1",
|
|
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 || ^0.14.0" },
|
|
5
5
|
"build": [["node", "scripts/prepare-dependencies.mjs"], ["npm", "run", "prepare:runtime"]]
|
|
6
6
|
}
|