farming-code 2.2.28 → 2.2.30
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/README.md +27 -90
- package/README.zh_cn.md +17 -90
- package/THIRD_PARTY_NOTICES.md +25 -6
- package/backend/acp/packaged-claude-acp.js +13 -0
- package/backend/acp/packaged-codex-acp.js +2 -2
- package/backend/acp-runtime.js +38 -17
- package/backend/acp-session-state.js +78 -88
- package/backend/acp-transcript.js +174 -9
- package/backend/agent-manager.js +27 -2
- package/backend/agent-session-history.js +45 -12
- package/backend/codex-session-history.js +1 -1
- package/backend/codex-transcript.js +0 -202
- package/backend/config-manager.js +44 -16
- package/backend/data/LICENSE.agent-browser +201 -0
- package/backend/data/runtime-dependency-manifest.json +199 -0
- package/backend/data/runtime-dependency-sources.json +5 -0
- package/backend/executable-discovery.js +7 -0
- package/backend/farming-agent-bootstrap.zh_cn.md +4 -2
- package/backend/farming-app-cli.js +161 -65
- package/backend/farming-cli.js +7 -59
- package/backend/index-html.js +31 -0
- package/backend/main-agent-skills.js +7 -28
- package/backend/npm-update-helper.js +43 -6
- package/backend/provider-adapters.js +10 -0
- package/backend/runtime-dependency-manager.js +759 -0
- package/backend/runtime-executable-invocation.js +20 -0
- package/backend/server-process-identity.js +47 -0
- package/backend/server.js +145 -204
- package/backend/slash-command-discovery.js +138 -1
- package/backend/storage-layout.js +30 -0
- package/backend/update-service.js +60 -914
- package/config/farming.deploy.env.example +1 -1
- package/config/farming.install.env.example +5 -1
- package/dist/acp/LICENSE.claude-agent-acp +191 -0
- package/dist/acp/LICENSE.claude-agent-sdk +1 -0
- package/dist/acp/claude-agent-acp-0.59.0.mjs +41606 -0
- package/dist/acp/{codex-acp-1.1.4.js → codex-acp-1.1.4.mjs} +387 -7
- package/dist/assets/{App-CM7Cy-l4.css → App-BKNUILuL.css} +1 -1
- package/dist/assets/App-Z1N7T0eM.js +695 -0
- package/dist/assets/{FileEditorMarkdownPreview-DYOMm-b1.js → FileEditorMarkdownPreview-Cs9cLv8a.js} +1 -1
- package/dist/assets/FileEditorPane-CNtuGjQ3.js +2 -0
- package/dist/assets/IconGlyphs-BClgag6E.js +1 -0
- package/dist/assets/ProjectFilesSection-K3GHuQ4U.js +12 -0
- package/dist/assets/ReviewPage-BRuxFaH5.js +3 -0
- package/dist/assets/code-dark-kLsQLvpf.css +1 -0
- package/dist/assets/{index-BzQO3pUr.js → index-D-zetSol.js} +2 -2
- package/dist/assets/main-DUTz-Rd2.css +1 -0
- package/dist/assets/{workspace-editor-monaco-tXA-udGx.js → workspace-editor-monaco-CJNwbpCy.js} +1 -1
- package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +1 -0
- package/dist/assets/workspace-view-state-BjKPYp0E.js +7 -0
- package/dist/index.html +33 -3
- package/extensions/browser/backend/agent-browser-runtime.js +1041 -0
- package/extensions/browser/backend/browser-mcp-server.js +352 -0
- package/extensions/browser/backend/browser-resource-manager.js +921 -114
- package/extensions/browser/backend/browser-resource-store.js +47 -6
- package/extensions/browser/backend/browser-router.js +15 -2
- package/extensions/browser/backend/executable-discovery.js +164 -17
- package/extensions/browser/backend/managed-chromium-installer.js +593 -0
- package/extensions/browser/bin/farming-browser +384 -30
- package/extensions/browser/frontend/BrowserSidebarPortals.tsx +17 -19
- package/extensions/browser/frontend/BrowserViewer.tsx +217 -46
- package/extensions/browser/frontend/browser.css +68 -17
- package/extensions/browser/frontend/types.ts +13 -0
- package/extensions/browser/frontend/useBrowserResources.ts +18 -3
- package/index.html +32 -2
- package/package.json +10 -6
- package/shared/backend-connection-status.d.ts +12 -0
- package/shared/backend-connection-status.js +35 -4
- package/backend/agent-activity.js +0 -35
- package/backend/agent-memory-report.js +0 -583
- package/backend/bundle-update-helper.js +0 -113
- package/backend/codex-rollout-follower.js +0 -326
- package/dist/assets/App-CPG4WcjO.js +0 -658
- package/dist/assets/FileEditorPane-DXXq82aM.js +0 -2
- package/dist/assets/IconGlyphs-DrdPjYXr.js +0 -1
- package/dist/assets/ProjectFilesSection-CP66XVPl.js +0 -12
- package/dist/assets/ReviewPage-w21MEPD6.js +0 -3
- package/dist/assets/code-dark-BDjwj7Um.css +0 -1
- package/dist/assets/main-BlVUXfxa.css +0 -1
- package/dist/assets/workspace-editor-monaco-CFEfFNcA.js +0 -1
- package/dist/assets/workspace-view-state-BS_V8JVs.js +0 -7
- package/extensions/browser/backend/cdp-browser-runtime.js +0 -648
- package/extensions/browser/backend/cdp-client.js +0 -167
|
@@ -3,14 +3,33 @@ const crypto = require('crypto');
|
|
|
3
3
|
const { atomicWriteJson } = require('../../../backend/atomic-json-store');
|
|
4
4
|
const storageLayout = require('../../../backend/storage-layout');
|
|
5
5
|
|
|
6
|
-
const STORE_VERSION =
|
|
6
|
+
const STORE_VERSION = 5;
|
|
7
7
|
const RESOURCE_ID_RE = /^browser_[A-Za-z0-9_-]+$/;
|
|
8
|
+
const TAB_ID_RE = /^t\d+$/;
|
|
8
9
|
const STATUSES = new Set(['stopped', 'starting', 'running', 'stopping', 'failed']);
|
|
9
10
|
|
|
10
11
|
function createBrowserId() {
|
|
11
12
|
return `browser_${Date.now().toString(36)}_${crypto.randomBytes(6).toString('hex')}`;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
function normalizeProcessIdentity(value) {
|
|
16
|
+
if (
|
|
17
|
+
!value
|
|
18
|
+
|| Number(value.pid) <= 0
|
|
19
|
+
|| !Number.isSafeInteger(Number(value.pid))
|
|
20
|
+
|| Number(value.processGroupId) <= 0
|
|
21
|
+
|| !Number.isSafeInteger(Number(value.processGroupId))
|
|
22
|
+
|| !String(value.startedAt || '').trim()
|
|
23
|
+
|| !String(value.format || '').trim()
|
|
24
|
+
) return null;
|
|
25
|
+
return {
|
|
26
|
+
pid: Number(value.pid),
|
|
27
|
+
processGroupId: Number(value.processGroupId),
|
|
28
|
+
startedAt: String(value.startedAt).trim(),
|
|
29
|
+
format: String(value.format).trim(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
14
33
|
function normalizeResource(value) {
|
|
15
34
|
if (!value || typeof value !== 'object' || !RESOURCE_ID_RE.test(String(value.id || ''))) return null;
|
|
16
35
|
const projectRootId = String(value.projectRootId || '').trim();
|
|
@@ -21,13 +40,21 @@ function normalizeResource(value) {
|
|
|
21
40
|
projectRootId,
|
|
22
41
|
workspace,
|
|
23
42
|
name: String(value.name || 'Browser').trim().slice(0, 120) || 'Browser',
|
|
43
|
+
autoName: value.autoName === true,
|
|
24
44
|
status: STATUSES.has(value.status) ? value.status : 'failed',
|
|
25
45
|
generation: Number.isSafeInteger(value.generation) && value.generation >= 0 ? value.generation : 0,
|
|
26
46
|
revision: Number.isSafeInteger(value.revision) && value.revision >= 0 ? value.revision : 0,
|
|
27
47
|
url: String(value.url || 'about:blank').slice(0, 8_192) || 'about:blank',
|
|
28
48
|
title: String(value.title || '').slice(0, 512),
|
|
29
49
|
browserKind: String(value.browserKind || ''),
|
|
50
|
+
runtimeKind: String(value.runtimeKind || ''),
|
|
51
|
+
sessionId: RESOURCE_ID_RE.test(String(value.sessionId || '')) ? String(value.sessionId) : '',
|
|
52
|
+
sessionGeneration: Number.isSafeInteger(value.sessionGeneration) && value.sessionGeneration >= 0
|
|
53
|
+
? value.sessionGeneration
|
|
54
|
+
: 0,
|
|
55
|
+
tabId: TAB_ID_RE.test(String(value.tabId || '')) ? String(value.tabId) : '',
|
|
30
56
|
error: String(value.error || '').slice(0, 2_000),
|
|
57
|
+
processIdentity: normalizeProcessIdentity(value.processIdentity),
|
|
31
58
|
createdAt: Number.isFinite(value.createdAt) ? value.createdAt : Date.now(),
|
|
32
59
|
updatedAt: Number.isFinite(value.updatedAt) ? value.updatedAt : Date.now(),
|
|
33
60
|
};
|
|
@@ -59,11 +86,6 @@ class BrowserResourceStore {
|
|
|
59
86
|
for (const value of resources) {
|
|
60
87
|
const resource = normalizeResource(value);
|
|
61
88
|
if (!resource || this.resources.has(resource.id)) continue;
|
|
62
|
-
if (resource.status === 'running' || resource.status === 'starting' || resource.status === 'stopping') {
|
|
63
|
-
resource.status = 'failed';
|
|
64
|
-
resource.error = 'Farming restarted before the Browser runtime could be reconciled';
|
|
65
|
-
resource.updatedAt = Date.now();
|
|
66
|
-
}
|
|
67
89
|
this.resources.set(resource.id, resource);
|
|
68
90
|
}
|
|
69
91
|
this.commit();
|
|
@@ -86,12 +108,16 @@ class BrowserResourceStore {
|
|
|
86
108
|
projectRootId: input.projectRootId,
|
|
87
109
|
workspace: input.workspace,
|
|
88
110
|
name: input.name || 'Browser',
|
|
111
|
+
autoName: input.autoName === true,
|
|
89
112
|
status: 'stopped',
|
|
90
113
|
generation: 0,
|
|
91
114
|
revision: 0,
|
|
92
115
|
url: input.url || 'about:blank',
|
|
93
116
|
title: '',
|
|
94
117
|
browserKind: '',
|
|
118
|
+
sessionId: input.sessionId || '',
|
|
119
|
+
sessionGeneration: input.sessionGeneration || 0,
|
|
120
|
+
tabId: input.tabId || '',
|
|
95
121
|
error: '',
|
|
96
122
|
createdAt: Date.now(),
|
|
97
123
|
updatedAt: Date.now(),
|
|
@@ -102,6 +128,21 @@ class BrowserResourceStore {
|
|
|
102
128
|
return { ...resource };
|
|
103
129
|
}
|
|
104
130
|
|
|
131
|
+
createRunningTab(input) {
|
|
132
|
+
const resource = this.create(input);
|
|
133
|
+
return this.update(resource.id, {
|
|
134
|
+
status: 'running',
|
|
135
|
+
autoName: true,
|
|
136
|
+
generation: 1,
|
|
137
|
+
browserKind: input.browserKind,
|
|
138
|
+
runtimeKind: 'agent-browser',
|
|
139
|
+
sessionId: input.sessionId,
|
|
140
|
+
sessionGeneration: input.sessionGeneration,
|
|
141
|
+
tabId: input.tabId,
|
|
142
|
+
title: input.title || '',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
105
146
|
update(id, patch) {
|
|
106
147
|
const current = this.resources.get(id);
|
|
107
148
|
if (!current) return null;
|
|
@@ -11,8 +11,21 @@ function createBrowserRouter(manager, workspaceRootRegistry) {
|
|
|
11
11
|
const router = express.Router();
|
|
12
12
|
router.use(express.json({ limit: '2mb' }));
|
|
13
13
|
|
|
14
|
-
router.get('/capability', (_req, res) => {
|
|
15
|
-
|
|
14
|
+
router.get('/capability', async (_req, res) => {
|
|
15
|
+
try {
|
|
16
|
+
await manager.refreshCapability();
|
|
17
|
+
res.json(manager.capability());
|
|
18
|
+
} catch (error) {
|
|
19
|
+
sendError(res, error);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
router.post('/install', async (_req, res) => {
|
|
24
|
+
try {
|
|
25
|
+
res.json(await manager.installManagedChromium());
|
|
26
|
+
} catch (error) {
|
|
27
|
+
sendError(res, error);
|
|
28
|
+
}
|
|
16
29
|
});
|
|
17
30
|
|
|
18
31
|
router.get('/', (_req, res) => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { execFileSync } = require('child_process');
|
|
4
|
+
const { verifyExecutable } = require('../../../backend/runtime-dependency-manager');
|
|
5
|
+
const { AGENT_BROWSER_VERSION } = require('./agent-browser-runtime');
|
|
4
6
|
|
|
5
7
|
function executable(pathname, kind) {
|
|
6
8
|
if (!pathname) return null;
|
|
@@ -20,30 +22,57 @@ function firstExecutable(candidates) {
|
|
|
20
22
|
return null;
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
function uniqueExecutables(candidates) {
|
|
26
|
+
const seen = new Set();
|
|
27
|
+
const result = [];
|
|
28
|
+
for (const candidate of candidates) {
|
|
29
|
+
const found = executable(candidate.path, candidate.kind);
|
|
30
|
+
if (!found || seen.has(found.path)) continue;
|
|
31
|
+
seen.add(found.path);
|
|
32
|
+
result.push(found);
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
|
|
23
37
|
function which(command) {
|
|
24
38
|
try {
|
|
25
|
-
|
|
39
|
+
const program = process.platform === 'win32' ? 'where.exe' : 'which';
|
|
40
|
+
return execFileSync(program, [command], {
|
|
26
41
|
encoding: 'utf8',
|
|
27
42
|
timeout: 1_000,
|
|
28
43
|
maxBuffer: 16_384,
|
|
29
|
-
}).trim();
|
|
44
|
+
}).split(/\r?\n/).map(value => value.trim()).find(Boolean) || '';
|
|
30
45
|
} catch {
|
|
31
46
|
return '';
|
|
32
47
|
}
|
|
33
48
|
}
|
|
34
49
|
|
|
35
|
-
function
|
|
36
|
-
|
|
50
|
+
function managedAgentBrowserPath(options = {}) {
|
|
51
|
+
const env = options.env || process.env;
|
|
52
|
+
return String(
|
|
53
|
+
options.agentBrowserPath
|
|
54
|
+
|| env.FARMING_AGENT_BROWSER_BIN
|
|
55
|
+
|| env.FARMING_AGENT_BROWSER_EXECUTABLE
|
|
56
|
+
|| '',
|
|
57
|
+
).trim();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function macBrowserCandidates() {
|
|
61
|
+
return [
|
|
37
62
|
{ kind: 'chrome', path: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' },
|
|
38
63
|
{ kind: 'brave', path: '/Applications/Brave Browser.app/Contents/MacOS/Brave Browser' },
|
|
39
64
|
{ kind: 'edge', path: '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge' },
|
|
40
65
|
{ kind: 'chromium', path: '/Applications/Chromium.app/Contents/MacOS/Chromium' },
|
|
41
66
|
{ kind: 'chrome', path: path.join(process.env.HOME || '', 'Applications/Google Chrome.app/Contents/MacOS/Google Chrome') },
|
|
42
67
|
{ kind: 'brave', path: path.join(process.env.HOME || '', 'Applications/Brave Browser.app/Contents/MacOS/Brave Browser') },
|
|
43
|
-
]
|
|
68
|
+
];
|
|
44
69
|
}
|
|
45
70
|
|
|
46
|
-
function
|
|
71
|
+
function discoverMacBrowser() {
|
|
72
|
+
return firstExecutable(macBrowserCandidates());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function linuxBrowserCandidates() {
|
|
47
76
|
const commands = [
|
|
48
77
|
['google-chrome', 'chrome'],
|
|
49
78
|
['google-chrome-stable', 'chrome'],
|
|
@@ -52,14 +81,14 @@ function discoverLinuxBrowser() {
|
|
|
52
81
|
['chromium', 'chromium'],
|
|
53
82
|
['chromium-browser', 'chromium'],
|
|
54
83
|
];
|
|
55
|
-
|
|
56
|
-
const found = executable(which(command), kind);
|
|
57
|
-
if (found) return found;
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
84
|
+
return commands.map(([command, kind]) => ({ kind, path: which(command) }));
|
|
60
85
|
}
|
|
61
86
|
|
|
62
|
-
function
|
|
87
|
+
function discoverLinuxBrowser() {
|
|
88
|
+
return firstExecutable(linuxBrowserCandidates());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function windowsBrowserCandidates(env) {
|
|
63
92
|
const roots = [env.PROGRAMFILES, env['PROGRAMFILES(X86)'], env.LOCALAPPDATA].filter(Boolean);
|
|
64
93
|
const candidates = [];
|
|
65
94
|
for (const root of roots) {
|
|
@@ -70,22 +99,140 @@ function discoverWindowsBrowser(env) {
|
|
|
70
99
|
{ kind: 'chromium', path: path.join(root, 'Chromium', 'Application', 'chrome.exe') },
|
|
71
100
|
);
|
|
72
101
|
}
|
|
73
|
-
return
|
|
102
|
+
return candidates;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function discoverWindowsBrowser(env) {
|
|
106
|
+
return firstExecutable(windowsBrowserCandidates(env));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function discoverBrowserExecutables(options = {}) {
|
|
110
|
+
const env = options.env || process.env;
|
|
111
|
+
const platform = options.platform || process.platform;
|
|
112
|
+
let candidates = [];
|
|
113
|
+
if (platform === 'darwin') candidates = macBrowserCandidates();
|
|
114
|
+
if (platform === 'linux') candidates = linuxBrowserCandidates();
|
|
115
|
+
if (platform === 'win32') candidates = windowsBrowserCandidates(env);
|
|
116
|
+
const managed = executable(options.managedBrowserPath, 'managed-chromium');
|
|
117
|
+
return [
|
|
118
|
+
...uniqueExecutables(candidates),
|
|
119
|
+
...(managed ? [managed] : []),
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function normalizeExternalCdpUrl(value) {
|
|
124
|
+
const input = String(value || '').trim();
|
|
125
|
+
if (!input) return '';
|
|
126
|
+
try {
|
|
127
|
+
const url = new URL(input);
|
|
128
|
+
if (!['http:', 'https:', 'ws:', 'wss:'].includes(url.protocol)) return '';
|
|
129
|
+
if (url.username || url.password || url.search) return '';
|
|
130
|
+
const hostname = url.hostname.toLowerCase();
|
|
131
|
+
if (!['localhost', '127.0.0.1', '[::1]'].includes(hostname)) return '';
|
|
132
|
+
url.hash = '';
|
|
133
|
+
return url.href;
|
|
134
|
+
} catch {
|
|
135
|
+
return '';
|
|
136
|
+
}
|
|
74
137
|
}
|
|
75
138
|
|
|
76
139
|
function discoverBrowserExecutable(options = {}) {
|
|
77
140
|
const env = options.env || process.env;
|
|
78
141
|
const platform = options.platform || process.platform;
|
|
142
|
+
const source = String(options.source || '').trim();
|
|
143
|
+
if (source === 'external-cdp') {
|
|
144
|
+
const cdpUrl = normalizeExternalCdpUrl(options.externalCdpUrl);
|
|
145
|
+
return cdpUrl
|
|
146
|
+
? { kind: 'external-cdp', path: '', cdpUrl }
|
|
147
|
+
: {
|
|
148
|
+
kind: 'external-cdp',
|
|
149
|
+
path: '',
|
|
150
|
+
cdpUrl: '',
|
|
151
|
+
error: 'External CDP must be a loopback http(s) or ws(s) endpoint without credentials or query parameters',
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (source === 'managed') {
|
|
155
|
+
return executable(options.managedBrowserPath, 'managed-chromium') || {
|
|
156
|
+
kind: 'managed-chromium',
|
|
157
|
+
path: String(options.managedBrowserPath || ''),
|
|
158
|
+
error: 'Install or update the Farming-managed Chromium for this agent-browser version',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (source === 'system') {
|
|
162
|
+
const configuredPath = String(options.executablePath || '').trim();
|
|
163
|
+
if (configuredPath) {
|
|
164
|
+
const configuredKind = String(options.executableKind || 'custom').trim() || 'custom';
|
|
165
|
+
return executable(path.resolve(configuredPath), configuredKind) || {
|
|
166
|
+
kind: configuredKind,
|
|
167
|
+
path: path.resolve(configuredPath),
|
|
168
|
+
error: 'The selected Chromium browser is no longer available',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
let systemBrowser = null;
|
|
172
|
+
if (platform === 'darwin') systemBrowser = discoverMacBrowser();
|
|
173
|
+
if (platform === 'linux') systemBrowser = discoverLinuxBrowser();
|
|
174
|
+
if (platform === 'win32') systemBrowser = discoverWindowsBrowser(env);
|
|
175
|
+
return systemBrowser || executable(options.managedBrowserPath, 'managed-chromium');
|
|
176
|
+
}
|
|
177
|
+
const externalCdpInput = String(options.externalCdpUrl || env.FARMING_BROWSER_CDP_URL || '').trim();
|
|
178
|
+
if (externalCdpInput) {
|
|
179
|
+
const cdpUrl = normalizeExternalCdpUrl(externalCdpInput);
|
|
180
|
+
return cdpUrl
|
|
181
|
+
? { kind: 'external-cdp', path: '', cdpUrl }
|
|
182
|
+
: {
|
|
183
|
+
kind: 'external-cdp',
|
|
184
|
+
path: '',
|
|
185
|
+
cdpUrl: '',
|
|
186
|
+
error: 'FARMING_BROWSER_CDP_URL must be a loopback http(s) or ws(s) CDP endpoint without credentials or query parameters',
|
|
187
|
+
};
|
|
188
|
+
}
|
|
79
189
|
const configured = String(options.executablePath || env.FARMING_BROWSER_EXECUTABLE || '').trim();
|
|
80
190
|
if (configured) {
|
|
81
191
|
return executable(path.resolve(configured), 'custom');
|
|
82
192
|
}
|
|
83
|
-
|
|
84
|
-
if (platform === '
|
|
85
|
-
if (platform === '
|
|
86
|
-
|
|
193
|
+
let systemBrowser = null;
|
|
194
|
+
if (platform === 'darwin') systemBrowser = discoverMacBrowser();
|
|
195
|
+
if (platform === 'linux') systemBrowser = discoverLinuxBrowser();
|
|
196
|
+
if (platform === 'win32') systemBrowser = discoverWindowsBrowser(env);
|
|
197
|
+
return systemBrowser || executable(options.managedBrowserPath, 'managed-chromium');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function discoverBrowserRuntime(options = {}) {
|
|
201
|
+
const browser = discoverBrowserExecutable(options);
|
|
202
|
+
if (!browser || browser.error) return browser;
|
|
203
|
+
const agentBrowserPath = managedAgentBrowserPath(options);
|
|
204
|
+
if (!agentBrowserPath) {
|
|
205
|
+
return {
|
|
206
|
+
...browser,
|
|
207
|
+
error: `agent-browser ${AGENT_BROWSER_VERSION} is required; restart Farming through its launcher to prepare startup dependencies`,
|
|
208
|
+
runtimeErrorCode: 'NOT_FOUND',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const verification = await verifyExecutable(agentBrowserPath, AGENT_BROWSER_VERSION, {
|
|
212
|
+
execFile: options.execFile,
|
|
213
|
+
env: options.env || process.env,
|
|
214
|
+
platform: options.platform || process.platform,
|
|
215
|
+
useConfiguredLoader: true,
|
|
216
|
+
});
|
|
217
|
+
if (!verification.valid) {
|
|
218
|
+
return {
|
|
219
|
+
...browser,
|
|
220
|
+
error: `The Farming-managed agent-browser must be version ${AGENT_BROWSER_VERSION}`,
|
|
221
|
+
runtimeErrorCode: 'VERSION_MISMATCH',
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
...browser,
|
|
226
|
+
agentBrowserPath,
|
|
227
|
+
agentBrowserVersion: AGENT_BROWSER_VERSION,
|
|
228
|
+
agentBrowserSource: 'managed',
|
|
229
|
+
};
|
|
87
230
|
}
|
|
88
231
|
|
|
89
232
|
module.exports = {
|
|
90
233
|
discoverBrowserExecutable,
|
|
234
|
+
discoverBrowserExecutables,
|
|
235
|
+
discoverBrowserRuntime,
|
|
236
|
+
managedAgentBrowserPath,
|
|
237
|
+
normalizeExternalCdpUrl,
|
|
91
238
|
};
|