@mearl/native-host 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentbay-browser.d.ts +53 -5
- package/dist/index.js +206 -33
- package/package.json +4 -4
|
@@ -9,7 +9,11 @@ export interface AgentBayBrowserRecord extends DaemonRecord {
|
|
|
9
9
|
name: string;
|
|
10
10
|
sessionId: string;
|
|
11
11
|
imageId?: string;
|
|
12
|
-
|
|
12
|
+
persistent?: boolean;
|
|
13
|
+
contextId?: string;
|
|
14
|
+
contextName?: string;
|
|
15
|
+
/** Successful context sync checkpoint for retrying deletion of the current session. */
|
|
16
|
+
contextSyncedAt?: string;
|
|
13
17
|
createdAt: string;
|
|
14
18
|
copiedCookies?: {
|
|
15
19
|
domains: string[];
|
|
@@ -18,11 +22,25 @@ export interface AgentBayBrowserRecord extends DaemonRecord {
|
|
|
18
22
|
}
|
|
19
23
|
export interface AgentBaySessionLike {
|
|
20
24
|
sessionId: string;
|
|
21
|
-
resourceUrl?: string;
|
|
22
25
|
browser: {
|
|
23
26
|
initializeAsync(options: Record<string, unknown>): Promise<boolean>;
|
|
24
27
|
getEndpointUrl(): Promise<string>;
|
|
25
28
|
};
|
|
29
|
+
info?(): Promise<{
|
|
30
|
+
success?: boolean;
|
|
31
|
+
data?: unknown;
|
|
32
|
+
errorMessage?: string;
|
|
33
|
+
}>;
|
|
34
|
+
callMcpTool?(toolName: string, args: Record<string, unknown>, autoGenSession?: boolean): Promise<{
|
|
35
|
+
success?: boolean;
|
|
36
|
+
errorMessage?: string;
|
|
37
|
+
}>;
|
|
38
|
+
context?: {
|
|
39
|
+
sync(): Promise<{
|
|
40
|
+
success: boolean;
|
|
41
|
+
errorMessage?: string;
|
|
42
|
+
}>;
|
|
43
|
+
};
|
|
26
44
|
delete(syncContext?: boolean): Promise<{
|
|
27
45
|
success: boolean;
|
|
28
46
|
errorMessage?: string;
|
|
@@ -43,16 +61,34 @@ export interface AgentBayClientLike {
|
|
|
43
61
|
session?: AgentBaySessionLike;
|
|
44
62
|
errorMessage?: string;
|
|
45
63
|
}>;
|
|
64
|
+
context?: {
|
|
65
|
+
get(name: string, create?: boolean): Promise<{
|
|
66
|
+
success: boolean;
|
|
67
|
+
context?: {
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
};
|
|
71
|
+
errorMessage?: string;
|
|
72
|
+
}>;
|
|
73
|
+
delete(context: {
|
|
74
|
+
id: string;
|
|
75
|
+
name: string;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
success: boolean;
|
|
78
|
+
errorMessage?: string;
|
|
79
|
+
}>;
|
|
80
|
+
};
|
|
46
81
|
}
|
|
47
82
|
export interface AgentBayBrowserSummary {
|
|
48
83
|
browserId: string;
|
|
49
84
|
name: string;
|
|
50
85
|
provider: 'agentbay';
|
|
51
86
|
headless: false;
|
|
52
|
-
persistent:
|
|
87
|
+
persistent: boolean;
|
|
53
88
|
agentbaySessionId: string;
|
|
54
89
|
agentbayImageId?: string;
|
|
55
|
-
|
|
90
|
+
agentbayContextId?: string;
|
|
91
|
+
agentbayContextName?: string;
|
|
56
92
|
createdAt: string;
|
|
57
93
|
copiedCookies?: AgentBayBrowserRecord['copiedCookies'];
|
|
58
94
|
running: boolean;
|
|
@@ -79,13 +115,25 @@ interface AgentBayBrowserSessionInitOptions {
|
|
|
79
115
|
export declare function agentBayBrowserId(name: string): string;
|
|
80
116
|
export declare function resolveAgentBayApiKey(): string;
|
|
81
117
|
export declare function resolveAgentBayImageId(value: unknown): string;
|
|
118
|
+
export declare function agentBayContextName(browserId: string): string;
|
|
82
119
|
export declare function normalizeDesktopUserAgent(value: unknown): string;
|
|
83
120
|
export declare function normalizeAgentBayAccessUrl(value: unknown): string | undefined;
|
|
84
121
|
export declare function hasAgentBayBrowser(selector: string): boolean;
|
|
85
122
|
export declare function listAgentBayBrowsers(): AgentBayBrowserSummary[];
|
|
123
|
+
export declare function getAgentBayAccessUrl(sessionId: string, dependencies?: Pick<AgentBayBrowserManagerDeps, 'createAgentBayClient' | 'resolveApiKey'>): Promise<string>;
|
|
86
124
|
export declare function resolveAgentBayEndpoint(sessionId: string): Promise<string>;
|
|
87
125
|
export declare function keepAgentBaySessionAlive(sessionId: string): Promise<void>;
|
|
88
126
|
export declare function initializeAgentBayBrowserSession(session: Pick<AgentBaySessionLike, 'browser'>, input: Pick<BrowserLaunchParams, 'url'>, cookies: TransferableCookie[], options?: AgentBayBrowserSessionInitOptions): Promise<number>;
|
|
89
127
|
export declare function launchAgentBayBrowser(input: BrowserLaunchParams, deps: AgentBayBrowserManagerDeps): Promise<AgentBayBrowserSummary>;
|
|
90
|
-
export declare function
|
|
128
|
+
export declare function releaseAgentBayBrowserResources(record: AgentBayBrowserRecord, agentBay: AgentBayClientLike, options?: {
|
|
129
|
+
deleteProfile?: boolean;
|
|
130
|
+
persistRecord?: (record: AgentBayBrowserRecord) => void;
|
|
131
|
+
}): Promise<{
|
|
132
|
+
sessionDeleted: boolean;
|
|
133
|
+
contextSynced?: boolean;
|
|
134
|
+
contextDeleted?: boolean;
|
|
135
|
+
}>;
|
|
136
|
+
export declare function closeAgentBayBrowser(selector: string, options?: {
|
|
137
|
+
deleteProfile?: boolean;
|
|
138
|
+
}): Promise<Record<string, any>>;
|
|
91
139
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -4795,7 +4795,15 @@ async function discoverTargets(port = 9222) {
|
|
|
4795
4795
|
});
|
|
4796
4796
|
}
|
|
4797
4797
|
async function isCdpAvailable(port = 9222, userDataDir) {
|
|
4798
|
-
|
|
4798
|
+
const activePort = readDevToolsActivePort(userDataDir)?.port;
|
|
4799
|
+
if (activePort !== void 0) {
|
|
4800
|
+
try {
|
|
4801
|
+
await discoverTargets(activePort);
|
|
4802
|
+
return true;
|
|
4803
|
+
} catch {
|
|
4804
|
+
if (activePort === port) return false;
|
|
4805
|
+
}
|
|
4806
|
+
}
|
|
4799
4807
|
try {
|
|
4800
4808
|
await discoverTargets(port);
|
|
4801
4809
|
return true;
|
|
@@ -9574,9 +9582,6 @@ function validateAgentBayInput(input) {
|
|
|
9574
9582
|
if (input.headless === true) {
|
|
9575
9583
|
throw new Error("headless=true is not supported by the AgentBay browser provider");
|
|
9576
9584
|
}
|
|
9577
|
-
if (input.persistent === true) {
|
|
9578
|
-
throw new Error("persistent is not supported by the AgentBay CDP provider yet");
|
|
9579
|
-
}
|
|
9580
9585
|
if (input.executablePath) {
|
|
9581
9586
|
throw new Error("executablePath is only supported by the local browser provider");
|
|
9582
9587
|
}
|
|
@@ -9592,6 +9597,9 @@ function resolveAgentBayImageId(value) {
|
|
|
9592
9597
|
}
|
|
9593
9598
|
return imageId;
|
|
9594
9599
|
}
|
|
9600
|
+
function agentBayContextName(browserId) {
|
|
9601
|
+
return `mearl-browser-${hashKey(browserId)}`;
|
|
9602
|
+
}
|
|
9595
9603
|
function normalizeDesktopUserAgent(value) {
|
|
9596
9604
|
const userAgent = typeof value === "string" ? value.trim() : "";
|
|
9597
9605
|
if (!userAgent) throw new Error("Could not determine the control browser user agent");
|
|
@@ -9608,16 +9616,16 @@ function normalizeAgentBayAccessUrl(value) {
|
|
|
9608
9616
|
}
|
|
9609
9617
|
}
|
|
9610
9618
|
function browserSummary2(record2, running) {
|
|
9611
|
-
const accessUrl = normalizeAgentBayAccessUrl(record2.accessUrl);
|
|
9612
9619
|
return {
|
|
9613
9620
|
browserId: record2.browserId,
|
|
9614
9621
|
name: record2.name,
|
|
9615
9622
|
provider: "agentbay",
|
|
9616
9623
|
headless: false,
|
|
9617
|
-
persistent:
|
|
9624
|
+
persistent: record2.persistent === true,
|
|
9618
9625
|
agentbaySessionId: record2.sessionId,
|
|
9619
9626
|
...record2.imageId ? { agentbayImageId: record2.imageId } : {},
|
|
9620
|
-
...
|
|
9627
|
+
...record2.contextId ? { agentbayContextId: record2.contextId } : {},
|
|
9628
|
+
...record2.contextName ? { agentbayContextName: record2.contextName } : {},
|
|
9621
9629
|
createdAt: record2.createdAt,
|
|
9622
9630
|
...record2.copiedCookies ? { copiedCookies: record2.copiedCookies } : {},
|
|
9623
9631
|
running
|
|
@@ -9626,11 +9634,13 @@ function browserSummary2(record2, running) {
|
|
|
9626
9634
|
function listRecords2() {
|
|
9627
9635
|
const records = [];
|
|
9628
9636
|
for (const file2 of listRecordFiles(keyedDir(AGENTBAY_BROWSERS_SUBDIR))) {
|
|
9629
|
-
const
|
|
9630
|
-
if (!
|
|
9637
|
+
const stored = readRecord(file2);
|
|
9638
|
+
if (!stored) {
|
|
9631
9639
|
removeRecord(file2);
|
|
9632
9640
|
continue;
|
|
9633
9641
|
}
|
|
9642
|
+
const { accessUrl: legacyAccessUrl, ...record2 } = stored;
|
|
9643
|
+
if (legacyAccessUrl !== void 0) writeRecord(file2, record2);
|
|
9634
9644
|
const running = isManagedProcess(record2.pid, `--browser-id ${record2.browserId}`);
|
|
9635
9645
|
if (!running) removeRecord(keyedConfigFile("browsers", record2.browserId));
|
|
9636
9646
|
records.push({ record: record2, running });
|
|
@@ -9651,12 +9661,46 @@ function listAgentBayBrowsers() {
|
|
|
9651
9661
|
}
|
|
9652
9662
|
async function requireSession(sessionId, apiKey) {
|
|
9653
9663
|
const agentBay = await createClient(apiKey);
|
|
9664
|
+
return requireSessionFromClient(agentBay, sessionId);
|
|
9665
|
+
}
|
|
9666
|
+
async function requireSessionFromClient(agentBay, sessionId) {
|
|
9654
9667
|
const result = await agentBay.get(sessionId);
|
|
9655
9668
|
if (!result.success || !result.session) {
|
|
9656
9669
|
throw new Error(result.errorMessage || `AgentBay session not found: ${sessionId}`);
|
|
9657
9670
|
}
|
|
9658
9671
|
return result.session;
|
|
9659
9672
|
}
|
|
9673
|
+
async function getAgentBayAccessUrl(sessionId, dependencies = {}) {
|
|
9674
|
+
const apiKey = (dependencies.resolveApiKey ?? resolveAgentBayApiKey)();
|
|
9675
|
+
const agentBay = dependencies.createAgentBayClient ? await dependencies.createAgentBayClient(apiKey) : await createClient(apiKey);
|
|
9676
|
+
const session = await requireSessionFromClient(agentBay, sessionId);
|
|
9677
|
+
if (!session.info) {
|
|
9678
|
+
throw new Error("The installed AgentBay SDK does not support live session information");
|
|
9679
|
+
}
|
|
9680
|
+
const result = await session.info();
|
|
9681
|
+
if (result.success === false) {
|
|
9682
|
+
throw new Error(result.errorMessage || `AgentBay session info failed: ${sessionId}`);
|
|
9683
|
+
}
|
|
9684
|
+
const data = result.data && typeof result.data === "object" ? result.data : null;
|
|
9685
|
+
const accessUrl = normalizeAgentBayAccessUrl(
|
|
9686
|
+
data && "resourceUrl" in data ? data.resourceUrl : void 0
|
|
9687
|
+
);
|
|
9688
|
+
if (!accessUrl) {
|
|
9689
|
+
throw new Error(`AgentBay session did not return a browser access URL: ${sessionId}`);
|
|
9690
|
+
}
|
|
9691
|
+
return accessUrl;
|
|
9692
|
+
}
|
|
9693
|
+
async function resolvePersistentContext(agentBay, browserId) {
|
|
9694
|
+
if (!agentBay.context) {
|
|
9695
|
+
throw new Error("The installed AgentBay SDK does not support persistent browser contexts");
|
|
9696
|
+
}
|
|
9697
|
+
const name = agentBayContextName(browserId);
|
|
9698
|
+
const result = await agentBay.context.get(name, true);
|
|
9699
|
+
if (!result.success || !result.context?.id) {
|
|
9700
|
+
throw new Error(result.errorMessage || `Failed to create AgentBay browser context: ${name}`);
|
|
9701
|
+
}
|
|
9702
|
+
return { id: result.context.id, name: result.context.name || name };
|
|
9703
|
+
}
|
|
9660
9704
|
async function resolveAgentBayEndpoint(sessionId) {
|
|
9661
9705
|
const apiKey = resolveAgentBayApiKey();
|
|
9662
9706
|
const { AgentBay, GetCdpLinkRequest } = await loadSdk();
|
|
@@ -9702,12 +9746,14 @@ async function launchAgentBayBrowser(input, deps) {
|
|
|
9702
9746
|
const browserId = agentBayBrowserId(name);
|
|
9703
9747
|
validateAgentBayInput(input);
|
|
9704
9748
|
const imageId = resolveAgentBayImageId(input.imageId);
|
|
9749
|
+
const persistent = input.persistent === true;
|
|
9705
9750
|
const userAgentMode = resolveUserAgentMode(input.userAgentMode);
|
|
9706
9751
|
const copyCookieDomains = input.copyCookieDomains === void 0 ? [] : normalizeCookieDomains(input.copyCookieDomains);
|
|
9707
9752
|
const apiKey = (deps.resolveApiKey ?? resolveAgentBayApiKey)();
|
|
9708
9753
|
const releaseLock = acquireLaunchLock(browserId);
|
|
9709
9754
|
const persistBrowserRecord = deps.persistBrowserRecord ?? ((record2) => writeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR, record2.browserId), record2));
|
|
9710
9755
|
let session = null;
|
|
9756
|
+
let context;
|
|
9711
9757
|
let hostPid = 0;
|
|
9712
9758
|
let recordWritten = false;
|
|
9713
9759
|
try {
|
|
@@ -9717,7 +9763,18 @@ async function launchAgentBayBrowser(input, deps) {
|
|
|
9717
9763
|
userAgentMode === "desktop" ? deps.getBrowserUserAgent().then(normalizeDesktopUserAgent) : Promise.resolve(void 0)
|
|
9718
9764
|
]);
|
|
9719
9765
|
const agentBay = await (deps.createAgentBayClient ?? createClient)(apiKey);
|
|
9720
|
-
|
|
9766
|
+
context = persistent ? await resolvePersistentContext(agentBay, browserId) : void 0;
|
|
9767
|
+
const created = await agentBay.create({
|
|
9768
|
+
imageId,
|
|
9769
|
+
framework: "mearl",
|
|
9770
|
+
...context ? {
|
|
9771
|
+
browserContext: {
|
|
9772
|
+
contextId: context.id,
|
|
9773
|
+
autoUpload: true,
|
|
9774
|
+
syncMode: "standard"
|
|
9775
|
+
}
|
|
9776
|
+
} : {}
|
|
9777
|
+
});
|
|
9721
9778
|
if (!created.success || !created.session) {
|
|
9722
9779
|
throw new Error(created.errorMessage || "AgentBay session creation failed");
|
|
9723
9780
|
}
|
|
@@ -9750,14 +9807,14 @@ async function launchAgentBayBrowser(input, deps) {
|
|
|
9750
9807
|
hostPid = host.pid ?? 0;
|
|
9751
9808
|
if (!hostPid) throw new Error("AgentBay native host launched without a process id");
|
|
9752
9809
|
host.unref();
|
|
9753
|
-
const accessUrl = normalizeAgentBayAccessUrl(session.resourceUrl);
|
|
9754
9810
|
const record2 = {
|
|
9755
9811
|
pid: hostPid,
|
|
9756
9812
|
browserId,
|
|
9757
9813
|
name,
|
|
9758
9814
|
sessionId: session.sessionId,
|
|
9759
9815
|
imageId,
|
|
9760
|
-
|
|
9816
|
+
persistent,
|
|
9817
|
+
...context ? { contextId: context.id, contextName: context.name } : {},
|
|
9761
9818
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9762
9819
|
...copyCookieDomains.length > 0 ? { copiedCookies: { domains: copyCookieDomains, count: copiedCookieCount } } : {}
|
|
9763
9820
|
};
|
|
@@ -9783,14 +9840,14 @@ async function launchAgentBayBrowser(input, deps) {
|
|
|
9783
9840
|
cleanupError = deleteError;
|
|
9784
9841
|
}
|
|
9785
9842
|
if (cleanupError) {
|
|
9786
|
-
const accessUrl = normalizeAgentBayAccessUrl(session.resourceUrl);
|
|
9787
9843
|
const recoveryRecord = {
|
|
9788
9844
|
pid: hostPid,
|
|
9789
9845
|
browserId,
|
|
9790
9846
|
name,
|
|
9791
9847
|
sessionId: session.sessionId,
|
|
9792
9848
|
imageId,
|
|
9793
|
-
|
|
9849
|
+
persistent,
|
|
9850
|
+
...context ? { contextId: context.id, contextName: context.name } : {},
|
|
9794
9851
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9795
9852
|
};
|
|
9796
9853
|
let recoverySaved = false;
|
|
@@ -9827,16 +9884,72 @@ function isMissingSessionError(error48) {
|
|
|
9827
9884
|
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
9828
9885
|
return /not[ -]?found|does not exist|already deleted|invalid session/i.test(message);
|
|
9829
9886
|
}
|
|
9830
|
-
async function
|
|
9831
|
-
const
|
|
9832
|
-
|
|
9887
|
+
async function releaseAgentBayBrowserResources(record2, agentBay, options = {}) {
|
|
9888
|
+
const deleteContext = record2.persistent === true && options.deleteProfile === true;
|
|
9889
|
+
const syncContext = record2.persistent === true && !deleteContext;
|
|
9890
|
+
let contextSynced = Boolean(record2.contextSyncedAt);
|
|
9891
|
+
let session;
|
|
9833
9892
|
try {
|
|
9834
|
-
|
|
9835
|
-
const result = await session.delete(false);
|
|
9836
|
-
if (!result.success) throw new Error(result.errorMessage || "AgentBay session deletion failed");
|
|
9893
|
+
session = await requireSessionFromClient(agentBay, record2.sessionId);
|
|
9837
9894
|
} catch (error48) {
|
|
9838
9895
|
if (!isMissingSessionError(error48)) throw error48;
|
|
9839
9896
|
}
|
|
9897
|
+
if (session) {
|
|
9898
|
+
if (syncContext && !contextSynced) {
|
|
9899
|
+
if (!session.callMcpTool) {
|
|
9900
|
+
throw new Error("The installed AgentBay SDK cannot stop the browser before context sync");
|
|
9901
|
+
}
|
|
9902
|
+
const stopped = await session.callMcpTool("stopChrome", {}, false);
|
|
9903
|
+
if (stopped.success === false) {
|
|
9904
|
+
throw new Error(stopped.errorMessage || "AgentBay browser shutdown failed");
|
|
9905
|
+
}
|
|
9906
|
+
if (!session.context) {
|
|
9907
|
+
throw new Error("The installed AgentBay SDK cannot synchronize browser context state");
|
|
9908
|
+
}
|
|
9909
|
+
const synced = await session.context.sync();
|
|
9910
|
+
if (!synced.success) {
|
|
9911
|
+
throw new Error(synced.errorMessage || "AgentBay browser context sync failed");
|
|
9912
|
+
}
|
|
9913
|
+
contextSynced = true;
|
|
9914
|
+
record2.contextSyncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9915
|
+
options.persistRecord?.(record2);
|
|
9916
|
+
}
|
|
9917
|
+
try {
|
|
9918
|
+
const result = await session.delete(false);
|
|
9919
|
+
if (!result.success) {
|
|
9920
|
+
throw new Error(result.errorMessage || "AgentBay session deletion failed");
|
|
9921
|
+
}
|
|
9922
|
+
} catch (error48) {
|
|
9923
|
+
if (!isMissingSessionError(error48)) throw error48;
|
|
9924
|
+
}
|
|
9925
|
+
}
|
|
9926
|
+
if (deleteContext) {
|
|
9927
|
+
if (!record2.contextId || !record2.contextName || !agentBay.context) {
|
|
9928
|
+
throw new Error("AgentBay browser context metadata is unavailable for profile deletion");
|
|
9929
|
+
}
|
|
9930
|
+
const result = await agentBay.context.delete({
|
|
9931
|
+
id: record2.contextId,
|
|
9932
|
+
name: record2.contextName
|
|
9933
|
+
});
|
|
9934
|
+
if (!result.success) throw new Error(result.errorMessage || "AgentBay context deletion failed");
|
|
9935
|
+
}
|
|
9936
|
+
return {
|
|
9937
|
+
sessionDeleted: true,
|
|
9938
|
+
...syncContext ? { contextSynced } : {},
|
|
9939
|
+
...deleteContext ? { contextDeleted: true } : {}
|
|
9940
|
+
};
|
|
9941
|
+
}
|
|
9942
|
+
async function closeAgentBayBrowser(selector, options = {}) {
|
|
9943
|
+
const record2 = findRecord(selector);
|
|
9944
|
+
if (!record2) throw new Error(`AgentBay browser not found: ${selector}`);
|
|
9945
|
+
const agentBay = await createClient(resolveAgentBayApiKey());
|
|
9946
|
+
const released = await releaseAgentBayBrowserResources(record2, agentBay, {
|
|
9947
|
+
...options,
|
|
9948
|
+
persistRecord: (updatedRecord) => writeRecord(
|
|
9949
|
+
keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR, updatedRecord.browserId),
|
|
9950
|
+
updatedRecord
|
|
9951
|
+
)
|
|
9952
|
+
});
|
|
9840
9953
|
const closingOwnHost = record2.pid === process.pid;
|
|
9841
9954
|
if (!closingOwnHost) await stopProcess(record2.pid, `--browser-id ${record2.browserId}`);
|
|
9842
9955
|
removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR, record2.browserId));
|
|
@@ -9849,7 +9962,8 @@ async function closeAgentBayBrowser(selector) {
|
|
|
9849
9962
|
browserId: record2.browserId,
|
|
9850
9963
|
provider: "agentbay",
|
|
9851
9964
|
closed: true,
|
|
9852
|
-
|
|
9965
|
+
...released,
|
|
9966
|
+
...record2.persistent === true ? { profileDeleted: options.deleteProfile === true } : { profileDeleted: true }
|
|
9853
9967
|
};
|
|
9854
9968
|
}
|
|
9855
9969
|
|
|
@@ -10006,7 +10120,8 @@ function mergeBrowserInventory(connected, managed) {
|
|
|
10006
10120
|
..."cdpPort" in managedBrowser ? { cdpPort: managedBrowser.cdpPort } : {},
|
|
10007
10121
|
..."agentbaySessionId" in managedBrowser ? { agentbaySessionId: managedBrowser.agentbaySessionId } : {},
|
|
10008
10122
|
..."agentbayImageId" in managedBrowser && managedBrowser.agentbayImageId ? { agentbayImageId: managedBrowser.agentbayImageId } : {},
|
|
10009
|
-
..."
|
|
10123
|
+
..."agentbayContextId" in managedBrowser && managedBrowser.agentbayContextId ? { agentbayContextId: managedBrowser.agentbayContextId } : {},
|
|
10124
|
+
..."agentbayContextName" in managedBrowser && managedBrowser.agentbayContextName ? { agentbayContextName: managedBrowser.agentbayContextName } : {},
|
|
10010
10125
|
createdAt: managedBrowser.createdAt,
|
|
10011
10126
|
..."account" in managedBrowser ? { account: managedBrowser.account } : {},
|
|
10012
10127
|
..."copiedCookies" in managedBrowser ? { copiedCookies: managedBrowser.copiedCookies } : {}
|
|
@@ -10023,7 +10138,8 @@ function mergeBrowserInventory(connected, managed) {
|
|
|
10023
10138
|
..."cdpPort" in browser ? { cdpPort: browser.cdpPort } : {},
|
|
10024
10139
|
..."agentbaySessionId" in browser ? { agentbaySessionId: browser.agentbaySessionId } : {},
|
|
10025
10140
|
..."agentbayImageId" in browser && browser.agentbayImageId ? { agentbayImageId: browser.agentbayImageId } : {},
|
|
10026
|
-
..."
|
|
10141
|
+
..."agentbayContextId" in browser && browser.agentbayContextId ? { agentbayContextId: browser.agentbayContextId } : {},
|
|
10142
|
+
..."agentbayContextName" in browser && browser.agentbayContextName ? { agentbayContextName: browser.agentbayContextName } : {},
|
|
10027
10143
|
createdAt: browser.createdAt,
|
|
10028
10144
|
..."account" in browser ? { account: browser.account } : {},
|
|
10029
10145
|
..."copiedCookies" in browser ? { copiedCookies: browser.copiedCookies } : {}
|
|
@@ -10047,7 +10163,7 @@ import os2 from "node:os";
|
|
|
10047
10163
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
10048
10164
|
|
|
10049
10165
|
// src/version.ts
|
|
10050
|
-
var NATIVE_HOST_VERSION = true ? "2.
|
|
10166
|
+
var NATIVE_HOST_VERSION = true ? "2.6.0" : "unknown";
|
|
10051
10167
|
|
|
10052
10168
|
// src/analytics.ts
|
|
10053
10169
|
var MEASUREMENT_ID = "G-W84LJDZ6PH";
|
|
@@ -30701,6 +30817,7 @@ var nativeMessageBuffer = Buffer.alloc(0);
|
|
|
30701
30817
|
var socketServer = null;
|
|
30702
30818
|
var legacyServer = null;
|
|
30703
30819
|
var inventoryExitTimer = null;
|
|
30820
|
+
var cdpRegistrationTimer = null;
|
|
30704
30821
|
function scheduleInventoryExit() {
|
|
30705
30822
|
if (inventoryExitTimer) clearTimeout(inventoryExitTimer);
|
|
30706
30823
|
inventoryExitTimer = setTimeout(() => cleanupAndExit(0), INVENTORY_IDLE_EXIT_MS);
|
|
@@ -31010,6 +31127,24 @@ async function handleSocketLine(socket, line) {
|
|
|
31010
31127
|
socket.write(JSON.stringify({ id, success: true, data: versions }) + "\n");
|
|
31011
31128
|
return;
|
|
31012
31129
|
}
|
|
31130
|
+
if (action === "get_agentbay_access_url") {
|
|
31131
|
+
try {
|
|
31132
|
+
if (!AGENTBAY_SESSION_ID) {
|
|
31133
|
+
throw new Error("The selected browser is not an AgentBay browser");
|
|
31134
|
+
}
|
|
31135
|
+
const agentbayAccessUrl = await getAgentBayAccessUrl(AGENTBAY_SESSION_ID);
|
|
31136
|
+
socket.write(JSON.stringify({ id, success: true, data: { agentbayAccessUrl } }) + "\n");
|
|
31137
|
+
} catch (error48) {
|
|
31138
|
+
socket.write(
|
|
31139
|
+
JSON.stringify({
|
|
31140
|
+
id,
|
|
31141
|
+
success: false,
|
|
31142
|
+
error: error48 instanceof Error ? error48.message : String(error48)
|
|
31143
|
+
}) + "\n"
|
|
31144
|
+
);
|
|
31145
|
+
}
|
|
31146
|
+
return;
|
|
31147
|
+
}
|
|
31013
31148
|
if (isInternalExtensionAction(action)) {
|
|
31014
31149
|
socket.write(
|
|
31015
31150
|
JSON.stringify({ id, success: false, error: "Internal action is not available to clients" }) + "\n"
|
|
@@ -31037,7 +31172,7 @@ async function handleSocketLine(socket, line) {
|
|
|
31037
31172
|
`Managed browser name is ambiguous: ${selector}. Use the full browserId from browser_list.`
|
|
31038
31173
|
);
|
|
31039
31174
|
}
|
|
31040
|
-
const result = agentBayExists ? await closeAgentBayBrowser(selector) : await closeManagedBrowser(selector, { deleteProfile: data?.deleteProfile });
|
|
31175
|
+
const result = agentBayExists ? await closeAgentBayBrowser(selector, { deleteProfile: data?.deleteProfile }) : await closeManagedBrowser(selector, { deleteProfile: data?.deleteProfile });
|
|
31041
31176
|
socket.write(JSON.stringify({ id, success: true, data: result }) + "\n");
|
|
31042
31177
|
} catch (error48) {
|
|
31043
31178
|
socket.write(
|
|
@@ -31405,6 +31540,10 @@ function cleanupAndExit(code) {
|
|
|
31405
31540
|
clearTimeout(inventoryExitTimer);
|
|
31406
31541
|
inventoryExitTimer = null;
|
|
31407
31542
|
}
|
|
31543
|
+
if (cdpRegistrationTimer) {
|
|
31544
|
+
clearInterval(cdpRegistrationTimer);
|
|
31545
|
+
cdpRegistrationTimer = null;
|
|
31546
|
+
}
|
|
31408
31547
|
cdpSession?.close();
|
|
31409
31548
|
agentChatManager?.dispose();
|
|
31410
31549
|
agentChatManager = null;
|
|
@@ -31426,6 +31565,47 @@ function restartAfterUpdate() {
|
|
|
31426
31565
|
forcedExit.unref();
|
|
31427
31566
|
cleanupAndExit(0);
|
|
31428
31567
|
}
|
|
31568
|
+
async function isDaemonBrowserAvailable() {
|
|
31569
|
+
if (AGENTBAY_SESSION_ID) {
|
|
31570
|
+
return getCdpSession().getBrowserClient().then(
|
|
31571
|
+
() => true,
|
|
31572
|
+
() => false
|
|
31573
|
+
);
|
|
31574
|
+
}
|
|
31575
|
+
return isCdpAvailable(CDP_PORT, CDP_USER_DATA_DIR);
|
|
31576
|
+
}
|
|
31577
|
+
async function monitorDaemonBrowser() {
|
|
31578
|
+
let published = false;
|
|
31579
|
+
let checking = false;
|
|
31580
|
+
const refresh = async () => {
|
|
31581
|
+
if (checking) return;
|
|
31582
|
+
checking = true;
|
|
31583
|
+
try {
|
|
31584
|
+
const available = await isDaemonBrowserAvailable();
|
|
31585
|
+
if (available && !published) {
|
|
31586
|
+
registerBrowser({
|
|
31587
|
+
browserId: CDP_BROWSER_ID,
|
|
31588
|
+
socketPath: INSTANCE_SOCKET_PATH,
|
|
31589
|
+
browserName: CDP_BROWSER_NAME,
|
|
31590
|
+
nativeHostVersion: NATIVE_HOST_VERSION,
|
|
31591
|
+
transport: "cdp",
|
|
31592
|
+
lastFocusedAt: CDP_BROWSER_ID.startsWith("managed:") ? 0 : void 0
|
|
31593
|
+
});
|
|
31594
|
+
published = true;
|
|
31595
|
+
} else if (!available && published) {
|
|
31596
|
+
unregisterBrowser();
|
|
31597
|
+
published = false;
|
|
31598
|
+
}
|
|
31599
|
+
} finally {
|
|
31600
|
+
checking = false;
|
|
31601
|
+
}
|
|
31602
|
+
};
|
|
31603
|
+
await refresh();
|
|
31604
|
+
cdpRegistrationTimer = setInterval(() => {
|
|
31605
|
+
void refresh();
|
|
31606
|
+
}, 2e3);
|
|
31607
|
+
cdpRegistrationTimer.unref();
|
|
31608
|
+
}
|
|
31429
31609
|
async function main() {
|
|
31430
31610
|
initBrowserRegistry({ log });
|
|
31431
31611
|
pruneDeadBrowsers();
|
|
@@ -31447,14 +31627,7 @@ async function main() {
|
|
|
31447
31627
|
return;
|
|
31448
31628
|
}
|
|
31449
31629
|
if (isDaemonMode && !skipBrowserRegistration) {
|
|
31450
|
-
|
|
31451
|
-
browserId: CDP_BROWSER_ID,
|
|
31452
|
-
socketPath: INSTANCE_SOCKET_PATH,
|
|
31453
|
-
browserName: CDP_BROWSER_NAME,
|
|
31454
|
-
nativeHostVersion: NATIVE_HOST_VERSION,
|
|
31455
|
-
transport: "cdp",
|
|
31456
|
-
lastFocusedAt: CDP_BROWSER_ID.startsWith("managed:") ? 0 : void 0
|
|
31457
|
-
});
|
|
31630
|
+
await monitorDaemonBrowser();
|
|
31458
31631
|
}
|
|
31459
31632
|
if (AGENTBAY_SESSION_ID) {
|
|
31460
31633
|
const keepAliveTimer = setInterval(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mearl/native-host",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Native Messaging Host for Mearl — bridges Chrome Extension and local socket server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/install.js",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"@types/ws": "^8.18.1",
|
|
38
38
|
"esbuild": "^0.25.2",
|
|
39
39
|
"typescript": "^5.8.3",
|
|
40
|
-
"@mearl/browser-core": "2.
|
|
41
|
-
"@mearl/daemon-core": "2.
|
|
42
|
-
"@mearl/setup": "2.
|
|
40
|
+
"@mearl/browser-core": "2.6.0",
|
|
41
|
+
"@mearl/daemon-core": "2.6.0",
|
|
42
|
+
"@mearl/setup": "2.6.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "rm -rf dist/ && node build.mjs",
|