@mearl/native-host 2.22.0 → 3.0.0-beta.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.
Files changed (91) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +4 -0
  3. package/dist/THIRD_PARTY_NOTICES.txt +773 -0
  4. package/dist/agent/event-transport.d.ts +3 -0
  5. package/dist/agent/manager.d.ts +59 -0
  6. package/dist/agent/skill-manager.d.ts +52 -0
  7. package/dist/agent/workspace-directory.d.ts +4 -0
  8. package/dist/alipay-auth-code.d.ts +13 -0
  9. package/dist/analytics.d.ts +3 -0
  10. package/dist/app-profile-catalog.d.ts +11 -0
  11. package/dist/browser-artifacts.d.ts +26 -0
  12. package/dist/browser-inventory.d.ts +22 -0
  13. package/dist/browser-provider-coordinator.d.ts +24 -0
  14. package/dist/browser-provider.d.ts +30 -0
  15. package/dist/browser-registry.d.ts +93 -0
  16. package/dist/browser-socket-request.d.ts +5 -0
  17. package/dist/builtin-browser-providers.d.ts +8 -0
  18. package/dist/builtin-provider-options.d.ts +11 -0
  19. package/dist/capability-contracts.d.ts +73 -0
  20. package/dist/cdp-backend/action-registry.d.ts +36 -0
  21. package/dist/cdp-backend/app-profile-handlers.d.ts +62 -0
  22. package/dist/cdp-backend/browser-handlers.d.ts +6 -0
  23. package/dist/cdp-backend/buffers.d.ts +72 -0
  24. package/dist/cdp-backend/cdp-session.d.ts +102 -0
  25. package/dist/cdp-backend/cdp-utils.d.ts +41 -0
  26. package/dist/cdp-backend/client.d.ts +41 -0
  27. package/dist/cdp-backend/composite-handlers.d.ts +17 -0
  28. package/dist/cdp-backend/controlled-indicator.d.ts +18 -0
  29. package/dist/cdp-backend/cookie-handlers.d.ts +7 -0
  30. package/dist/cdp-backend/cookie-transfer.d.ts +37 -0
  31. package/dist/cdp-backend/device-shell.d.ts +26 -0
  32. package/dist/cdp-backend/discover.d.ts +29 -0
  33. package/dist/cdp-backend/domain-manager.d.ts +4 -0
  34. package/dist/cdp-backend/download-handlers.d.ts +9 -0
  35. package/dist/cdp-backend/fetch-interceptor.d.ts +26 -0
  36. package/dist/cdp-backend/frame-evaluation.d.ts +3 -0
  37. package/dist/cdp-backend/frame-tree.d.ts +16 -0
  38. package/dist/cdp-backend/handlers.d.ts +30 -0
  39. package/dist/cdp-backend/http-handlers.d.ts +33 -0
  40. package/dist/cdp-backend/interaction-handlers.d.ts +19 -0
  41. package/dist/cdp-backend/mock-handlers.d.ts +10 -0
  42. package/dist/cdp-backend/mtop-environment.d.ts +7 -0
  43. package/dist/cdp-backend/navigation-observer.d.ts +9 -0
  44. package/dist/cdp-backend/page-observer.d.ts +5 -0
  45. package/dist/cdp-backend/page-refs.d.ts +9 -0
  46. package/dist/cdp-backend/page-session-initializers.d.ts +6 -0
  47. package/dist/cdp-backend/plugin-pages.d.ts +12 -0
  48. package/dist/cdp-backend/release-control.d.ts +13 -0
  49. package/dist/cdp-backend/request-handlers.d.ts +10 -0
  50. package/dist/cdp-backend/rule-handlers.d.ts +11 -0
  51. package/dist/cdp-backend/send-request.d.ts +2 -0
  52. package/dist/cdp-backend/snapshot-handlers.d.ts +7 -0
  53. package/dist/cdp-backend/tab-handlers.d.ts +8 -0
  54. package/dist/cdp-backend/timezone-handlers.d.ts +4 -0
  55. package/dist/cloud-connector.d.ts +61 -0
  56. package/dist/config.d.ts +7 -0
  57. package/dist/control-session-manager.d.ts +30 -0
  58. package/dist/control-session.d.ts +31 -0
  59. package/dist/extension-file-transfer.d.ts +7 -0
  60. package/dist/extension-updater.d.ts +18 -0
  61. package/dist/host-updater.d.ts +39 -0
  62. package/dist/index.d.ts +2 -0
  63. package/dist/index.js +263 -350
  64. package/dist/install.d.ts +1 -0
  65. package/dist/install.js +1 -1
  66. package/dist/internal-extension-actions.d.ts +10 -0
  67. package/dist/launcher.d.ts +1 -0
  68. package/dist/managed-browser.d.ts +61 -0
  69. package/dist/native-capability-services.d.ts +21 -0
  70. package/dist/node-capabilities.d.ts +20 -0
  71. package/dist/node-capabilities.js +4 -0
  72. package/dist/page-runtime-store.d.ts +27 -0
  73. package/dist/persistent-browser-record.d.ts +8 -0
  74. package/dist/plugin-host-services.d.ts +7 -0
  75. package/dist/plugin-page-results.d.ts +7 -0
  76. package/dist/plugin-task-host.js +21 -21
  77. package/dist/plugin-worker.js +19 -19
  78. package/dist/pluginModelSessionWorker.js +1 -1
  79. package/dist/preset-components.d.ts +35 -0
  80. package/dist/preset-installation.d.ts +19 -0
  81. package/dist/provider-control-host.d.ts +1 -0
  82. package/dist/provider-control.d.ts +28 -0
  83. package/dist/provider-request-timeout.d.ts +2 -0
  84. package/dist/runtimeArgs.d.ts +14 -0
  85. package/dist/sandbox-browser-access.d.ts +10 -0
  86. package/dist/send-request-file-utils.d.ts +14 -0
  87. package/dist/socketLines.d.ts +12 -0
  88. package/dist/toolbox-permissions.d.ts +8 -0
  89. package/dist/toolbox-service.d.ts +26 -0
  90. package/dist/version.d.ts +1 -0
  91. package/package.json +31 -16
