@reconcrap/boss-recommend-mcp 2.0.3 → 2.0.4
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 +3 -3
- package/config/screening-config.example.json +10 -8
- package/package.json +1 -1
- package/src/chat-mcp.js +16 -9
- package/src/chat-runtime-config.js +28 -1
- package/src/core/screening/index.js +3 -3
- package/src/index.js +4 -2
- package/src/recommend-mcp.js +20 -6
- package/src/recruit-mcp.js +18 -6
package/README.md
CHANGED
|
@@ -221,10 +221,10 @@ config/screening-config.example.json
|
|
|
221
221
|
|
|
222
222
|
- `openaiOrganization`
|
|
223
223
|
- `openaiProject`
|
|
224
|
-
- `debugPort`
|
|
225
|
-
- `outputDir
|
|
224
|
+
- `debugPort`:未显式传 `port` 时,recommend / search / chat CDP-only MCP run 和健康检查默认连接这个 Chrome 调试端口。
|
|
225
|
+
- `outputDir`:recommend / search / chat 完成后的最终 CSV 与 report JSON 会写入这里;run state / checkpoint 仍保留在各自状态目录,方便 pause/resume/cancel。
|
|
226
226
|
- `llmThinkingLevel`:默认 `low`。可设为 `off/minimal/low/medium/high/auto/current`,用于控制 OpenAI-compatible LLM 的 thinking/reasoning 强度。
|
|
227
|
-
- `humanRestEnabled`:默认 `false
|
|
227
|
+
- `humanRestEnabled`:默认 `false`。当前 CDP-only recommend / search / chat run 尚未实现随机休息层,因此会读取并保留该字段但不改变节奏;如后续重新加入 human rest,应以此字段为默认值。
|
|
228
228
|
|
|
229
229
|
## 常用命令
|
|
230
230
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"baseUrl": "https://api.openai.com/v1",
|
|
3
3
|
"apiKey": "replace-with-openai-api-key",
|
|
4
|
-
"model": "gpt-4.1-mini",
|
|
5
|
-
"llmThinkingLevel": "low",
|
|
6
|
-
"llmTimeoutMs": 60000,
|
|
7
|
-
"llmMaxRetries": 3,
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
4
|
+
"model": "gpt-4.1-mini",
|
|
5
|
+
"llmThinkingLevel": "low",
|
|
6
|
+
"llmTimeoutMs": 60000,
|
|
7
|
+
"llmMaxRetries": 3,
|
|
8
|
+
"debugPort": 9222,
|
|
9
|
+
"outputDir": "",
|
|
10
|
+
"humanRestEnabled": false,
|
|
11
|
+
"openaiOrganization": "optional-org-id",
|
|
12
|
+
"openaiProject": "optional-project-id"
|
|
13
|
+
}
|
package/package.json
CHANGED
package/src/chat-mcp.js
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
getBossChatDataDir,
|
|
46
46
|
getBossChatTargetCountValue,
|
|
47
47
|
normalizeTargetCountInput,
|
|
48
|
+
resolveBossConfiguredOutputDir,
|
|
48
49
|
resolveBossChatRuntimeLayout,
|
|
49
50
|
resolveBossScreeningConfig
|
|
50
51
|
} from "./chat-runtime-config.js";
|
|
@@ -123,12 +124,14 @@ function getChatRunArtifacts(runId) {
|
|
|
123
124
|
const normalized = normalizeRunId(runId);
|
|
124
125
|
if (!normalized) return null;
|
|
125
126
|
const runsDir = getChatRunsDir();
|
|
127
|
+
const outputDir = resolveBossConfiguredOutputDir("", runsDir);
|
|
126
128
|
return {
|
|
127
129
|
runs_dir: runsDir,
|
|
130
|
+
output_dir: outputDir,
|
|
128
131
|
run_state_path: path.join(runsDir, `${normalized}.json`),
|
|
129
132
|
checkpoint_path: path.join(runsDir, `${normalized}.checkpoint.json`),
|
|
130
|
-
output_csv: path.join(
|
|
131
|
-
report_json: path.join(
|
|
133
|
+
output_csv: path.join(outputDir, `${normalized}.results.csv`),
|
|
134
|
+
report_json: path.join(outputDir, `${normalized}.report.json`)
|
|
132
135
|
};
|
|
133
136
|
}
|
|
134
137
|
|
|
@@ -633,7 +636,7 @@ async function readChatJobOptionsFromSession(session) {
|
|
|
633
636
|
return readChatJobOptions(session.client, roots.rootNodes.top);
|
|
634
637
|
}
|
|
635
638
|
|
|
636
|
-
function normalizeChatStartInput(args = {}) {
|
|
639
|
+
function normalizeChatStartInput(args = {}, configResolution = null) {
|
|
637
640
|
const target = normalizeTargetCountInput(getBossChatTargetCountValue(args));
|
|
638
641
|
return {
|
|
639
642
|
profile: normalizeText(args.profile) || "default",
|
|
@@ -645,7 +648,10 @@ function normalizeChatStartInput(args = {}) {
|
|
|
645
648
|
targetCount: target.targetCount,
|
|
646
649
|
publicTargetCount: target.publicValue,
|
|
647
650
|
host: normalizeText(args.host) || DEFAULT_CHAT_HOST,
|
|
648
|
-
port: parsePositiveInteger(
|
|
651
|
+
port: parsePositiveInteger(
|
|
652
|
+
args.port,
|
|
653
|
+
configResolution?.ok ? configResolution.config.debugPort : DEFAULT_CHAT_PORT
|
|
654
|
+
),
|
|
649
655
|
targetUrlIncludes: normalizeText(args.target_url_includes) || CHAT_TARGET_URL,
|
|
650
656
|
allowNavigate: args.allow_navigate !== false,
|
|
651
657
|
slowLive: args.slow_live === true
|
|
@@ -800,7 +806,6 @@ function getRunOptions(args, normalized, session, { workspaceRoot = "" } = {}) {
|
|
|
800
806
|
const shouldRequestResume = shouldRequestChatResume(args);
|
|
801
807
|
const useLlm = shouldUseChatLlm(args, shouldRequestResume);
|
|
802
808
|
const configResolution = useLlm ? resolveBossScreeningConfig(workspaceRoot) : { ok: false };
|
|
803
|
-
const configFile = configResolution.ok ? readJsonFile(configResolution.config_path) : null;
|
|
804
809
|
return {
|
|
805
810
|
client: session.client,
|
|
806
811
|
targetUrl: CHAT_TARGET_URL,
|
|
@@ -827,8 +832,7 @@ function getRunOptions(args, normalized, session, { workspaceRoot = "" } = {}) {
|
|
|
827
832
|
maxImagePages: parsePositiveInteger(args.max_image_pages, 8),
|
|
828
833
|
imageWheelDeltaY: parsePositiveInteger(args.image_wheel_delta_y, 650),
|
|
829
834
|
llmConfig: configResolution.ok ? {
|
|
830
|
-
...configResolution.config
|
|
831
|
-
apiKey: configFile?.apiKey || ""
|
|
835
|
+
...configResolution.config
|
|
832
836
|
} : null,
|
|
833
837
|
llmTimeoutMs: parsePositiveInteger(args.llm_timeout_ms, slowLive ? 180000 : 120000),
|
|
834
838
|
llmImageLimit: parsePositiveInteger(args.llm_image_limit, 8),
|
|
@@ -888,7 +892,8 @@ function trackChatRun(runId) {
|
|
|
888
892
|
}
|
|
889
893
|
|
|
890
894
|
async function startBossChatRunInternal(args = {}, { workspaceRoot = "" } = {}) {
|
|
891
|
-
const
|
|
895
|
+
const defaultConfigResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
896
|
+
const normalized = normalizeChatStartInput(args, defaultConfigResolution);
|
|
892
897
|
const missingFields = getMissingChatStartFields(args, normalized);
|
|
893
898
|
if (missingFields.length) {
|
|
894
899
|
return buildNeedInputResponse({
|
|
@@ -987,7 +992,8 @@ async function startBossChatRunInternal(args = {}, { workspaceRoot = "" } = {})
|
|
|
987
992
|
}
|
|
988
993
|
|
|
989
994
|
export async function prepareBossChatRunTool({ workspaceRoot = "", args = {} } = {}) {
|
|
990
|
-
const
|
|
995
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
996
|
+
const normalized = normalizeChatStartInput(args, configResolution);
|
|
991
997
|
let session;
|
|
992
998
|
try {
|
|
993
999
|
session = await chatConnectorImpl({
|
|
@@ -1129,6 +1135,7 @@ export async function bossChatHealthCheckTool({ workspaceRoot = "", args = {} }
|
|
|
1129
1135
|
cli_path: null,
|
|
1130
1136
|
config_path: configResolution.config_path || null,
|
|
1131
1137
|
config_dir: configResolution.config_dir || null,
|
|
1138
|
+
output_dir: configResolution.ok ? configResolution.config.outputDir || null : null,
|
|
1132
1139
|
debug_port: port,
|
|
1133
1140
|
shared_llm_config: configResolution.ok === true,
|
|
1134
1141
|
data_dir: runtimeLayout.data_dir,
|
|
@@ -223,6 +223,22 @@ function parsePositiveInteger(raw, fallback = null) {
|
|
|
223
223
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
function parseConfigBoolean(raw, fallback = false) {
|
|
227
|
+
if (typeof raw === "boolean") return raw;
|
|
228
|
+
const normalized = normalizeText(raw).toLowerCase();
|
|
229
|
+
if (["true", "1", "yes", "y", "on", "enabled"].includes(normalized)) return true;
|
|
230
|
+
if (["false", "0", "no", "n", "off", "disabled"].includes(normalized)) return false;
|
|
231
|
+
return fallback;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function resolveConfigPathValue(raw, configDir) {
|
|
235
|
+
const normalized = normalizeText(raw);
|
|
236
|
+
if (!normalized) return "";
|
|
237
|
+
return path.isAbsolute(normalized)
|
|
238
|
+
? path.resolve(normalized)
|
|
239
|
+
: path.resolve(configDir || process.cwd(), normalized);
|
|
240
|
+
}
|
|
241
|
+
|
|
226
242
|
function validateScreeningConfig(config) {
|
|
227
243
|
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
228
244
|
return {
|
|
@@ -369,8 +385,12 @@ export function resolveBossScreeningConfig(workspaceRoot) {
|
|
|
369
385
|
ok: true,
|
|
370
386
|
config: {
|
|
371
387
|
baseUrl: normalizeText(parsed.baseUrl).replace(/\/+$/, ""),
|
|
388
|
+
apiKey: normalizeText(parsed.apiKey),
|
|
372
389
|
model: normalizeText(parsed.model),
|
|
373
|
-
debugPort: parsePositiveInteger(parsed.debugPort, 9222)
|
|
390
|
+
debugPort: parsePositiveInteger(parsed.debugPort, 9222),
|
|
391
|
+
llmThinkingLevel: normalizeText(parsed.llmThinkingLevel || parsed.thinkingLevel || parsed.reasoningEffort),
|
|
392
|
+
outputDir: resolveConfigPathValue(parsed.outputDir, configDir),
|
|
393
|
+
humanRestEnabled: parseConfigBoolean(parsed.humanRestEnabled, false)
|
|
374
394
|
},
|
|
375
395
|
config_path: configPath,
|
|
376
396
|
config_dir: configDir,
|
|
@@ -378,6 +398,13 @@ export function resolveBossScreeningConfig(workspaceRoot) {
|
|
|
378
398
|
};
|
|
379
399
|
}
|
|
380
400
|
|
|
401
|
+
export function resolveBossConfiguredOutputDir(workspaceRoot, fallbackDir = "") {
|
|
402
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
403
|
+
const configuredDir = configResolution.ok ? normalizeText(configResolution.config.outputDir) : "";
|
|
404
|
+
if (configuredDir) return configuredDir;
|
|
405
|
+
return fallbackDir ? path.resolve(fallbackDir) : "";
|
|
406
|
+
}
|
|
407
|
+
|
|
381
408
|
function isUnlimitedTargetCountToken(value) {
|
|
382
409
|
const token = normalizeText(value).toLowerCase();
|
|
383
410
|
if (!token) return false;
|
|
@@ -37,7 +37,7 @@ const GENDER_CODE_MAP = {
|
|
|
37
37
|
2: "女"
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
const LLM_THINKING_LEVELS = new Set(["off", "low", "medium", "high", "current"]);
|
|
40
|
+
const LLM_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "auto", "current"]);
|
|
41
41
|
|
|
42
42
|
function nowIso() {
|
|
43
43
|
return new Date().toISOString();
|
|
@@ -64,9 +64,9 @@ function isVolcengineModel(baseUrl, model) {
|
|
|
64
64
|
|
|
65
65
|
function applyChatCompletionThinking(payload, { baseUrl = "", model = "", thinkingLevel = "" } = {}) {
|
|
66
66
|
const level = normalizeLlmThinkingLevel(thinkingLevel);
|
|
67
|
-
if (!level || level === "current") return payload;
|
|
67
|
+
if (!level || level === "current" || level === "auto") return payload;
|
|
68
68
|
if (isVolcengineModel(baseUrl, model)) {
|
|
69
|
-
if (level === "off") {
|
|
69
|
+
if (level === "off" || level === "minimal") {
|
|
70
70
|
payload.thinking = { type: "disabled" };
|
|
71
71
|
} else {
|
|
72
72
|
payload.thinking = { type: "enabled" };
|
package/src/index.js
CHANGED
|
@@ -7,7 +7,8 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import {
|
|
8
8
|
getFeaturedCalibrationResolution,
|
|
9
9
|
getBossChatTargetCountValue,
|
|
10
|
-
normalizeTargetCountInput
|
|
10
|
+
normalizeTargetCountInput,
|
|
11
|
+
resolveBossScreeningConfig
|
|
11
12
|
} from "./chat-runtime-config.js";
|
|
12
13
|
import {
|
|
13
14
|
__resetChatMcpStateForTests,
|
|
@@ -1890,7 +1891,8 @@ async function handleRunRecommendSelfHealTool({ workspaceRoot, args }) {
|
|
|
1890
1891
|
}
|
|
1891
1892
|
|
|
1892
1893
|
const host = "127.0.0.1";
|
|
1893
|
-
const
|
|
1894
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
1895
|
+
const port = parsePositiveInteger(args.port, configResolution.ok ? configResolution.config.debugPort : 9222);
|
|
1894
1896
|
let session = null;
|
|
1895
1897
|
try {
|
|
1896
1898
|
session = await connectToChromeTarget({
|
package/src/recommend-mcp.js
CHANGED
|
@@ -44,6 +44,10 @@ import {
|
|
|
44
44
|
parseRecommendInstruction
|
|
45
45
|
} from "./parser.js";
|
|
46
46
|
import { getRunsDir } from "./run-state.js";
|
|
47
|
+
import {
|
|
48
|
+
resolveBossConfiguredOutputDir,
|
|
49
|
+
resolveBossScreeningConfig
|
|
50
|
+
} from "./chat-runtime-config.js";
|
|
47
51
|
|
|
48
52
|
const DEFAULT_RECOMMEND_HOST = "127.0.0.1";
|
|
49
53
|
const DEFAULT_RECOMMEND_PORT = 9222;
|
|
@@ -115,12 +119,14 @@ function getRecommendRunArtifacts(runId) {
|
|
|
115
119
|
const normalized = normalizeRunId(runId);
|
|
116
120
|
if (!normalized) return null;
|
|
117
121
|
const runsDir = getRunsDir();
|
|
122
|
+
const outputDir = resolveBossConfiguredOutputDir("", runsDir);
|
|
118
123
|
return {
|
|
119
124
|
runs_dir: runsDir,
|
|
125
|
+
output_dir: outputDir,
|
|
120
126
|
run_state_path: path.join(runsDir, `${normalized}.json`),
|
|
121
127
|
checkpoint_path: path.join(runsDir, `${normalized}.checkpoint.json`),
|
|
122
|
-
output_csv: path.join(
|
|
123
|
-
report_json: path.join(
|
|
128
|
+
output_csv: path.join(outputDir, `${normalized}.results.csv`),
|
|
129
|
+
report_json: path.join(outputDir, `${normalized}.report.json`)
|
|
124
130
|
};
|
|
125
131
|
}
|
|
126
132
|
|
|
@@ -484,8 +490,12 @@ async function readRecommendJobOptionsFromSession(session) {
|
|
|
484
490
|
}
|
|
485
491
|
|
|
486
492
|
export async function listRecommendJobsTool({ workspaceRoot = "", args = {} } = {}) {
|
|
493
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
487
494
|
const host = normalizeText(args.host) || DEFAULT_RECOMMEND_HOST;
|
|
488
|
-
const port = parsePositiveInteger(
|
|
495
|
+
const port = parsePositiveInteger(
|
|
496
|
+
args.port,
|
|
497
|
+
configResolution.ok ? configResolution.config.debugPort : DEFAULT_RECOMMEND_PORT
|
|
498
|
+
);
|
|
489
499
|
const targetUrlIncludes = normalizeText(args.target_url_includes) || RECOMMEND_TARGET_URL;
|
|
490
500
|
const allowNavigate = args.allow_navigate !== false;
|
|
491
501
|
const slowLive = args.slow_live === true;
|
|
@@ -922,7 +932,7 @@ function buildRecommendFilter(parsed, args = {}) {
|
|
|
922
932
|
return groups.length ? { filterGroups: groups } : { enabled: false };
|
|
923
933
|
}
|
|
924
934
|
|
|
925
|
-
function normalizeRecommendStartInput(args = {}, parsed) {
|
|
935
|
+
function normalizeRecommendStartInput(args = {}, parsed, configResolution = null) {
|
|
926
936
|
const confirmation = args.confirmation || {};
|
|
927
937
|
const overrides = args.overrides || {};
|
|
928
938
|
const slowLive = args.slow_live === true;
|
|
@@ -932,7 +942,10 @@ function normalizeRecommendStartInput(args = {}, parsed) {
|
|
|
932
942
|
);
|
|
933
943
|
return {
|
|
934
944
|
host: normalizeText(args.host) || DEFAULT_RECOMMEND_HOST,
|
|
935
|
-
port: parsePositiveInteger(
|
|
945
|
+
port: parsePositiveInteger(
|
|
946
|
+
args.port,
|
|
947
|
+
configResolution?.ok ? configResolution.config.debugPort : DEFAULT_RECOMMEND_PORT
|
|
948
|
+
),
|
|
936
949
|
targetUrlIncludes: normalizeText(args.target_url_includes) || RECOMMEND_TARGET_URL,
|
|
937
950
|
allowNavigate: args.allow_navigate !== false,
|
|
938
951
|
slowLive,
|
|
@@ -1038,7 +1051,8 @@ async function startRecommendPipelineRunInternal(args = {}, { workspaceRoot = ""
|
|
|
1038
1051
|
const parsed = parseRecommendPipelineRequest(args);
|
|
1039
1052
|
const gate = evaluateRecommendPipelineGate(parsed, args);
|
|
1040
1053
|
if (gate) return gate;
|
|
1041
|
-
const
|
|
1054
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
1055
|
+
const normalized = normalizeRecommendStartInput(args, parsed, configResolution);
|
|
1042
1056
|
|
|
1043
1057
|
let session;
|
|
1044
1058
|
try {
|
package/src/recruit-mcp.js
CHANGED
|
@@ -32,6 +32,10 @@ import {
|
|
|
32
32
|
runRecruitWorkflow,
|
|
33
33
|
waitForRecruitSearchControls
|
|
34
34
|
} from "./domains/recruit/index.js";
|
|
35
|
+
import {
|
|
36
|
+
resolveBossConfiguredOutputDir,
|
|
37
|
+
resolveBossScreeningConfig
|
|
38
|
+
} from "./chat-runtime-config.js";
|
|
35
39
|
|
|
36
40
|
const RUN_MODE_ASYNC = "async";
|
|
37
41
|
const RUN_MODE_SYNC = "sync";
|
|
@@ -108,12 +112,14 @@ function getRecruitRunArtifacts(runId) {
|
|
|
108
112
|
const normalized = normalizeRunId(runId);
|
|
109
113
|
if (!normalized) return null;
|
|
110
114
|
const runsDir = getRecruitRunsDir();
|
|
115
|
+
const outputDir = resolveBossConfiguredOutputDir("", runsDir);
|
|
111
116
|
return {
|
|
112
117
|
runs_dir: runsDir,
|
|
118
|
+
output_dir: outputDir,
|
|
113
119
|
run_state_path: path.join(runsDir, `${normalized}.json`),
|
|
114
120
|
checkpoint_path: path.join(runsDir, `${normalized}.checkpoint.json`),
|
|
115
|
-
output_csv: path.join(
|
|
116
|
-
report_json: path.join(
|
|
121
|
+
output_csv: path.join(outputDir, `${normalized}.results.csv`),
|
|
122
|
+
report_json: path.join(outputDir, `${normalized}.report.json`)
|
|
117
123
|
};
|
|
118
124
|
}
|
|
119
125
|
|
|
@@ -807,12 +813,18 @@ async function startRecruitPipelineRunInternal(args = {}, { workspaceRoot = "" }
|
|
|
807
813
|
const parsed = parseRecruitPipelineRequest(args);
|
|
808
814
|
const gate = evaluateRecruitPipelineGate(parsed);
|
|
809
815
|
if (gate) return gate;
|
|
816
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
817
|
+
const host = normalizeText(args.host) || DEFAULT_RECRUIT_HOST;
|
|
818
|
+
const port = parsePositiveInteger(
|
|
819
|
+
args.port,
|
|
820
|
+
configResolution.ok ? configResolution.config.debugPort : DEFAULT_RECRUIT_PORT
|
|
821
|
+
);
|
|
810
822
|
|
|
811
823
|
let session;
|
|
812
824
|
try {
|
|
813
825
|
session = await recruitConnectorImpl({
|
|
814
|
-
host
|
|
815
|
-
port
|
|
826
|
+
host,
|
|
827
|
+
port,
|
|
816
828
|
targetUrlIncludes: normalizeText(args.target_url_includes) || RECRUIT_TARGET_URL,
|
|
817
829
|
allowNavigate: args.allow_navigate !== false,
|
|
818
830
|
slowLive: args.slow_live === true
|
|
@@ -858,8 +870,8 @@ async function startRecruitPipelineRunInternal(args = {}, { workspaceRoot = "" }
|
|
|
858
870
|
workspaceRoot: normalizeText(workspaceRoot) || globalThis.process?.cwd?.() || "",
|
|
859
871
|
args: clonePlain(args, {}),
|
|
860
872
|
chrome: {
|
|
861
|
-
host
|
|
862
|
-
port
|
|
873
|
+
host,
|
|
874
|
+
port,
|
|
863
875
|
target_url: session.target?.url || RECRUIT_TARGET_URL,
|
|
864
876
|
target_id: session.target?.id || null,
|
|
865
877
|
auto_launch: session.chrome || null
|