@reconcrap/boss-recommend-mcp 2.0.16 → 2.0.17

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.
@@ -4,7 +4,10 @@
4
4
  "model": "gpt-4.1-mini",
5
5
  "llmThinkingLevel": "low",
6
6
  "llmTimeoutMs": 60000,
7
+ "llmMaxTokens": 512,
7
8
  "llmMaxRetries": 3,
9
+ "llmImageLimit": 8,
10
+ "llmImageDetail": "low",
8
11
  "debugPort": 9222,
9
12
  "outputDir": "",
10
13
  "humanRestEnabled": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reconcrap/boss-recommend-mcp",
3
- "version": "2.0.16",
3
+ "version": "2.0.17",
4
4
  "description": "Unified MCP pipeline for recommend-page filtering and screening on Boss Zhipin",
5
5
  "keywords": [
6
6
  "boss",
@@ -10,6 +10,7 @@ const SCREEN_CONFIG_TEMPLATE_DEFAULTS = Object.freeze({
10
10
  apiKey: "replace-with-your-api-key",
11
11
  model: "gpt-4.1-mini"
12
12
  });
13
+ const LLM_THINKING_LEVELS = new Set(["off", "minimal", "low", "medium", "high", "auto", "current"]);
13
14
 
14
15
  export const TARGET_COUNT_CANONICAL_ALL = "all";
15
16
  export const TARGET_COUNT_ACCEPTED_EXAMPLES = [TARGET_COUNT_CANONICAL_ALL, -1, 20, "全部候选人"];
@@ -223,6 +224,12 @@ function parsePositiveInteger(raw, fallback = null) {
223
224
  return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
224
225
  }
225
226
 
227
+ function parseConfigNumber(raw, fallback = null) {
228
+ if (raw === undefined || raw === null || raw === "") return fallback;
229
+ const parsed = Number(raw);
230
+ return Number.isFinite(parsed) ? parsed : fallback;
231
+ }
232
+
226
233
  function parseConfigBoolean(raw, fallback = false) {
227
234
  if (typeof raw === "boolean") return raw;
228
235
  const normalized = normalizeText(raw).toLowerCase();
@@ -231,6 +238,11 @@ function parseConfigBoolean(raw, fallback = false) {
231
238
  return fallback;
232
239
  }
233
240
 
241
+ function normalizeLlmThinkingLevel(raw, fallback = "low") {
242
+ const normalized = normalizeText(raw).toLowerCase();
243
+ return LLM_THINKING_LEVELS.has(normalized) ? normalized : fallback;
244
+ }
245
+
234
246
  function resolveConfigPathValue(raw, configDir) {
235
247
  const normalized = normalizeText(raw);
236
248
  if (!normalized) return "";
@@ -387,8 +399,18 @@ export function resolveBossScreeningConfig(workspaceRoot) {
387
399
  baseUrl: normalizeText(parsed.baseUrl).replace(/\/+$/, ""),
388
400
  apiKey: normalizeText(parsed.apiKey),
389
401
  model: normalizeText(parsed.model),
402
+ openaiOrganization: normalizeText(parsed.openaiOrganization || parsed.organization),
403
+ openaiProject: normalizeText(parsed.openaiProject || parsed.project),
390
404
  debugPort: parsePositiveInteger(parsed.debugPort, 9222),
391
- llmThinkingLevel: normalizeText(parsed.llmThinkingLevel || parsed.thinkingLevel || parsed.reasoningEffort),
405
+ llmThinkingLevel: normalizeLlmThinkingLevel(parsed.llmThinkingLevel || parsed.thinkingLevel || parsed.reasoningEffort, "low"),
406
+ llmTimeoutMs: parsePositiveInteger(parsed.llmTimeoutMs || parsed.timeoutMs, null),
407
+ llmMaxRetries: parsePositiveInteger(parsed.llmMaxRetries || parsed.maxRetries, null),
408
+ llmMaxTokens: parsePositiveInteger(parsed.llmMaxTokens || parsed.maxTokens, null),
409
+ llmMaxCompletionTokens: parsePositiveInteger(parsed.llmMaxCompletionTokens || parsed.maxCompletionTokens, null),
410
+ llmImageLimit: parsePositiveInteger(parsed.llmImageLimit || parsed.imageLimit, null),
411
+ llmImageDetail: normalizeText(parsed.llmImageDetail || parsed.imageDetail),
412
+ temperature: parseConfigNumber(parsed.temperature, null),
413
+ topP: parseConfigNumber(parsed.topP || parsed.top_p, null),
392
414
  outputDir: resolveConfigPathValue(parsed.outputDir, configDir),
393
415
  humanRestEnabled: parseConfigBoolean(parsed.humanRestEnabled, false)
394
416
  },
package/src/cli.js CHANGED
@@ -55,6 +55,10 @@ const externalMcpTargetsEnv = "BOSS_RECOMMEND_MCP_CONFIG_TARGETS";
55
55
  const externalSkillDirsEnv = "BOSS_RECOMMEND_EXTERNAL_SKILL_DIRS";
56
56
  const installConfigDefaults = Object.freeze({
57
57
  llmThinkingLevel: "low",
58
+ llmMaxTokens: 512,
59
+ llmMaxRetries: 3,
60
+ llmImageLimit: 8,
61
+ llmImageDetail: "low",
58
62
  humanRestEnabled: false
59
63
  });
60
64
  const bossChatRuntimeChildDirs = ["logs", "runs", "profiles", "reports", "artifacts", "state"];
@@ -77,6 +77,31 @@ function applyChatCompletionThinking(payload, { baseUrl = "", model = "", thinki
77
77
  return payload;
78
78
  }
79
79
 
80
+ function parsePositiveNumber(value, fallback = null) {
81
+ if (value === undefined || value === null || value === "") return fallback;
82
+ const parsed = Number(value);
83
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
84
+ }
85
+
86
+ function parseFiniteNumber(value, fallback = null) {
87
+ if (value === undefined || value === null || value === "") return fallback;
88
+ const parsed = Number(value);
89
+ return Number.isFinite(parsed) ? parsed : fallback;
90
+ }
91
+
92
+ function resolveLlmOutputTokenBudget(config = {}, thinkingLevel = "") {
93
+ const explicit = parsePositiveNumber(
94
+ config.llmMaxCompletionTokens
95
+ ?? config.maxCompletionTokens
96
+ ?? config.llmMaxTokens
97
+ ?? config.maxTokens,
98
+ null
99
+ );
100
+ if (explicit) return Math.max(1, Math.floor(explicit));
101
+ const normalizedThinking = normalizeLlmThinkingLevel(thinkingLevel || "low") || "low";
102
+ return normalizedThinking === "off" || normalizedThinking === "minimal" ? 64 : 512;
103
+ }
104
+
80
105
  export function normalizeText(input) {
81
106
  return String(input || "").replace(/\s+/g, " ").trim();
82
107
  }
@@ -1436,20 +1461,31 @@ export async function callScreeningLlm({
1436
1461
  throw new Error("Candidate text and image evidence are empty");
1437
1462
  }
1438
1463
 
1464
+ const thinkingLevel = config.llmThinkingLevel || config.thinkingLevel || config.reasoningEffort || "low";
1465
+ const outputTokenBudget = resolveLlmOutputTokenBudget(config, thinkingLevel);
1439
1466
  const payload = {
1440
1467
  model,
1441
- temperature: 0.1,
1442
- max_tokens: Math.max(1, Number(config.maxTokens || config.llmMaxTokens) || 64),
1468
+ temperature: parseFiniteNumber(config.temperature, 0.1),
1469
+ max_tokens: outputTokenBudget,
1443
1470
  messages: buildScreeningLlmMessages({
1444
1471
  candidate,
1445
1472
  criteria,
1446
1473
  imageInputs
1447
1474
  })
1448
1475
  };
1476
+ const topP = parseFiniteNumber(config.topP ?? config.top_p, null);
1477
+ if (topP !== null) payload.top_p = topP;
1478
+ const maxCompletionTokens = parsePositiveNumber(
1479
+ config.llmMaxCompletionTokens ?? config.maxCompletionTokens,
1480
+ null
1481
+ );
1482
+ if (maxCompletionTokens !== null) {
1483
+ payload.max_completion_tokens = Math.max(1, Math.floor(maxCompletionTokens));
1484
+ }
1449
1485
  applyChatCompletionThinking(payload, {
1450
1486
  baseUrl,
1451
1487
  model,
1452
- thinkingLevel: config.llmThinkingLevel || config.thinkingLevel || config.reasoningEffort || "low"
1488
+ thinkingLevel
1453
1489
  });
1454
1490
 
1455
1491
  const maxRetries = normalizeLlmMaxRetries(config.llmMaxRetries ?? config.maxRetries);
@@ -1504,7 +1540,12 @@ export async function callScreeningLlm({
1504
1540
  ok: true,
1505
1541
  provider: {
1506
1542
  baseUrl: baseUrl.replace(/\/\/[^/]+/, "//[redacted-host]"),
1507
- model
1543
+ model,
1544
+ thinking_level: normalizeLlmThinkingLevel(thinkingLevel) || "low",
1545
+ thinking: payload.thinking || null,
1546
+ reasoning_effort: payload.reasoning_effort || null,
1547
+ max_tokens: payload.max_tokens,
1548
+ max_completion_tokens: payload.max_completion_tokens || null
1508
1549
  },
1509
1550
  passed,
1510
1551
  reason: "",