@reconcrap/boss-recommend-mcp 2.0.50 → 2.0.52
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 +2 -2
- package/bin/boss-recommend-mcp.js +0 -0
- package/config/screening-config.example.json +1 -1
- package/package.json +120 -120
- package/src/cli.js +115 -48
- package/src/core/browser/index.js +629 -23
- package/src/core/run/index.js +310 -310
- package/src/domains/recommend/detail.js +544 -544
- package/src/domains/recommend/run-service.js +1235 -1235
- package/src/recommend-mcp.js +1701 -1701
- package/src/run-state.js +358 -358
package/README.md
CHANGED
|
@@ -134,8 +134,8 @@ node src/cli.js start
|
|
|
134
134
|
|
|
135
135
|
全局 npm 安装会自动运行 `boss-recommend-mcp install`。该安装器会在 Windows 和 macOS 上自动检测 Trae / Trae CN / OpenClaw / QClaw 的常见配置目录:
|
|
136
136
|
|
|
137
|
-
- Windows: `%APPDATA%\Trae*\User\mcp.json`、`%USERPROFILE%\.trae*\mcp.json`、`%USERPROFILE%\.openclaw\mcp.json`、`%APPDATA%\OpenClaw\User\mcp.json`、`%USERPROFILE%\.qclaw\openclaw.json`
|
|
138
|
-
- macOS: `~/Library/Application Support/Trae*/User/mcp.json`、`~/.trae*/mcp.json`、`~/.openclaw/mcp.json`、`~/Library/Application Support/OpenClaw/User/mcp.json`
|
|
137
|
+
- Windows: `%APPDATA%\Trae*\User\mcp.json`、`%USERPROFILE%\.trae*\mcp.json`、`%USERPROFILE%\.openclaw\mcp.json`、`%USERPROFILE%\.openclaw\openclaw.json`、`%APPDATA%\OpenClaw\User\mcp.json`、`%USERPROFILE%\.qclaw\openclaw.json`
|
|
138
|
+
- macOS: `~/Library/Application Support/Trae*/User/mcp.json`、`~/.trae*/mcp.json`、`~/.openclaw/mcp.json`、`~/.openclaw/openclaw.json`、`~/Library/Application Support/OpenClaw/User/mcp.json`
|
|
139
139
|
|
|
140
140
|
如果检测到 legacy Boss server entries,installer 会:
|
|
141
141
|
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@reconcrap/boss-recommend-mcp",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Unified MCP pipeline for recommend-page filtering and screening on Boss Zhipin",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"boss",
|
|
7
|
-
"mcp",
|
|
8
|
-
"codex",
|
|
9
|
-
"recruiting",
|
|
10
|
-
"boss-zhipin",
|
|
11
|
-
"recommend"
|
|
12
|
-
],
|
|
13
|
-
"type": "module",
|
|
14
|
-
"main": "src/index.js",
|
|
15
|
-
"bin": {
|
|
16
|
-
"boss-recommend-mcp": "bin/boss-recommend-mcp.js"
|
|
17
|
-
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"start": "node src/index.js",
|
|
20
|
-
"cli": "node src/cli.js",
|
|
21
|
-
"install:local": "node src/cli.js install",
|
|
22
|
-
"postinstall": "node scripts/postinstall.cjs",
|
|
23
|
-
"test:parser": "node src/test-parser.js",
|
|
24
|
-
"test:run-state": "node src/test-run-state.js",
|
|
25
|
-
"test:cdp-browser": "node src/test-cdp-browser.js",
|
|
26
|
-
"test:core-capture": "node src/test-core-capture.js",
|
|
27
|
-
"test:core-cv-capture-target": "node src/test-core-cv-capture-target.js",
|
|
28
|
-
"test:core-cv-acquisition": "node src/test-core-cv-acquisition.js",
|
|
29
|
-
"test:core-greet-quota": "node src/test-core-greet-quota.js",
|
|
30
|
-
"test:core-infinite-list": "node src/test-core-infinite-list.js",
|
|
31
|
-
"test:core-reporting": "node src/test-core-reporting.js",
|
|
32
|
-
"test:core-run": "node src/test-core-run.js",
|
|
33
|
-
"test:core-screening": "node src/test-core-screening.js",
|
|
34
|
-
"test:core-self-heal": "node src/test-core-self-heal.js",
|
|
35
|
-
"test:installer-migration": "node src/test-installer-migration.js",
|
|
36
|
-
"test:recommend-actions": "node src/test-recommend-actions.js",
|
|
37
|
-
"test:recommend-domain": "node src/test-recommend-domain.js",
|
|
38
|
-
"test:recommend-run-service": "node src/test-recommend-run-service.js",
|
|
39
|
-
"test:recommend-mcp": "node src/test-recommend-mcp.js",
|
|
40
|
-
"test:recruit-domain": "node src/test-recruit-domain.js",
|
|
41
|
-
"test:recruit-mcp": "node src/test-recruit-mcp.js",
|
|
42
|
-
"test:chat-domain": "node src/test-chat-domain.js",
|
|
43
|
-
"test:chat-run-service": "node src/test-chat-run-service.js",
|
|
44
|
-
"test:chat-mcp": "node src/test-chat-mcp.js",
|
|
45
|
-
"test:async": "node src/test-index-async.js",
|
|
46
|
-
"test:runtime-scan": "node src/test-runtime-scan.js",
|
|
47
|
-
"scan:runtime": "node scripts/scan-forbidden-runtime.js",
|
|
48
|
-
"scan:runtime:json": "node scripts/scan-forbidden-runtime.js --json",
|
|
49
|
-
"scan:runtime:strict": "node scripts/scan-forbidden-runtime.js --fail-on-findings",
|
|
50
|
-
"scan:runtime:package": "node scripts/scan-forbidden-runtime.js --package-surface",
|
|
51
|
-
"scan:runtime:package:strict": "node scripts/scan-forbidden-runtime.js --package-surface --fail-on-legacy",
|
|
52
|
-
"scan:legacy-boundary": "node scripts/scan-legacy-boundary.js",
|
|
53
|
-
"scan:package-boundary": "node scripts/scan-package-boundary.js",
|
|
54
|
-
"gate:phase9-static": "node scripts/phase9-static-gate.js",
|
|
55
|
-
"gate:phase10-complete": "node scripts/phase10-completion-gate.js",
|
|
56
|
-
"live:cdp-smoke": "node scripts/live-cdp-smoke.js",
|
|
57
|
-
"live:run-lifecycle": "node scripts/live-run-lifecycle-smoke.js",
|
|
58
|
-
"live:screening": "node scripts/live-screening-smoke.js",
|
|
59
|
-
"live:detail": "node scripts/live-detail-smoke.js",
|
|
60
|
-
"live:infinite-list": "node scripts/live-infinite-list-smoke.js",
|
|
61
|
-
"live:scroll-end": "node scripts/live-scroll-end-screenshot.js",
|
|
62
|
-
"live:refresh-round": "node scripts/live-refresh-round-smoke.js",
|
|
63
|
-
"live:recommend-recovery": "node scripts/live-recommend-recovery-smoke.js",
|
|
64
|
-
"live:self-heal": "node scripts/live-self-heal-smoke.js",
|
|
65
|
-
"live:recommend-actions": "node scripts/live-recommend-actions-smoke.js",
|
|
66
|
-
"live:recommend-phase10-full": "node scripts/live-recommend-phase10-full.js",
|
|
67
|
-
"live:recommend-domain": "node scripts/live-recommend-domain-smoke.js",
|
|
68
|
-
"live:recommend-run-service": "node scripts/live-recommend-run-service-smoke.js",
|
|
69
|
-
"live:recommend-mcp": "node scripts/live-recommend-mcp-smoke.js",
|
|
70
|
-
"live:search-phase10-full": "node scripts/live-search-phase10-full.js",
|
|
71
|
-
"live:recruit-domain": "node scripts/live-recruit-domain-smoke.js",
|
|
72
|
-
"live:recruit-run-service": "node scripts/live-recruit-run-service-smoke.js",
|
|
73
|
-
"live:recruit-mcp": "node scripts/live-recruit-mcp-smoke.js",
|
|
74
|
-
"live:chat-domain": "node scripts/live-chat-domain-smoke.js",
|
|
75
|
-
"live:chat-run-service": "node scripts/live-chat-run-service-smoke.js",
|
|
76
|
-
"live:chat-mcp": "node scripts/live-chat-mcp-smoke.js",
|
|
77
|
-
"live:cv-capture-target": "node scripts/live-cv-capture-target-smoke.js",
|
|
78
|
-
"live:chat-phase10-full": "node scripts/live-chat-phase10-full.js",
|
|
79
|
-
"live:chat-image-screening": "node scripts/live-chat-image-screening-smoke.js"
|
|
80
|
-
},
|
|
81
|
-
"files": [
|
|
82
|
-
"bin",
|
|
83
|
-
"config/screening-config.example.json",
|
|
84
|
-
"skills",
|
|
85
|
-
"scripts/postinstall.cjs",
|
|
86
|
-
"src/core",
|
|
87
|
-
"src/domains",
|
|
88
|
-
"src/chat-mcp.js",
|
|
89
|
-
"src/chat-runtime-config.js",
|
|
90
|
-
"src/cli.js",
|
|
91
|
-
"src/index.js",
|
|
92
|
-
"src/parser.js",
|
|
93
|
-
"src/recommend-mcp.js",
|
|
94
|
-
"src/recruit-mcp.js",
|
|
95
|
-
"src/run-state.js",
|
|
96
|
-
"README.md"
|
|
97
|
-
],
|
|
98
|
-
"dependencies": {
|
|
99
|
-
"chrome-remote-interface": "^0.33.3",
|
|
100
|
-
"sharp": "^0.34.4",
|
|
101
|
-
"ws": "^8.19.0"
|
|
102
|
-
},
|
|
103
|
-
"engines": {
|
|
104
|
-
"node": ">=18"
|
|
105
|
-
},
|
|
106
|
-
"publishConfig": {
|
|
107
|
-
"access": "public"
|
|
108
|
-
},
|
|
109
|
-
"license": "MIT",
|
|
110
|
-
"devDependencies": {},
|
|
111
|
-
"repository": {
|
|
112
|
-
"type": "git",
|
|
113
|
-
"url": "git+https://github.com/reconcrap-cpu/boss-recommend-mcp.git"
|
|
114
|
-
},
|
|
115
|
-
"author": "",
|
|
116
|
-
"bugs": {
|
|
117
|
-
"url": "https://github.com/reconcrap-cpu/boss-recommend-mcp/issues"
|
|
118
|
-
},
|
|
119
|
-
"homepage": "https://github.com/reconcrap-cpu/boss-recommend-mcp#readme"
|
|
120
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@reconcrap/boss-recommend-mcp",
|
|
3
|
+
"version": "2.0.52",
|
|
4
|
+
"description": "Unified MCP pipeline for recommend-page filtering and screening on Boss Zhipin",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"boss",
|
|
7
|
+
"mcp",
|
|
8
|
+
"codex",
|
|
9
|
+
"recruiting",
|
|
10
|
+
"boss-zhipin",
|
|
11
|
+
"recommend"
|
|
12
|
+
],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "src/index.js",
|
|
15
|
+
"bin": {
|
|
16
|
+
"boss-recommend-mcp": "bin/boss-recommend-mcp.js"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"start": "node src/index.js",
|
|
20
|
+
"cli": "node src/cli.js",
|
|
21
|
+
"install:local": "node src/cli.js install",
|
|
22
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
23
|
+
"test:parser": "node src/test-parser.js",
|
|
24
|
+
"test:run-state": "node src/test-run-state.js",
|
|
25
|
+
"test:cdp-browser": "node src/test-cdp-browser.js",
|
|
26
|
+
"test:core-capture": "node src/test-core-capture.js",
|
|
27
|
+
"test:core-cv-capture-target": "node src/test-core-cv-capture-target.js",
|
|
28
|
+
"test:core-cv-acquisition": "node src/test-core-cv-acquisition.js",
|
|
29
|
+
"test:core-greet-quota": "node src/test-core-greet-quota.js",
|
|
30
|
+
"test:core-infinite-list": "node src/test-core-infinite-list.js",
|
|
31
|
+
"test:core-reporting": "node src/test-core-reporting.js",
|
|
32
|
+
"test:core-run": "node src/test-core-run.js",
|
|
33
|
+
"test:core-screening": "node src/test-core-screening.js",
|
|
34
|
+
"test:core-self-heal": "node src/test-core-self-heal.js",
|
|
35
|
+
"test:installer-migration": "node src/test-installer-migration.js",
|
|
36
|
+
"test:recommend-actions": "node src/test-recommend-actions.js",
|
|
37
|
+
"test:recommend-domain": "node src/test-recommend-domain.js",
|
|
38
|
+
"test:recommend-run-service": "node src/test-recommend-run-service.js",
|
|
39
|
+
"test:recommend-mcp": "node src/test-recommend-mcp.js",
|
|
40
|
+
"test:recruit-domain": "node src/test-recruit-domain.js",
|
|
41
|
+
"test:recruit-mcp": "node src/test-recruit-mcp.js",
|
|
42
|
+
"test:chat-domain": "node src/test-chat-domain.js",
|
|
43
|
+
"test:chat-run-service": "node src/test-chat-run-service.js",
|
|
44
|
+
"test:chat-mcp": "node src/test-chat-mcp.js",
|
|
45
|
+
"test:async": "node src/test-index-async.js",
|
|
46
|
+
"test:runtime-scan": "node src/test-runtime-scan.js",
|
|
47
|
+
"scan:runtime": "node scripts/scan-forbidden-runtime.js",
|
|
48
|
+
"scan:runtime:json": "node scripts/scan-forbidden-runtime.js --json",
|
|
49
|
+
"scan:runtime:strict": "node scripts/scan-forbidden-runtime.js --fail-on-findings",
|
|
50
|
+
"scan:runtime:package": "node scripts/scan-forbidden-runtime.js --package-surface",
|
|
51
|
+
"scan:runtime:package:strict": "node scripts/scan-forbidden-runtime.js --package-surface --fail-on-legacy",
|
|
52
|
+
"scan:legacy-boundary": "node scripts/scan-legacy-boundary.js",
|
|
53
|
+
"scan:package-boundary": "node scripts/scan-package-boundary.js",
|
|
54
|
+
"gate:phase9-static": "node scripts/phase9-static-gate.js",
|
|
55
|
+
"gate:phase10-complete": "node scripts/phase10-completion-gate.js",
|
|
56
|
+
"live:cdp-smoke": "node scripts/live-cdp-smoke.js",
|
|
57
|
+
"live:run-lifecycle": "node scripts/live-run-lifecycle-smoke.js",
|
|
58
|
+
"live:screening": "node scripts/live-screening-smoke.js",
|
|
59
|
+
"live:detail": "node scripts/live-detail-smoke.js",
|
|
60
|
+
"live:infinite-list": "node scripts/live-infinite-list-smoke.js",
|
|
61
|
+
"live:scroll-end": "node scripts/live-scroll-end-screenshot.js",
|
|
62
|
+
"live:refresh-round": "node scripts/live-refresh-round-smoke.js",
|
|
63
|
+
"live:recommend-recovery": "node scripts/live-recommend-recovery-smoke.js",
|
|
64
|
+
"live:self-heal": "node scripts/live-self-heal-smoke.js",
|
|
65
|
+
"live:recommend-actions": "node scripts/live-recommend-actions-smoke.js",
|
|
66
|
+
"live:recommend-phase10-full": "node scripts/live-recommend-phase10-full.js",
|
|
67
|
+
"live:recommend-domain": "node scripts/live-recommend-domain-smoke.js",
|
|
68
|
+
"live:recommend-run-service": "node scripts/live-recommend-run-service-smoke.js",
|
|
69
|
+
"live:recommend-mcp": "node scripts/live-recommend-mcp-smoke.js",
|
|
70
|
+
"live:search-phase10-full": "node scripts/live-search-phase10-full.js",
|
|
71
|
+
"live:recruit-domain": "node scripts/live-recruit-domain-smoke.js",
|
|
72
|
+
"live:recruit-run-service": "node scripts/live-recruit-run-service-smoke.js",
|
|
73
|
+
"live:recruit-mcp": "node scripts/live-recruit-mcp-smoke.js",
|
|
74
|
+
"live:chat-domain": "node scripts/live-chat-domain-smoke.js",
|
|
75
|
+
"live:chat-run-service": "node scripts/live-chat-run-service-smoke.js",
|
|
76
|
+
"live:chat-mcp": "node scripts/live-chat-mcp-smoke.js",
|
|
77
|
+
"live:cv-capture-target": "node scripts/live-cv-capture-target-smoke.js",
|
|
78
|
+
"live:chat-phase10-full": "node scripts/live-chat-phase10-full.js",
|
|
79
|
+
"live:chat-image-screening": "node scripts/live-chat-image-screening-smoke.js"
|
|
80
|
+
},
|
|
81
|
+
"files": [
|
|
82
|
+
"bin",
|
|
83
|
+
"config/screening-config.example.json",
|
|
84
|
+
"skills",
|
|
85
|
+
"scripts/postinstall.cjs",
|
|
86
|
+
"src/core",
|
|
87
|
+
"src/domains",
|
|
88
|
+
"src/chat-mcp.js",
|
|
89
|
+
"src/chat-runtime-config.js",
|
|
90
|
+
"src/cli.js",
|
|
91
|
+
"src/index.js",
|
|
92
|
+
"src/parser.js",
|
|
93
|
+
"src/recommend-mcp.js",
|
|
94
|
+
"src/recruit-mcp.js",
|
|
95
|
+
"src/run-state.js",
|
|
96
|
+
"README.md"
|
|
97
|
+
],
|
|
98
|
+
"dependencies": {
|
|
99
|
+
"chrome-remote-interface": "^0.33.3",
|
|
100
|
+
"sharp": "^0.34.4",
|
|
101
|
+
"ws": "^8.19.0"
|
|
102
|
+
},
|
|
103
|
+
"engines": {
|
|
104
|
+
"node": ">=18"
|
|
105
|
+
},
|
|
106
|
+
"publishConfig": {
|
|
107
|
+
"access": "public"
|
|
108
|
+
},
|
|
109
|
+
"license": "MIT",
|
|
110
|
+
"devDependencies": {},
|
|
111
|
+
"repository": {
|
|
112
|
+
"type": "git",
|
|
113
|
+
"url": "git+https://github.com/reconcrap-cpu/boss-recommend-mcp.git"
|
|
114
|
+
},
|
|
115
|
+
"author": "",
|
|
116
|
+
"bugs": {
|
|
117
|
+
"url": "https://github.com/reconcrap-cpu/boss-recommend-mcp/issues"
|
|
118
|
+
},
|
|
119
|
+
"homepage": "https://github.com/reconcrap-cpu/boss-recommend-mcp#readme"
|
|
120
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -7,10 +7,10 @@ import { createRequire } from "node:module";
|
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import {
|
|
9
9
|
assertNoForbiddenCdpCalls,
|
|
10
|
-
buildBossChromeLaunchArgs,
|
|
11
10
|
bringPageToFront,
|
|
12
11
|
connectToChromeTarget,
|
|
13
12
|
enableDomains,
|
|
13
|
+
ensureChromeDebugPort,
|
|
14
14
|
getDocumentRoot,
|
|
15
15
|
querySelector,
|
|
16
16
|
sleep as sleepMs
|
|
@@ -88,6 +88,10 @@ function getPackageVersion() {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const packageVersion = getPackageVersion();
|
|
91
|
+
const detachedRecommendMcpEnv = {
|
|
92
|
+
BOSS_RECOMMEND_CDP_DETACHED: "1",
|
|
93
|
+
BOSS_RECOMMEND_RUN_HEARTBEAT_MS: "10000"
|
|
94
|
+
};
|
|
91
95
|
|
|
92
96
|
function isInstalledPackageRoot(rootPath = packageRoot) {
|
|
93
97
|
const normalized = path.resolve(String(rootPath || ""))
|
|
@@ -726,6 +730,25 @@ function parseMcpClientTargets(rawValue) {
|
|
|
726
730
|
return unique;
|
|
727
731
|
}
|
|
728
732
|
|
|
733
|
+
function isPlainObject(value) {
|
|
734
|
+
return value && typeof value === "object" && !Array.isArray(value);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function shouldDefaultRecommendDetachedMcpEnv(options = {}) {
|
|
738
|
+
const client = normalizeMcpClientName(options.client);
|
|
739
|
+
const agent = normalizeAgentName(options.agent);
|
|
740
|
+
return client === "openclaw"
|
|
741
|
+
|| client === "qclaw"
|
|
742
|
+
|| agent === "openclaw"
|
|
743
|
+
|| agent === "qclaw";
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function getDefaultMcpEnv(options = {}) {
|
|
747
|
+
return shouldDefaultRecommendDetachedMcpEnv(options)
|
|
748
|
+
? { ...detachedRecommendMcpEnv }
|
|
749
|
+
: {};
|
|
750
|
+
}
|
|
751
|
+
|
|
729
752
|
function getAgentConfigOutputDir(options = {}) {
|
|
730
753
|
if (typeof options["output-dir"] === "string" && options["output-dir"].trim()) {
|
|
731
754
|
return path.resolve(options["output-dir"]);
|
|
@@ -745,12 +768,29 @@ function buildMcpLaunchConfig(options = {}) {
|
|
|
745
768
|
? ["start"]
|
|
746
769
|
: buildDefaultMcpArgs(options);
|
|
747
770
|
const launchConfig = { command, args: launchArgs };
|
|
748
|
-
|
|
749
|
-
|
|
771
|
+
const mergedEnv = {
|
|
772
|
+
...getDefaultMcpEnv(options),
|
|
773
|
+
...(isPlainObject(env) ? env : {})
|
|
774
|
+
};
|
|
775
|
+
if (Object.keys(mergedEnv).length > 0) {
|
|
776
|
+
launchConfig.env = mergedEnv;
|
|
750
777
|
}
|
|
751
778
|
return launchConfig;
|
|
752
779
|
}
|
|
753
780
|
|
|
781
|
+
function mergeExistingMcpEntryEnv(existingEntry, launchConfig) {
|
|
782
|
+
if (!isPlainObject(existingEntry?.env) || !isPlainObject(launchConfig)) {
|
|
783
|
+
return launchConfig;
|
|
784
|
+
}
|
|
785
|
+
return {
|
|
786
|
+
...launchConfig,
|
|
787
|
+
env: {
|
|
788
|
+
...existingEntry.env,
|
|
789
|
+
...(isPlainObject(launchConfig.env) ? launchConfig.env : {})
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
|
|
754
794
|
function buildMcpConfigFileContent(options = {}) {
|
|
755
795
|
const serverName = typeof options["server-name"] === "string" && options["server-name"].trim()
|
|
756
796
|
? options["server-name"].trim()
|
|
@@ -872,7 +912,7 @@ function getKnownExternalMcpConfigPathsByAgent() {
|
|
|
872
912
|
trae: [...traeConfigPaths, path.join(home, ".trae", "mcp.json"), path.join(home, ".trae-cn", "mcp.json")],
|
|
873
913
|
"trae-cn": [...traeConfigPaths, path.join(home, ".trae-cn", "mcp.json"), path.join(home, ".trae", "mcp.json")],
|
|
874
914
|
claude: [path.join(home, ".claude", "mcp.json")],
|
|
875
|
-
openclaw: [path.join(home, ".openclaw", "mcp.json"), ...openClawConfigPaths],
|
|
915
|
+
openclaw: [path.join(home, ".openclaw", "mcp.json"), path.join(home, ".openclaw", "openclaw.json"), ...openClawConfigPaths],
|
|
876
916
|
qclaw: [path.join(home, ".qclaw", "openclaw.json")]
|
|
877
917
|
};
|
|
878
918
|
}
|
|
@@ -920,9 +960,12 @@ function mergeMcpServerConfigFile(filePath, options = {}) {
|
|
|
920
960
|
const nextConfig = buildMcpConfigFileContent({ ...options, client: useQClawShape ? "qclaw" : options.client });
|
|
921
961
|
const nextServers = useQClawShape ? nextConfig.mcp?.servers : nextConfig.mcpServers;
|
|
922
962
|
const serverName = Object.keys(nextServers || {})[0] || defaultMcpServerName;
|
|
923
|
-
const launchConfig = nextServers?.[serverName] || buildMcpLaunchConfig(options);
|
|
924
963
|
const existingServers = getMcpServersFromConfig(current, useQClawShape);
|
|
925
964
|
const existingEntry = existingServers[serverName];
|
|
965
|
+
const launchConfig = mergeExistingMcpEntryEnv(
|
|
966
|
+
existingEntry,
|
|
967
|
+
nextServers?.[serverName] || buildMcpLaunchConfig(options)
|
|
968
|
+
);
|
|
926
969
|
const retainedServers = {};
|
|
927
970
|
const migratedLegacyServers = [];
|
|
928
971
|
for (const [name, config] of Object.entries(existingServers)) {
|
|
@@ -2209,51 +2252,38 @@ async function launchChrome(options = {}) {
|
|
|
2209
2252
|
const port = parsePositivePort(options.port) || parsePositivePort(process.env.BOSS_RECOMMEND_CHROME_PORT) || 9222;
|
|
2210
2253
|
process.env.BOSS_RECOMMEND_CHROME_PORT = String(port);
|
|
2211
2254
|
const timing = getLaunchChromeTiming(options);
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
inspectTimeoutMs: timing.inspectTimeoutMs,
|
|
2222
|
-
pollMs: timing.pollMs,
|
|
2223
|
-
settleMs: timing.settleMs
|
|
2255
|
+
const userDataDir = getChromeUserDataDir(port);
|
|
2256
|
+
let chromeGuard = null;
|
|
2257
|
+
try {
|
|
2258
|
+
chromeGuard = await ensureChromeDebugPort({
|
|
2259
|
+
port,
|
|
2260
|
+
url: bossUrl,
|
|
2261
|
+
slowLive: Boolean(options["slow-live"] || options.slowLive),
|
|
2262
|
+
launchIfMissing: true,
|
|
2263
|
+
userDataDir
|
|
2224
2264
|
});
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
console.log(`CDP methods: ${frontResult.method_log.join(", ") || "none"}`);
|
|
2230
|
-
}
|
|
2231
|
-
} else {
|
|
2232
|
-
console.log(pageState.page_state?.message || "Boss recommend page is not ready.");
|
|
2265
|
+
} catch (error) {
|
|
2266
|
+
console.error(error?.message || String(error || "Chrome launch failed"));
|
|
2267
|
+
if (error?.chrome_guard) {
|
|
2268
|
+
console.error(JSON.stringify(error.chrome_guard, null, 2));
|
|
2233
2269
|
}
|
|
2234
|
-
return;
|
|
2235
|
-
}
|
|
2236
|
-
|
|
2237
|
-
const chromePath = getChromeExecutable();
|
|
2238
|
-
if (!chromePath) {
|
|
2239
|
-
console.error("Chrome executable not found. Set BOSS_RECOMMEND_CHROME_PATH or install Google Chrome.");
|
|
2240
2270
|
process.exitCode = 1;
|
|
2241
2271
|
return;
|
|
2242
2272
|
}
|
|
2243
2273
|
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2274
|
+
if (chromeGuard.replaced) {
|
|
2275
|
+
console.log(`Replaced Chrome debug instance on port ${port} because required flags were missing: ${chromeGuard.missing_flags.join(", ")}`);
|
|
2276
|
+
} else if (chromeGuard.launched) {
|
|
2277
|
+
console.log(`Chrome launched with remote debugging port ${port}`);
|
|
2278
|
+
} else {
|
|
2279
|
+
console.log(`Reusing existing Chrome debug instance on port ${port} with required flags`);
|
|
2280
|
+
}
|
|
2281
|
+
console.log(`User data dir: ${chromeGuard.user_data_dir || userDataDir}`);
|
|
2282
|
+
if (chromeGuard.launched || chromeGuard.replaced) {
|
|
2283
|
+
await sleepMs(timing.settleMs + 1200);
|
|
2284
|
+
}
|
|
2255
2285
|
const pageState = await ensureBossRecommendPageReadyCdp(port, {
|
|
2256
|
-
attempts: 6,
|
|
2286
|
+
attempts: chromeGuard.launched || chromeGuard.replaced ? 6 : 2,
|
|
2257
2287
|
inspectTimeoutMs: timing.inspectTimeoutMs,
|
|
2258
2288
|
pollMs: timing.pollMs,
|
|
2259
2289
|
settleMs: timing.settleMs
|
|
@@ -2382,15 +2412,30 @@ async function printDoctor(options = {}) {
|
|
|
2382
2412
|
const configResolution = getBossScreenConfigResolution(workspaceRoot);
|
|
2383
2413
|
const calibrationResolution = getFeaturedCalibrationResolutionLocal(workspaceRoot);
|
|
2384
2414
|
const timing = getLaunchChromeTiming(options);
|
|
2415
|
+
const slowLive = Boolean(options["slow-live"] || options.slowLive);
|
|
2416
|
+
let chromeGuard = null;
|
|
2417
|
+
let chromeGuardError = null;
|
|
2418
|
+
try {
|
|
2419
|
+
chromeGuard = await ensureChromeDebugPort({
|
|
2420
|
+
port,
|
|
2421
|
+
url: bossUrl,
|
|
2422
|
+
slowLive,
|
|
2423
|
+
launchIfMissing: true,
|
|
2424
|
+
userDataDir: getChromeUserDataDir(port)
|
|
2425
|
+
});
|
|
2426
|
+
} catch (error) {
|
|
2427
|
+
chromeGuardError = error;
|
|
2428
|
+
chromeGuard = error?.chrome_guard || null;
|
|
2429
|
+
}
|
|
2385
2430
|
let pageState = await inspectBossRecommendPageStateCdp(port, {
|
|
2386
|
-
timeoutMs:
|
|
2387
|
-
pollMs:
|
|
2431
|
+
timeoutMs: slowLive ? timing.initialTimeoutMs : 2000,
|
|
2432
|
+
pollMs: slowLive ? timing.pollMs : 500
|
|
2388
2433
|
});
|
|
2389
2434
|
if (pageState.state === "RECOMMEND_READY") {
|
|
2390
2435
|
pageState = await verifyRecommendPageStableCdp(port, {
|
|
2391
|
-
settleMs:
|
|
2392
|
-
recheckTimeoutMs:
|
|
2393
|
-
pollMs:
|
|
2436
|
+
settleMs: slowLive ? timing.settleMs : 800,
|
|
2437
|
+
recheckTimeoutMs: slowLive ? timing.inspectTimeoutMs : 3000,
|
|
2438
|
+
pollMs: slowLive ? timing.pollMs : 500
|
|
2394
2439
|
});
|
|
2395
2440
|
}
|
|
2396
2441
|
const resolvedConfigPath = configResolution.resolved_path || configResolution.writable_path;
|
|
@@ -2407,6 +2452,28 @@ async function printDoctor(options = {}) {
|
|
|
2407
2452
|
? `检测到配置文件(resolved_path):${resolvedConfigPath}`
|
|
2408
2453
|
: "用户配置不存在(可通过 `boss-recommend-mcp init-config` 创建模板,或 `boss-recommend-mcp config set` 写入真实值)"
|
|
2409
2454
|
});
|
|
2455
|
+
const requiredFlags = chromeGuard?.required_flags || [];
|
|
2456
|
+
const missingFlags = chromeGuard?.missing_flags || [];
|
|
2457
|
+
const chromeFlagsOk = Boolean(chromeGuard && !chromeGuardError && chromeGuard.required_flags_ok);
|
|
2458
|
+
checks.push({
|
|
2459
|
+
key: "chrome_required_flags",
|
|
2460
|
+
ok: chromeFlagsOk,
|
|
2461
|
+
path: `http://localhost:${port}`,
|
|
2462
|
+
required_flags: requiredFlags,
|
|
2463
|
+
missing_flags: missingFlags,
|
|
2464
|
+
replaced: Boolean(chromeGuard?.replaced),
|
|
2465
|
+
close_method: chromeGuard?.close_method || null,
|
|
2466
|
+
relaunch: chromeGuard?.relaunch || null,
|
|
2467
|
+
message: chromeFlagsOk
|
|
2468
|
+
? chromeGuard?.replaced
|
|
2469
|
+
? `Chrome 调试端口 ${port} 原实例缺少必需 flags,已自动关闭并用正确 flags 重新启动。`
|
|
2470
|
+
: chromeGuard?.launched
|
|
2471
|
+
? `Chrome 调试端口 ${port} 已用必需 flags 启动。`
|
|
2472
|
+
: `Chrome 调试端口 ${port} 已确认包含必需 flags。`
|
|
2473
|
+
: chromeGuardError
|
|
2474
|
+
? `Chrome 必需 flags 检查失败:${chromeGuardError.message}`
|
|
2475
|
+
: `Chrome 调试端口 ${port} 未确认包含必需 flags。`
|
|
2476
|
+
});
|
|
2410
2477
|
checks.push({
|
|
2411
2478
|
key: "chrome_debug_port",
|
|
2412
2479
|
ok: pageState.state !== "DEBUG_PORT_UNREACHABLE",
|