@@ -0,0 +1,3 @@
1
+ import type { AgentChatEvent } from '@mearl/browser-core';
2
+ export declare const MAX_AGENT_EVENT_BYTES: number;
3
+ export declare function sanitizeAgentChatEvent(event: AgentChatEvent): AgentChatEvent;
@@ -0,0 +1,59 @@
1
+ import type { AgentChatEvent, AgentChatEventsOptions, AgentChatEventsResult, AgentChatListSessionsOptions, AgentChatListSessionsResult, AgentChatOpenWorkspaceOptions, AgentChatPrepareOptions, AgentChatRefreshResult, AgentChatRunOptions, AgentChatRunResult, AgentChatRespondOptions, AgentChatSendOptions, AgentChatSession, AgentChatSessionTarget, AgentChatStartOptions, AgentChatStatus, AgentInstalledSkill, AgentSkillInstalledListOptions, AgentSkillReadOptions, AgentSkillReadResult } from '@mearl/browser-core';
2
+ import { type ToolboxAgentRuntime } from '../toolbox-service.js';
3
+ import type { AgentProvider, AgentProviderSessionOptions, AgentProviderTurnOptions } from '@mearl/agent-runtime';
4
+ export interface AgentChatManagerDependencies {
5
+ resolveToolboxAgent?: (toolId: string) => ToolboxAgentRuntime;
6
+ }
7
+ interface AgentProviderLoader {
8
+ id: string;
9
+ load(): Promise<AgentProvider>;
10
+ }
11
+ export declare class AgentChatManager {
12
+ private readonly emit;
13
+ private readonly dependencies;
14
+ private readonly providers;
15
+ private readonly providerLoaders;
16
+ private readonly providerLoads;
17
+ private disposed;
18
+ private readonly sessions;
19
+ private readonly sessionByProviderThread;
20
+ private readonly pendingRequests;
21
+ private readonly completedTurns;
22
+ private readonly recentEvents;
23
+ private readonly recentEventBytes;
24
+ private readonly compactedEventCounts;
25
+ private readonly truncatedEventSessions;
26
+ private readonly unsubscribe;
27
+ private readonly taskListeners;
28
+ constructor(providers: Array<AgentProvider | AgentProviderLoader>, emit: (event: AgentChatEvent) => void, dependencies?: AgentChatManagerDependencies);
29
+ getStatus(): Promise<AgentChatStatus>;
30
+ prepare(options: AgentChatPrepareOptions): Promise<void>;
31
+ listSkills(options: AgentSkillInstalledListOptions): Promise<AgentInstalledSkill[]>;
32
+ readSkill(options: AgentSkillReadOptions): Promise<AgentSkillReadResult>;
33
+ listSessions(options: AgentChatListSessionsOptions): Promise<AgentChatListSessionsResult>;
34
+ startSession(options: AgentChatStartOptions, providerOptionsOverride?: Pick<AgentProviderSessionOptions, 'readOnly'>): Promise<AgentChatSession>;
35
+ sendMessage(options: AgentChatSendOptions, turnOptions?: AgentProviderTurnOptions): Promise<{
36
+ turnId: string;
37
+ }>;
38
+ runTask(options: AgentChatRunOptions): Promise<AgentChatRunResult>;
39
+ interrupt(options: AgentChatSessionTarget): Promise<void>;
40
+ openSession(options: AgentChatSessionTarget): Promise<void>;
41
+ openWorkspace(options: AgentChatOpenWorkspaceOptions): Promise<void>;
42
+ closeSession(options: AgentChatSessionTarget): Promise<void>;
43
+ getEvents(options: AgentChatEventsOptions): AgentChatEventsResult;
44
+ refreshSession(options: AgentChatEventsOptions): Promise<AgentChatRefreshResult>;
45
+ respondToRequest(options: AgentChatRespondOptions): void;
46
+ dispose(): void;
47
+ private handleProviderEvent;
48
+ private emitEvent;
49
+ private recordEvent;
50
+ private trimReplayBuffer;
51
+ private getProvider;
52
+ private registerProvider;
53
+ private loadProvider;
54
+ private getSession;
55
+ private providerThreadKey;
56
+ private providerRequestKey;
57
+ private sessionTurnKey;
58
+ }
59
+ export {};
@@ -0,0 +1,52 @@
1
+ import type { AgentSkillCheckUpdatesResult, AgentSkillCheckUpdatesOptions, AgentSkillInstallOptions, AgentSkillMutationOptions, AgentSkillMutationResult, AgentSkillProviderId } from '@mearl/browser-core';
2
+ import { checkTrackedSkillUpdates, readTrackedSkillSources, type SkillInstallationStatus } from '@mearl/setup/skill-sources';
3
+ export type SkillCliRunner = (executable: string, args: string[], cwd?: string) => Promise<{
4
+ stdout: string;
5
+ stderr: string;
6
+ }>;
7
+ export type SkillBackendBatchOptions = Omit<AgentSkillInstallOptions, 'name' | 'providerId'> & {
8
+ names: string[];
9
+ providerId?: AgentSkillProviderId;
10
+ };
11
+ /** A preset supplies CLI behavior; directory state and plugin registration stay in the host. */
12
+ export interface AgentSkillBackend {
13
+ id: string;
14
+ install(data: AgentSkillInstallOptions): ReturnType<SkillCliRunner>;
15
+ installBatch?(data: SkillBackendBatchOptions): ReturnType<SkillCliRunner>;
16
+ normalizeSource?(source: string, sourceType?: string): string;
17
+ update(data: AgentSkillMutationOptions): ReturnType<SkillCliRunner>;
18
+ uninstall(data: AgentSkillMutationOptions): ReturnType<SkillCliRunner>;
19
+ checkUpdates(data: AgentSkillCheckUpdatesOptions): Promise<AgentSkillCheckUpdatesResult>;
20
+ }
21
+ export declare const runSkillCli: SkillCliRunner;
22
+ export interface AgentSkillManagerOptions {
23
+ run?: SkillCliRunner;
24
+ checkUpdates?: typeof checkTrackedSkillUpdates;
25
+ readSources?: typeof readTrackedSkillSources;
26
+ backend?: () => AgentSkillBackend | undefined;
27
+ }
28
+ export type { SkillInstallationStatus } from '@mearl/setup/skill-sources';
29
+ export declare class AgentSkillManager {
30
+ private readonly run;
31
+ private readonly check;
32
+ private readonly sources;
33
+ private readonly selectedBackend;
34
+ constructor(options?: AgentSkillManagerOptions);
35
+ private backend;
36
+ /** A preset batch keeps one accepted manager for all of its operations. */
37
+ capture(): AgentSkillManager;
38
+ inspectGlobal(source: string, name: string, version?: string): SkillInstallationStatus;
39
+ repairGlobalRegistration(name: string, options?: {
40
+ registrationManagedBy?: string;
41
+ }): Promise<void>;
42
+ install(data: AgentSkillInstallOptions): Promise<AgentSkillMutationResult>;
43
+ installGlobal(source: string, name: string): Promise<AgentSkillMutationResult>;
44
+ installGlobals(source: string, names: string[], options?: {
45
+ registrationManagedBy?: string;
46
+ }): Promise<AgentSkillMutationResult>;
47
+ private installAccepted;
48
+ checkUpdates(data: AgentSkillCheckUpdatesOptions): Promise<AgentSkillCheckUpdatesResult>;
49
+ update(data: AgentSkillMutationOptions): Promise<AgentSkillMutationResult>;
50
+ uninstall(data: AgentSkillMutationOptions): Promise<AgentSkillMutationResult>;
51
+ private mutationContext;
52
+ }
@@ -0,0 +1,4 @@
1
+ export type DirectoryPickerRunner = (command: string, args: string[]) => Promise<string | null>;
2
+ export declare const runDirectoryPickerCommand: DirectoryPickerRunner;
3
+ export declare function pickWorkspaceDirectory(platform?: NodeJS.Platform, run?: DirectoryPickerRunner): Promise<string | null>;
4
+ export declare function resolveWorkspaceDirectory(directory: unknown): string;
@@ -0,0 +1,13 @@
1
+ export type AlipayAuthCodeProgress = 'installing' | 'connected' | 'authorizing';
2
+ export interface AlipayAuthCodeParams {
3
+ appId: string;
4
+ scopeNicks: string[];
5
+ showErrorTip?: boolean;
6
+ }
7
+ export declare function validateAlipayAuthCodeParams(value: unknown): AlipayAuthCodeParams;
8
+ export declare function startAlipayAuthCode(value: unknown, onProgress?: (phase: AlipayAuthCodeProgress) => void): Promise<{
9
+ browserId: string;
10
+ qrSvg: string;
11
+ }>;
12
+ export declare function waitAlipayAuthCode(browserId: string, value: unknown, onProgress?: (phase: AlipayAuthCodeProgress) => void): Promise<Record<string, unknown>>;
13
+ export declare function closeAlipayAuthCode(browserId: string): Promise<void>;
@@ -0,0 +1,3 @@
1
+ export declare function setAnalyticsClientId(value: unknown): boolean;
2
+ export declare function classifyAnalyticsError(error: unknown): string;
3
+ export declare function trackAction(action: string, params?: Record<string, string | number | boolean>): void;
@@ -0,0 +1,11 @@
1
+ import { type ResolveAppProfileOptions } from '@mearl/app-profiles';
2
+ import { type AppProfileCatalogEntry } from '@mearl/browser-core';
3
+ export declare function findCapabilityAppProfile(id: string): AppProfileCatalogEntry | undefined;
4
+ export declare function listInstalledAppProfiles(): Promise<{
5
+ profiles: AppProfileCatalogEntry[];
6
+ errors: Array<{
7
+ plugin: string;
8
+ error: string;
9
+ }>;
10
+ }>;
11
+ export declare function resolveInstalledAppProfile(name: string, options?: ResolveAppProfileOptions): Promise<import("@mearl/app-profiles").ResolvedAppProfile>;
@@ -0,0 +1,26 @@
1
+ import type { BrowserArtifact } from '@mearl/browser-core';
2
+ export declare const ARTIFACT_CHUNK_BYTES: number;
3
+ /** Opaque ids keep browser-host paths out of remote file requests. */
4
+ export declare class BrowserArtifactStore {
5
+ private root;
6
+ private files;
7
+ private directory?;
8
+ private sweeper?;
9
+ constructor(root?: string);
10
+ create(filename: string, sessionId?: string): Promise<BrowserArtifact>;
11
+ importFile(filename: string, sourcePath: string, sessionId?: string): Promise<BrowserArtifact>;
12
+ private require;
13
+ private info;
14
+ write(id: string, offset: number, base64: string, sessionId?: string): Promise<BrowserArtifact>;
15
+ complete(id: string, bytes: number, sessionId?: string): BrowserArtifact;
16
+ resolve(id: string, sessionId?: string): string;
17
+ read(id: string, offset: number, sessionId?: string): Promise<{
18
+ base64: string;
19
+ bytes: number;
20
+ totalBytes: number;
21
+ }>;
22
+ remove(id: string, sessionId?: string): Promise<void>;
23
+ release(sessionId: string, keep?: string[]): Promise<void>;
24
+ disposeSync(): void;
25
+ dispose(): Promise<void>;
26
+ }
@@ -0,0 +1,22 @@
1
+ import type { BrowserListResult, BrowserProviderIdentity, ManagedBrowserInfo } from '@mearl/browser-core';
2
+ import type { ProviderBrowser, ProviderDescriptor, ProviderRuntime } from '@mearl/provider';
3
+ import { type BrowserRecord } from './browser-registry.js';
4
+ type BrowserInventoryResult = Omit<BrowserListResult, 'defaultBrowserId'>;
5
+ export interface CdpBrowserDiscovery {
6
+ isPublished: () => boolean;
7
+ isAvailable: () => Promise<boolean>;
8
+ publish: () => boolean;
9
+ monitor: () => void;
10
+ }
11
+ export declare function providerIdentity(descriptor: ProviderDescriptor): BrowserProviderIdentity;
12
+ export interface ProviderInventoryBrowser {
13
+ provider: BrowserProviderIdentity;
14
+ browser: ProviderBrowser;
15
+ }
16
+ /** Register the default CDP browser only after a live browser-level connection succeeds. */
17
+ export declare function ensureDiscoverableCdpBrowser(discovery: CdpBrowserDiscovery): Promise<boolean>;
18
+ export declare function providerBrowserInfo(entry: ProviderInventoryBrowser, route?: BrowserRecord): ManagedBrowserInfo;
19
+ export declare function mergeBrowserInventory(routes: BrowserRecord[], providerBrowsers: ProviderInventoryBrowser[]): BrowserInventoryResult;
20
+ export declare function providerInventory(runtimes: ProviderRuntime[]): Promise<ProviderInventoryBrowser[]>;
21
+ export declare function listBrowserInventory(runtimes: ProviderRuntime[]): Promise<BrowserInventoryResult>;
22
+ export {};
@@ -0,0 +1,24 @@
1
+ import type { BrowserAccessResult, BrowserLaunchParams, ManagedBrowserInfo, BrowserProviderListResult } from '@mearl/browser-core';
2
+ import type { JsonObject, ProviderRuntime, ProviderLaunchFormRequest } from '@mearl/provider';
3
+ import { type TransferableCookie } from './cdp-backend/cookie-transfer.js';
4
+ export declare class BrowserProviderCoordinator {
5
+ private readonly runtimes;
6
+ private readonly hostServices?;
7
+ constructor(runtimes: ProviderRuntime[], hostServices?: {
8
+ exportCookies: (domains: string[]) => Promise<TransferableCookie[]>;
9
+ getBrowserUserAgent: () => Promise<string>;
10
+ } | undefined);
11
+ private hostContext;
12
+ definitions(): BrowserProviderListResult;
13
+ get providerRuntimes(): ProviderRuntime[];
14
+ launch(input: BrowserLaunchParams): Promise<ManagedBrowserInfo>;
15
+ close(selector: string, deleteProfile?: boolean): Promise<unknown>;
16
+ start(selector: string): Promise<ManagedBrowserInfo>;
17
+ syncCookies(selector: string, scope: JsonObject): Promise<unknown>;
18
+ access(selector: string): Promise<BrowserAccessResult>;
19
+ detach(selector: string): Promise<unknown>;
20
+ configure(providerId: string, options: JsonObject): Promise<unknown>;
21
+ getLaunchForm(providerId: string, request: ProviderLaunchFormRequest): Promise<import("@mearl/provider").ProviderLaunchForm>;
22
+ private findRuntimeBrowsers;
23
+ private requireOne;
24
+ }
@@ -0,0 +1,30 @@
1
+ import { type JsonObject, type ProviderAccess, type ProviderBrowser, type ProviderBrowserType, type ProviderHostContextData, type ProviderLaunchForm, type ProviderLaunchFormRequest } from '@mearl/provider';
2
+ import { type BrowserRecord } from './browser-registry.js';
3
+ export interface BrowserProviderSummary {
4
+ provider: {
5
+ id: string;
6
+ name: string;
7
+ builtin: false;
8
+ version: string;
9
+ protocolVersion: number;
10
+ };
11
+ browserType: ProviderBrowserType;
12
+ }
13
+ export declare function listExternalBrowserProviders(): BrowserProviderSummary[];
14
+ export declare function getProviderLaunchForm(providerId: string, request: ProviderLaunchFormRequest): Promise<ProviderLaunchForm>;
15
+ export declare function launchProviderBrowser(input: {
16
+ provider: string;
17
+ providerOptions: JsonObject;
18
+ host?: ProviderHostContextData;
19
+ }): Promise<ProviderBrowser>;
20
+ export declare function findProviderBrowser(selector: string): BrowserRecord | null;
21
+ export declare function listProviderControlSessions(): Promise<any>;
22
+ export declare function updateProviderControlSession(sessionId: string, operation: string): Promise<any>;
23
+ export declare function closeProviderBrowser(browser: BrowserRecord, options?: {
24
+ deleteProfile?: boolean;
25
+ }): Promise<unknown>;
26
+ export declare function detachProviderBrowser(browser: BrowserRecord): Promise<unknown>;
27
+ export declare function accessProviderBrowser(browser: BrowserRecord): Promise<ProviderAccess>;
28
+ export declare function startProviderBrowser(browser: BrowserRecord): Promise<ProviderBrowser>;
29
+ export declare function syncProviderBrowserCookies(browser: BrowserRecord, scope: JsonObject, host?: ProviderHostContextData): Promise<unknown>;
30
+ export declare function configureProvider(providerId: string, options: JsonObject): Promise<unknown>;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Browser registry — advertises this native-host's connection in a shared,
3
+ * on-disk registry so clients can discover and address multiple browsers at
4
+ * once (multiple Chrome profiles / Chromium-based browsers, each with the
5
+ * extension, each launching its own native-host).
6
+ *
7
+ * Why a registry instead of the old single well-known socket
8
+ * ----------------------------------------------------------
9
+ * Historically every native-host fought over one fixed socket; the last one to
10
+ * start kicked the others off, so at most one browser was reachable and the two
11
+ * flapped on every reconnect. Here each native-host listens on its own unique
12
+ * per-process socket and publishes a record; the client reads the registry and
13
+ * connects to the socket of whichever browser it wants (default: most-recently
14
+ * focused). No contention, N browsers reachable simultaneously.
15
+ *
16
+ * Ownership
17
+ * ---------
18
+ * The record is keyed by the browser's stable installation id, so a browser
19
+ * that reconnects (extension reload → new native-host pid → new socket) simply
20
+ * overwrites its own record. To avoid a briefly-overlapping predecessor wiping
21
+ * the successor's record during a reload, every mutation first checks that the
22
+ * on-disk record still belongs to this process (or is stale) before writing.
23
+ */
24
+ import { type DaemonRecord } from '@mearl/daemon-core';
25
+ import type { BrowserCapabilities, BrowserDetails, BrowserPairingInfo, BrowserProviderOperation, BrowserProviderIdentity, BrowserReference, BrowserTransport } from '@mearl/browser-core';
26
+ export interface BrowserRecord extends DaemonRecord {
27
+ /** native-host pid — used for liveness pruning. */
28
+ pid: number;
29
+ /** Stable per-installation id reported by the extension (or 'cdp' for daemon mode). */
30
+ browserId: string;
31
+ /** Absolute path of the per-process socket this native-host listens on. */
32
+ socketPath: string;
33
+ /** Human-readable browser name, e.g. "Chrome", "Edge". */
34
+ browserName: string;
35
+ extensionVersion?: string;
36
+ nativeHostVersion?: string;
37
+ transport: BrowserTransport;
38
+ providerBrowserId?: string;
39
+ provider?: BrowserProviderIdentity;
40
+ capabilities?: BrowserCapabilities;
41
+ status?: 'connected' | 'pairing' | 'running_disconnected' | 'stopped';
42
+ ownership?: 'owned' | 'attached';
43
+ persistence?: 'ephemeral' | 'persistent';
44
+ operations?: BrowserProviderOperation[];
45
+ references?: BrowserReference[];
46
+ details?: BrowserDetails;
47
+ pairing?: BrowserPairingInfo;
48
+ /** Epoch ms when this browser window last gained focus; drives default target selection. */
49
+ lastFocusedAt?: number;
50
+ startedAt: string;
51
+ /** Epoch ms of the last record write; latest-wins tiebreak. */
52
+ updatedAt: number;
53
+ }
54
+ export declare function initBrowserRegistry(deps: {
55
+ log: (...args: any[]) => void;
56
+ }): void;
57
+ /** Retire a CDP record whose process remains alive but its instance socket no longer accepts connections. */
58
+ export declare function retireUnreachableBrowserRecord(browserId: string, canConnect: (socketPath: string) => Promise<boolean>): Promise<boolean>;
59
+ /**
60
+ * Publish (or refresh) this native-host's registry record. Called once the
61
+ * browser identity is known — from the extension handshake, or immediately with
62
+ * a synthetic identity in CDP daemon mode.
63
+ */
64
+ export declare function registerBrowser(info: {
65
+ browserId: string;
66
+ socketPath: string;
67
+ browserName: string;
68
+ nativeHostVersion: string;
69
+ transport: 'extension' | 'cdp';
70
+ extensionVersion?: string;
71
+ /** Initial focus rank. Managed headless browsers use 0 so they do not steal the default target. */
72
+ lastFocusedAt?: number;
73
+ /** Keep a previous focus rank when this browser reconnects. */
74
+ preserveFocus?: boolean;
75
+ }): boolean;
76
+ /**
77
+ * Mark this browser as most-recently focused, so it becomes the default target.
78
+ * Focus can change in rapid bursts (fast window switching), so writes are
79
+ * throttled: the first change in an interval writes immediately, further changes
80
+ * schedule a single trailing write rather than one write each.
81
+ */
82
+ export declare function touchFocus(): void;
83
+ /** Remove our record on shutdown — but only if it is still ours. */
84
+ export declare function unregisterBrowser(): void;
85
+ /**
86
+ * Reap registry records left behind by native-hosts that exited without
87
+ * cleanup (crashes). Live records are kept; a dead record is kept until it is
88
+ * older than STALE_RECORD_TTL_MS so a quickly-reconnecting browser can still
89
+ * inherit its own last-focus time. Meant to run once at startup.
90
+ */
91
+ export declare function pruneDeadBrowsers(): void;
92
+ /** Live browser connections, ordered by the same focus rank used for default routing. */
93
+ export declare function listRegisteredBrowsers(): BrowserRecord[];
@@ -0,0 +1,5 @@
1
+ import { type ProviderHostContextData } from '@mearl/provider';
2
+ export declare function requestBrowserSocket(socketPath: string, action: string, data: Record<string, any>, version: string, timeoutMs?: number, browserId?: string, host?: ProviderHostContextData, routing?: {
3
+ providerTarget?: string;
4
+ controlSource?: string;
5
+ }): Promise<any>;
@@ -0,0 +1,8 @@
1
+ import { type ProviderRuntime } from '@mearl/provider';
2
+ import type { TransferableCookie } from './cdp-backend/cookie-transfer.js';
3
+ export interface BuiltinProviderDependencies {
4
+ nativeHostScript: string;
5
+ exportCookies: (domains: string[]) => Promise<TransferableCookie[]>;
6
+ log: (...args: any[]) => void;
7
+ }
8
+ export declare function createBuiltinBrowserProviders(deps: BuiltinProviderDependencies): ProviderRuntime[];
@@ -0,0 +1,11 @@
1
+ import type { CookieCopyScope } from '@mearl/browser-core';
2
+ /** Launch values understood by the built-in local Provider. */
3
+ export interface BuiltinBrowserLaunchOptions {
4
+ name?: string;
5
+ headless?: boolean;
6
+ userAgentMode?: 'default' | 'desktop';
7
+ persistent?: boolean;
8
+ executablePath?: string;
9
+ url?: string;
10
+ copyCookieDomains?: string[] | string | CookieCopyScope;
11
+ }
@@ -0,0 +1,73 @@
1
+ import type { MtopRequest, ParsedSseEvent, RumEvent, SendMtopRequestParams } from '@mearl/browser-core';
2
+ export interface ResolvedMtopRequest {
3
+ api: string;
4
+ requestData: unknown;
5
+ dataStr: string;
6
+ version: string;
7
+ normalizedMethod: 'GET' | 'POST';
8
+ appKey: string;
9
+ gatewayUrl: URL;
10
+ customHeaders: Record<string, string>;
11
+ ttid?: string;
12
+ timeout: number;
13
+ isMopen: boolean;
14
+ }
15
+ export interface PreparedSignedMtopRequest extends ResolvedMtopRequest {
16
+ targetUrl: URL;
17
+ requestHeaders: Record<string, string>;
18
+ cookieHeader: string;
19
+ body?: string;
20
+ }
21
+ export interface MtopStreamCapture {
22
+ request: MtopRequest;
23
+ startTimeMs: number;
24
+ lastMessageTimeMs?: number;
25
+ }
26
+ export interface MtopStreamCaptureStart {
27
+ id: number;
28
+ api: string;
29
+ url?: string;
30
+ method: string;
31
+ requestHeaders?: Array<{
32
+ name: string;
33
+ value: string;
34
+ }>;
35
+ requestData?: unknown;
36
+ timestampMs?: number;
37
+ tabId?: number;
38
+ captureSequence: number;
39
+ }
40
+ export interface MtopStreamCaptureResponse {
41
+ status: number;
42
+ statusText: string;
43
+ responseHeaders: Array<{
44
+ name: string;
45
+ value: string;
46
+ }>;
47
+ }
48
+ export interface MtopCapability {
49
+ resolveRequest(data: SendMtopRequestParams): ResolvedMtopRequest;
50
+ prepareRequest(resolved: ResolvedMtopRequest, cookies: Map<string, string>, stream?: boolean): PreparedSignedMtopRequest;
51
+ parseResponse(text: string): unknown;
52
+ consumeResponse(response: Response, onReceive: (event: ParsedSseEvent) => void | Promise<void>): Promise<unknown>;
53
+ createCapture(data: MtopStreamCaptureStart): MtopStreamCapture;
54
+ updateCapture(capture: MtopStreamCapture, response: MtopStreamCaptureResponse): void;
55
+ appendCapture(capture: MtopStreamCapture, data: unknown, timestampMs?: number): boolean;
56
+ finishCapture(capture: MtopStreamCapture, options?: {
57
+ timestampMs?: number;
58
+ error?: string;
59
+ }): void;
60
+ gateways: Array<{
61
+ prod: string;
62
+ pre: string;
63
+ }>;
64
+ }
65
+ export interface TrackingCapability {
66
+ matches(url: string): boolean;
67
+ parse(url: string, postData?: string, options?: {
68
+ sequence?: number;
69
+ now?: number;
70
+ }): RumEvent[];
71
+ }
72
+ export declare function getMtopCapability(): MtopCapability;
73
+ export declare function getTrackingCapability(): TrackingCapability | undefined;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * CDP action registry.
3
+ *
4
+ * Each handler sub-module registers its actions here. The registry replaces
5
+ * the giant switch/case in handleViaCdp with a data-driven lookup.
6
+ *
7
+ * Two session levels:
8
+ * - `browser`: handler receives CdpSession for tab and page management
9
+ * - `page`: handler receives PageSession (for most page-level actions)
10
+ */
11
+ import { type BrowserCommandAction, type ControlSource } from '@mearl/browser-core';
12
+ import type { CdpSession, PageSession } from './cdp-session.js';
13
+ export interface BrowserAction {
14
+ name: BrowserCommandAction;
15
+ session: 'browser';
16
+ handler: (session: CdpSession, data: any, controlSource: ControlSource) => Promise<any>;
17
+ }
18
+ export interface PageAction {
19
+ name: BrowserCommandAction;
20
+ session: 'page';
21
+ handler: (session: PageSession, data: any, controlSource: ControlSource) => Promise<any>;
22
+ }
23
+ export type CdpAction = BrowserAction | PageAction;
24
+ /** Register one or more CDP actions. Called by each handler sub-module. */
25
+ export declare function registerActions(actions: CdpAction[]): void;
26
+ /** Look up a registered action by name. Returns undefined if not found. */
27
+ export declare function getAction(name: string): CdpAction | undefined;
28
+ /** Get all registered action names (useful for diagnostics). */
29
+ export declare function getRegisteredActionNames(): string[];
30
+ /**
31
+ * Dispatch an action by name.
32
+ *
33
+ * Resolves the appropriate session level and calls the handler.
34
+ * Throws if the action is unknown or CDP is not available.
35
+ */
36
+ export declare function dispatchCdpAction(cdpSession: CdpSession, action: string, data: any, controlSource?: ControlSource): Promise<any>;
@@ -0,0 +1,62 @@
1
+ /** CDP App environment and JSBridge injection. */
2
+ import { type ResolvedAppProfile } from '@mearl/app-profiles';
3
+ import { type AppProfileBinding, type AppProfileDefinition, type BrowserDevicePresetName, type InjectedAppProfileConfig, type ResolvedEmulationConfig, type SetAppProfileParams } from '@mearl/browser-core';
4
+ import type { PageSession } from './cdp-session.js';
5
+ declare const APP_PROFILE_RESTORE_VERSION = 1;
6
+ interface CdpAppProfileRestoreOptions {
7
+ lockDefinition?: boolean;
8
+ os: 'ios' | 'android';
9
+ appVersion: string;
10
+ language?: SetAppProfileParams['language'];
11
+ deviceModel: string;
12
+ devicePreset?: BrowserDevicePresetName;
13
+ orientation?: 'portrait' | 'landscape';
14
+ bridgeConfig?: ResolveCdpAppProfileOptions['bridgeConfig'];
15
+ }
16
+ interface CdpAppProfileRestoreEmulation {
17
+ preset?: BrowserDevicePresetName;
18
+ width: number;
19
+ height: number;
20
+ deviceScaleFactor: number;
21
+ scale: number;
22
+ mobile: boolean;
23
+ userAgent: string;
24
+ orientation: 'portrait' | 'landscape';
25
+ touch: boolean;
26
+ deviceShell: boolean;
27
+ splitScreen?: boolean;
28
+ }
29
+ interface CdpAppProfileRestoreState {
30
+ version: typeof APP_PROFILE_RESTORE_VERSION;
31
+ profile: string;
32
+ binding: Omit<AppProfileBinding, 'options'>;
33
+ options: CdpAppProfileRestoreOptions;
34
+ emulation?: CdpAppProfileRestoreEmulation;
35
+ activeDocument: boolean;
36
+ }
37
+ export interface ResolvedCdpAppProfile {
38
+ profile: ResolvedAppProfile;
39
+ restoreState: Omit<CdpAppProfileRestoreState, 'activeDocument'>;
40
+ }
41
+ interface ResolveCdpAppProfileOptions extends Omit<SetAppProfileParams, 'enabled' | 'profile' | 'tabId' | 'reload'> {
42
+ devicePreset?: BrowserDevicePresetName;
43
+ orientation?: 'portrait' | 'landscape';
44
+ }
45
+ export declare function resolveCdpAppProfile(profile: string, options?: ResolveCdpAppProfileOptions, definition?: AppProfileDefinition, current?: InjectedAppProfileConfig): ResolvedCdpAppProfile;
46
+ /** Reconnect daemon-owned CDP listeners for an App profile already installed in this target. */
47
+ export declare function restoreCdpAppProfile(session: PageSession): Promise<boolean>;
48
+ export declare function applyResolvedCdpAppProfile(session: PageSession, resolved: ResolvedCdpAppProfile): Promise<void>;
49
+ /** Update future-document scripts without replacing the active runtime or its bridge listeners. */
50
+ export declare function refreshCdpAppProfileForNavigation(session: PageSession, beforeApply?: () => Promise<void>): Promise<string | undefined>;
51
+ export declare function updateCdpAppProfileDeviceEmulation(session: PageSession, emulation: ResolvedEmulationConfig | null, deviceShell?: boolean, splitScreen?: boolean): Promise<{
52
+ userAgent: string;
53
+ platform: string;
54
+ } | undefined>;
55
+ export declare function isCdpAppProfileActive(session: PageSession): boolean;
56
+ export declare function waitForCdpAppProfileLoad(session: PageSession, timeoutMs?: number): Promise<void>;
57
+ export declare function clearCdpAppProfile(session: PageSession, reload?: boolean): Promise<{
58
+ enabled: false;
59
+ reloaded: boolean;
60
+ }>;
61
+ export declare function cdpSetAppProfile(session: PageSession, data: SetAppProfileParams): Promise<any>;
62
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * CDP browser-level handlers: screenshots.
3
+ */
4
+ import type { PageScreenshotParams } from '@mearl/browser-core';
5
+ import type { PageSession } from './cdp-session.js';
6
+ export declare function cdpPageScreenshot(session: PageSession, data: PageScreenshotParams): Promise<any>;
@@ -0,0 +1,72 @@
1
+ import { type MtopStreamCapture, type MtopStreamCaptureResponse, type MtopStreamCaptureStart } from '../capability-contracts.js';
2
+ /**
3
+ * In-memory circular buffers for CDP network requests, console logs, and
4
+ * RUM/tracking events. A single CdpSession subscribes to CDP events and
5
+ * fills these buffers; callers read from them without CDP interaction.
6
+ */
7
+ import { TextDecoder } from 'node:util';
8
+ import type { MtopRequest, RumEvent, ConsoleLog, RequestBufferAccounting } from '@mearl/browser-core';
9
+ import { type CaptureSequenceState, type SseEventParser } from '@mearl/browser-core';
10
+ import type { CdpClient, CdpChildSession } from './client.js';
11
+ interface PartialRequest extends MtopRequest {
12
+ id: number;
13
+ requestId: string;
14
+ timestamp: string;
15
+ timestampMs: number;
16
+ method: string;
17
+ url: string;
18
+ apiName: string;
19
+ headers: Array<{
20
+ name: string;
21
+ value: string;
22
+ }>;
23
+ postData: any;
24
+ queryString: Array<{
25
+ name: string;
26
+ value: string;
27
+ }>;
28
+ status: number;
29
+ statusText: string;
30
+ responseHeaders: Array<{
31
+ name: string;
32
+ value: string;
33
+ }>;
34
+ responseBody: any;
35
+ isProxy: boolean;
36
+ proxyRequestUrl: string | null;
37
+ proxyData: any;
38
+ startTs?: number;
39
+ }
40
+ interface CdpSseStream {
41
+ parser: SseEventParser;
42
+ decoder: TextDecoder;
43
+ mode: 'eventsource' | 'resource' | 'fallback';
44
+ lastMessageTimeMs?: number;
45
+ }
46
+ export type CdpMtopStreamCapture = MtopStreamCapture;
47
+ export type CdpMtopStreamStart = Omit<MtopStreamCaptureStart, 'id' | 'tabId' | 'captureSequence'>;
48
+ export type CdpMtopStreamResponse = MtopStreamCaptureResponse;
49
+ export interface CdpBuffers {
50
+ requests: MtopRequest[];
51
+ logs: ConsoleLog[];
52
+ events: RumEvent[];
53
+ pending: Map<string, PartialRequest>;
54
+ sseStreams: Map<string, CdpSseStream>;
55
+ requestCounter: number;
56
+ requestBufferAccounting: RequestBufferAccounting;
57
+ capture: CaptureSequenceState & {
58
+ droppedRequestsThroughSequence: number;
59
+ droppedLogsThroughSequence: number;
60
+ droppedEventsThroughSequence: number;
61
+ };
62
+ }
63
+ export declare function createBuffers(tabId?: number): CdpBuffers;
64
+ export declare function recordCdpMtopStreamStart(buffers: CdpBuffers, data: CdpMtopStreamStart): CdpMtopStreamCapture;
65
+ export declare function recordCdpMtopStreamResponse(buffers: CdpBuffers, capture: CdpMtopStreamCapture, response: CdpMtopStreamResponse): void;
66
+ export declare function recordCdpMtopStreamChunk(buffers: CdpBuffers, capture: CdpMtopStreamCapture, data: unknown, timestampMs?: number): void;
67
+ export declare function recordCdpMtopStreamEnd(buffers: CdpBuffers, capture: CdpMtopStreamCapture, options?: {
68
+ timestampMs?: number;
69
+ error?: string;
70
+ }): void;
71
+ export declare function setupBufferListeners(client: CdpClient | CdpChildSession, buffers: CdpBuffers): Promise<void>;
72
+ export {};