@reconcrap/boss-recommend-mcp 1.2.3 → 1.2.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/bin/boss-recommend-mcp.js +2 -2
- package/config/screening-config.example.json +7 -7
- package/package.json +62 -62
- package/scripts/postinstall.cjs +44 -44
- package/skills/boss-recommend-pipeline/README.md +12 -12
- package/skills/boss-recommend-pipeline/SKILL.md +244 -244
- package/src/index.js +182 -51
- package/src/pipeline.js +1432 -1432
- package/src/run-state.js +351 -351
- package/src/test-adapters-runtime.js +469 -469
- package/src/test-index-async.js +264 -264
- package/src/test-run-state.js +152 -152
- package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +3721 -3840
- package/vendor/boss-recommend-screen-cli/scripts/stitch_resume_chunks.py +141 -141
- package/vendor/boss-recommend-screen-cli/test-recoverable-resume-failures.cjs +832 -880
- package/vendor/boss-recommend-search-cli/src/cli.js +1650 -1650
- package/vendor/boss-recommend-search-cli/src/test-job-selection.js +211 -211
package/src/index.js
CHANGED
|
@@ -4,7 +4,11 @@ import { spawn } from "node:child_process";
|
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
getFeaturedCalibrationResolution,
|
|
9
|
+
runRecommendCalibration
|
|
10
|
+
} from "./adapters.js";
|
|
11
|
+
import { runRecommendPipeline } from "./pipeline.js";
|
|
8
12
|
import {
|
|
9
13
|
RUN_MODE_ASYNC,
|
|
10
14
|
RUN_STAGE_PREFLIGHT,
|
|
@@ -28,11 +32,13 @@ import {
|
|
|
28
32
|
const require = createRequire(import.meta.url);
|
|
29
33
|
const { version: SERVER_VERSION } = require("../package.json");
|
|
30
34
|
|
|
31
|
-
const TOOL_START_RUN = "start_recommend_pipeline_run";
|
|
32
|
-
const TOOL_GET_RUN = "get_recommend_pipeline_run";
|
|
33
|
-
const TOOL_CANCEL_RUN = "cancel_recommend_pipeline_run";
|
|
34
|
-
const TOOL_PAUSE_RUN = "pause_recommend_pipeline_run";
|
|
35
|
-
const TOOL_RESUME_RUN = "resume_recommend_pipeline_run";
|
|
35
|
+
const TOOL_START_RUN = "start_recommend_pipeline_run";
|
|
36
|
+
const TOOL_GET_RUN = "get_recommend_pipeline_run";
|
|
37
|
+
const TOOL_CANCEL_RUN = "cancel_recommend_pipeline_run";
|
|
38
|
+
const TOOL_PAUSE_RUN = "pause_recommend_pipeline_run";
|
|
39
|
+
const TOOL_RESUME_RUN = "resume_recommend_pipeline_run";
|
|
40
|
+
const TOOL_RUN_FEATURED_CALIBRATION = "run_featured_calibration";
|
|
41
|
+
const TOOL_GET_FEATURED_CALIBRATION_STATUS = "get_featured_calibration_status";
|
|
36
42
|
|
|
37
43
|
const SERVER_NAME = "boss-recommend-mcp";
|
|
38
44
|
const FRAMING_UNKNOWN = "unknown";
|
|
@@ -141,7 +147,7 @@ function createJsonRpcError(id, code, message) {
|
|
|
141
147
|
};
|
|
142
148
|
}
|
|
143
149
|
|
|
144
|
-
function createRunInputSchema() {
|
|
150
|
+
function createRunInputSchema() {
|
|
145
151
|
return {
|
|
146
152
|
type: "object",
|
|
147
153
|
properties: {
|
|
@@ -290,10 +296,33 @@ function createRunInputSchema() {
|
|
|
290
296
|
required: ["instruction"],
|
|
291
297
|
additionalProperties: false
|
|
292
298
|
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
function
|
|
296
|
-
return
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function createRunFeaturedCalibrationInputSchema() {
|
|
302
|
+
return {
|
|
303
|
+
type: "object",
|
|
304
|
+
properties: {
|
|
305
|
+
port: {
|
|
306
|
+
type: "integer",
|
|
307
|
+
minimum: 1,
|
|
308
|
+
description: "可选,Boss Chrome 远程调试端口(默认读取配置或 9222)"
|
|
309
|
+
},
|
|
310
|
+
timeout_ms: {
|
|
311
|
+
type: "integer",
|
|
312
|
+
minimum: 1000,
|
|
313
|
+
description: "可选,等待收藏点击的超时时间(毫秒)"
|
|
314
|
+
},
|
|
315
|
+
output: {
|
|
316
|
+
type: "string",
|
|
317
|
+
description: "可选,校准文件输出路径(默认 favorite-calibration.json)"
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
additionalProperties: false
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function createToolsSchema() {
|
|
325
|
+
return [
|
|
297
326
|
{
|
|
298
327
|
name: TOOL_START_RUN,
|
|
299
328
|
description: "异步启动 Boss 推荐页流水线(含同步门禁预检);只有在前置确认与页面就绪通过后才返回 run_id。",
|
|
@@ -335,20 +364,34 @@ function createToolsSchema() {
|
|
|
335
364
|
additionalProperties: false
|
|
336
365
|
}
|
|
337
366
|
},
|
|
338
|
-
{
|
|
339
|
-
name: TOOL_RESUME_RUN,
|
|
340
|
-
description: "继续指定 run_id 的 paused 流水线;沿用原 CSV 与 checkpoint 续跑。",
|
|
341
|
-
inputSchema: {
|
|
367
|
+
{
|
|
368
|
+
name: TOOL_RESUME_RUN,
|
|
369
|
+
description: "继续指定 run_id 的 paused 流水线;沿用原 CSV 与 checkpoint 续跑。",
|
|
370
|
+
inputSchema: {
|
|
342
371
|
type: "object",
|
|
343
372
|
properties: {
|
|
344
373
|
run_id: { type: "string" }
|
|
345
374
|
},
|
|
346
|
-
required: ["run_id"],
|
|
347
|
-
additionalProperties: false
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
375
|
+
required: ["run_id"],
|
|
376
|
+
additionalProperties: false
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
name: TOOL_RUN_FEATURED_CALIBRATION,
|
|
381
|
+
description: "手动执行精选页收藏按钮校准。执行前请先在 Boss 推荐页切换到精选 tab 并打开任意候选人详情页。",
|
|
382
|
+
inputSchema: createRunFeaturedCalibrationInputSchema()
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
name: TOOL_GET_FEATURED_CALIBRATION_STATUS,
|
|
386
|
+
description: "查询精选页收藏校准文件与校准脚本可用性。",
|
|
387
|
+
inputSchema: {
|
|
388
|
+
type: "object",
|
|
389
|
+
properties: {},
|
|
390
|
+
additionalProperties: false
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
];
|
|
394
|
+
}
|
|
352
395
|
|
|
353
396
|
function createToolResultResponse(id, payload, isError = false) {
|
|
354
397
|
return {
|
|
@@ -367,7 +410,7 @@ function createToolResultResponse(id, payload, isError = false) {
|
|
|
367
410
|
};
|
|
368
411
|
}
|
|
369
412
|
|
|
370
|
-
function validateRunArgs(args) {
|
|
413
|
+
function validateRunArgs(args) {
|
|
371
414
|
if (!args || typeof args !== "object") {
|
|
372
415
|
return "arguments must be an object";
|
|
373
416
|
}
|
|
@@ -375,9 +418,37 @@ function validateRunArgs(args) {
|
|
|
375
418
|
return "instruction is required and must be a string";
|
|
376
419
|
}
|
|
377
420
|
return null;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
function validateRunFeaturedCalibrationArgs(args) {
|
|
424
|
+
if (!args || typeof args !== "object" || Array.isArray(args)) {
|
|
425
|
+
return "arguments must be an object";
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
if (Object.prototype.hasOwnProperty.call(args, "port")) {
|
|
429
|
+
const port = Number.parseInt(String(args.port), 10);
|
|
430
|
+
if (!Number.isFinite(port) || port <= 0) {
|
|
431
|
+
return "port must be a positive integer";
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (Object.prototype.hasOwnProperty.call(args, "timeout_ms")) {
|
|
436
|
+
const timeoutMs = Number.parseInt(String(args.timeout_ms), 10);
|
|
437
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 1000) {
|
|
438
|
+
return "timeout_ms must be an integer >= 1000";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (Object.prototype.hasOwnProperty.call(args, "output")) {
|
|
443
|
+
if (typeof args.output !== "string" || !normalizeText(args.output)) {
|
|
444
|
+
return "output must be a non-empty string when provided";
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function getLastOutputLine(text) {
|
|
381
452
|
const lines = String(text || "")
|
|
382
453
|
.split(/\r?\n/)
|
|
383
454
|
.map((line) => normalizeText(line))
|
|
@@ -1219,8 +1290,57 @@ function handleResumeRunTool(args) {
|
|
|
1219
1290
|
message: "已恢复 Recommend 流水线(detached)。默认不自动轮询;如需进度请按需调用 get_recommend_pipeline_run。"
|
|
1220
1291
|
};
|
|
1221
1292
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1293
|
+
|
|
1294
|
+
function handleGetFeaturedCalibrationStatusTool(workspaceRoot) {
|
|
1295
|
+
const resolution = getFeaturedCalibrationResolution(workspaceRoot);
|
|
1296
|
+
return {
|
|
1297
|
+
status: "CALIBRATION_STATUS",
|
|
1298
|
+
ready: resolution.calibration_usable === true,
|
|
1299
|
+
calibration_path: resolution.calibration_path,
|
|
1300
|
+
calibration_exists: resolution.calibration_exists,
|
|
1301
|
+
calibration_usable: resolution.calibration_usable,
|
|
1302
|
+
calibration_script_path: resolution.calibration_script_path,
|
|
1303
|
+
message: resolution.calibration_usable
|
|
1304
|
+
? "精选页收藏校准文件可用。"
|
|
1305
|
+
: "精选页收藏校准文件不存在或无效。"
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
async function handleRunFeaturedCalibrationTool({ workspaceRoot, args }) {
|
|
1310
|
+
const result = await runRecommendCalibration(workspaceRoot, {
|
|
1311
|
+
port: args.port,
|
|
1312
|
+
timeoutMs: args.timeout_ms,
|
|
1313
|
+
output: args.output
|
|
1314
|
+
});
|
|
1315
|
+
|
|
1316
|
+
if (!result?.ok) {
|
|
1317
|
+
return {
|
|
1318
|
+
status: "FAILED",
|
|
1319
|
+
error: {
|
|
1320
|
+
code: result?.error?.code || "CALIBRATION_REQUIRED",
|
|
1321
|
+
message: result?.error?.message || "精选页收藏校准失败,请在推荐页精选 tab 打开候选人详情后点击收藏按钮再重试。",
|
|
1322
|
+
retryable: true
|
|
1323
|
+
},
|
|
1324
|
+
calibration_path: result?.calibration_path || null,
|
|
1325
|
+
calibration_script_path: result?.calibration_script_path || null,
|
|
1326
|
+
debug_port: result?.debug_port || null,
|
|
1327
|
+
diagnostics: {
|
|
1328
|
+
stdout_last_line: getLastOutputLine(result?.stdout),
|
|
1329
|
+
stderr_last_line: getLastOutputLine(result?.stderr)
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
return {
|
|
1335
|
+
status: "CALIBRATED",
|
|
1336
|
+
message: "精选页收藏按钮校准完成,可重新执行 start_recommend_pipeline_run。",
|
|
1337
|
+
calibration_path: result.calibration_path,
|
|
1338
|
+
calibration_script_path: result.calibration_script_path,
|
|
1339
|
+
debug_port: result.debug_port
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
async function handleRequest(message, workspaceRoot) {
|
|
1224
1344
|
if (!message || message.jsonrpc !== "2.0") {
|
|
1225
1345
|
return createJsonRpcError(null, -32600, "Invalid JSON-RPC request");
|
|
1226
1346
|
}
|
|
@@ -1262,34 +1382,45 @@ async function handleRequest(message, workspaceRoot) {
|
|
|
1262
1382
|
const toolName = params?.name;
|
|
1263
1383
|
const args = params?.arguments || {};
|
|
1264
1384
|
|
|
1265
|
-
if (toolName === TOOL_START_RUN) {
|
|
1266
|
-
const inputError = validateRunArgs(args);
|
|
1267
|
-
if (inputError) {
|
|
1268
|
-
return createJsonRpcError(id, -32602, inputError);
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
if (
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1385
|
+
if (toolName === TOOL_START_RUN) {
|
|
1386
|
+
const inputError = validateRunArgs(args);
|
|
1387
|
+
if (inputError) {
|
|
1388
|
+
return createJsonRpcError(id, -32602, inputError);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
if (toolName === TOOL_RUN_FEATURED_CALIBRATION) {
|
|
1393
|
+
const inputError = validateRunFeaturedCalibrationArgs(args);
|
|
1394
|
+
if (inputError) {
|
|
1395
|
+
return createJsonRpcError(id, -32602, inputError);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
if ([TOOL_GET_RUN, TOOL_CANCEL_RUN, TOOL_PAUSE_RUN, TOOL_RESUME_RUN].includes(toolName)) {
|
|
1400
|
+
if (!args || typeof args.run_id !== "string" || !normalizeText(args.run_id)) {
|
|
1401
|
+
return createJsonRpcError(id, -32602, "run_id is required and must be a string");
|
|
1402
|
+
}
|
|
1276
1403
|
}
|
|
1277
1404
|
|
|
1278
1405
|
try {
|
|
1279
1406
|
let payload;
|
|
1280
|
-
if (toolName === TOOL_START_RUN) {
|
|
1281
|
-
payload = await handleStartRunTool({ workspaceRoot, args });
|
|
1282
|
-
} else if (toolName === TOOL_GET_RUN) {
|
|
1283
|
-
payload = handleGetRunTool(args);
|
|
1284
|
-
} else if (toolName === TOOL_CANCEL_RUN) {
|
|
1285
|
-
payload = handleCancelRunTool(args);
|
|
1286
|
-
} else if (toolName === TOOL_PAUSE_RUN) {
|
|
1287
|
-
payload = handlePauseRunTool(args);
|
|
1288
|
-
} else if (toolName === TOOL_RESUME_RUN) {
|
|
1289
|
-
payload = handleResumeRunTool(args);
|
|
1290
|
-
} else {
|
|
1291
|
-
|
|
1292
|
-
}
|
|
1407
|
+
if (toolName === TOOL_START_RUN) {
|
|
1408
|
+
payload = await handleStartRunTool({ workspaceRoot, args });
|
|
1409
|
+
} else if (toolName === TOOL_GET_RUN) {
|
|
1410
|
+
payload = handleGetRunTool(args);
|
|
1411
|
+
} else if (toolName === TOOL_CANCEL_RUN) {
|
|
1412
|
+
payload = handleCancelRunTool(args);
|
|
1413
|
+
} else if (toolName === TOOL_PAUSE_RUN) {
|
|
1414
|
+
payload = handlePauseRunTool(args);
|
|
1415
|
+
} else if (toolName === TOOL_RESUME_RUN) {
|
|
1416
|
+
payload = handleResumeRunTool(args);
|
|
1417
|
+
} else if (toolName === TOOL_GET_FEATURED_CALIBRATION_STATUS) {
|
|
1418
|
+
payload = handleGetFeaturedCalibrationStatusTool(workspaceRoot);
|
|
1419
|
+
} else if (toolName === TOOL_RUN_FEATURED_CALIBRATION) {
|
|
1420
|
+
payload = await handleRunFeaturedCalibrationTool({ workspaceRoot, args });
|
|
1421
|
+
} else {
|
|
1422
|
+
return createJsonRpcError(id, -32602, `Unknown tool: ${toolName || ""}`);
|
|
1423
|
+
}
|
|
1293
1424
|
const isError = payload?.status === "FAILED";
|
|
1294
1425
|
return createToolResultResponse(id, payload, isError);
|
|
1295
1426
|
} catch (error) {
|