@reconcrap/boss-recommend-mcp 1.3.39 → 2.0.0

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 (85) hide show
  1. package/README.md +53 -33
  2. package/package.json +61 -9
  3. package/skills/boss-recommend-pipeline/SKILL.md +4 -0
  4. package/src/chat-mcp.js +1333 -0
  5. package/src/chat-runtime-config.js +559 -0
  6. package/src/cli.js +1095 -196
  7. package/src/core/browser/index.js +378 -0
  8. package/src/core/capture/index.js +298 -0
  9. package/src/core/cv-acquisition/index.js +219 -0
  10. package/src/core/greet-quota/index.js +54 -0
  11. package/src/core/infinite-list/index.js +459 -0
  12. package/src/core/reporting/legacy-csv.js +332 -0
  13. package/src/core/run/index.js +286 -0
  14. package/src/core/screening/index.js +1166 -0
  15. package/src/core/self-heal/index.js +848 -0
  16. package/src/domains/chat/cards.js +129 -0
  17. package/src/domains/chat/constants.js +183 -0
  18. package/src/domains/chat/detail.js +1369 -0
  19. package/src/domains/chat/index.js +7 -0
  20. package/src/domains/chat/jobs.js +334 -0
  21. package/src/domains/chat/page-guard.js +88 -0
  22. package/src/domains/chat/roots.js +56 -0
  23. package/src/domains/chat/run-service.js +1101 -0
  24. package/src/domains/recommend/actions.js +457 -0
  25. package/src/domains/recommend/cards.js +228 -0
  26. package/src/domains/recommend/constants.js +141 -0
  27. package/src/domains/recommend/detail.js +341 -0
  28. package/src/domains/recommend/filters.js +581 -0
  29. package/src/domains/recommend/index.js +10 -0
  30. package/src/domains/recommend/jobs.js +232 -0
  31. package/src/domains/recommend/refresh.js +204 -0
  32. package/src/domains/recommend/roots.js +78 -0
  33. package/src/domains/recommend/run-service.js +903 -0
  34. package/src/domains/recommend/scopes.js +245 -0
  35. package/src/domains/recruit/actions.js +277 -0
  36. package/src/domains/recruit/cards.js +67 -0
  37. package/src/domains/recruit/constants.js +130 -0
  38. package/src/domains/recruit/detail.js +414 -0
  39. package/src/domains/recruit/index.js +9 -0
  40. package/src/domains/recruit/instruction-parser.js +451 -0
  41. package/src/domains/recruit/refresh.js +40 -0
  42. package/src/domains/recruit/roots.js +68 -0
  43. package/src/domains/recruit/run-service.js +580 -0
  44. package/src/domains/recruit/search.js +1149 -0
  45. package/src/index.js +578 -419
  46. package/src/recommend-mcp.js +1257 -0
  47. package/src/recruit-mcp.js +1035 -0
  48. package/src/adapters.js +0 -3079
  49. package/src/boss-chat.js +0 -1037
  50. package/src/pipeline.js +0 -2249
  51. package/src/recommend-healing-config.js +0 -131
  52. package/src/recommend-healing-rules.json +0 -261
  53. package/src/self-heal.js +0 -2237
  54. package/src/test-adapters-runtime.js +0 -628
  55. package/src/test-boss-chat.js +0 -3196
  56. package/src/test-index-async.js +0 -498
  57. package/src/test-parser.js +0 -742
  58. package/src/test-pipeline.js +0 -2703
  59. package/src/test-run-state.js +0 -152
  60. package/src/test-self-heal.js +0 -224
  61. package/vendor/boss-chat-cli/README.md +0 -134
  62. package/vendor/boss-chat-cli/package.json +0 -53
  63. package/vendor/boss-chat-cli/src/app.js +0 -1501
  64. package/vendor/boss-chat-cli/src/browser/chat-page.js +0 -3562
  65. package/vendor/boss-chat-cli/src/cli.js +0 -1713
  66. package/vendor/boss-chat-cli/src/mcp/server.js +0 -149
  67. package/vendor/boss-chat-cli/src/mcp/tool-runtime.js +0 -193
  68. package/vendor/boss-chat-cli/src/runtime/async-run-state.js +0 -260
  69. package/vendor/boss-chat-cli/src/runtime/interaction.js +0 -102
  70. package/vendor/boss-chat-cli/src/runtime/run-control.js +0 -102
  71. package/vendor/boss-chat-cli/src/services/chrome-client.js +0 -107
  72. package/vendor/boss-chat-cli/src/services/llm.js +0 -1292
  73. package/vendor/boss-chat-cli/src/services/llm.test.js +0 -326
  74. package/vendor/boss-chat-cli/src/services/profile-store.js +0 -173
  75. package/vendor/boss-chat-cli/src/services/report-store.js +0 -317
  76. package/vendor/boss-chat-cli/src/services/resume-capture.js +0 -469
  77. package/vendor/boss-chat-cli/src/services/resume-network.js +0 -727
  78. package/vendor/boss-chat-cli/src/services/state-store.js +0 -90
  79. package/vendor/boss-chat-cli/src/utils/customer-key.js +0 -82
  80. package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +0 -7072
  81. package/vendor/boss-recommend-screen-cli/scripts/capture-full-resume-canvas.cjs +0 -817
  82. package/vendor/boss-recommend-screen-cli/scripts/stitch_resume_chunks.py +0 -141
  83. package/vendor/boss-recommend-screen-cli/test-recoverable-resume-failures.cjs +0 -2423
  84. package/vendor/boss-recommend-search-cli/src/cli.js +0 -1698
  85. 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
+ }