@reconcrap/boss-recommend-mcp 2.1.19 → 2.1.20
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/package.json +1 -1
- package/src/recommend-mcp.js +253 -105
- package/src/recommend-scheduler.js +15 -1
package/package.json
CHANGED
package/src/recommend-mcp.js
CHANGED
|
@@ -54,6 +54,7 @@ import { DEFAULT_MAX_IMAGE_PAGES } from "./core/cv-acquisition/index.js";
|
|
|
54
54
|
const DEFAULT_RECOMMEND_HOST = "127.0.0.1";
|
|
55
55
|
const DEFAULT_RECOMMEND_PORT = 9222;
|
|
56
56
|
const DEFAULT_RECOMMEND_POLL_AFTER_SEC = 10;
|
|
57
|
+
const STATUS_METHOD_LOG_TAIL_LIMIT = 25;
|
|
57
58
|
const TARGET_COUNT_SEMANTICS = "target_count means candidates that pass screening; scan continues until that many candidates pass or the list ends";
|
|
58
59
|
const RUN_MODE_ASYNC = "async";
|
|
59
60
|
const REST_LEVEL_OPTIONS = ["low", "medium", "high"];
|
|
@@ -302,15 +303,23 @@ function resolveRecommendDetailLimit(args = {}, normalized = {}) {
|
|
|
302
303
|
return requested;
|
|
303
304
|
}
|
|
304
305
|
|
|
305
|
-
function methodSummary(methodLog = []) {
|
|
306
|
+
function methodSummary(methodLog = []) {
|
|
306
307
|
const summary = {};
|
|
307
308
|
for (const entry of methodLog || []) {
|
|
308
309
|
summary[entry.method] = (summary[entry.method] || 0) + 1;
|
|
309
310
|
}
|
|
310
|
-
return summary;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function
|
|
311
|
+
return summary;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function compactMethodLogForStatus(methodLog = []) {
|
|
315
|
+
if (!Array.isArray(methodLog)) return [];
|
|
316
|
+
return methodLog.slice(-STATUS_METHOD_LOG_TAIL_LIMIT).map((entry) => ({
|
|
317
|
+
method: normalizeText(entry?.method || entry || ""),
|
|
318
|
+
at: normalizeText(entry?.at || "")
|
|
319
|
+
}));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function clonePlain(value, fallback = null) {
|
|
314
323
|
try {
|
|
315
324
|
return value === undefined ? fallback : JSON.parse(JSON.stringify(value));
|
|
316
325
|
} catch {
|
|
@@ -477,7 +486,7 @@ function secondsBetween(startedAt, endedAt) {
|
|
|
477
486
|
return Math.max(1, Math.round((endMs - startMs) / 1000));
|
|
478
487
|
}
|
|
479
488
|
|
|
480
|
-
function normalizeLegacyProgress(progress = {}, summary = null) {
|
|
489
|
+
function normalizeLegacyProgress(progress = {}, summary = null) {
|
|
481
490
|
const processed = Number.isInteger(progress.processed)
|
|
482
491
|
? progress.processed
|
|
483
492
|
: Number.isInteger(summary?.processed)
|
|
@@ -502,12 +511,146 @@ function normalizeLegacyProgress(progress = {}, summary = null) {
|
|
|
502
511
|
skipped: Number.isInteger(progress.skipped) ? progress.skipped : Math.max(processed - passed, 0),
|
|
503
512
|
greet_count: Number.isInteger(progress.greet_count) ? progress.greet_count : 0,
|
|
504
513
|
post_action_clicked: Number.isInteger(progress.post_action_clicked) ? progress.post_action_clicked : 0
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
const STATUS_COUNT_KEYS = [
|
|
518
|
+
"processed",
|
|
519
|
+
"screened",
|
|
520
|
+
"detail_opened",
|
|
521
|
+
"passed",
|
|
522
|
+
"skipped",
|
|
523
|
+
"llm_screened",
|
|
524
|
+
"greet_count",
|
|
525
|
+
"post_action_clicked",
|
|
526
|
+
"image_capture_failed",
|
|
527
|
+
"detail_open_failed",
|
|
528
|
+
"transient_recovered",
|
|
529
|
+
"colleague_contact_checked",
|
|
530
|
+
"recent_colleague_contact_skipped",
|
|
531
|
+
"colleague_contact_panel_missing",
|
|
532
|
+
"context_recoveries",
|
|
533
|
+
"human_rest_count",
|
|
534
|
+
"human_rest_ms",
|
|
535
|
+
"card_count",
|
|
536
|
+
"refresh_rounds"
|
|
537
|
+
];
|
|
538
|
+
|
|
539
|
+
function compactPositiveInteger(value, fallback = null) {
|
|
540
|
+
return Number.isInteger(value) && value >= 0 ? value : fallback;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function compactSmallRecord(value, fallback = null) {
|
|
544
|
+
const record = plainRecord(value);
|
|
545
|
+
if (!Object.keys(record).length) return fallback;
|
|
546
|
+
return clonePlain(record, fallback);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function compactRecommendSummaryForStatus(summary) {
|
|
550
|
+
if (!summary || typeof summary !== "object" || Array.isArray(summary)) return null;
|
|
551
|
+
const compact = {
|
|
552
|
+
domain: normalizeText(summary.domain || "recommend") || "recommend"
|
|
553
|
+
};
|
|
554
|
+
for (const key of STATUS_COUNT_KEYS) {
|
|
555
|
+
if (Number.isInteger(summary[key])) compact[key] = summary[key];
|
|
556
|
+
}
|
|
557
|
+
if (summary.target_url) compact.target_url = normalizeText(summary.target_url);
|
|
558
|
+
if (summary.list_end_reason) compact.list_end_reason = normalizeText(summary.list_end_reason);
|
|
559
|
+
if (Array.isArray(summary.results)) {
|
|
560
|
+
compact.results_count = summary.results.length;
|
|
561
|
+
} else if (Number.isInteger(summary.results_count)) {
|
|
562
|
+
compact.results_count = summary.results_count;
|
|
563
|
+
}
|
|
564
|
+
if (Array.isArray(summary.refresh_attempts)) {
|
|
565
|
+
compact.refresh_attempt_count = summary.refresh_attempts.length;
|
|
566
|
+
}
|
|
567
|
+
if (Array.isArray(summary.context_recoveries)) {
|
|
568
|
+
compact.context_recovery_count = summary.context_recoveries.length;
|
|
569
|
+
} else if (Number.isInteger(summary.context_recoveries)) {
|
|
570
|
+
compact.context_recoveries = summary.context_recoveries;
|
|
571
|
+
}
|
|
572
|
+
if (summary.job_selection) compact.job_selection = compactSmallRecord(summary.job_selection);
|
|
573
|
+
if (summary.page_scope) compact.page_scope = compactSmallRecord(summary.page_scope);
|
|
574
|
+
if (summary.filter) compact.filter = compactSmallRecord(summary.filter);
|
|
575
|
+
if (summary.candidate_list) {
|
|
576
|
+
const candidateList = plainRecord(summary.candidate_list);
|
|
577
|
+
compact.candidate_list = {
|
|
578
|
+
total_count: compactPositiveInteger(candidateList.total_count ?? candidateList.card_count, null),
|
|
579
|
+
visible_count: compactPositiveInteger(candidateList.visible_count, null),
|
|
580
|
+
list_end_reason: normalizeText(candidateList.list_end_reason || "")
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
if (summary.viewport_health?.stats) {
|
|
584
|
+
compact.viewport_health = {
|
|
585
|
+
stats: clonePlain(summary.viewport_health.stats, {})
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
if (summary.human_behavior) {
|
|
589
|
+
compact.human_behavior = {
|
|
590
|
+
enabled: summary.human_behavior.enabled === true,
|
|
591
|
+
profile: normalizeText(summary.human_behavior.profile || ""),
|
|
592
|
+
restLevel: normalizeText(summary.human_behavior.restLevel || summary.human_behavior.rest_level || "")
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
if (summary.human_rest) {
|
|
596
|
+
const humanRest = plainRecord(summary.human_rest);
|
|
597
|
+
compact.human_rest = {
|
|
598
|
+
enabled: humanRest.enabled === true,
|
|
599
|
+
restLevel: normalizeText(humanRest.restLevel || humanRest.rest_level || ""),
|
|
600
|
+
rest_count: compactPositiveInteger(humanRest.rest_count ?? humanRest.count, null),
|
|
601
|
+
total_pause_ms: compactPositiveInteger(humanRest.total_pause_ms ?? humanRest.pause_ms, null)
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
return compact;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
function compactRecommendCheckpointForStatus(checkpoint) {
|
|
608
|
+
if (!checkpoint || typeof checkpoint !== "object" || Array.isArray(checkpoint)) return {};
|
|
609
|
+
const compact = {};
|
|
610
|
+
if (checkpoint.updatedAt || checkpoint.updated_at) {
|
|
611
|
+
compact.updatedAt = normalizeText(checkpoint.updatedAt || checkpoint.updated_at);
|
|
612
|
+
}
|
|
613
|
+
if (Array.isArray(checkpoint.results)) {
|
|
614
|
+
compact.results_count = checkpoint.results.length;
|
|
615
|
+
} else if (Number.isInteger(checkpoint.results_count)) {
|
|
616
|
+
compact.results_count = checkpoint.results_count;
|
|
617
|
+
}
|
|
618
|
+
for (const key of STATUS_COUNT_KEYS) {
|
|
619
|
+
if (Number.isInteger(checkpoint[key])) compact[key] = checkpoint[key];
|
|
620
|
+
}
|
|
621
|
+
return compact;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function compactRecommendResultForStatus(result) {
|
|
625
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return result || null;
|
|
626
|
+
const compact = {
|
|
627
|
+
...result
|
|
628
|
+
};
|
|
629
|
+
if (Array.isArray(result.results)) {
|
|
630
|
+
compact.results_count = result.results.length;
|
|
631
|
+
compact.results_available = result.results.length > 0;
|
|
632
|
+
} else if (Number.isInteger(result.results_count)) {
|
|
633
|
+
compact.results_count = result.results_count;
|
|
634
|
+
compact.results_available = result.results_available === true || result.results_count > 0;
|
|
635
|
+
}
|
|
636
|
+
delete compact.results;
|
|
637
|
+
return compact;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
export function compactRecommendRunForStatus(run) {
|
|
641
|
+
if (!run || typeof run !== "object" || Array.isArray(run)) return run || null;
|
|
642
|
+
const compact = {
|
|
643
|
+
...run
|
|
644
|
+
};
|
|
645
|
+
if (compact.result) compact.result = compactRecommendResultForStatus(compact.result);
|
|
646
|
+
if (compact.summary) compact.summary = compactRecommendSummaryForStatus(compact.summary);
|
|
647
|
+
if (compact.checkpoint) compact.checkpoint = compactRecommendCheckpointForStatus(compact.checkpoint);
|
|
648
|
+
return compact;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function completionReason(status) {
|
|
652
|
+
if (status === RUN_STATUS_COMPLETED) return "completed";
|
|
653
|
+
if (status === RUN_STATUS_CANCELED) return "canceled_by_user";
|
|
511
654
|
if (status === RUN_STATUS_FAILED) return "failed";
|
|
512
655
|
if (status === RUN_STATUS_PAUSED) return "paused";
|
|
513
656
|
return null;
|
|
@@ -685,13 +828,14 @@ function buildLegacyRecommendResult(snapshot) {
|
|
|
685
828
|
effective_scope: meta.normalized?.pageScope || meta.parsed?.page_scope || "recommend"
|
|
686
829
|
},
|
|
687
830
|
search_params: clonePlain(meta.parsed?.searchParams || {}, {}),
|
|
688
|
-
screen_params: clonePlain(meta.parsed?.screenParams || {}, {}),
|
|
689
|
-
target_count_semantics: TARGET_COUNT_SEMANTICS,
|
|
690
|
-
error: snapshot.error || null,
|
|
691
|
-
recovery: buildConstrainedAgentRecovery(snapshot, meta, artifacts),
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
}
|
|
831
|
+
screen_params: clonePlain(meta.parsed?.screenParams || {}, {}),
|
|
832
|
+
target_count_semantics: TARGET_COUNT_SEMANTICS,
|
|
833
|
+
error: snapshot.error || null,
|
|
834
|
+
recovery: buildConstrainedAgentRecovery(snapshot, meta, artifacts),
|
|
835
|
+
results_count: resultRows.length,
|
|
836
|
+
results_available: resultRows.length > 0
|
|
837
|
+
};
|
|
838
|
+
}
|
|
695
839
|
|
|
696
840
|
function normalizeRunSnapshot(snapshot) {
|
|
697
841
|
if (!snapshot) return null;
|
|
@@ -714,10 +858,12 @@ function normalizeRunSnapshot(snapshot) {
|
|
|
714
858
|
follow_up: clonePlain(metaArgs.follow_up ?? snapshotContext.follow_up ?? null, null),
|
|
715
859
|
target_count_semantics: TARGET_COUNT_SEMANTICS
|
|
716
860
|
};
|
|
717
|
-
return {
|
|
718
|
-
...snapshot,
|
|
719
|
-
|
|
720
|
-
|
|
861
|
+
return {
|
|
862
|
+
...snapshot,
|
|
863
|
+
checkpoint: compactRecommendCheckpointForStatus(snapshot.checkpoint),
|
|
864
|
+
summary: compactRecommendSummaryForStatus(summary),
|
|
865
|
+
progress,
|
|
866
|
+
run_id: snapshot.runId,
|
|
721
867
|
mode: RUN_MODE_ASYNC,
|
|
722
868
|
state: snapshot.status,
|
|
723
869
|
stage: snapshot.phase,
|
|
@@ -874,7 +1020,7 @@ function persistRecommendRunSnapshot(snapshot, {
|
|
|
874
1020
|
normalized.control = mergePersistedControlRequest(normalized, existing);
|
|
875
1021
|
normalized = coerceCanceledTerminalSnapshot(normalized, existing);
|
|
876
1022
|
if (persistActiveCheckpoint) {
|
|
877
|
-
persistRecommendCheckpointSnapshot(
|
|
1023
|
+
persistRecommendCheckpointSnapshot(snapshot);
|
|
878
1024
|
}
|
|
879
1025
|
const payload = {
|
|
880
1026
|
run_id: normalized.run_id,
|
|
@@ -970,17 +1116,19 @@ function persistRecommendLifecycleSnapshot(snapshot, event = {}) {
|
|
|
970
1116
|
});
|
|
971
1117
|
}
|
|
972
1118
|
|
|
973
|
-
function attachMethodEvidence(payload, runId) {
|
|
974
|
-
const meta = getRecommendRunMeta(runId);
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1119
|
+
function attachMethodEvidence(payload, runId) {
|
|
1120
|
+
const meta = getRecommendRunMeta(runId);
|
|
1121
|
+
const methodLog = meta.methodLog || [];
|
|
1122
|
+
assertNoForbiddenCdpCalls(methodLog);
|
|
1123
|
+
return {
|
|
1124
|
+
...payload,
|
|
1125
|
+
runtime_evaluate_used: false,
|
|
1126
|
+
method_summary: methodSummary(methodLog),
|
|
1127
|
+
method_log: compactMethodLogForStatus(methodLog),
|
|
1128
|
+
method_log_total: Array.isArray(methodLog) ? methodLog.length : 0,
|
|
1129
|
+
chrome: meta.chrome || null
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
984
1132
|
|
|
985
1133
|
function compactRecommendJobListOption(option, index) {
|
|
986
1134
|
const label = normalizeText(option?.label);
|
|
@@ -1945,19 +2093,19 @@ export function getRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
1945
2093
|
};
|
|
1946
2094
|
}
|
|
1947
2095
|
try {
|
|
1948
|
-
const run = recommendRunService.getRecommendRun(runId);
|
|
1949
|
-
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
1950
|
-
return attachMethodEvidence({
|
|
1951
|
-
status: "RUN_STATUS",
|
|
1952
|
-
run: normalizedRun
|
|
1953
|
-
}, runId);
|
|
1954
|
-
} catch {
|
|
1955
|
-
const persisted = readRecommendRunState(runId);
|
|
1956
|
-
if (persisted) {
|
|
1957
|
-
const reconciled = reconcilePersistedRecommendRunIfNeeded(persisted);
|
|
1958
|
-
return {
|
|
1959
|
-
status: "RUN_STATUS",
|
|
1960
|
-
run: reconciled,
|
|
2096
|
+
const run = recommendRunService.getRecommendRun(runId);
|
|
2097
|
+
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2098
|
+
return attachMethodEvidence({
|
|
2099
|
+
status: "RUN_STATUS",
|
|
2100
|
+
run: compactRecommendRunForStatus(normalizedRun)
|
|
2101
|
+
}, runId);
|
|
2102
|
+
} catch {
|
|
2103
|
+
const persisted = readRecommendRunState(runId);
|
|
2104
|
+
if (persisted) {
|
|
2105
|
+
const reconciled = compactRecommendRunForStatus(reconcilePersistedRecommendRunIfNeeded(persisted));
|
|
2106
|
+
return {
|
|
2107
|
+
status: "RUN_STATUS",
|
|
2108
|
+
run: reconciled,
|
|
1961
2109
|
persistence: {
|
|
1962
2110
|
source: "disk",
|
|
1963
2111
|
active_control_available: false,
|
|
@@ -1985,36 +2133,36 @@ export function pauseRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
1985
2133
|
try {
|
|
1986
2134
|
const before = recommendRunService.getRecommendRun(runId);
|
|
1987
2135
|
if (TERMINAL_STATUSES.has(before.status)) {
|
|
1988
|
-
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
1989
|
-
return attachMethodEvidence({
|
|
1990
|
-
status: "PAUSE_IGNORED",
|
|
1991
|
-
run: normalizedBefore,
|
|
1992
|
-
message: "目标任务已结束,无需暂停。"
|
|
1993
|
-
}, runId);
|
|
2136
|
+
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2137
|
+
return attachMethodEvidence({
|
|
2138
|
+
status: "PAUSE_IGNORED",
|
|
2139
|
+
run: compactRecommendRunForStatus(normalizedBefore),
|
|
2140
|
+
message: "目标任务已结束,无需暂停。"
|
|
2141
|
+
}, runId);
|
|
1994
2142
|
}
|
|
1995
2143
|
if (before.status === RUN_STATUS_PAUSED) {
|
|
1996
|
-
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
1997
|
-
return attachMethodEvidence({
|
|
1998
|
-
status: "PAUSE_IGNORED",
|
|
1999
|
-
run: normalizedBefore,
|
|
2000
|
-
message: "目标任务已经处于 paused 状态。"
|
|
2001
|
-
}, runId);
|
|
2144
|
+
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2145
|
+
return attachMethodEvidence({
|
|
2146
|
+
status: "PAUSE_IGNORED",
|
|
2147
|
+
run: compactRecommendRunForStatus(normalizedBefore),
|
|
2148
|
+
message: "目标任务已经处于 paused 状态。"
|
|
2149
|
+
}, runId);
|
|
2002
2150
|
}
|
|
2003
2151
|
const run = recommendRunService.pauseRecommendRun(runId);
|
|
2004
|
-
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2005
|
-
return attachMethodEvidence({
|
|
2006
|
-
status: "PAUSE_REQUESTED",
|
|
2007
|
-
run: normalizedRun,
|
|
2008
|
-
message: "暂停请求已接收,将在当前候选人处理完成后进入 paused。"
|
|
2009
|
-
}, runId);
|
|
2152
|
+
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2153
|
+
return attachMethodEvidence({
|
|
2154
|
+
status: "PAUSE_REQUESTED",
|
|
2155
|
+
run: compactRecommendRunForStatus(normalizedRun),
|
|
2156
|
+
message: "暂停请求已接收,将在当前候选人处理完成后进入 paused。"
|
|
2157
|
+
}, runId);
|
|
2010
2158
|
} catch {
|
|
2011
2159
|
const persisted = readRecommendRunState(runId);
|
|
2012
2160
|
if (persisted && TERMINAL_STATUSES.has(persisted.state)) {
|
|
2013
|
-
return {
|
|
2014
|
-
status: "PAUSE_IGNORED",
|
|
2015
|
-
run: persisted,
|
|
2016
|
-
message: "目标任务已结束,无需暂停。",
|
|
2017
|
-
runtime_evaluate_used: false,
|
|
2161
|
+
return {
|
|
2162
|
+
status: "PAUSE_IGNORED",
|
|
2163
|
+
run: compactRecommendRunForStatus(persisted),
|
|
2164
|
+
message: "目标任务已结束,无需暂停。",
|
|
2165
|
+
runtime_evaluate_used: false,
|
|
2018
2166
|
method_summary: {},
|
|
2019
2167
|
method_log: [],
|
|
2020
2168
|
chrome: null
|
|
@@ -2029,28 +2177,28 @@ export function resumeRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
2029
2177
|
try {
|
|
2030
2178
|
const before = recommendRunService.getRecommendRun(runId);
|
|
2031
2179
|
if (TERMINAL_STATUSES.has(before.status)) {
|
|
2032
|
-
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2033
|
-
return attachMethodEvidence({
|
|
2034
|
-
status: "FAILED",
|
|
2180
|
+
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2181
|
+
return attachMethodEvidence({
|
|
2182
|
+
status: "FAILED",
|
|
2035
2183
|
error: {
|
|
2036
2184
|
code: "RUN_ALREADY_TERMINATED",
|
|
2037
2185
|
message: "目标任务已结束,无法继续。",
|
|
2038
2186
|
retryable: false
|
|
2039
2187
|
},
|
|
2040
|
-
run: normalizedBefore
|
|
2041
|
-
}, runId);
|
|
2188
|
+
run: compactRecommendRunForStatus(normalizedBefore)
|
|
2189
|
+
}, runId);
|
|
2042
2190
|
}
|
|
2043
2191
|
if (before.status !== RUN_STATUS_PAUSED) {
|
|
2044
|
-
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2045
|
-
return attachMethodEvidence({
|
|
2046
|
-
status: "FAILED",
|
|
2192
|
+
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2193
|
+
return attachMethodEvidence({
|
|
2194
|
+
status: "FAILED",
|
|
2047
2195
|
error: {
|
|
2048
2196
|
code: "RUN_NOT_PAUSED",
|
|
2049
2197
|
message: "仅 paused 状态的 run 才能继续。",
|
|
2050
2198
|
retryable: true
|
|
2051
2199
|
},
|
|
2052
|
-
run: normalizedBefore
|
|
2053
|
-
}, runId);
|
|
2200
|
+
run: compactRecommendRunForStatus(normalizedBefore)
|
|
2201
|
+
}, runId);
|
|
2054
2202
|
}
|
|
2055
2203
|
const run = recommendRunService.resumeRecommendRun(runId);
|
|
2056
2204
|
const meta = getRecommendRunMeta(runId);
|
|
@@ -2058,12 +2206,12 @@ export function resumeRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
2058
2206
|
meta.resumeCount = (meta.resumeCount || 0) + 1;
|
|
2059
2207
|
meta.lastResumedAt = new Date().toISOString();
|
|
2060
2208
|
}
|
|
2061
|
-
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2062
|
-
return attachMethodEvidence({
|
|
2063
|
-
status: "RESUME_REQUESTED",
|
|
2064
|
-
run: normalizedRun,
|
|
2065
|
-
poll_after_sec: DEFAULT_RECOMMEND_POLL_AFTER_SEC,
|
|
2066
|
-
message: "已恢复 Recommend run,请使用 get_recommend_pipeline_run 按需轮询。"
|
|
2209
|
+
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2210
|
+
return attachMethodEvidence({
|
|
2211
|
+
status: "RESUME_REQUESTED",
|
|
2212
|
+
run: compactRecommendRunForStatus(normalizedRun),
|
|
2213
|
+
poll_after_sec: DEFAULT_RECOMMEND_POLL_AFTER_SEC,
|
|
2214
|
+
message: "已恢复 Recommend run,请使用 get_recommend_pipeline_run 按需轮询。"
|
|
2067
2215
|
}, runId);
|
|
2068
2216
|
} catch {
|
|
2069
2217
|
const persisted = readRecommendRunState(runId);
|
|
@@ -2077,9 +2225,9 @@ export function resumeRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
2077
2225
|
: "该 run 只有磁盘快照,没有当前进程内的活动 CDP 会话,无法安全继续。",
|
|
2078
2226
|
retryable: !TERMINAL_STATUSES.has(persisted.state)
|
|
2079
2227
|
},
|
|
2080
|
-
run: persisted,
|
|
2081
|
-
persistence: {
|
|
2082
|
-
source: "disk",
|
|
2228
|
+
run: compactRecommendRunForStatus(persisted),
|
|
2229
|
+
persistence: {
|
|
2230
|
+
source: "disk",
|
|
2083
2231
|
active_control_available: false
|
|
2084
2232
|
},
|
|
2085
2233
|
runtime_evaluate_used: false,
|
|
@@ -2097,28 +2245,28 @@ export function cancelRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
2097
2245
|
try {
|
|
2098
2246
|
const before = recommendRunService.getRecommendRun(runId);
|
|
2099
2247
|
if (TERMINAL_STATUSES.has(before.status)) {
|
|
2100
|
-
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2101
|
-
return attachMethodEvidence({
|
|
2102
|
-
status: "CANCEL_IGNORED",
|
|
2103
|
-
run: normalizedBefore,
|
|
2104
|
-
message: "目标任务已结束,无需取消。"
|
|
2105
|
-
}, runId);
|
|
2248
|
+
const normalizedBefore = persistRecommendRunSnapshot(before);
|
|
2249
|
+
return attachMethodEvidence({
|
|
2250
|
+
status: "CANCEL_IGNORED",
|
|
2251
|
+
run: compactRecommendRunForStatus(normalizedBefore),
|
|
2252
|
+
message: "目标任务已结束,无需取消。"
|
|
2253
|
+
}, runId);
|
|
2106
2254
|
}
|
|
2107
2255
|
const run = recommendRunService.cancelRecommendRun(runId);
|
|
2108
|
-
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2109
|
-
return attachMethodEvidence({
|
|
2110
|
-
status: "CANCEL_REQUESTED",
|
|
2111
|
-
run: normalizedRun,
|
|
2112
|
-
message: "已收到取消请求,将在当前候选人处理完成后安全停止。"
|
|
2113
|
-
}, runId);
|
|
2256
|
+
const normalizedRun = persistRecommendRunSnapshot(run);
|
|
2257
|
+
return attachMethodEvidence({
|
|
2258
|
+
status: "CANCEL_REQUESTED",
|
|
2259
|
+
run: compactRecommendRunForStatus(normalizedRun),
|
|
2260
|
+
message: "已收到取消请求,将在当前候选人处理完成后安全停止。"
|
|
2261
|
+
}, runId);
|
|
2114
2262
|
} catch {
|
|
2115
2263
|
const persisted = readRecommendRunState(runId);
|
|
2116
2264
|
if (persisted && TERMINAL_STATUSES.has(persisted.state)) {
|
|
2117
2265
|
return {
|
|
2118
2266
|
status: "CANCEL_IGNORED",
|
|
2119
|
-
run: persisted,
|
|
2267
|
+
run: compactRecommendRunForStatus(persisted),
|
|
2120
2268
|
message: "目标任务已结束,无需取消。",
|
|
2121
|
-
runtime_evaluate_used: false,
|
|
2269
|
+
runtime_evaluate_used: false,
|
|
2122
2270
|
method_summary: {},
|
|
2123
2271
|
method_log: [],
|
|
2124
2272
|
chrome: null
|
|
@@ -2136,7 +2284,7 @@ export function cancelRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
2136
2284
|
if (patched) {
|
|
2137
2285
|
return {
|
|
2138
2286
|
status: "CANCEL_REQUESTED",
|
|
2139
|
-
run: patched,
|
|
2287
|
+
run: compactRecommendRunForStatus(patched),
|
|
2140
2288
|
message: cancelMessage,
|
|
2141
2289
|
persistence: {
|
|
2142
2290
|
source: "disk",
|
|
@@ -5,6 +5,7 @@ import { spawn } from "node:child_process";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { getStateHome } from "./run-state.js";
|
|
7
7
|
import {
|
|
8
|
+
compactRecommendRunForStatus,
|
|
8
9
|
getRecommendPipelineRunTool,
|
|
9
10
|
prepareRecommendPipelineRunTool,
|
|
10
11
|
startRecommendPipelineRunTool
|
|
@@ -142,6 +143,19 @@ function writeSchedule(scheduleId, patch) {
|
|
|
142
143
|
});
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
function compactScheduleForStatus(schedule) {
|
|
147
|
+
if (!schedule || typeof schedule !== "object" || Array.isArray(schedule)) return schedule || null;
|
|
148
|
+
const compact = clonePlain(schedule, schedule);
|
|
149
|
+
if (compact.run) compact.run = compactRecommendRunForStatus(compact.run);
|
|
150
|
+
if (compact.launch_payload?.run) {
|
|
151
|
+
compact.launch_payload = {
|
|
152
|
+
...compact.launch_payload,
|
|
153
|
+
run: compactRecommendRunForStatus(compact.launch_payload.run)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return compact;
|
|
157
|
+
}
|
|
158
|
+
|
|
145
159
|
function isProcessAlive(pid) {
|
|
146
160
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
147
161
|
try {
|
|
@@ -355,7 +369,7 @@ export function getRecommendScheduledRunTool({ args = {} } = {}) {
|
|
|
355
369
|
return {
|
|
356
370
|
status: "OK",
|
|
357
371
|
schedule_id: scheduleId,
|
|
358
|
-
schedule: next
|
|
372
|
+
schedule: compactScheduleForStatus(next)
|
|
359
373
|
};
|
|
360
374
|
}
|
|
361
375
|
|