@reconcrap/boss-recommend-mcp 1.3.39 → 2.0.1

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 (88) hide show
  1. package/README.md +86 -33
  2. package/package.json +62 -9
  3. package/skills/boss-chat/SKILL.md +5 -4
  4. package/skills/boss-recommend-pipeline/SKILL.md +21 -31
  5. package/skills/boss-recruit-pipeline/README.md +17 -0
  6. package/skills/boss-recruit-pipeline/SKILL.md +55 -0
  7. package/src/chat-mcp.js +1333 -0
  8. package/src/chat-runtime-config.js +559 -0
  9. package/src/cli.js +1254 -225
  10. package/src/core/browser/index.js +378 -0
  11. package/src/core/capture/index.js +298 -0
  12. package/src/core/cv-acquisition/index.js +219 -0
  13. package/src/core/greet-quota/index.js +54 -0
  14. package/src/core/infinite-list/index.js +459 -0
  15. package/src/core/reporting/legacy-csv.js +332 -0
  16. package/src/core/run/index.js +286 -0
  17. package/src/core/screening/index.js +1166 -0
  18. package/src/core/self-heal/index.js +848 -0
  19. package/src/domains/chat/cards.js +129 -0
  20. package/src/domains/chat/constants.js +183 -0
  21. package/src/domains/chat/detail.js +1369 -0
  22. package/src/domains/chat/index.js +7 -0
  23. package/src/domains/chat/jobs.js +334 -0
  24. package/src/domains/chat/page-guard.js +88 -0
  25. package/src/domains/chat/roots.js +56 -0
  26. package/src/domains/chat/run-service.js +1101 -0
  27. package/src/domains/recommend/actions.js +457 -0
  28. package/src/domains/recommend/cards.js +228 -0
  29. package/src/domains/recommend/constants.js +141 -0
  30. package/src/domains/recommend/detail.js +341 -0
  31. package/src/domains/recommend/filters.js +581 -0
  32. package/src/domains/recommend/index.js +10 -0
  33. package/src/domains/recommend/jobs.js +232 -0
  34. package/src/domains/recommend/refresh.js +204 -0
  35. package/src/domains/recommend/roots.js +78 -0
  36. package/src/domains/recommend/run-service.js +903 -0
  37. package/src/domains/recommend/scopes.js +245 -0
  38. package/src/domains/recruit/actions.js +277 -0
  39. package/src/domains/recruit/cards.js +66 -0
  40. package/src/domains/recruit/constants.js +130 -0
  41. package/src/domains/recruit/detail.js +414 -0
  42. package/src/domains/recruit/index.js +9 -0
  43. package/src/domains/recruit/instruction-parser.js +451 -0
  44. package/src/domains/recruit/refresh.js +40 -0
  45. package/src/domains/recruit/roots.js +67 -0
  46. package/src/domains/recruit/run-service.js +580 -0
  47. package/src/domains/recruit/search.js +1149 -0
  48. package/src/index.js +578 -419
  49. package/src/recommend-mcp.js +1257 -0
  50. package/src/recruit-mcp.js +1035 -0
  51. package/src/adapters.js +0 -3079
  52. package/src/boss-chat.js +0 -1037
  53. package/src/pipeline.js +0 -2249
  54. package/src/recommend-healing-config.js +0 -131
  55. package/src/recommend-healing-rules.json +0 -261
  56. package/src/self-heal.js +0 -2237
  57. package/src/test-adapters-runtime.js +0 -628
  58. package/src/test-boss-chat.js +0 -3196
  59. package/src/test-index-async.js +0 -498
  60. package/src/test-parser.js +0 -742
  61. package/src/test-pipeline.js +0 -2703
  62. package/src/test-run-state.js +0 -152
  63. package/src/test-self-heal.js +0 -224
  64. package/vendor/boss-chat-cli/README.md +0 -134
  65. package/vendor/boss-chat-cli/package.json +0 -53
  66. package/vendor/boss-chat-cli/src/app.js +0 -1501
  67. package/vendor/boss-chat-cli/src/browser/chat-page.js +0 -3562
  68. package/vendor/boss-chat-cli/src/cli.js +0 -1713
  69. package/vendor/boss-chat-cli/src/mcp/server.js +0 -149
  70. package/vendor/boss-chat-cli/src/mcp/tool-runtime.js +0 -193
  71. package/vendor/boss-chat-cli/src/runtime/async-run-state.js +0 -260
  72. package/vendor/boss-chat-cli/src/runtime/interaction.js +0 -102
  73. package/vendor/boss-chat-cli/src/runtime/run-control.js +0 -102
  74. package/vendor/boss-chat-cli/src/services/chrome-client.js +0 -107
  75. package/vendor/boss-chat-cli/src/services/llm.js +0 -1292
  76. package/vendor/boss-chat-cli/src/services/llm.test.js +0 -326
  77. package/vendor/boss-chat-cli/src/services/profile-store.js +0 -173
  78. package/vendor/boss-chat-cli/src/services/report-store.js +0 -317
  79. package/vendor/boss-chat-cli/src/services/resume-capture.js +0 -469
  80. package/vendor/boss-chat-cli/src/services/resume-network.js +0 -727
  81. package/vendor/boss-chat-cli/src/services/state-store.js +0 -90
  82. package/vendor/boss-chat-cli/src/utils/customer-key.js +0 -82
  83. package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +0 -7072
  84. package/vendor/boss-recommend-screen-cli/scripts/capture-full-resume-canvas.cjs +0 -817
  85. package/vendor/boss-recommend-screen-cli/scripts/stitch_resume_chunks.py +0 -141
  86. package/vendor/boss-recommend-screen-cli/test-recoverable-resume-failures.cjs +0 -2423
  87. package/vendor/boss-recommend-search-cli/src/cli.js +0 -1698
  88. package/vendor/boss-recommend-search-cli/src/test-job-selection.js +0 -211
