@reconcrap/boss-recommend-mcp 2.0.45 → 2.0.47

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.
Files changed (56) hide show
  1. package/bin/boss-recommend-mcp.js +4 -4
  2. package/config/screening-config.example.json +27 -27
  3. package/package.json +1 -1
  4. package/scripts/postinstall.cjs +44 -44
  5. package/skills/boss-chat/README.md +39 -39
  6. package/skills/boss-chat/SKILL.md +93 -93
  7. package/skills/boss-recommend-pipeline/README.md +12 -12
  8. package/skills/boss-recommend-pipeline/SKILL.md +180 -180
  9. package/skills/boss-recruit-pipeline/README.md +17 -17
  10. package/skills/boss-recruit-pipeline/SKILL.md +58 -58
  11. package/src/chat-mcp.js +1780 -1780
  12. package/src/chat-runtime-config.js +749 -749
  13. package/src/cli.js +3054 -3054
  14. package/src/core/boss-cards/index.js +199 -199
  15. package/src/core/browser/index.js +1453 -1446
  16. package/src/core/capture/index.js +1201 -1201
  17. package/src/core/cv-acquisition/index.js +238 -238
  18. package/src/core/cv-capture-target/index.js +299 -299
  19. package/src/core/greet-quota/index.js +54 -54
  20. package/src/core/infinite-list/index.js +1326 -1326
  21. package/src/core/reporting/legacy-csv.js +341 -341
  22. package/src/core/run/timing.js +33 -33
  23. package/src/core/screening/index.js +50 -3
  24. package/src/core/self-heal/index.js +973 -973
  25. package/src/core/self-heal/viewport.js +564 -564
  26. package/src/domains/chat/cards.js +137 -137
  27. package/src/domains/chat/constants.js +221 -221
  28. package/src/domains/chat/detail.js +1668 -1661
  29. package/src/domains/chat/index.js +7 -7
  30. package/src/domains/chat/jobs.js +592 -588
  31. package/src/domains/chat/page-guard.js +98 -98
  32. package/src/domains/chat/roots.js +56 -56
  33. package/src/domains/chat/run-service.js +1977 -1955
  34. package/src/domains/recommend/actions.js +457 -457
  35. package/src/domains/recommend/cards.js +243 -243
  36. package/src/domains/recommend/constants.js +165 -165
  37. package/src/domains/recommend/detail.js +36 -28
  38. package/src/domains/recommend/filters.js +610 -581
  39. package/src/domains/recommend/index.js +10 -10
  40. package/src/domains/recommend/jobs.js +316 -263
  41. package/src/domains/recommend/refresh.js +472 -472
  42. package/src/domains/recommend/roots.js +80 -80
  43. package/src/domains/recommend/run-service.js +75 -35
  44. package/src/domains/recommend/scopes.js +246 -245
  45. package/src/domains/recruit/actions.js +277 -277
  46. package/src/domains/recruit/cards.js +74 -74
  47. package/src/domains/recruit/constants.js +167 -167
  48. package/src/domains/recruit/detail.js +461 -460
  49. package/src/domains/recruit/index.js +9 -9
  50. package/src/domains/recruit/instruction-parser.js +451 -451
  51. package/src/domains/recruit/refresh.js +44 -44
  52. package/src/domains/recruit/roots.js +68 -68
  53. package/src/domains/recruit/run-service.js +1207 -1161
  54. package/src/domains/recruit/search.js +1202 -1149
  55. package/src/recommend-mcp.js +22 -22
  56. package/src/recruit-mcp.js +1338 -1338
@@ -1,33 +1,33 @@
1
- import path from "node:path";
2
-
3
- export function addTiming(timings, key, value) {
4
- if (!timings || !key) return;
5
- const numeric = Number(value);
6
- if (!Number.isFinite(numeric) || numeric < 0) return;
7
- timings[key] = (Number(timings[key]) || 0) + Math.round(numeric);
8
- }
9
-
10
- export async function measureTiming(timings, key, task) {
11
- const started = Date.now();
12
- try {
13
- return await task();
14
- } finally {
15
- addTiming(timings, key, Date.now() - started);
16
- }
17
- }
18
-
19
- export function imageEvidenceFilePath({
20
- imageOutputDir = "",
21
- domain = "candidate",
22
- runId = "",
23
- index = 0,
24
- extension = "png"
25
- } = {}) {
26
- const dir = String(imageOutputDir || "").trim();
27
- if (!dir) return "";
28
- const safeDomain = String(domain || "candidate").replace(/[^\w.-]+/g, "_");
29
- const safeRunId = String(runId || `${safeDomain}-run`).replace(/[^\w.-]+/g, "_");
30
- const safeIndex = String((Number(index) || 0) + 1).padStart(3, "0");
31
- const safeExt = String(extension || "png").replace(/^\./, "") || "png";
32
- return path.join(dir, safeRunId, `${safeDomain}-candidate-${safeIndex}.${safeExt}`);
33
- }
1
+ import path from "node:path";
2
+
3
+ export function addTiming(timings, key, value) {
4
+ if (!timings || !key) return;
5
+ const numeric = Number(value);
6
+ if (!Number.isFinite(numeric) || numeric < 0) return;
7
+ timings[key] = (Number(timings[key]) || 0) + Math.round(numeric);
8
+ }
9
+
10
+ export async function measureTiming(timings, key, task) {
11
+ const started = Date.now();
12
+ try {
13
+ return await task();
14
+ } finally {
15
+ addTiming(timings, key, Date.now() - started);
16
+ }
17
+ }
18
+
19
+ export function imageEvidenceFilePath({
20
+ imageOutputDir = "",
21
+ domain = "candidate",
22
+ runId = "",
23
+ index = 0,
24
+ extension = "png"
25
+ } = {}) {
26
+ const dir = String(imageOutputDir || "").trim();
27
+ if (!dir) return "";
28
+ const safeDomain = String(domain || "candidate").replace(/[^\w.-]+/g, "_");
29
+ const safeRunId = String(runId || `${safeDomain}-run`).replace(/[^\w.-]+/g, "_");
30
+ const safeIndex = String((Number(index) || 0) + 1).padStart(3, "0");
31
+ const safeExt = String(extension || "png").replace(/^\./, "") || "png";
32
+ return path.join(dir, safeRunId, `${safeDomain}-candidate-${safeIndex}.${safeExt}`);
33
+ }
@@ -189,6 +189,44 @@ function normalizeBlockText(input) {
189
189
  return String(input ?? "").trim();
190
190
  }
