@reconcrap/boss-recommend-mcp 2.1.21 → 2.1.23
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 +5 -2
- package/bin/boss-recommend-mcp.js +4 -4
- package/config/screening-config.example.json +33 -33
- package/package.json +2 -1
- package/scripts/install-macos.sh +280 -280
- package/scripts/postinstall.cjs +44 -44
- package/skills/boss-chat/README.md +42 -42
- package/skills/boss-chat/SKILL.md +106 -106
- package/skills/boss-recommend-pipeline/README.md +13 -13
- package/skills/boss-recommend-pipeline/SKILL.md +219 -214
- package/skills/boss-recruit-pipeline/README.md +19 -19
- package/skills/boss-recruit-pipeline/SKILL.md +89 -89
- package/src/chat-mcp.js +127 -127
- package/src/chat-runtime-config.js +775 -775
- package/src/cli.js +573 -573
- package/src/core/boss-cards/index.js +199 -199
- package/src/core/browser/index.js +2416 -2385
- package/src/core/capture/index.js +1201 -1201
- package/src/core/cv-acquisition/index.js +238 -238
- package/src/core/cv-capture-target/index.js +299 -299
- package/src/core/greet-quota/index.js +71 -71
- package/src/core/infinite-list/index.js +1315 -1306
- package/src/core/reporting/legacy-csv.js +334 -332
- package/src/core/run/index.js +44 -27
- package/src/core/run/timing.js +33 -33
- package/src/core/screening/index.js +2135 -2135
- package/src/core/self-heal/index.js +973 -973
- package/src/core/self-heal/viewport.js +564 -564
- package/src/detached-worker.js +99 -99
- package/src/domains/chat/cards.js +137 -137
- package/src/domains/chat/constants.js +9 -9
- package/src/domains/chat/detail.js +113 -113
- package/src/domains/chat/index.js +7 -7
- package/src/domains/chat/jobs.js +620 -620
- package/src/domains/chat/page-guard.js +122 -122
- package/src/domains/chat/roots.js +56 -56
- package/src/domains/chat/run-service.js +571 -571
- package/src/domains/common/account-rights-panel.js +314 -314
- package/src/domains/common/recovery-settle.js +159 -159
- package/src/domains/recommend/actions.js +472 -472
- package/src/domains/recommend/cards.js +243 -243
- package/src/domains/recommend/colleague-contact.js +333 -333
- package/src/domains/recommend/constants.js +228 -159
- package/src/domains/recommend/detail.js +655 -646
- package/src/domains/recommend/filters.js +748 -377
- package/src/domains/recommend/index.js +4 -3
- package/src/domains/recommend/jobs.js +542 -542
- package/src/domains/recommend/location.js +736 -0
- package/src/domains/recommend/refresh.js +575 -351
- package/src/domains/recommend/roots.js +80 -80
- package/src/domains/recommend/run-service.js +1616 -878
- package/src/domains/recommend/scopes.js +246 -246
- package/src/domains/recruit/actions.js +277 -277
- package/src/domains/recruit/cards.js +74 -74
- package/src/domains/recruit/constants.js +236 -236
- package/src/domains/recruit/detail.js +588 -588
- package/src/domains/recruit/index.js +9 -9
- package/src/domains/recruit/instruction-parser.js +866 -866
- package/src/domains/recruit/refresh.js +45 -45
- package/src/domains/recruit/roots.js +68 -68
- package/src/domains/recruit/run-service.js +1620 -1620
- package/src/domains/recruit/search.js +3229 -3229
- package/src/index.js +121 -4
- package/src/parser.js +376 -8
- package/src/recommend-mcp.js +1174 -914
- package/src/recommend-scheduler.js +535 -469
- package/src/recruit-mcp.js +2121 -2121
package/src/cli.js
CHANGED
|
@@ -23,19 +23,19 @@ import {
|
|
|
23
23
|
prepareBossChatRunTool,
|
|
24
24
|
resumeBossChatRunTool
|
|
25
25
|
} from "./chat-mcp.js";
|
|
26
|
-
import {
|
|
27
|
-
cancelRecommendPipelineRunTool,
|
|
28
|
-
getRecommendPipelineRunTool,
|
|
29
|
-
listRecommendJobsTool,
|
|
30
|
-
pauseRecommendPipelineRunTool,
|
|
31
|
-
prepareRecommendPipelineRunTool,
|
|
32
|
-
resumeRecommendPipelineRunTool,
|
|
33
|
-
startRecommendPipelineRunTool
|
|
34
|
-
} from "./recommend-mcp.js";
|
|
35
|
-
import {
|
|
36
|
-
getRecommendScheduledRunTool,
|
|
37
|
-
scheduleRecommendPipelineRunTool
|
|
38
|
-
} from "./recommend-scheduler.js";
|
|
26
|
+
import {
|
|
27
|
+
cancelRecommendPipelineRunTool,
|
|
28
|
+
getRecommendPipelineRunTool,
|
|
29
|
+
listRecommendJobsTool,
|
|
30
|
+
pauseRecommendPipelineRunTool,
|
|
31
|
+
prepareRecommendPipelineRunTool,
|
|
32
|
+
resumeRecommendPipelineRunTool,
|
|
33
|
+
startRecommendPipelineRunTool
|
|
34
|
+
} from "./recommend-mcp.js";
|
|
35
|
+
import {
|
|
36
|
+
getRecommendScheduledRunTool,
|
|
37
|
+
scheduleRecommendPipelineRunTool
|
|
38
|
+
} from "./recommend-scheduler.js";
|
|
39
39
|
import {
|
|
40
40
|
getBossScreenConfigResolution,
|
|
41
41
|
resolveBossChatRuntimeLayout as resolveCdpBossChatRuntimeLayout,
|
|
@@ -57,17 +57,17 @@ const bossLoginUrl = "https://www.zhipin.com/web/user/?ka=bticket";
|
|
|
57
57
|
const chromeOnboardingUrlPattern = /^chrome:\/\/(welcome|intro|newtab|signin|history-sync|settings\/syncSetup)/i;
|
|
58
58
|
const bossLoginUrlPattern = /(?:zhipin\.com\/web\/user(?:\/|\?|$)|passport\.zhipin\.com)/i;
|
|
59
59
|
const bossLoginTitlePattern = /登录|signin|扫码登录|BOSS直聘登录/i;
|
|
60
|
-
const supportedMcpClients = ["generic", "cursor", "trae", "claudecode", "openclaw", "qclaw"];
|
|
61
|
-
const defaultMcpServerName = "boss-recommend";
|
|
62
|
-
const bossChatMcpServerName = "boss-chat";
|
|
63
|
-
const bossRecruitMcpServerName = "boss-recruit";
|
|
64
|
-
const defaultMcpCommand = "npx";
|
|
65
|
-
const recommendMcpPackageName = "@reconcrap/boss-recommend-mcp";
|
|
66
|
-
const recommendMcpBinaryName = "boss-recommend-mcp";
|
|
67
|
-
const globalMcpWrapperFileName = "boss-recommend-mcp-mcp-server";
|
|
68
|
-
const mcpToolsetEnv = "BOSS_RECOMMEND_MCP_TOOLSET";
|
|
69
|
-
const supportedMcpLaunchModes = ["npx", "global-wrapper"];
|
|
70
|
-
const autoSyncSkipCommands = new Set(["install", "install-skill", "where", "help", "--help", "-h", "list-jobs", "jobs", "recommend-jobs"]);
|
|
60
|
+
const supportedMcpClients = ["generic", "cursor", "trae", "claudecode", "openclaw", "qclaw"];
|
|
61
|
+
const defaultMcpServerName = "boss-recommend";
|
|
62
|
+
const bossChatMcpServerName = "boss-chat";
|
|
63
|
+
const bossRecruitMcpServerName = "boss-recruit";
|
|
64
|
+
const defaultMcpCommand = "npx";
|
|
65
|
+
const recommendMcpPackageName = "@reconcrap/boss-recommend-mcp";
|
|
66
|
+
const recommendMcpBinaryName = "boss-recommend-mcp";
|
|
67
|
+
const globalMcpWrapperFileName = "boss-recommend-mcp-mcp-server";
|
|
68
|
+
const mcpToolsetEnv = "BOSS_RECOMMEND_MCP_TOOLSET";
|
|
69
|
+
const supportedMcpLaunchModes = ["npx", "global-wrapper"];
|
|
70
|
+
const autoSyncSkipCommands = new Set(["install", "install-skill", "where", "help", "--help", "-h", "list-jobs", "jobs", "recommend-jobs"]);
|
|
71
71
|
const externalMcpTargetsEnv = "BOSS_RECOMMEND_MCP_CONFIG_TARGETS";
|
|
72
72
|
const externalSkillDirsEnv = "BOSS_RECOMMEND_EXTERNAL_SKILL_DIRS";
|
|
73
73
|
const installConfigDefaults = Object.freeze({
|
|
@@ -77,13 +77,13 @@ const installConfigDefaults = Object.freeze({
|
|
|
77
77
|
llmMaxRetries: 3,
|
|
78
78
|
llmImageLimit: 8,
|
|
79
79
|
llmImageDetail: "low",
|
|
80
|
-
humanRestEnabled: true,
|
|
81
|
-
humanBehavior: {
|
|
82
|
-
enabled: true,
|
|
83
|
-
profile: "paced_with_rests",
|
|
84
|
-
restLevel: "low"
|
|
85
|
-
}
|
|
86
|
-
});
|
|
80
|
+
humanRestEnabled: true,
|
|
81
|
+
humanBehavior: {
|
|
82
|
+
enabled: true,
|
|
83
|
+
profile: "paced_with_rests",
|
|
84
|
+
restLevel: "low"
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
87
|
const bossChatRuntimeChildDirs = ["logs", "runs", "profiles", "reports", "artifacts", "state"];
|
|
88
88
|
const bossChatCliUnsupportedStartCode = "CHAT_CLI_ASYNC_UNSUPPORTED_CDP_ONLY";
|
|
89
89
|
const calibrateUnsupportedCode = "CALIBRATE_UNSUPPORTED_CDP_ONLY";
|
|
@@ -137,22 +137,22 @@ function getCodexHome() {
|
|
|
137
137
|
: path.join(os.homedir(), ".codex");
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
function getStateHome() {
|
|
141
|
-
return process.env.BOSS_RECOMMEND_HOME
|
|
142
|
-
? path.resolve(process.env.BOSS_RECOMMEND_HOME)
|
|
143
|
-
: path.join(os.homedir(), ".boss-recommend-mcp");
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function getGlobalMcpWrapperPath(options = {}) {
|
|
147
|
-
if (typeof options["mcp-wrapper-path"] === "string" && options["mcp-wrapper-path"].trim()) {
|
|
148
|
-
return path.resolve(options["mcp-wrapper-path"].trim());
|
|
149
|
-
}
|
|
150
|
-
return path.join(getStateHome(), "bin", globalMcpWrapperFileName);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function ensureDir(targetPath) {
|
|
154
|
-
fs.mkdirSync(targetPath, { recursive: true });
|
|
155
|
-
}
|
|
140
|
+
function getStateHome() {
|
|
141
|
+
return process.env.BOSS_RECOMMEND_HOME
|
|
142
|
+
? path.resolve(process.env.BOSS_RECOMMEND_HOME)
|
|
143
|
+
: path.join(os.homedir(), ".boss-recommend-mcp");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function getGlobalMcpWrapperPath(options = {}) {
|
|
147
|
+
if (typeof options["mcp-wrapper-path"] === "string" && options["mcp-wrapper-path"].trim()) {
|
|
148
|
+
return path.resolve(options["mcp-wrapper-path"].trim());
|
|
149
|
+
}
|
|
150
|
+
return path.join(getStateHome(), "bin", globalMcpWrapperFileName);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function ensureDir(targetPath) {
|
|
154
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
155
|
+
}
|
|
156
156
|
|
|
157
157
|
function pathExists(targetPath) {
|
|
158
158
|
try {
|
|
@@ -635,20 +635,20 @@ function parseBossChatTargetCountOption(raw) {
|
|
|
635
635
|
return parsed ?? text;
|
|
636
636
|
}
|
|
637
637
|
|
|
638
|
-
function parseBooleanOption(raw, fallback = undefined) {
|
|
639
|
-
if (raw === undefined || raw === null || raw === "") return fallback;
|
|
640
|
-
if (raw === true) return true;
|
|
641
|
-
const normalized = String(raw).trim().toLowerCase();
|
|
642
|
-
if (["true", "1", "yes", "y", "on"].includes(normalized)) return true;
|
|
643
|
-
if (["false", "0", "no", "n", "off"].includes(normalized)) return false;
|
|
644
|
-
return fallback;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
function parseRestLevelOption(raw) {
|
|
648
|
-
if (raw === undefined || raw === null || raw === "") return undefined;
|
|
649
|
-
const normalized = String(raw).trim().toLowerCase();
|
|
650
|
-
return ["low", "medium", "high"].includes(normalized) ? normalized : undefined;
|
|
651
|
-
}
|
|
638
|
+
function parseBooleanOption(raw, fallback = undefined) {
|
|
639
|
+
if (raw === undefined || raw === null || raw === "") return fallback;
|
|
640
|
+
if (raw === true) return true;
|
|
641
|
+
const normalized = String(raw).trim().toLowerCase();
|
|
642
|
+
if (["true", "1", "yes", "y", "on"].includes(normalized)) return true;
|
|
643
|
+
if (["false", "0", "no", "n", "off"].includes(normalized)) return false;
|
|
644
|
+
return fallback;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
function parseRestLevelOption(raw) {
|
|
648
|
+
if (raw === undefined || raw === null || raw === "") return undefined;
|
|
649
|
+
const normalized = String(raw).trim().toLowerCase();
|
|
650
|
+
return ["low", "medium", "high"].includes(normalized) ? normalized : undefined;
|
|
651
|
+
}
|
|
652
652
|
|
|
653
653
|
function normalizePageScope(value) {
|
|
654
654
|
const normalized = String(value || "").trim().toLowerCase();
|
|
@@ -758,87 +758,87 @@ function parseMcpClientTargets(rawValue) {
|
|
|
758
758
|
return unique;
|
|
759
759
|
}
|
|
760
760
|
|
|
761
|
-
function isPlainObject(value) {
|
|
762
|
-
return value && typeof value === "object" && !Array.isArray(value);
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
function normalizeMcpLaunchMode(options = {}) {
|
|
766
|
-
const raw = String(options["mcp-launch"] || options.mcpLaunch || "").trim().toLowerCase().replace(/_/g, "-");
|
|
767
|
-
if (!raw) return "npx";
|
|
768
|
-
if (raw === "default") return "npx";
|
|
769
|
-
if (raw === "global" || raw === "wrapper") return "global-wrapper";
|
|
770
|
-
if (supportedMcpLaunchModes.includes(raw)) return raw;
|
|
771
|
-
throw new Error(`Unsupported --mcp-launch value: ${raw}. Supported: ${supportedMcpLaunchModes.join(", ")}`);
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
function buildGlobalMcpWrapperScript() {
|
|
775
|
-
return `#!/usr/bin/env bash
|
|
776
|
-
set -euo pipefail
|
|
777
|
-
|
|
778
|
-
export NVM_DIR="\${NVM_DIR:-$HOME/.nvm}"
|
|
779
|
-
if [ -s "$NVM_DIR/nvm.sh" ]; then
|
|
780
|
-
. "$NVM_DIR/nvm.sh"
|
|
781
|
-
elif [ -s "$HOME/.nvm/nvm.sh" ]; then
|
|
782
|
-
export NVM_DIR="$HOME/.nvm"
|
|
783
|
-
. "$NVM_DIR/nvm.sh"
|
|
784
|
-
fi
|
|
785
|
-
|
|
786
|
-
if ! command -v ${recommendMcpBinaryName} >/dev/null 2>&1; then
|
|
787
|
-
echo "${recommendMcpBinaryName} not found on PATH. Install or reload nvm, then run: npm -g i ${recommendMcpPackageName}@latest" >&2
|
|
788
|
-
exit 127
|
|
789
|
-
fi
|
|
790
|
-
|
|
791
|
-
exec ${recommendMcpBinaryName} start "$@"
|
|
792
|
-
`;
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
function ensureGlobalMcpWrapper(options = {}) {
|
|
796
|
-
const wrapperPath = getGlobalMcpWrapperPath(options);
|
|
797
|
-
ensureDir(path.dirname(wrapperPath));
|
|
798
|
-
fs.writeFileSync(wrapperPath, buildGlobalMcpWrapperScript(), "utf8");
|
|
799
|
-
try {
|
|
800
|
-
fs.chmodSync(wrapperPath, 0o755);
|
|
801
|
-
} catch {
|
|
802
|
-
// Some filesystems ignore POSIX executable bits; the path is still valid for POSIX hosts.
|
|
803
|
-
}
|
|
804
|
-
return wrapperPath;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
function shouldDefaultRecommendDetachedMcpEnv(options = {}) {
|
|
808
|
-
const client = normalizeMcpClientName(options.client);
|
|
809
|
-
const agent = normalizeAgentName(options.agent);
|
|
761
|
+
function isPlainObject(value) {
|
|
762
|
+
return value && typeof value === "object" && !Array.isArray(value);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
function normalizeMcpLaunchMode(options = {}) {
|
|
766
|
+
const raw = String(options["mcp-launch"] || options.mcpLaunch || "").trim().toLowerCase().replace(/_/g, "-");
|
|
767
|
+
if (!raw) return "npx";
|
|
768
|
+
if (raw === "default") return "npx";
|
|
769
|
+
if (raw === "global" || raw === "wrapper") return "global-wrapper";
|
|
770
|
+
if (supportedMcpLaunchModes.includes(raw)) return raw;
|
|
771
|
+
throw new Error(`Unsupported --mcp-launch value: ${raw}. Supported: ${supportedMcpLaunchModes.join(", ")}`);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function buildGlobalMcpWrapperScript() {
|
|
775
|
+
return `#!/usr/bin/env bash
|
|
776
|
+
set -euo pipefail
|
|
777
|
+
|
|
778
|
+
export NVM_DIR="\${NVM_DIR:-$HOME/.nvm}"
|
|
779
|
+
if [ -s "$NVM_DIR/nvm.sh" ]; then
|
|
780
|
+
. "$NVM_DIR/nvm.sh"
|
|
781
|
+
elif [ -s "$HOME/.nvm/nvm.sh" ]; then
|
|
782
|
+
export NVM_DIR="$HOME/.nvm"
|
|
783
|
+
. "$NVM_DIR/nvm.sh"
|
|
784
|
+
fi
|
|
785
|
+
|
|
786
|
+
if ! command -v ${recommendMcpBinaryName} >/dev/null 2>&1; then
|
|
787
|
+
echo "${recommendMcpBinaryName} not found on PATH. Install or reload nvm, then run: npm -g i ${recommendMcpPackageName}@latest" >&2
|
|
788
|
+
exit 127
|
|
789
|
+
fi
|
|
790
|
+
|
|
791
|
+
exec ${recommendMcpBinaryName} start "$@"
|
|
792
|
+
`;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
function ensureGlobalMcpWrapper(options = {}) {
|
|
796
|
+
const wrapperPath = getGlobalMcpWrapperPath(options);
|
|
797
|
+
ensureDir(path.dirname(wrapperPath));
|
|
798
|
+
fs.writeFileSync(wrapperPath, buildGlobalMcpWrapperScript(), "utf8");
|
|
799
|
+
try {
|
|
800
|
+
fs.chmodSync(wrapperPath, 0o755);
|
|
801
|
+
} catch {
|
|
802
|
+
// Some filesystems ignore POSIX executable bits; the path is still valid for POSIX hosts.
|
|
803
|
+
}
|
|
804
|
+
return wrapperPath;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function shouldDefaultRecommendDetachedMcpEnv(options = {}) {
|
|
808
|
+
const client = normalizeMcpClientName(options.client);
|
|
809
|
+
const agent = normalizeAgentName(options.agent);
|
|
810
810
|
return client === "openclaw"
|
|
811
811
|
|| client === "qclaw"
|
|
812
812
|
|| agent === "openclaw"
|
|
813
|
-
|| agent === "qclaw";
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
function normalizeMcpToolsetOption(value) {
|
|
817
|
-
const raw = String(value || "").trim().toLowerCase().replace(/[\s_]+/g, "-");
|
|
818
|
-
if (!raw || raw === "all") return "";
|
|
819
|
-
if (raw === "boss-recommend" || raw === "recommend-page") return "recommend";
|
|
820
|
-
if (raw === "boss-chat" || raw === "chat-only" || raw === "chat-page") return "chat";
|
|
821
|
-
if (raw === "boss-recruit" || raw === "search" || raw === "search-page" || raw === "recruit-page") return "recruit";
|
|
822
|
-
if (["recommend", "chat", "recruit"].includes(raw)) return raw;
|
|
823
|
-
throw new Error(`Unsupported --toolset value: ${raw}. Supported: recommend, chat, recruit, all`);
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
function getMcpToolsetEnv(options = {}) {
|
|
827
|
-
const toolset = normalizeMcpToolsetOption(options.toolset || options["toolset"]);
|
|
828
|
-
return toolset ? { [mcpToolsetEnv]: toolset } : {};
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
function shouldUseSplitBossMcpServers(options = {}) {
|
|
832
|
-
if (options["server-name"] || options.serverName || options.toolset || options["toolset"]) return false;
|
|
833
|
-
if (options.split === true || options["split-tools"] === true || options.splitTools === true) return true;
|
|
834
|
-
const client = normalizeMcpClientName(options.client);
|
|
835
|
-
const agent = normalizeAgentName(options.agent);
|
|
836
|
-
return client === "trae" || agent === "trae" || agent === "trae-cn";
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
function getDefaultMcpEnv(options = {}) {
|
|
840
|
-
return shouldDefaultRecommendDetachedMcpEnv(options)
|
|
841
|
-
? { ...detachedRecommendMcpEnv }
|
|
813
|
+
|| agent === "qclaw";
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function normalizeMcpToolsetOption(value) {
|
|
817
|
+
const raw = String(value || "").trim().toLowerCase().replace(/[\s_]+/g, "-");
|
|
818
|
+
if (!raw || raw === "all") return "";
|
|
819
|
+
if (raw === "boss-recommend" || raw === "recommend-page") return "recommend";
|
|
820
|
+
if (raw === "boss-chat" || raw === "chat-only" || raw === "chat-page") return "chat";
|
|
821
|
+
if (raw === "boss-recruit" || raw === "search" || raw === "search-page" || raw === "recruit-page") return "recruit";
|
|
822
|
+
if (["recommend", "chat", "recruit"].includes(raw)) return raw;
|
|
823
|
+
throw new Error(`Unsupported --toolset value: ${raw}. Supported: recommend, chat, recruit, all`);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
function getMcpToolsetEnv(options = {}) {
|
|
827
|
+
const toolset = normalizeMcpToolsetOption(options.toolset || options["toolset"]);
|
|
828
|
+
return toolset ? { [mcpToolsetEnv]: toolset } : {};
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
function shouldUseSplitBossMcpServers(options = {}) {
|
|
832
|
+
if (options["server-name"] || options.serverName || options.toolset || options["toolset"]) return false;
|
|
833
|
+
if (options.split === true || options["split-tools"] === true || options.splitTools === true) return true;
|
|
834
|
+
const client = normalizeMcpClientName(options.client);
|
|
835
|
+
const agent = normalizeAgentName(options.agent);
|
|
836
|
+
return client === "trae" || agent === "trae" || agent === "trae-cn";
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
function getDefaultMcpEnv(options = {}) {
|
|
840
|
+
return shouldDefaultRecommendDetachedMcpEnv(options)
|
|
841
|
+
? { ...detachedRecommendMcpEnv }
|
|
842
842
|
: {};
|
|
843
843
|
}
|
|
844
844
|
|
|
@@ -849,29 +849,29 @@ function getAgentConfigOutputDir(options = {}) {
|
|
|
849
849
|
return path.join(getStateHome(), "agent-mcp-configs");
|
|
850
850
|
}
|
|
851
851
|
|
|
852
|
-
function buildMcpLaunchConfig(options = {}) {
|
|
853
|
-
const mcpLaunchMode = normalizeMcpLaunchMode(options);
|
|
854
|
-
if (mcpLaunchMode === "global-wrapper") {
|
|
855
|
-
const args = parseJsonOption(options["args-json"], "args-json");
|
|
856
|
-
const env = parseJsonOption(options["env-json"], "env-json");
|
|
857
|
-
const launchConfig = {
|
|
858
|
-
command: ensureGlobalMcpWrapper(options),
|
|
859
|
-
args: Array.isArray(args) ? args : []
|
|
860
|
-
};
|
|
861
|
-
const mergedEnv = {
|
|
862
|
-
...getDefaultMcpEnv(options),
|
|
863
|
-
...getMcpToolsetEnv(options),
|
|
864
|
-
...(isPlainObject(env) ? env : {})
|
|
865
|
-
};
|
|
866
|
-
if (Object.keys(mergedEnv).length > 0) {
|
|
867
|
-
launchConfig.env = mergedEnv;
|
|
868
|
-
}
|
|
869
|
-
return launchConfig;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
const command = typeof options.command === "string" && options.command.trim()
|
|
873
|
-
? options.command.trim()
|
|
874
|
-
: defaultMcpCommand;
|
|
852
|
+
function buildMcpLaunchConfig(options = {}) {
|
|
853
|
+
const mcpLaunchMode = normalizeMcpLaunchMode(options);
|
|
854
|
+
if (mcpLaunchMode === "global-wrapper") {
|
|
855
|
+
const args = parseJsonOption(options["args-json"], "args-json");
|
|
856
|
+
const env = parseJsonOption(options["env-json"], "env-json");
|
|
857
|
+
const launchConfig = {
|
|
858
|
+
command: ensureGlobalMcpWrapper(options),
|
|
859
|
+
args: Array.isArray(args) ? args : []
|
|
860
|
+
};
|
|
861
|
+
const mergedEnv = {
|
|
862
|
+
...getDefaultMcpEnv(options),
|
|
863
|
+
...getMcpToolsetEnv(options),
|
|
864
|
+
...(isPlainObject(env) ? env : {})
|
|
865
|
+
};
|
|
866
|
+
if (Object.keys(mergedEnv).length > 0) {
|
|
867
|
+
launchConfig.env = mergedEnv;
|
|
868
|
+
}
|
|
869
|
+
return launchConfig;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
const command = typeof options.command === "string" && options.command.trim()
|
|
873
|
+
? options.command.trim()
|
|
874
|
+
: defaultMcpCommand;
|
|
875
875
|
const args = parseJsonOption(options["args-json"], "args-json");
|
|
876
876
|
const env = parseJsonOption(options["env-json"], "env-json");
|
|
877
877
|
const launchArgs = Array.isArray(args) && args.length > 0
|
|
@@ -880,36 +880,36 @@ function buildMcpLaunchConfig(options = {}) {
|
|
|
880
880
|
? ["start"]
|
|
881
881
|
: buildDefaultMcpArgs(options);
|
|
882
882
|
const launchConfig = { command, args: launchArgs };
|
|
883
|
-
const mergedEnv = {
|
|
884
|
-
...getDefaultMcpEnv(options),
|
|
885
|
-
...getMcpToolsetEnv(options),
|
|
886
|
-
...(isPlainObject(env) ? env : {})
|
|
887
|
-
};
|
|
883
|
+
const mergedEnv = {
|
|
884
|
+
...getDefaultMcpEnv(options),
|
|
885
|
+
...getMcpToolsetEnv(options),
|
|
886
|
+
...(isPlainObject(env) ? env : {})
|
|
887
|
+
};
|
|
888
888
|
if (Object.keys(mergedEnv).length > 0) {
|
|
889
889
|
launchConfig.env = mergedEnv;
|
|
890
890
|
}
|
|
891
891
|
return launchConfig;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
function buildBossMcpServerEntries(options = {}) {
|
|
895
|
-
if (shouldUseSplitBossMcpServers(options)) {
|
|
896
|
-
return {
|
|
897
|
-
[defaultMcpServerName]: buildMcpLaunchConfig({ ...options, toolset: "recommend" }),
|
|
898
|
-
[bossChatMcpServerName]: buildMcpLaunchConfig({ ...options, toolset: "chat" }),
|
|
899
|
-
[bossRecruitMcpServerName]: buildMcpLaunchConfig({ ...options, toolset: "recruit" })
|
|
900
|
-
};
|
|
901
|
-
}
|
|
902
|
-
const serverName = typeof options["server-name"] === "string" && options["server-name"].trim()
|
|
903
|
-
? options["server-name"].trim()
|
|
904
|
-
: defaultMcpServerName;
|
|
905
|
-
return {
|
|
906
|
-
[serverName]: buildMcpLaunchConfig(options)
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
function mergeExistingMcpEntryEnv(existingEntry, launchConfig) {
|
|
911
|
-
if (!isPlainObject(existingEntry?.env) || !isPlainObject(launchConfig)) {
|
|
912
|
-
return launchConfig;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
function buildBossMcpServerEntries(options = {}) {
|
|
895
|
+
if (shouldUseSplitBossMcpServers(options)) {
|
|
896
|
+
return {
|
|
897
|
+
[defaultMcpServerName]: buildMcpLaunchConfig({ ...options, toolset: "recommend" }),
|
|
898
|
+
[bossChatMcpServerName]: buildMcpLaunchConfig({ ...options, toolset: "chat" }),
|
|
899
|
+
[bossRecruitMcpServerName]: buildMcpLaunchConfig({ ...options, toolset: "recruit" })
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
const serverName = typeof options["server-name"] === "string" && options["server-name"].trim()
|
|
903
|
+
? options["server-name"].trim()
|
|
904
|
+
: defaultMcpServerName;
|
|
905
|
+
return {
|
|
906
|
+
[serverName]: buildMcpLaunchConfig(options)
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function mergeExistingMcpEntryEnv(existingEntry, launchConfig) {
|
|
911
|
+
if (!isPlainObject(existingEntry?.env) || !isPlainObject(launchConfig)) {
|
|
912
|
+
return launchConfig;
|
|
913
913
|
}
|
|
914
914
|
return {
|
|
915
915
|
...launchConfig,
|
|
@@ -918,21 +918,21 @@ function mergeExistingMcpEntryEnv(existingEntry, launchConfig) {
|
|
|
918
918
|
...(isPlainObject(launchConfig.env) ? launchConfig.env : {})
|
|
919
919
|
}
|
|
920
920
|
};
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
function buildMcpConfigFileContent(options = {}) {
|
|
924
|
-
const servers = buildBossMcpServerEntries(options);
|
|
925
|
-
if (normalizeMcpClientName(options.client) === "qclaw") {
|
|
926
|
-
return {
|
|
927
|
-
mcp: {
|
|
928
|
-
servers
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
return {
|
|
933
|
-
mcpServers: servers
|
|
934
|
-
};
|
|
935
|
-
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
function buildMcpConfigFileContent(options = {}) {
|
|
924
|
+
const servers = buildBossMcpServerEntries(options);
|
|
925
|
+
if (normalizeMcpClientName(options.client) === "qclaw") {
|
|
926
|
+
return {
|
|
927
|
+
mcp: {
|
|
928
|
+
servers
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
return {
|
|
933
|
+
mcpServers: servers
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
936
|
|
|
937
937
|
function writeMcpConfigFiles(options = {}) {
|
|
938
938
|
const clients = parseMcpClientTargets(options.client);
|
|
@@ -1076,28 +1076,28 @@ function getMcpServersFromConfig(config = {}, useQClawShape = false) {
|
|
|
1076
1076
|
return {};
|
|
1077
1077
|
}
|
|
1078
1078
|
|
|
1079
|
-
function mergeMcpServerConfigFile(filePath, options = {}) {
|
|
1080
|
-
const current = readJsonObjectFileSafe(filePath);
|
|
1081
|
-
const useQClawShape = isQClawMcpConfigTarget(filePath, options, current);
|
|
1082
|
-
const nextConfig = buildMcpConfigFileContent({ ...options, client: useQClawShape ? "qclaw" : options.client });
|
|
1083
|
-
const nextServers = useQClawShape ? nextConfig.mcp?.servers : nextConfig.mcpServers;
|
|
1084
|
-
const serverNames = Object.keys(nextServers || {});
|
|
1085
|
-
const nextBossServerNames = new Set(serverNames);
|
|
1086
|
-
const existingServers = getMcpServersFromConfig(current, useQClawShape);
|
|
1087
|
-
const mergedBossServers = {};
|
|
1088
|
-
for (const serverName of serverNames) {
|
|
1089
|
-
mergedBossServers[serverName] = mergeExistingMcpEntryEnv(
|
|
1090
|
-
existingServers[serverName],
|
|
1091
|
-
nextServers?.[serverName] || buildMcpLaunchConfig(options)
|
|
1092
|
-
);
|
|
1093
|
-
}
|
|
1094
|
-
const retainedServers = {};
|
|
1095
|
-
const migratedLegacyServers = [];
|
|
1096
|
-
for (const [name, config] of Object.entries(existingServers)) {
|
|
1097
|
-
if (nextBossServerNames.has(name)) continue;
|
|
1098
|
-
if (isBossMcpServerEntry(name, config)) {
|
|
1099
|
-
migratedLegacyServers.push(name);
|
|
1100
|
-
continue;
|
|
1079
|
+
function mergeMcpServerConfigFile(filePath, options = {}) {
|
|
1080
|
+
const current = readJsonObjectFileSafe(filePath);
|
|
1081
|
+
const useQClawShape = isQClawMcpConfigTarget(filePath, options, current);
|
|
1082
|
+
const nextConfig = buildMcpConfigFileContent({ ...options, client: useQClawShape ? "qclaw" : options.client });
|
|
1083
|
+
const nextServers = useQClawShape ? nextConfig.mcp?.servers : nextConfig.mcpServers;
|
|
1084
|
+
const serverNames = Object.keys(nextServers || {});
|
|
1085
|
+
const nextBossServerNames = new Set(serverNames);
|
|
1086
|
+
const existingServers = getMcpServersFromConfig(current, useQClawShape);
|
|
1087
|
+
const mergedBossServers = {};
|
|
1088
|
+
for (const serverName of serverNames) {
|
|
1089
|
+
mergedBossServers[serverName] = mergeExistingMcpEntryEnv(
|
|
1090
|
+
existingServers[serverName],
|
|
1091
|
+
nextServers?.[serverName] || buildMcpLaunchConfig(options)
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
const retainedServers = {};
|
|
1095
|
+
const migratedLegacyServers = [];
|
|
1096
|
+
for (const [name, config] of Object.entries(existingServers)) {
|
|
1097
|
+
if (nextBossServerNames.has(name)) continue;
|
|
1098
|
+
if (isBossMcpServerEntry(name, config)) {
|
|
1099
|
+
migratedLegacyServers.push(name);
|
|
1100
|
+
continue;
|
|
1101
1101
|
}
|
|
1102
1102
|
retainedServers[name] = config;
|
|
1103
1103
|
}
|
|
@@ -1105,20 +1105,20 @@ function mergeMcpServerConfigFile(filePath, options = {}) {
|
|
|
1105
1105
|
? {
|
|
1106
1106
|
...current,
|
|
1107
1107
|
mcp: {
|
|
1108
|
-
...(current?.mcp && typeof current.mcp === "object" && !Array.isArray(current.mcp) ? current.mcp : {}),
|
|
1109
|
-
servers: {
|
|
1110
|
-
...retainedServers,
|
|
1111
|
-
...mergedBossServers
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
: {
|
|
1116
|
-
...current,
|
|
1117
|
-
mcpServers: {
|
|
1118
|
-
...retainedServers,
|
|
1119
|
-
...mergedBossServers
|
|
1120
|
-
}
|
|
1121
|
-
};
|
|
1108
|
+
...(current?.mcp && typeof current.mcp === "object" && !Array.isArray(current.mcp) ? current.mcp : {}),
|
|
1109
|
+
servers: {
|
|
1110
|
+
...retainedServers,
|
|
1111
|
+
...mergedBossServers
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
: {
|
|
1116
|
+
...current,
|
|
1117
|
+
mcpServers: {
|
|
1118
|
+
...retainedServers,
|
|
1119
|
+
...mergedBossServers
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
1122
|
|
|
1123
1123
|
ensureDir(path.dirname(filePath));
|
|
1124
1124
|
const before = pathExists(filePath) ? fs.readFileSync(filePath, "utf8") : "";
|
|
@@ -1128,15 +1128,15 @@ function mergeMcpServerConfigFile(filePath, options = {}) {
|
|
|
1128
1128
|
backupFile = `${filePath}.boss-mcp-migration-${new Date().toISOString().replace(/[:.]/g, "-")}.bak`;
|
|
1129
1129
|
fs.writeFileSync(backupFile, before, "utf8");
|
|
1130
1130
|
}
|
|
1131
|
-
fs.writeFileSync(filePath, JSON.stringify(merged, null, 2), "utf8");
|
|
1132
|
-
const updated = before.trim() !== next.trim();
|
|
1133
|
-
return {
|
|
1134
|
-
file: filePath,
|
|
1135
|
-
server: serverNames[0] || defaultMcpServerName,
|
|
1136
|
-
servers: serverNames,
|
|
1137
|
-
config_shape: useQClawShape ? "qclaw" : "mcpServers",
|
|
1138
|
-
updated,
|
|
1139
|
-
migrated_legacy_servers: migratedLegacyServers,
|
|
1131
|
+
fs.writeFileSync(filePath, JSON.stringify(merged, null, 2), "utf8");
|
|
1132
|
+
const updated = before.trim() !== next.trim();
|
|
1133
|
+
return {
|
|
1134
|
+
file: filePath,
|
|
1135
|
+
server: serverNames[0] || defaultMcpServerName,
|
|
1136
|
+
servers: serverNames,
|
|
1137
|
+
config_shape: useQClawShape ? "qclaw" : "mcpServers",
|
|
1138
|
+
updated,
|
|
1139
|
+
migrated_legacy_servers: migratedLegacyServers,
|
|
1140
1140
|
backup_file: backupFile
|
|
1141
1141
|
};
|
|
1142
1142
|
}
|
|
@@ -1149,13 +1149,13 @@ function installExternalMcpConfigs(options = {}) {
|
|
|
1149
1149
|
try {
|
|
1150
1150
|
const existed = pathExists(target);
|
|
1151
1151
|
const merged = mergeMcpServerConfigFile(target, options);
|
|
1152
|
-
applied.push({
|
|
1153
|
-
file: target,
|
|
1154
|
-
server: merged.server,
|
|
1155
|
-
servers: merged.servers,
|
|
1156
|
-
created: !existed,
|
|
1157
|
-
updated: merged.updated,
|
|
1158
|
-
migrated_legacy_servers: merged.migrated_legacy_servers,
|
|
1152
|
+
applied.push({
|
|
1153
|
+
file: target,
|
|
1154
|
+
server: merged.server,
|
|
1155
|
+
servers: merged.servers,
|
|
1156
|
+
created: !existed,
|
|
1157
|
+
updated: merged.updated,
|
|
1158
|
+
migrated_legacy_servers: merged.migrated_legacy_servers,
|
|
1159
1159
|
backup_file: merged.backup_file
|
|
1160
1160
|
});
|
|
1161
1161
|
} catch (error) {
|
|
@@ -1398,33 +1398,33 @@ async function resolveCliConfigTarget(options = {}) {
|
|
|
1398
1398
|
};
|
|
1399
1399
|
}
|
|
1400
1400
|
|
|
1401
|
-
function applyMissingInstallConfigDefaults(config = {}) {
|
|
1402
|
-
const nextConfig = { ...config };
|
|
1403
|
-
const patchedKeys = [];
|
|
1404
|
-
for (const [key, defaultValue] of Object.entries(installConfigDefaults)) {
|
|
1401
|
+
function applyMissingInstallConfigDefaults(config = {}) {
|
|
1402
|
+
const nextConfig = { ...config };
|
|
1403
|
+
const patchedKeys = [];
|
|
1404
|
+
for (const [key, defaultValue] of Object.entries(installConfigDefaults)) {
|
|
1405
1405
|
if (!Object.prototype.hasOwnProperty.call(nextConfig, key)) {
|
|
1406
1406
|
nextConfig[key] = defaultValue;
|
|
1407
|
-
patchedKeys.push(key);
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
if (
|
|
1411
|
-
nextConfig.humanBehavior
|
|
1412
|
-
&& typeof nextConfig.humanBehavior === "object"
|
|
1413
|
-
&& !Array.isArray(nextConfig.humanBehavior)
|
|
1414
|
-
&& !Object.prototype.hasOwnProperty.call(nextConfig.humanBehavior, "restLevel")
|
|
1415
|
-
&& !Object.prototype.hasOwnProperty.call(nextConfig.humanBehavior, "rest_level")
|
|
1416
|
-
) {
|
|
1417
|
-
nextConfig.humanBehavior = {
|
|
1418
|
-
...nextConfig.humanBehavior,
|
|
1419
|
-
restLevel: "low"
|
|
1420
|
-
};
|
|
1421
|
-
patchedKeys.push("humanBehavior.restLevel");
|
|
1422
|
-
}
|
|
1423
|
-
return {
|
|
1424
|
-
nextConfig,
|
|
1425
|
-
patchedKeys
|
|
1426
|
-
};
|
|
1427
|
-
}
|
|
1407
|
+
patchedKeys.push(key);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
if (
|
|
1411
|
+
nextConfig.humanBehavior
|
|
1412
|
+
&& typeof nextConfig.humanBehavior === "object"
|
|
1413
|
+
&& !Array.isArray(nextConfig.humanBehavior)
|
|
1414
|
+
&& !Object.prototype.hasOwnProperty.call(nextConfig.humanBehavior, "restLevel")
|
|
1415
|
+
&& !Object.prototype.hasOwnProperty.call(nextConfig.humanBehavior, "rest_level")
|
|
1416
|
+
) {
|
|
1417
|
+
nextConfig.humanBehavior = {
|
|
1418
|
+
...nextConfig.humanBehavior,
|
|
1419
|
+
restLevel: "low"
|
|
1420
|
+
};
|
|
1421
|
+
patchedKeys.push("humanBehavior.restLevel");
|
|
1422
|
+
}
|
|
1423
|
+
return {
|
|
1424
|
+
nextConfig,
|
|
1425
|
+
patchedKeys
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
1428
|
|
|
1429
1429
|
async function ensureUserConfig(options = {}) {
|
|
1430
1430
|
const { configPath, workspacePreferred } = await resolveCliConfigTarget(options);
|
|
@@ -2741,33 +2741,33 @@ function printHelp() {
|
|
|
2741
2741
|
console.log("boss-recommend-mcp");
|
|
2742
2742
|
console.log("");
|
|
2743
2743
|
console.log("Usage:");
|
|
2744
|
-
console.log(" boss-recommend-mcp Start the MCP server");
|
|
2745
|
-
console.log(" boss-recommend-mcp start Start the MCP server");
|
|
2746
|
-
console.log(" boss-recommend-mcp prepare-run Validate a cron-ready recommend run payload without starting screening");
|
|
2747
|
-
console.log(" boss-recommend-mcp schedule-run Create a package-owned delayed recommend run");
|
|
2748
|
-
console.log(" boss-recommend-mcp schedule-status Check a package-owned delayed recommend run");
|
|
2749
|
-
console.log(" boss-recommend-mcp run Start a CDP-only recommend run through the shared run service");
|
|
2750
|
-
console.log(" boss-recommend-mcp list-jobs CDP-only list of exact recommend job names for cron/one-shot inputs");
|
|
2744
|
+
console.log(" boss-recommend-mcp Start the MCP server");
|
|
2745
|
+
console.log(" boss-recommend-mcp start Start the MCP server");
|
|
2746
|
+
console.log(" boss-recommend-mcp prepare-run Validate a cron-ready recommend run payload without starting screening");
|
|
2747
|
+
console.log(" boss-recommend-mcp schedule-run Create a package-owned delayed recommend run");
|
|
2748
|
+
console.log(" boss-recommend-mcp schedule-status Check a package-owned delayed recommend run");
|
|
2749
|
+
console.log(" boss-recommend-mcp run Start a CDP-only recommend run through the shared run service");
|
|
2750
|
+
console.log(" boss-recommend-mcp list-jobs CDP-only list of exact recommend job names for cron/one-shot inputs");
|
|
2751
2751
|
console.log(" boss-recommend-mcp chat <subcommand> Run CDP-only boss-chat health/prepare/status commands");
|
|
2752
2752
|
console.log(" boss-recommend-mcp install Install/migrate skills and MCP configs; replaces legacy Boss MCP routes (supports --agent trae-cn/openclaw/qclaw/...)");
|
|
2753
2753
|
console.log(" boss-recommend-mcp install-skill Install bundled Codex skills (recommend/recruit/chat)");
|
|
2754
2754
|
console.log(" boss-recommend-mcp init-config Create screening-config.json if missing (prefer workspace config/, fallback ~/.boss-recommend-mcp)");
|
|
2755
2755
|
console.log(" boss-recommend-mcp config set Write baseUrl/apiKey/model (prefer workspace config/, fallback ~/.boss-recommend-mcp)");
|
|
2756
2756
|
console.log(" boss-recommend-mcp set-port Persist preferred Chrome debug port to screening-config.json");
|
|
2757
|
-
console.log(" boss-recommend-mcp mcp-config Generate MCP config JSON for Cursor/Trae(含 trae-cn)/Claude Code/OpenClaw/QClaw");
|
|
2758
|
-
console.log(" boss-recommend-mcp doctor Check config/runtime/calibration prerequisites (supports --agent trae-cn/qclaw/cursor/...)");
|
|
2759
|
-
console.log(" boss-recommend-mcp calibrate Disabled until CDP-only featured calibration is live-verified");
|
|
2760
|
-
console.log(" boss-recommend-mcp launch-chrome Launch or reuse Chrome debug instance and open Boss recommend page");
|
|
2761
|
-
console.log(" boss-recommend-mcp where Print installed package, skill, and config paths");
|
|
2762
|
-
console.log(" boss-recommend-mcp install --mcp-launch global-wrapper Use ~/.boss-recommend-mcp/bin wrapper so npm global upgrades affect MCP hosts");
|
|
2763
|
-
console.log(" boss-recommend-mcp start --toolset recommend Start a narrowed MCP server (all|recommend|chat|recruit)");
|
|
2764
|
-
console.log("");
|
|
2765
|
-
console.log("Run command:");
|
|
2766
|
-
console.log(" boss-recommend-mcp prepare-run --instruction \"...\" --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2767
|
-
console.log(" boss-recommend-mcp schedule-run --schedule-delay-minutes 10 --instruction-file boss-recommend-instruction.txt --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2768
|
-
console.log(" boss-recommend-mcp schedule-status --schedule-id <id>");
|
|
2769
|
-
console.log(" boss-recommend-mcp run --instruction \"推荐页上筛选211男生,近14天没有,有大模型平台经验\" --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2770
|
-
console.log(" boss-recommend-mcp run --detached --instruction \"...\" --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2757
|
+
console.log(" boss-recommend-mcp mcp-config Generate MCP config JSON for Cursor/Trae(含 trae-cn)/Claude Code/OpenClaw/QClaw");
|
|
2758
|
+
console.log(" boss-recommend-mcp doctor Check config/runtime/calibration prerequisites (supports --agent trae-cn/qclaw/cursor/...)");
|
|
2759
|
+
console.log(" boss-recommend-mcp calibrate Disabled until CDP-only featured calibration is live-verified");
|
|
2760
|
+
console.log(" boss-recommend-mcp launch-chrome Launch or reuse Chrome debug instance and open Boss recommend page");
|
|
2761
|
+
console.log(" boss-recommend-mcp where Print installed package, skill, and config paths");
|
|
2762
|
+
console.log(" boss-recommend-mcp install --mcp-launch global-wrapper Use ~/.boss-recommend-mcp/bin wrapper so npm global upgrades affect MCP hosts");
|
|
2763
|
+
console.log(" boss-recommend-mcp start --toolset recommend Start a narrowed MCP server (all|recommend|chat|recruit)");
|
|
2764
|
+
console.log("");
|
|
2765
|
+
console.log("Run command:");
|
|
2766
|
+
console.log(" boss-recommend-mcp prepare-run --instruction \"...\" --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2767
|
+
console.log(" boss-recommend-mcp schedule-run --schedule-delay-minutes 10 --instruction-file boss-recommend-instruction.txt --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2768
|
+
console.log(" boss-recommend-mcp schedule-status --schedule-id <id>");
|
|
2769
|
+
console.log(" boss-recommend-mcp run --instruction \"推荐页上筛选211男生,近14天没有,有大模型平台经验\" --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2770
|
+
console.log(" boss-recommend-mcp run --detached --instruction \"...\" --overrides-file overrides.json --confirmation-file confirmation.json --rest-level medium");
|
|
2771
2771
|
console.log(" boss-recommend-mcp list-jobs --slow-live --port 9222");
|
|
2772
2772
|
console.log(" boss-recommend-mcp chat prepare-run --slow-live --port 9222 # CDP-only preflight; start runs through MCP start_boss_chat_run");
|
|
2773
2773
|
console.log(" boss-recommend-mcp config set --base-url <url> --api-key <key> --model <model> [--thinking-level off|low|medium|high|current] [--greeting-message <text>] [--openai-organization <id>] [--openai-project <id>]");
|
|
@@ -2790,15 +2790,15 @@ function printMcpConfig(options = {}) {
|
|
|
2790
2790
|
}
|
|
2791
2791
|
}
|
|
2792
2792
|
|
|
2793
|
-
async function installAll(options = {}) {
|
|
2794
|
-
const runtimeDirsResult = await ensureRuntimeDirectories(options);
|
|
2795
|
-
const skillResults = installSkill();
|
|
2796
|
-
const configResult = await ensureUserConfig(options);
|
|
2797
|
-
const mcpLaunchMode = normalizeMcpLaunchMode(options);
|
|
2798
|
-
const mcpTemplateResult = writeMcpConfigFiles({ ...options, agent: undefined, client: "all" });
|
|
2799
|
-
const externalMcpResult = installExternalMcpConfigs(options);
|
|
2800
|
-
const externalSkillResult = mirrorSkillToExternalDirs(options);
|
|
2801
|
-
console.log(
|
|
2793
|
+
async function installAll(options = {}) {
|
|
2794
|
+
const runtimeDirsResult = await ensureRuntimeDirectories(options);
|
|
2795
|
+
const skillResults = installSkill();
|
|
2796
|
+
const configResult = await ensureUserConfig(options);
|
|
2797
|
+
const mcpLaunchMode = normalizeMcpLaunchMode(options);
|
|
2798
|
+
const mcpTemplateResult = writeMcpConfigFiles({ ...options, agent: undefined, client: "all" });
|
|
2799
|
+
const externalMcpResult = installExternalMcpConfigs(options);
|
|
2800
|
+
const externalSkillResult = mirrorSkillToExternalDirs(options);
|
|
2801
|
+
console.log(
|
|
2802
2802
|
`Runtime directories prepared: created=${runtimeDirsResult.created.length}, existing=${runtimeDirsResult.existed.length}, failed=${runtimeDirsResult.failed.length}`
|
|
2803
2803
|
);
|
|
2804
2804
|
console.log(`- recommend runtime: ${runtimeDirsResult.stateHome}`);
|
|
@@ -2826,13 +2826,13 @@ async function installAll(options = {}) {
|
|
|
2826
2826
|
console.warn(`screening-config.json skip default patch: ${configResult.patch_error}`);
|
|
2827
2827
|
}
|
|
2828
2828
|
console.log(`请在该目录修改 baseUrl/apiKey/model 并替换占位词后再运行:${path.dirname(configResult.path)}`);
|
|
2829
|
-
console.log(`MCP config templates exported to: ${mcpTemplateResult.outputDir}`);
|
|
2830
|
-
for (const item of mcpTemplateResult.files) {
|
|
2831
|
-
console.log(`- ${item.client}: ${item.file}`);
|
|
2832
|
-
}
|
|
2833
|
-
if (mcpLaunchMode === "global-wrapper") {
|
|
2834
|
-
console.log(`Upgrade-stable MCP wrapper: ${getGlobalMcpWrapperPath(options)}`);
|
|
2835
|
-
}
|
|
2829
|
+
console.log(`MCP config templates exported to: ${mcpTemplateResult.outputDir}`);
|
|
2830
|
+
for (const item of mcpTemplateResult.files) {
|
|
2831
|
+
console.log(`- ${item.client}: ${item.file}`);
|
|
2832
|
+
}
|
|
2833
|
+
if (mcpLaunchMode === "global-wrapper") {
|
|
2834
|
+
console.log(`Upgrade-stable MCP wrapper: ${getGlobalMcpWrapperPath(options)}`);
|
|
2835
|
+
}
|
|
2836
2836
|
if (externalMcpResult.targets.length > 0) {
|
|
2837
2837
|
console.log(`Auto-configured external MCP files: ${externalMcpResult.applied.length}`);
|
|
2838
2838
|
for (const item of externalMcpResult.applied) {
|
|
@@ -2865,37 +2865,37 @@ async function installAll(options = {}) {
|
|
|
2865
2865
|
}
|
|
2866
2866
|
}
|
|
2867
2867
|
|
|
2868
|
-
function buildRecommendRunCliInput(options = {}) {
|
|
2869
|
-
const instruction = getRunInstruction(options);
|
|
2870
|
-
const confirmation = getRunConfirmation(options);
|
|
2871
|
-
const overrides = getRunOverrides(options);
|
|
2872
|
-
const followUp = getRunFollowUp(options);
|
|
2873
|
-
const port = parsePositivePort(options.port) || parsePositivePort(process.env.BOSS_RECOMMEND_CHROME_PORT) || 9222;
|
|
2874
|
-
|
|
2875
|
-
const args = {
|
|
2876
|
-
instruction,
|
|
2877
|
-
confirmation: confirmation ?? undefined,
|
|
2878
|
-
overrides: overrides ?? undefined,
|
|
2879
|
-
follow_up: followUp ?? undefined,
|
|
2868
|
+
function buildRecommendRunCliInput(options = {}) {
|
|
2869
|
+
const instruction = getRunInstruction(options);
|
|
2870
|
+
const confirmation = getRunConfirmation(options);
|
|
2871
|
+
const overrides = getRunOverrides(options);
|
|
2872
|
+
const followUp = getRunFollowUp(options);
|
|
2873
|
+
const port = parsePositivePort(options.port) || parsePositivePort(process.env.BOSS_RECOMMEND_CHROME_PORT) || 9222;
|
|
2874
|
+
|
|
2875
|
+
const args = {
|
|
2876
|
+
instruction,
|
|
2877
|
+
confirmation: confirmation ?? undefined,
|
|
2878
|
+
overrides: overrides ?? undefined,
|
|
2879
|
+
follow_up: followUp ?? undefined,
|
|
2880
2880
|
host: typeof options.host === "string" && options.host.trim() ? options.host.trim() : undefined,
|
|
2881
2881
|
port,
|
|
2882
2882
|
target_url_includes: typeof options["target-url-includes"] === "string" && options["target-url-includes"].trim()
|
|
2883
2883
|
? options["target-url-includes"].trim()
|
|
2884
2884
|
: undefined,
|
|
2885
2885
|
allow_navigate: !(options["no-navigate"] === true || options.noNavigate === true || options.allow_navigate === false),
|
|
2886
|
-
slow_live: options["slow-live"] === true || options.slowLive === true || options.slow_live === true
|
|
2887
|
-
};
|
|
2888
|
-
const restLevel = parseRestLevelOption(
|
|
2889
|
-
options["rest-level"]
|
|
2890
|
-
?? options.rest_level
|
|
2891
|
-
?? options["human-behavior-rest-level"]
|
|
2892
|
-
?? options.human_behavior_rest_level
|
|
2893
|
-
);
|
|
2894
|
-
if (restLevel) {
|
|
2895
|
-
args.human_behavior = {
|
|
2896
|
-
restLevel
|
|
2897
|
-
};
|
|
2898
|
-
}
|
|
2886
|
+
slow_live: options["slow-live"] === true || options.slowLive === true || options.slow_live === true
|
|
2887
|
+
};
|
|
2888
|
+
const restLevel = parseRestLevelOption(
|
|
2889
|
+
options["rest-level"]
|
|
2890
|
+
?? options.rest_level
|
|
2891
|
+
?? options["human-behavior-rest-level"]
|
|
2892
|
+
?? options.human_behavior_rest_level
|
|
2893
|
+
);
|
|
2894
|
+
if (restLevel) {
|
|
2895
|
+
args.human_behavior = {
|
|
2896
|
+
restLevel
|
|
2897
|
+
};
|
|
2898
|
+
}
|
|
2899
2899
|
|
|
2900
2900
|
const optionalPassthrough = [
|
|
2901
2901
|
"detail_limit",
|
|
@@ -2928,129 +2928,129 @@ function buildRecommendRunCliInput(options = {}) {
|
|
|
2928
2928
|
"llm_image_limit",
|
|
2929
2929
|
"llm_image_detail"
|
|
2930
2930
|
];
|
|
2931
|
-
for (const key of optionalPassthrough) {
|
|
2932
|
-
const kebab = key.replace(/_/g, "-");
|
|
2933
|
-
if (options[key] !== undefined) args[key] = options[key];
|
|
2934
|
-
else if (options[kebab] !== undefined) args[key] = options[kebab];
|
|
2935
|
-
}
|
|
2936
|
-
|
|
2937
|
-
return {
|
|
2938
|
-
args,
|
|
2939
|
-
port
|
|
2940
|
-
};
|
|
2941
|
-
}
|
|
2942
|
-
|
|
2943
|
-
async function preparePipelineOnce(options = {}) {
|
|
2944
|
-
const workspaceRoot = getWorkspaceRoot(options);
|
|
2945
|
-
const { args, port } = buildRecommendRunCliInput(options);
|
|
2946
|
-
const result = prepareRecommendPipelineRunTool({
|
|
2947
|
-
workspaceRoot,
|
|
2948
|
-
args
|
|
2949
|
-
});
|
|
2950
|
-
printJson({
|
|
2951
|
-
...result,
|
|
2952
|
-
cli: {
|
|
2953
|
-
command: "prepare-run",
|
|
2954
|
-
cdp_only: true,
|
|
2955
|
-
shared_run_service: true,
|
|
2956
|
-
workspace_root: workspaceRoot,
|
|
2957
|
-
port
|
|
2958
|
-
}
|
|
2959
|
-
});
|
|
2960
|
-
if (result.status !== "READY" || result.cron_ready !== true) {
|
|
2961
|
-
process.exitCode = 1;
|
|
2962
|
-
}
|
|
2963
|
-
}
|
|
2964
|
-
|
|
2965
|
-
function addScheduleOptions(args, options = {}) {
|
|
2966
|
-
const scheduleId = String(options["schedule-id"] || options.schedule_id || options.scheduleId || "").trim();
|
|
2967
|
-
if (scheduleId) args.schedule_id = scheduleId;
|
|
2968
|
-
const runAt = String(options["schedule-run-at"] || options.schedule_run_at || options.scheduleRunAt || options["run-at"] || options.run_at || "").trim();
|
|
2969
|
-
if (runAt) args.schedule_run_at = runAt;
|
|
2970
|
-
const delayMinutes = parseNonNegativeInteger(options["schedule-delay-minutes"] ?? options.schedule_delay_minutes ?? options.scheduleDelayMinutes);
|
|
2971
|
-
if (delayMinutes !== undefined) args.schedule_delay_minutes = delayMinutes;
|
|
2972
|
-
const delaySeconds = parseNonNegativeInteger(options["schedule-delay-seconds"] ?? options.schedule_delay_seconds ?? options.scheduleDelaySeconds);
|
|
2973
|
-
if (delaySeconds !== undefined) args.schedule_delay_seconds = delaySeconds;
|
|
2974
|
-
return args;
|
|
2975
|
-
}
|
|
2976
|
-
|
|
2977
|
-
async function schedulePipelineOnce(options = {}) {
|
|
2978
|
-
const workspaceRoot = getWorkspaceRoot(options);
|
|
2979
|
-
const { args, port } = buildRecommendRunCliInput(options);
|
|
2980
|
-
addScheduleOptions(args, options);
|
|
2981
|
-
const result = await scheduleRecommendPipelineRunTool({
|
|
2982
|
-
workspaceRoot,
|
|
2983
|
-
args
|
|
2984
|
-
});
|
|
2985
|
-
printJson({
|
|
2986
|
-
...result,
|
|
2987
|
-
cli: {
|
|
2988
|
-
...(result.cli || {}),
|
|
2989
|
-
command: "schedule-run",
|
|
2990
|
-
cdp_only: true,
|
|
2991
|
-
package_owned_scheduler: true,
|
|
2992
|
-
workspace_root: workspaceRoot,
|
|
2993
|
-
port
|
|
2994
|
-
}
|
|
2995
|
-
});
|
|
2996
|
-
if (result.status !== "SCHEDULED") {
|
|
2997
|
-
process.exitCode = 1;
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
|
|
3001
|
-
function scheduleStatusCli(options = {}) {
|
|
3002
|
-
const scheduleId = String(options["schedule-id"] || options.schedule_id || options.scheduleId || "").trim();
|
|
3003
|
-
const result = getRecommendScheduledRunTool({
|
|
3004
|
-
args: {
|
|
3005
|
-
schedule_id: scheduleId
|
|
3006
|
-
}
|
|
3007
|
-
});
|
|
3008
|
-
printJson({
|
|
3009
|
-
...result,
|
|
3010
|
-
cli: {
|
|
3011
|
-
command: "schedule-status",
|
|
3012
|
-
cdp_only: true,
|
|
3013
|
-
package_owned_scheduler: true
|
|
3014
|
-
}
|
|
3015
|
-
});
|
|
3016
|
-
if (result.status !== "OK") {
|
|
3017
|
-
process.exitCode = 1;
|
|
3018
|
-
}
|
|
3019
|
-
}
|
|
3020
|
-
|
|
3021
|
-
function isTerminalRecommendCliState(state) {
|
|
3022
|
-
return ["completed", "failed", "canceled"].includes(String(state || "").trim().toLowerCase());
|
|
3023
|
-
}
|
|
3024
|
-
|
|
3025
|
-
async function monitorDetachedRecommendCliRunControls(runId) {
|
|
3026
|
-
const normalizedRunId = String(runId || "").trim();
|
|
3027
|
-
if (!normalizedRunId) return;
|
|
3028
|
-
while (true) {
|
|
3029
|
-
const payload = getRecommendPipelineRunTool({
|
|
3030
|
-
args: {
|
|
3031
|
-
run_id: normalizedRunId
|
|
3032
|
-
}
|
|
3033
|
-
});
|
|
3034
|
-
const state = String(payload?.run?.state || payload?.run?.status || "").trim().toLowerCase();
|
|
3035
|
-
if (isTerminalRecommendCliState(state)) return;
|
|
3036
|
-
const control = payload?.run?.control || {};
|
|
3037
|
-
if (control.cancel_requested === true) {
|
|
3038
|
-
cancelRecommendPipelineRunTool({ args: { run_id: normalizedRunId } });
|
|
3039
|
-
} else if (control.pause_requested === true && state === "running") {
|
|
3040
|
-
pauseRecommendPipelineRunTool({ args: { run_id: normalizedRunId } });
|
|
3041
|
-
} else if (control.pause_requested === false && state === "paused") {
|
|
3042
|
-
resumeRecommendPipelineRunTool({ args: { run_id: normalizedRunId } });
|
|
3043
|
-
}
|
|
3044
|
-
await sleepMs(1000);
|
|
3045
|
-
}
|
|
3046
|
-
}
|
|
3047
|
-
|
|
3048
|
-
async function runPipelineOnce(options = {}) {
|
|
3049
|
-
const workspaceRoot = getWorkspaceRoot(options);
|
|
3050
|
-
const { args, port } = buildRecommendRunCliInput(options);
|
|
3051
|
-
const result = await startRecommendPipelineRunTool({
|
|
3052
|
-
workspaceRoot,
|
|
3053
|
-
args
|
|
2931
|
+
for (const key of optionalPassthrough) {
|
|
2932
|
+
const kebab = key.replace(/_/g, "-");
|
|
2933
|
+
if (options[key] !== undefined) args[key] = options[key];
|
|
2934
|
+
else if (options[kebab] !== undefined) args[key] = options[kebab];
|
|
2935
|
+
}
|
|
2936
|
+
|
|
2937
|
+
return {
|
|
2938
|
+
args,
|
|
2939
|
+
port
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
async function preparePipelineOnce(options = {}) {
|
|
2944
|
+
const workspaceRoot = getWorkspaceRoot(options);
|
|
2945
|
+
const { args, port } = buildRecommendRunCliInput(options);
|
|
2946
|
+
const result = prepareRecommendPipelineRunTool({
|
|
2947
|
+
workspaceRoot,
|
|
2948
|
+
args
|
|
2949
|
+
});
|
|
2950
|
+
printJson({
|
|
2951
|
+
...result,
|
|
2952
|
+
cli: {
|
|
2953
|
+
command: "prepare-run",
|
|
2954
|
+
cdp_only: true,
|
|
2955
|
+
shared_run_service: true,
|
|
2956
|
+
workspace_root: workspaceRoot,
|
|
2957
|
+
port
|
|
2958
|
+
}
|
|
2959
|
+
});
|
|
2960
|
+
if (result.status !== "READY" || result.cron_ready !== true) {
|
|
2961
|
+
process.exitCode = 1;
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
function addScheduleOptions(args, options = {}) {
|
|
2966
|
+
const scheduleId = String(options["schedule-id"] || options.schedule_id || options.scheduleId || "").trim();
|
|
2967
|
+
if (scheduleId) args.schedule_id = scheduleId;
|
|
2968
|
+
const runAt = String(options["schedule-run-at"] || options.schedule_run_at || options.scheduleRunAt || options["run-at"] || options.run_at || "").trim();
|
|
2969
|
+
if (runAt) args.schedule_run_at = runAt;
|
|
2970
|
+
const delayMinutes = parseNonNegativeInteger(options["schedule-delay-minutes"] ?? options.schedule_delay_minutes ?? options.scheduleDelayMinutes);
|
|
2971
|
+
if (delayMinutes !== undefined) args.schedule_delay_minutes = delayMinutes;
|
|
2972
|
+
const delaySeconds = parseNonNegativeInteger(options["schedule-delay-seconds"] ?? options.schedule_delay_seconds ?? options.scheduleDelaySeconds);
|
|
2973
|
+
if (delaySeconds !== undefined) args.schedule_delay_seconds = delaySeconds;
|
|
2974
|
+
return args;
|
|
2975
|
+
}
|
|
2976
|
+
|
|
2977
|
+
async function schedulePipelineOnce(options = {}) {
|
|
2978
|
+
const workspaceRoot = getWorkspaceRoot(options);
|
|
2979
|
+
const { args, port } = buildRecommendRunCliInput(options);
|
|
2980
|
+
addScheduleOptions(args, options);
|
|
2981
|
+
const result = await scheduleRecommendPipelineRunTool({
|
|
2982
|
+
workspaceRoot,
|
|
2983
|
+
args
|
|
2984
|
+
});
|
|
2985
|
+
printJson({
|
|
2986
|
+
...result,
|
|
2987
|
+
cli: {
|
|
2988
|
+
...(result.cli || {}),
|
|
2989
|
+
command: "schedule-run",
|
|
2990
|
+
cdp_only: true,
|
|
2991
|
+
package_owned_scheduler: true,
|
|
2992
|
+
workspace_root: workspaceRoot,
|
|
2993
|
+
port
|
|
2994
|
+
}
|
|
2995
|
+
});
|
|
2996
|
+
if (result.status !== "SCHEDULED") {
|
|
2997
|
+
process.exitCode = 1;
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
function scheduleStatusCli(options = {}) {
|
|
3002
|
+
const scheduleId = String(options["schedule-id"] || options.schedule_id || options.scheduleId || "").trim();
|
|
3003
|
+
const result = getRecommendScheduledRunTool({
|
|
3004
|
+
args: {
|
|
3005
|
+
schedule_id: scheduleId
|
|
3006
|
+
}
|
|
3007
|
+
});
|
|
3008
|
+
printJson({
|
|
3009
|
+
...result,
|
|
3010
|
+
cli: {
|
|
3011
|
+
command: "schedule-status",
|
|
3012
|
+
cdp_only: true,
|
|
3013
|
+
package_owned_scheduler: true
|
|
3014
|
+
}
|
|
3015
|
+
});
|
|
3016
|
+
if (result.status !== "OK") {
|
|
3017
|
+
process.exitCode = 1;
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
function isTerminalRecommendCliState(state) {
|
|
3022
|
+
return ["completed", "failed", "canceled"].includes(String(state || "").trim().toLowerCase());
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
async function monitorDetachedRecommendCliRunControls(runId) {
|
|
3026
|
+
const normalizedRunId = String(runId || "").trim();
|
|
3027
|
+
if (!normalizedRunId) return;
|
|
3028
|
+
while (true) {
|
|
3029
|
+
const payload = getRecommendPipelineRunTool({
|
|
3030
|
+
args: {
|
|
3031
|
+
run_id: normalizedRunId
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
3034
|
+
const state = String(payload?.run?.state || payload?.run?.status || "").trim().toLowerCase();
|
|
3035
|
+
if (isTerminalRecommendCliState(state)) return;
|
|
3036
|
+
const control = payload?.run?.control || {};
|
|
3037
|
+
if (control.cancel_requested === true) {
|
|
3038
|
+
cancelRecommendPipelineRunTool({ args: { run_id: normalizedRunId } });
|
|
3039
|
+
} else if (control.pause_requested === true && state === "running") {
|
|
3040
|
+
pauseRecommendPipelineRunTool({ args: { run_id: normalizedRunId } });
|
|
3041
|
+
} else if (control.pause_requested === false && state === "paused") {
|
|
3042
|
+
resumeRecommendPipelineRunTool({ args: { run_id: normalizedRunId } });
|
|
3043
|
+
}
|
|
3044
|
+
await sleepMs(1000);
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
|
|
3048
|
+
async function runPipelineOnce(options = {}) {
|
|
3049
|
+
const workspaceRoot = getWorkspaceRoot(options);
|
|
3050
|
+
const { args, port } = buildRecommendRunCliInput(options);
|
|
3051
|
+
const result = await startRecommendPipelineRunTool({
|
|
3052
|
+
workspaceRoot,
|
|
3053
|
+
args
|
|
3054
3054
|
});
|
|
3055
3055
|
printJson({
|
|
3056
3056
|
...result,
|
|
@@ -3061,13 +3061,13 @@ async function runPipelineOnce(options = {}) {
|
|
|
3061
3061
|
workspace_root: workspaceRoot,
|
|
3062
3062
|
port
|
|
3063
3063
|
}
|
|
3064
|
-
});
|
|
3065
|
-
if (result.status !== "ACCEPTED") {
|
|
3066
|
-
process.exitCode = 1;
|
|
3067
|
-
} else if (process.env[detachedRecommendRunChildEnv] === "1") {
|
|
3068
|
-
await monitorDetachedRecommendCliRunControls(result.run_id);
|
|
3069
|
-
}
|
|
3070
|
-
}
|
|
3064
|
+
});
|
|
3065
|
+
if (result.status !== "ACCEPTED") {
|
|
3066
|
+
process.exitCode = 1;
|
|
3067
|
+
} else if (process.env[detachedRecommendRunChildEnv] === "1") {
|
|
3068
|
+
await monitorDetachedRecommendCliRunControls(result.run_id);
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
3071
|
|
|
3072
3072
|
function buildRecommendJobListCliInput(options = {}) {
|
|
3073
3073
|
const targetUrlIncludes = String(options["target-url-includes"] || options.target_url_includes || "").trim();
|
|
@@ -3088,22 +3088,22 @@ async function listRecommendJobsCli(options = {}) {
|
|
|
3088
3088
|
}));
|
|
3089
3089
|
}
|
|
3090
3090
|
|
|
3091
|
-
function buildBossChatCliInput(options = {}) {
|
|
3092
|
-
const greetingTextRaw =
|
|
3093
|
-
options["greeting-text"]
|
|
3094
|
-
?? options.greeting_text
|
|
3095
|
-
?? options.greetingText
|
|
3096
|
-
?? options.greeting;
|
|
3097
|
-
const greetingText = typeof greetingTextRaw === "string" ? greetingTextRaw.trim() : undefined;
|
|
3098
|
-
const targetUrlIncludes = String(options["target-url-includes"] || options.target_url_includes || "").trim();
|
|
3099
|
-
const host = String(options.host || "").trim();
|
|
3100
|
-
const restLevel = parseRestLevelOption(
|
|
3101
|
-
options["rest-level"]
|
|
3102
|
-
?? options.rest_level
|
|
3103
|
-
?? options["human-behavior-rest-level"]
|
|
3104
|
-
?? options.human_behavior_rest_level
|
|
3105
|
-
);
|
|
3106
|
-
return {
|
|
3091
|
+
function buildBossChatCliInput(options = {}) {
|
|
3092
|
+
const greetingTextRaw =
|
|
3093
|
+
options["greeting-text"]
|
|
3094
|
+
?? options.greeting_text
|
|
3095
|
+
?? options.greetingText
|
|
3096
|
+
?? options.greeting;
|
|
3097
|
+
const greetingText = typeof greetingTextRaw === "string" ? greetingTextRaw.trim() : undefined;
|
|
3098
|
+
const targetUrlIncludes = String(options["target-url-includes"] || options.target_url_includes || "").trim();
|
|
3099
|
+
const host = String(options.host || "").trim();
|
|
3100
|
+
const restLevel = parseRestLevelOption(
|
|
3101
|
+
options["rest-level"]
|
|
3102
|
+
?? options.rest_level
|
|
3103
|
+
?? options["human-behavior-rest-level"]
|
|
3104
|
+
?? options.human_behavior_rest_level
|
|
3105
|
+
);
|
|
3106
|
+
return {
|
|
3107
3107
|
profile: typeof options.profile === "string" ? options.profile.trim() : undefined,
|
|
3108
3108
|
job: typeof options.job === "string" ? options.job.trim() : undefined,
|
|
3109
3109
|
start_from: String(options["start-from"] || options.start_from || "").trim().toLowerCase() || undefined,
|
|
@@ -3121,18 +3121,18 @@ function buildBossChatCliInput(options = {}) {
|
|
|
3121
3121
|
dry_run: options["dry-run"] === true || options.dryRun === true,
|
|
3122
3122
|
no_state: options["no-state"] === true || options.noState === true,
|
|
3123
3123
|
human_behavior_enabled: parseBooleanOption(options["human-behavior-enabled"] ?? options.human_behavior_enabled),
|
|
3124
|
-
human_behavior_profile: typeof (options["human-behavior-profile"] ?? options.human_behavior_profile) === "string"
|
|
3125
|
-
? (options["human-behavior-profile"] ?? options.human_behavior_profile).trim()
|
|
3126
|
-
: undefined,
|
|
3127
|
-
human_behavior: restLevel
|
|
3128
|
-
? {
|
|
3129
|
-
restLevel
|
|
3130
|
-
}
|
|
3131
|
-
: undefined,
|
|
3132
|
-
safe_pacing: parseBooleanOption(options["safe-pacing"] ?? options.safe_pacing),
|
|
3133
|
-
batch_rest_enabled: parseBooleanOption(options["batch-rest"] ?? options.batch_rest_enabled)
|
|
3134
|
-
};
|
|
3135
|
-
}
|
|
3124
|
+
human_behavior_profile: typeof (options["human-behavior-profile"] ?? options.human_behavior_profile) === "string"
|
|
3125
|
+
? (options["human-behavior-profile"] ?? options.human_behavior_profile).trim()
|
|
3126
|
+
: undefined,
|
|
3127
|
+
human_behavior: restLevel
|
|
3128
|
+
? {
|
|
3129
|
+
restLevel
|
|
3130
|
+
}
|
|
3131
|
+
: undefined,
|
|
3132
|
+
safe_pacing: parseBooleanOption(options["safe-pacing"] ?? options.safe_pacing),
|
|
3133
|
+
batch_rest_enabled: parseBooleanOption(options["batch-rest"] ?? options.batch_rest_enabled)
|
|
3134
|
+
};
|
|
3135
|
+
}
|
|
3136
3136
|
|
|
3137
3137
|
function getBossChatCliRunTarget(options = {}) {
|
|
3138
3138
|
return {
|
|
@@ -3221,11 +3221,11 @@ export async function runCli(argv = process.argv) {
|
|
|
3221
3221
|
case "mcp":
|
|
3222
3222
|
startServer();
|
|
3223
3223
|
break;
|
|
3224
|
-
case "run":
|
|
3225
|
-
try {
|
|
3226
|
-
if (
|
|
3227
|
-
(options.detached === true || options.background === true)
|
|
3228
|
-
&& process.env[detachedRecommendRunChildEnv] !== "1"
|
|
3224
|
+
case "run":
|
|
3225
|
+
try {
|
|
3226
|
+
if (
|
|
3227
|
+
(options.detached === true || options.background === true)
|
|
3228
|
+
&& process.env[detachedRecommendRunChildEnv] !== "1"
|
|
3229
3229
|
) {
|
|
3230
3230
|
await runPipelineDetached(argv.slice(3), options);
|
|
3231
3231
|
} else {
|
|
@@ -3240,59 +3240,59 @@ export async function runCli(argv = process.argv) {
|
|
|
3240
3240
|
retryable: false
|
|
3241
3241
|
}
|
|
3242
3242
|
});
|
|
3243
|
-
process.exitCode = 1;
|
|
3244
|
-
}
|
|
3245
|
-
break;
|
|
3246
|
-
case "prepare-run":
|
|
3247
|
-
case "prepare":
|
|
3248
|
-
try {
|
|
3249
|
-
await preparePipelineOnce(options);
|
|
3250
|
-
} catch (error) {
|
|
3251
|
-
printJson({
|
|
3252
|
-
status: "FAILED",
|
|
3253
|
-
cron_ready: false,
|
|
3254
|
-
error: {
|
|
3255
|
-
code: "INVALID_CLI_INPUT",
|
|
3256
|
-
message: error.message || "Invalid CLI input",
|
|
3257
|
-
retryable: false
|
|
3258
|
-
}
|
|
3259
|
-
});
|
|
3260
|
-
process.exitCode = 1;
|
|
3261
|
-
}
|
|
3262
|
-
break;
|
|
3263
|
-
case "schedule-run":
|
|
3264
|
-
case "schedule":
|
|
3265
|
-
try {
|
|
3266
|
-
await schedulePipelineOnce(options);
|
|
3267
|
-
} catch (error) {
|
|
3268
|
-
printJson({
|
|
3269
|
-
status: "FAILED",
|
|
3270
|
-
schedule_created: false,
|
|
3271
|
-
error: {
|
|
3272
|
-
code: "INVALID_CLI_INPUT",
|
|
3273
|
-
message: error.message || "Invalid CLI input",
|
|
3274
|
-
retryable: false
|
|
3275
|
-
}
|
|
3276
|
-
});
|
|
3277
|
-
process.exitCode = 1;
|
|
3278
|
-
}
|
|
3279
|
-
break;
|
|
3280
|
-
case "schedule-status":
|
|
3281
|
-
case "scheduled-run":
|
|
3282
|
-
try {
|
|
3283
|
-
scheduleStatusCli(options);
|
|
3284
|
-
} catch (error) {
|
|
3285
|
-
printJson({
|
|
3286
|
-
status: "FAILED",
|
|
3287
|
-
error: {
|
|
3288
|
-
code: "INVALID_CLI_INPUT",
|
|
3289
|
-
message: error.message || "Invalid CLI input",
|
|
3290
|
-
retryable: false
|
|
3291
|
-
}
|
|
3292
|
-
});
|
|
3293
|
-
process.exitCode = 1;
|
|
3294
|
-
}
|
|
3295
|
-
break;
|
|
3243
|
+
process.exitCode = 1;
|
|
3244
|
+
}
|
|
3245
|
+
break;
|
|
3246
|
+
case "prepare-run":
|
|
3247
|
+
case "prepare":
|
|
3248
|
+
try {
|
|
3249
|
+
await preparePipelineOnce(options);
|
|
3250
|
+
} catch (error) {
|
|
3251
|
+
printJson({
|
|
3252
|
+
status: "FAILED",
|
|
3253
|
+
cron_ready: false,
|
|
3254
|
+
error: {
|
|
3255
|
+
code: "INVALID_CLI_INPUT",
|
|
3256
|
+
message: error.message || "Invalid CLI input",
|
|
3257
|
+
retryable: false
|
|
3258
|
+
}
|
|
3259
|
+
});
|
|
3260
|
+
process.exitCode = 1;
|
|
3261
|
+
}
|
|
3262
|
+
break;
|
|
3263
|
+
case "schedule-run":
|
|
3264
|
+
case "schedule":
|
|
3265
|
+
try {
|
|
3266
|
+
await schedulePipelineOnce(options);
|
|
3267
|
+
} catch (error) {
|
|
3268
|
+
printJson({
|
|
3269
|
+
status: "FAILED",
|
|
3270
|
+
schedule_created: false,
|
|
3271
|
+
error: {
|
|
3272
|
+
code: "INVALID_CLI_INPUT",
|
|
3273
|
+
message: error.message || "Invalid CLI input",
|
|
3274
|
+
retryable: false
|
|
3275
|
+
}
|
|
3276
|
+
});
|
|
3277
|
+
process.exitCode = 1;
|
|
3278
|
+
}
|
|
3279
|
+
break;
|
|
3280
|
+
case "schedule-status":
|
|
3281
|
+
case "scheduled-run":
|
|
3282
|
+
try {
|
|
3283
|
+
scheduleStatusCli(options);
|
|
3284
|
+
} catch (error) {
|
|
3285
|
+
printJson({
|
|
3286
|
+
status: "FAILED",
|
|
3287
|
+
error: {
|
|
3288
|
+
code: "INVALID_CLI_INPUT",
|
|
3289
|
+
message: error.message || "Invalid CLI input",
|
|
3290
|
+
retryable: false
|
|
3291
|
+
}
|
|
3292
|
+
});
|
|
3293
|
+
process.exitCode = 1;
|
|
3294
|
+
}
|
|
3295
|
+
break;
|
|
3296
3296
|
case "list-jobs":
|
|
3297
3297
|
case "jobs":
|
|
3298
3298
|
case "recommend-jobs":
|
|
@@ -3436,14 +3436,14 @@ export async function runCli(argv = process.argv) {
|
|
|
3436
3436
|
}
|
|
3437
3437
|
|
|
3438
3438
|
export const __testables = {
|
|
3439
|
-
buildRecommendJobListCliInput,
|
|
3440
|
-
buildBossChatCliInput,
|
|
3441
|
-
buildDefaultMcpArgs,
|
|
3442
|
-
buildMcpLaunchConfig,
|
|
3443
|
-
buildMcpConfigFileContent,
|
|
3444
|
-
ensureGlobalMcpWrapper,
|
|
3445
|
-
getGlobalMcpWrapperPath,
|
|
3446
|
-
collectRuntimeDirectories,
|
|
3439
|
+
buildRecommendJobListCliInput,
|
|
3440
|
+
buildBossChatCliInput,
|
|
3441
|
+
buildDefaultMcpArgs,
|
|
3442
|
+
buildMcpLaunchConfig,
|
|
3443
|
+
buildMcpConfigFileContent,
|
|
3444
|
+
ensureGlobalMcpWrapper,
|
|
3445
|
+
getGlobalMcpWrapperPath,
|
|
3446
|
+
collectRuntimeDirectories,
|
|
3447
3447
|
ensureBossChatRuntimeReady: ensureBossChatRuntimeReadyLocal,
|
|
3448
3448
|
ensureRuntimeDirectories,
|
|
3449
3449
|
getBossChatCliRunTarget,
|
|
@@ -3453,13 +3453,13 @@ export const __testables = {
|
|
|
3453
3453
|
installSkill,
|
|
3454
3454
|
isInstalledPackageRoot,
|
|
3455
3455
|
mergeMcpServerConfigFile,
|
|
3456
|
-
resolveBossChatRuntimeLayout: resolveCdpBossChatRuntimeLayout,
|
|
3457
|
-
runBossChatCliCommand,
|
|
3458
|
-
preparePipelineOnce,
|
|
3459
|
-
schedulePipelineOnce,
|
|
3460
|
-
scheduleStatusCli,
|
|
3461
|
-
runPipelineOnce
|
|
3462
|
-
};
|
|
3456
|
+
resolveBossChatRuntimeLayout: resolveCdpBossChatRuntimeLayout,
|
|
3457
|
+
runBossChatCliCommand,
|
|
3458
|
+
preparePipelineOnce,
|
|
3459
|
+
schedulePipelineOnce,
|
|
3460
|
+
scheduleStatusCli,
|
|
3461
|
+
runPipelineOnce
|
|
3462
|
+
};
|
|
3463
3463
|
|
|
3464
3464
|
if (process.argv[1] && path.resolve(process.argv[1]) === currentFilePath) {
|
|
3465
3465
|
await runCli(process.argv);
|