@@ -0,0 +1,219 @@
1
+ export const CV_ACQUISITION_MODE_UNKNOWN = "unknown";
2
+ export const CV_ACQUISITION_MODE_NETWORK = "network";
3
+ export const CV_ACQUISITION_MODE_IMAGE = "image";
4
+
5
+ export const NETWORK_RESUME_WAIT_MS = 4200;
6
+ export const NETWORK_RESUME_RETRY_WAIT_MS = 2000;
7
+ export const NETWORK_RESUME_IMAGE_MODE_GRACE_MS = 1000;
8
+
9
+ const VALID_MODES = new Set([
10
+ CV_ACQUISITION_MODE_UNKNOWN,
11
+ CV_ACQUISITION_MODE_NETWORK,
12
+ CV_ACQUISITION_MODE_IMAGE
13
+ ]);
14
+
15
+ function normalizeMode(mode) {
16
+ const normalized = String(mode || "").trim().toLowerCase();
17
+ return VALID_MODES.has(normalized) ? normalized : CV_ACQUISITION_MODE_UNKNOWN;
18
+ }
19
+
20
+ function positiveNumber(value, fallback) {
21
+ const parsed = Number(value);
22
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
23
+ }
24
+
25
+ function nowIso() {
26
+ return new Date().toISOString();
27
+ }
28
+
29
+ export function createCvAcquisitionState({
30
+ mode = CV_ACQUISITION_MODE_UNKNOWN
31
+ } = {}) {
32
+ return {
33
+ schema_version: 1,
34
+ mode: normalizeMode(mode),
35
+ attempts: 0,
36
+ network_hits: 0,
37
+ image_fallbacks: 0,
38
+ misses: 0,
39
+ last_result: null,
40
+ history: []
41
+ };
42
+ }
43
+
44
+ export function getCvNetworkWaitPlan(state = {}, {
45
+ networkWaitMs = NETWORK_RESUME_WAIT_MS,
46
+ networkRetryWaitMs = NETWORK_RESUME_RETRY_WAIT_MS,
47
+ imageModeGraceMs = NETWORK_RESUME_IMAGE_MODE_GRACE_MS
48
+ } = {}) {
49
+ const modeBefore = normalizeMode(state?.mode);
50
+ if (modeBefore === CV_ACQUISITION_MODE_IMAGE) {
51
+ return {
52
+ schema_version: 1,
53
+ mode_before: modeBefore,
54
+ reason: "previous_image_mode_short_network_grace",
55
+ initial_wait_ms: positiveNumber(imageModeGraceMs, NETWORK_RESUME_IMAGE_MODE_GRACE_MS),
56
+ retry_wait_ms: 0
57
+ };
58
+ }
59
+
60
+ return {
61
+ schema_version: 1,
62
+ mode_before: modeBefore,
63
+ reason: "network_primary_full_wait",
64
+ initial_wait_ms: positiveNumber(networkWaitMs, NETWORK_RESUME_WAIT_MS),
65
+ retry_wait_ms: positiveNumber(networkRetryWaitMs, NETWORK_RESUME_RETRY_WAIT_MS)
66
+ };
67
+ }
68
+
69
+ export async function waitForCvNetworkEvents(waitForNetworkEvents, recorder, {
70
+ waitPlan = getCvNetworkWaitPlan(),
71
+ minCount = 1,
72
+ requireLoaded = true,
73
+ intervalMs = 120
74
+ } = {}) {
75
+ if (typeof waitForNetworkEvents !== "function") {
76
+ throw new Error("waitForCvNetworkEvents requires a domain wait function");
77
+ }
78
+ const started = Date.now();
79
+ const stages = [];
80
+
81
+ const initial = await waitForNetworkEvents(recorder, {
82
+ minCount,
83
+ requireLoaded,
84
+ timeoutMs: waitPlan.initial_wait_ms,
85
+ intervalMs
86
+ });
87
+ stages.push({
88
+ stage: "initial",
89
+ ...compactNetworkWait(initial)
90
+ });
91
+
92
+ if (!initial.ok && waitPlan.retry_wait_ms > 0) {
93
+ const retry = await waitForNetworkEvents(recorder, {
94
+ minCount,
95
+ requireLoaded,
96
+ timeoutMs: waitPlan.retry_wait_ms,
97
+ intervalMs
98
+ });
99
+ stages.push({
100
+ stage: "retry",
101
+ ...compactNetworkWait(retry)
102
+ });
103
+ }
104
+
105
+ const last = stages[stages.length - 1] || {};
106
+ return {
107
+ ok: stages.some((stage) => stage.ok),
108
+ elapsed_ms: Date.now() - started,
109
+ count: Math.max(...stages.map((stage) => Number(stage.count) || 0), 0),
110
+ total_event_count: last.total_event_count ?? last.count ?? 0,
111
+ wait_plan: waitPlan,
112
+ stages
113
+ };
114
+ }
115
+
116
+ export function countParsedNetworkProfiles(detailResult = {}) {
117
+ return (detailResult?.parsed_network_profiles || []).filter((item) => item?.ok).length;
118
+ }
119
+
120
+ export function hasParsedNetworkProfile(detailResult = {}) {
121
+ return countParsedNetworkProfiles(detailResult) > 0;
122
+ }
123
+
124
+ export function summarizeImageEvidence(imageEvidence = null) {
125
+ if (!imageEvidence) return null;
126
+ return {
127
+ source: imageEvidence.source || "",
128
+ screenshot_count: imageEvidence.screenshot_count || 0,
129
+ unique_screenshot_count: imageEvidence.unique_screenshot_count || 0,
130
+ file_paths: imageEvidence.file_paths || [],
131
+ first_clip: imageEvidence.screenshots?.[0]?.clip || imageEvidence.clip || null
132
+ };
133
+ }
134
+
135
+ export function recordCvNetworkHit(state, {
136
+ reason = "parsed_network_profile",
137
+ parsedNetworkProfileCount = 0,
138
+ waitResult = null
139
+ } = {}) {
140
+ return recordCvAcquisitionResult(state, {
141
+ source: CV_ACQUISITION_MODE_NETWORK,
142
+ reason,
143
+ parsed_network_profile_count: parsedNetworkProfileCount,
144
+ wait_result: waitResult
145
+ });
146
+ }
147
+
148
+ export function recordCvImageFallback(state, {
149
+ reason = "network_miss_image_fallback",
150
+ parsedNetworkProfileCount = 0,
151
+ waitResult = null,
152
+ imageEvidence = null
153
+ } = {}) {
154
+ return recordCvAcquisitionResult(state, {
155
+ source: CV_ACQUISITION_MODE_IMAGE,
156
+ reason,
157
+ parsed_network_profile_count: parsedNetworkProfileCount,
158
+ wait_result: waitResult,
159
+ image_evidence: summarizeImageEvidence(imageEvidence)
160
+ });
161
+ }
162
+
163
+ export function recordCvNetworkMiss(state, {
164
+ reason = "network_miss",
165
+ parsedNetworkProfileCount = 0,
166
+ waitResult = null
167
+ } = {}) {
168
+ return recordCvAcquisitionResult(state, {
169
+ source: "miss",
170
+ reason,
171
+ parsed_network_profile_count: parsedNetworkProfileCount,
172
+ wait_result: waitResult
173
+ });
174
+ }
175
+
176
+ export function compactCvAcquisitionState(state = {}) {
177
+ return {
178
+ mode: normalizeMode(state.mode),
179
+ attempts: Number(state.attempts) || 0,
180
+ network_hits: Number(state.network_hits) || 0,
181
+ image_fallbacks: Number(state.image_fallbacks) || 0,
182
+ misses: Number(state.misses) || 0,
183
+ last_result: state.last_result || null
184
+ };
185
+ }
186
+
187
+ function recordCvAcquisitionResult(state, result) {
188
+ if (!state || typeof state !== "object") {
189
+ throw new Error("CV acquisition state is required");
190
+ }
191
+ const recorded = {
192
+ schema_version: 1,
193
+ recorded_at: nowIso(),
194
+ ...result
195
+ };
196
+ state.attempts = (Number(state.attempts) || 0) + 1;
197
+ if (result.source === CV_ACQUISITION_MODE_NETWORK) {
198
+ state.mode = CV_ACQUISITION_MODE_NETWORK;
199
+ state.network_hits = (Number(state.network_hits) || 0) + 1;
200
+ } else if (result.source === CV_ACQUISITION_MODE_IMAGE) {
201
+ state.mode = CV_ACQUISITION_MODE_IMAGE;
202
+ state.image_fallbacks = (Number(state.image_fallbacks) || 0) + 1;
203
+ } else {
204
+ state.misses = (Number(state.misses) || 0) + 1;
205
+ }
206
+ state.last_result = recorded;
207
+ if (!Array.isArray(state.history)) state.history = [];
208
+ state.history.push(recorded);
209
+ return compactCvAcquisitionState(state);
210
+ }
211
+
212
+ function compactNetworkWait(waitResult = {}) {
213
+ return {
214
+ ok: Boolean(waitResult?.ok),
215
+ elapsed_ms: waitResult?.elapsed_ms || 0,
216
+ count: waitResult?.count || 0,
217
+ total_event_count: waitResult?.total_event_count ?? waitResult?.events?.length ?? 0
218
+ };
219
+ }
@@ -0,0 +1,54 @@
1
+ import { normalizeText } from "../screening/index.js";
2
+
3
+ export const GREET_CREDITS_EXHAUSTED_CODE = "GREET_CREDITS_EXHAUSTED";
4
+
5
+ function coerceQuota(quota) {
6
+ if (!quota || typeof quota !== "object") return null;
7
+ return {
8
+ found: Boolean(quota.found),
9
+ text: normalizeText(quota.text),
10
+ numerator: Number.isFinite(Number(quota.numerator)) ? Number(quota.numerator) : null,
11
+ denominator: Number.isFinite(Number(quota.denominator)) ? Number(quota.denominator) : null,
12
+ exhausted: Boolean(quota.exhausted)
13
+ };
14
+ }
15
+
16
+ export function parseGreetQuota(label = "") {
17
+ const text = normalizeText(label);
18
+ const match = text.match(/立即沟通\s*[\((]\s*(\d+)\s*[//]\s*(\d+)\s*[\))]/);
19
+ if (!match) {
20
+ return {
21
+ found: false,
22
+ text,
23
+ numerator: null,
24
+ denominator: null,
25
+ exhausted: false
26
+ };
27
+ }
28
+ const numerator = Number(match[1]);
29
+ const denominator = Number(match[2]);
30
+ return {
31
+ found: true,
32
+ text,
33
+ numerator,
34
+ denominator,
35
+ exhausted: numerator > denominator
36
+ };
37
+ }
38
+
39
+ export function normalizeGreetQuotaSource(source = "") {
40
+ return coerceQuota(source) || parseGreetQuota(source);
41
+ }
42
+
43
+ export function assertGreetQuotaAvailable(source = "") {
44
+ const quota = normalizeGreetQuotaSource(source);
45
+ if (quota.exhausted) {
46
+ const error = new Error(
47
+ `Greet credits exhausted according to Boss quota text: ${quota.numerator}/${quota.denominator}`
48
+ );
49
+ error.code = GREET_CREDITS_EXHAUSTED_CODE;
50
+ error.greet_quota = quota;
51
+ throw error;
52
+ }
53
+ return quota;
54
+ }