191
191
 
192
+ function normalizeReasoningKey(input) {
193
+ return normalizeBlockText(input).replace(/\s+/g, " ");
194
+ }
195
+
196
+ function collapseRepeatedReasoningText(input) {
197
+ const text = normalizeBlockText(input);
198
+ if (!text) return "";
199
+ const chunks = text.split(/\n{2,}/).map(normalizeBlockText).filter(Boolean);
200
+ if (chunks.length >= 2 && chunks.length % 2 === 0) {
201
+ const midpoint = chunks.length / 2;
202
+ const first = chunks.slice(0, midpoint);
203
+ const second = chunks.slice(midpoint);
204
+ if (normalizeReasoningKey(first.join("\n\n")) === normalizeReasoningKey(second.join("\n\n"))) {
205
+ return first.join("\n\n");
206
+ }
207
+ }
208
+
209
+ const compacted = normalizeReasoningKey(text);
210
+ if (compacted.length < 160) return text;
211
+ const midpoint = Math.floor(compacted.length / 2);
212
+ for (let offset = -32; offset <= 32; offset += 1) {
213
+ const split = midpoint + offset;
214
+ if (split <= 80 || split >= compacted.length - 80) continue;
215
+ const first = compacted.slice(0, split).trim();
216
+ const second = compacted.slice(split).trim();
217
+ if (first && first === second) return first;
218
+ }
219
+ return text;
220
+ }
221
+
222
+ function firstReasoningText(lines) {
223
+ for (const line of lines) {
224
+ const cleaned = collapseRepeatedReasoningText(line);
225
+ if (cleaned) return cleaned;
226
+ }
227
+ return "";
228
+ }
229
+
192
230
  function compact(input) {
193
231
  return normalizeText(input).toLowerCase();
194
232
  }
@@ -472,7 +510,9 @@ function flattenChatMessageContent(content) {
472
510
 
473
511
  function collectLlmReasoningText(choice = {}) {
474
512
  const message = choice?.message || {};
475
- return [
513
+ const seen = new Set();
514
+ const unique = [];
515
+ for (const item of [
476
516
  message.reasoning_content,
477
517
  message.provider_specific_fields?.reasoning_content,
478
518
  message.reasoning,
@@ -489,7 +529,14 @@ function collectLlmReasoningText(choice = {}) {
489
529
  choice.provider_specific_fields?.cot,
490
530
  choice.chain_of_thought,
491
531
  choice.provider_specific_fields?.chain_of_thought
492
- ].map(flattenChatMessageContent).map(normalizeBlockText).filter(Boolean).join("\n\n");
532
+ ]) {
533
+ const text = collapseRepeatedReasoningText(flattenChatMessageContent(item));
534
+ const key = normalizeReasoningKey(text);
535
+ if (!key || seen.has(key)) continue;
536
+ seen.add(key);
537
+ unique.push(text);
538
+ }
539
+ return collapseRepeatedReasoningText(unique.join("\n\n"));
493
540
  }
494
541
 
495
542
  function mimeTypeForImagePath(filePath) {
@@ -1621,7 +1668,7 @@ async function callScreeningLlmWithProvider({
1621
1668
  const evidence = Array.isArray(parsed?.evidence)
1622
1669
  ? parsed.evidence.map(normalizeText).filter(Boolean)
1623
1670
  : [];
1624
- const decisionCot = firstUsefulLine([
1671
+ const decisionCot = firstReasoningText([
1625
1672
  parsed?.cot,
1626
1673
  parsed?.decision_cot,
1627
1674
  parsed?.reasoning,