@reconcrap/boss-recommend-mcp 2.0.36 → 2.0.38
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/bin/boss-recommend-mcp.js +0 -0
- package/config/screening-config.example.json +1 -1
- package/package.json +119 -119
- package/src/core/run/index.js +7 -2
- package/src/domains/recommend/detail.js +61 -18
- package/src/domains/recommend/run-service.js +4 -0
- package/src/index.js +429 -42
- package/src/recommend-mcp.js +216 -49
- package/src/run-state.js +2 -0
package/src/recommend-mcp.js
CHANGED
|
@@ -140,6 +140,15 @@ function clonePlain(value, fallback = null) {
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
function plainRecord(value) {
|
|
144
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function nonEmptyRecord(value) {
|
|
148
|
+
const record = plainRecord(value);
|
|
149
|
+
return Object.keys(record).length ? record : null;
|
|
150
|
+
}
|
|
151
|
+
|
|
143
152
|
function normalizeRunId(runId) {
|
|
144
153
|
const normalized = normalizeText(runId);
|
|
145
154
|
if (!normalized || normalized.includes("/") || normalized.includes("\\")) return "";
|
|
@@ -156,6 +165,8 @@ function getRecommendRunArtifacts(runId) {
|
|
|
156
165
|
output_dir: outputDir,
|
|
157
166
|
run_state_path: path.join(runsDir, `${normalized}.json`),
|
|
158
167
|
checkpoint_path: path.join(runsDir, `${normalized}.checkpoint.json`),
|
|
168
|
+
worker_stdout_path: path.join(runsDir, `${normalized}.worker.stdout.log`),
|
|
169
|
+
worker_stderr_path: path.join(runsDir, `${normalized}.worker.stderr.log`),
|
|
159
170
|
output_csv: path.join(outputDir, `${normalized}.results.csv`),
|
|
160
171
|
report_json: path.join(outputDir, `${normalized}.report.json`)
|
|
161
172
|
};
|
|
@@ -191,11 +202,29 @@ function recommendSearchParamsForCsv(searchParams = {}) {
|
|
|
191
202
|
};
|
|
192
203
|
}
|
|
193
204
|
|
|
194
|
-
function
|
|
205
|
+
function getSnapshotRequestContext(snapshot = {}) {
|
|
206
|
+
const context = plainRecord(snapshot?.context);
|
|
207
|
+
const shared = plainRecord(context.shared_run_context);
|
|
208
|
+
return {
|
|
209
|
+
context,
|
|
210
|
+
confirmation: nonEmptyRecord(context.confirmation) || plainRecord(shared.confirmation),
|
|
211
|
+
overrides: nonEmptyRecord(context.overrides) || plainRecord(shared.overrides),
|
|
212
|
+
followUp: context.follow_up ?? shared.follow_up ?? null,
|
|
213
|
+
shared
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function selectedRecommendJobForCsv(meta = {}, snapshot = {}) {
|
|
218
|
+
const { confirmation, overrides, shared } = getSnapshotRequestContext(snapshot);
|
|
195
219
|
const value = normalizeText(
|
|
196
220
|
meta.args?.confirmation?.job_value
|
|
197
221
|
|| meta.normalized?.job
|
|
198
222
|
|| meta.args?.overrides?.job
|
|
223
|
+
|| confirmation.job_value
|
|
224
|
+
|| overrides.job
|
|
225
|
+
|| shared.confirmation?.job_value
|
|
226
|
+
|| shared.overrides?.job
|
|
227
|
+
|| shared.job_label
|
|
199
228
|
|| ""
|
|
200
229
|
);
|
|
201
230
|
return {
|
|
@@ -206,21 +235,28 @@ function selectedRecommendJobForCsv(meta = {}) {
|
|
|
206
235
|
}
|
|
207
236
|
|
|
208
237
|
function buildRecommendCsvInputRows(snapshot = {}, meta = {}) {
|
|
209
|
-
const
|
|
210
|
-
const
|
|
238
|
+
const { context, confirmation, overrides, followUp, shared } = getSnapshotRequestContext(snapshot);
|
|
239
|
+
const searchParams = recommendSearchParamsForCsv(meta.parsed?.searchParams || {
|
|
240
|
+
school_tag: overrides.school_tag ?? confirmation.school_tag_value,
|
|
241
|
+
degree: overrides.degree ?? confirmation.degree_value,
|
|
242
|
+
gender: overrides.gender ?? confirmation.gender_value,
|
|
243
|
+
recent_not_view: overrides.recent_not_view ?? confirmation.recent_not_view_value
|
|
244
|
+
});
|
|
245
|
+
const parsedScreenParams = meta.parsed?.screenParams || {};
|
|
246
|
+
const screenParams = {
|
|
247
|
+
criteria: parsedScreenParams.criteria || meta.normalized?.criteria || overrides.criteria || "",
|
|
248
|
+
target_count: parsedScreenParams.target_count || snapshot.progress?.target_count || meta.normalized?.targetCount || overrides.target_count || confirmation.target_count_value || shared.max_candidates || "",
|
|
249
|
+
post_action: parsedScreenParams.post_action || overrides.post_action || confirmation.post_action_value || shared.post_action || "none",
|
|
250
|
+
max_greet_count: parsedScreenParams.max_greet_count ?? overrides.max_greet_count ?? confirmation.max_greet_count_value ?? shared.max_greet_count ?? ""
|
|
251
|
+
};
|
|
211
252
|
return buildLegacyScreenInputRows({
|
|
212
|
-
instruction: meta.args?.instruction || "",
|
|
253
|
+
instruction: meta.args?.instruction || context.instruction || shared.instruction || "",
|
|
213
254
|
selectedPage: "recommend",
|
|
214
|
-
selectedJob: selectedRecommendJobForCsv(meta),
|
|
255
|
+
selectedJob: selectedRecommendJobForCsv(meta, snapshot),
|
|
215
256
|
userSearchParams: cloneReportInput(searchParams, {}),
|
|
216
257
|
effectiveSearchParams: cloneReportInput(searchParams, {}),
|
|
217
|
-
screenParams
|
|
218
|
-
|
|
219
|
-
target_count: screenParams.target_count || snapshot.progress?.target_count || meta.normalized?.targetCount || "",
|
|
220
|
-
post_action: screenParams.post_action || "none",
|
|
221
|
-
max_greet_count: screenParams.max_greet_count ?? ""
|
|
222
|
-
},
|
|
223
|
-
followUp: meta.args?.follow_up || meta.args?.overrides?.follow_up || null
|
|
258
|
+
screenParams,
|
|
259
|
+
followUp: meta.args?.follow_up || meta.args?.overrides?.follow_up || followUp || overrides.follow_up || null
|
|
224
260
|
});
|
|
225
261
|
}
|
|
226
262
|
|
|
@@ -237,6 +273,16 @@ function readRecommendRunState(runId) {
|
|
|
237
273
|
return readJsonFile(artifacts.run_state_path);
|
|
238
274
|
}
|
|
239
275
|
|
|
276
|
+
function isProcessAlive(pid) {
|
|
277
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
278
|
+
try {
|
|
279
|
+
process.kill(pid, 0);
|
|
280
|
+
return true;
|
|
281
|
+
} catch {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
240
286
|
function getRecommendRunMeta(runId) {
|
|
241
287
|
return recommendRunMeta.get(runId) || {};
|
|
242
288
|
}
|
|
@@ -475,12 +521,14 @@ function normalizeRunSnapshot(snapshot) {
|
|
|
475
521
|
|| snapshot.status === RUN_STATUS_PAUSED
|
|
476
522
|
) ? buildLegacyRecommendResult({ ...snapshot, progress }) : null;
|
|
477
523
|
const recovery = buildConstrainedAgentRecovery(snapshot, meta, artifacts);
|
|
524
|
+
const snapshotContext = plainRecord(snapshot.context);
|
|
525
|
+
const metaArgs = plainRecord(meta.args);
|
|
478
526
|
const oldContext = {
|
|
479
|
-
workspace_root: meta.workspaceRoot || null,
|
|
480
|
-
instruction:
|
|
481
|
-
confirmation: clonePlain(
|
|
482
|
-
overrides: clonePlain(
|
|
483
|
-
follow_up: clonePlain(
|
|
527
|
+
workspace_root: meta.workspaceRoot || snapshotContext.workspace_root || null,
|
|
528
|
+
instruction: metaArgs.instruction || snapshotContext.instruction || "",
|
|
529
|
+
confirmation: clonePlain(metaArgs.confirmation ?? snapshotContext.confirmation ?? {}, {}),
|
|
530
|
+
overrides: clonePlain(metaArgs.overrides ?? snapshotContext.overrides ?? {}, {}),
|
|
531
|
+
follow_up: clonePlain(metaArgs.follow_up ?? snapshotContext.follow_up ?? null, null),
|
|
484
532
|
target_count_semantics: TARGET_COUNT_SEMANTICS
|
|
485
533
|
};
|
|
486
534
|
return {
|
|
@@ -494,12 +542,12 @@ function normalizeRunSnapshot(snapshot) {
|
|
|
494
542
|
updated_at: snapshot.updatedAt,
|
|
495
543
|
completed_at: toIsoOrNull(snapshot.completedAt),
|
|
496
544
|
heartbeat_at: snapshot.updatedAt,
|
|
497
|
-
pid: process.pid || null,
|
|
545
|
+
pid: Number.isInteger(snapshot.pid) && snapshot.pid > 0 ? snapshot.pid : process.pid || null,
|
|
498
546
|
last_message: snapshot.error?.message || snapshot.phase || null,
|
|
499
547
|
context: {
|
|
500
|
-
...
|
|
548
|
+
...snapshotContext,
|
|
501
549
|
...oldContext,
|
|
502
|
-
shared_run_context:
|
|
550
|
+
shared_run_context: snapshotContext
|
|
503
551
|
},
|
|
504
552
|
control: {
|
|
505
553
|
pause_requested: snapshot.status === RUN_STATUS_PAUSED,
|
|
@@ -511,6 +559,8 @@ function normalizeRunSnapshot(snapshot) {
|
|
|
511
559
|
checkpoint_path: legacyResult?.checkpoint_path || meta.checkpointPath || artifacts?.checkpoint_path || null,
|
|
512
560
|
pause_control_path: artifacts?.run_state_path || null,
|
|
513
561
|
output_csv: legacyResult?.output_csv || null,
|
|
562
|
+
worker_stdout_path: artifacts?.worker_stdout_path || null,
|
|
563
|
+
worker_stderr_path: artifacts?.worker_stderr_path || null,
|
|
514
564
|
resume_count: meta.resumeCount || 0,
|
|
515
565
|
last_resumed_at: meta.lastResumedAt || null,
|
|
516
566
|
last_paused_at: snapshot.status === RUN_STATUS_PAUSED ? snapshot.updatedAt : null
|
|
@@ -521,6 +571,41 @@ function normalizeRunSnapshot(snapshot) {
|
|
|
521
571
|
};
|
|
522
572
|
}
|
|
523
573
|
|
|
574
|
+
function mergePersistedControlRequest(normalized, existing) {
|
|
575
|
+
const control = {
|
|
576
|
+
...(normalized?.control || {})
|
|
577
|
+
};
|
|
578
|
+
if (!normalized || TERMINAL_STATUSES.has(normalized.state)) return control;
|
|
579
|
+
const existingControl = plainRecord(existing?.control);
|
|
580
|
+
if (existingControl.cancel_requested === true) {
|
|
581
|
+
return {
|
|
582
|
+
...control,
|
|
583
|
+
pause_requested: true,
|
|
584
|
+
pause_requested_at: existingControl.pause_requested_at || control.pause_requested_at || new Date().toISOString(),
|
|
585
|
+
pause_requested_by: existingControl.pause_requested_by || control.pause_requested_by || "cancel_recommend_pipeline_run",
|
|
586
|
+
cancel_requested: true
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
if (existingControl.pause_requested === true && normalized.state !== RUN_STATUS_PAUSED) {
|
|
590
|
+
return {
|
|
591
|
+
...control,
|
|
592
|
+
pause_requested: true,
|
|
593
|
+
pause_requested_at: existingControl.pause_requested_at || control.pause_requested_at || new Date().toISOString(),
|
|
594
|
+
pause_requested_by: existingControl.pause_requested_by || control.pause_requested_by || "pause_recommend_pipeline_run"
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
if (existingControl.pause_requested === false && normalized.state === RUN_STATUS_PAUSED) {
|
|
598
|
+
return {
|
|
599
|
+
...control,
|
|
600
|
+
pause_requested: false,
|
|
601
|
+
pause_requested_at: null,
|
|
602
|
+
pause_requested_by: null,
|
|
603
|
+
cancel_requested: false
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
return control;
|
|
607
|
+
}
|
|
608
|
+
|
|
524
609
|
function persistRecommendRunSnapshot(snapshot, {
|
|
525
610
|
persistActiveCheckpoint = false
|
|
526
611
|
} = {}) {
|
|
@@ -528,6 +613,8 @@ function persistRecommendRunSnapshot(snapshot, {
|
|
|
528
613
|
if (!normalized?.run_id) return normalized;
|
|
529
614
|
const artifacts = getRecommendRunArtifacts(normalized.run_id);
|
|
530
615
|
if (!artifacts) return normalized;
|
|
616
|
+
const existing = readJsonFile(artifacts.run_state_path);
|
|
617
|
+
normalized.control = mergePersistedControlRequest(normalized, existing);
|
|
531
618
|
if (persistActiveCheckpoint) {
|
|
532
619
|
persistRecommendCheckpointSnapshot(normalized);
|
|
533
620
|
}
|
|
@@ -557,6 +644,38 @@ function persistRecommendRunSnapshot(snapshot, {
|
|
|
557
644
|
return normalized;
|
|
558
645
|
}
|
|
559
646
|
|
|
647
|
+
function reconcilePersistedRecommendRunIfNeeded(persisted) {
|
|
648
|
+
if (!persisted || typeof persisted !== "object") return persisted;
|
|
649
|
+
const persistedState = normalizeText(persisted.state || persisted.status);
|
|
650
|
+
if (TERMINAL_STATUSES.has(persistedState)) return persisted;
|
|
651
|
+
if (isProcessAlive(persisted.pid)) return persisted;
|
|
652
|
+
|
|
653
|
+
const runId = normalizeRunId(persisted.run_id || persisted.runId);
|
|
654
|
+
const artifacts = getRecommendRunArtifacts(runId);
|
|
655
|
+
const checkpoint = artifacts?.checkpoint_path ? readJsonFile(artifacts.checkpoint_path) : null;
|
|
656
|
+
const now = new Date().toISOString();
|
|
657
|
+
const error = {
|
|
658
|
+
code: "RUN_PROCESS_EXITED",
|
|
659
|
+
message: `检测到推荐任务进程已退出(pid=${persisted.pid || "unknown"}),已自动标记为失败。`,
|
|
660
|
+
retryable: true
|
|
661
|
+
};
|
|
662
|
+
return persistRecommendRunSnapshot({
|
|
663
|
+
runId,
|
|
664
|
+
name: persisted.name || runId,
|
|
665
|
+
status: RUN_STATUS_FAILED,
|
|
666
|
+
phase: persisted.stage || persisted.phase || "recommend:orphaned",
|
|
667
|
+
progress: persisted.progress || {},
|
|
668
|
+
context: persisted.context || {},
|
|
669
|
+
checkpoint: checkpoint || persisted.checkpoint || {},
|
|
670
|
+
startedAt: persisted.started_at || persisted.startedAt || now,
|
|
671
|
+
updatedAt: now,
|
|
672
|
+
completedAt: now,
|
|
673
|
+
pid: Number.isInteger(persisted.pid) && persisted.pid > 0 ? persisted.pid : null,
|
|
674
|
+
error,
|
|
675
|
+
summary: persisted.summary || null
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
560
679
|
function persistRecommendLifecycleSnapshot(snapshot, event = {}) {
|
|
561
680
|
return persistRecommendRunSnapshot(snapshot, {
|
|
562
681
|
persistActiveCheckpoint: event?.type === "checkpoint"
|
|
@@ -1154,6 +1273,47 @@ function getRunOptions(args, parsed, normalized, session, configResolution = nul
|
|
|
1154
1273
|
};
|
|
1155
1274
|
}
|
|
1156
1275
|
|
|
1276
|
+
function prepareRecommendPipelineStart(args = {}, { workspaceRoot = "" } = {}) {
|
|
1277
|
+
const parsed = parseRecommendPipelineRequest(args);
|
|
1278
|
+
const gate = evaluateRecommendPipelineGate(parsed, args);
|
|
1279
|
+
if (gate) return { response: gate };
|
|
1280
|
+
const configResolution = resolveBossScreeningConfig(workspaceRoot);
|
|
1281
|
+
const normalized = normalizeRecommendStartInput(args, parsed, configResolution);
|
|
1282
|
+
const debugTestOptions = collectRecommendDebugTestOptions(args, normalized);
|
|
1283
|
+
if (debugTestOptions.length && !isDebugTestMode(args)) {
|
|
1284
|
+
return {
|
|
1285
|
+
response: {
|
|
1286
|
+
status: "FAILED",
|
|
1287
|
+
error: {
|
|
1288
|
+
code: "DEBUG_TEST_MODE_REQUIRED",
|
|
1289
|
+
message: `这些参数属于调试/测试路径,正式 live run 不会默认启用:${debugTestOptions.join(", ")}。如确需测试,请显式传 debug_test_mode=true。`,
|
|
1290
|
+
retryable: false
|
|
1291
|
+
},
|
|
1292
|
+
debug_test_options: debugTestOptions
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
if (normalized.screeningMode === "llm" && !configResolution.ok) {
|
|
1297
|
+
return {
|
|
1298
|
+
response: {
|
|
1299
|
+
status: "FAILED",
|
|
1300
|
+
error: {
|
|
1301
|
+
code: "SCREEN_CONFIG_ERROR",
|
|
1302
|
+
message: configResolution.error?.message || "screening-config.json is required for LLM screening.",
|
|
1303
|
+
retryable: true
|
|
1304
|
+
},
|
|
1305
|
+
config_path: configResolution.config_path || null,
|
|
1306
|
+
candidate_paths: configResolution.candidate_paths || []
|
|
1307
|
+
}
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
return {
|
|
1311
|
+
parsed,
|
|
1312
|
+
configResolution,
|
|
1313
|
+
normalized
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1157
1317
|
async function closeRecommendRunSession(runId) {
|
|
1158
1318
|
const meta = recommendRunMeta.get(runId);
|
|
1159
1319
|
if (!meta || meta.closed) return;
|
|
@@ -1199,34 +1359,19 @@ function trackRecommendRun(runId) {
|
|
|
1199
1359
|
});
|
|
1200
1360
|
}
|
|
1201
1361
|
|
|
1202
|
-
async function startRecommendPipelineRunInternal(args = {}, { workspaceRoot = "" } = {}) {
|
|
1203
|
-
const
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
const debugTestOptions = collectRecommendDebugTestOptions(args, normalized);
|
|
1209
|
-
if (debugTestOptions.length && !isDebugTestMode(args)) {
|
|
1362
|
+
async function startRecommendPipelineRunInternal(args = {}, { workspaceRoot = "", runId = "" } = {}) {
|
|
1363
|
+
const prepared = prepareRecommendPipelineStart(args, { workspaceRoot });
|
|
1364
|
+
if (prepared.response) return prepared.response;
|
|
1365
|
+
const { parsed, configResolution, normalized } = prepared;
|
|
1366
|
+
const fixedRunId = normalizeRunId(runId);
|
|
1367
|
+
if (runId && !fixedRunId) {
|
|
1210
1368
|
return {
|
|
1211
1369
|
status: "FAILED",
|
|
1212
1370
|
error: {
|
|
1213
|
-
code: "
|
|
1214
|
-
message:
|
|
1371
|
+
code: "INVALID_RUN_ID",
|
|
1372
|
+
message: "run_id is invalid",
|
|
1215
1373
|
retryable: false
|
|
1216
|
-
}
|
|
1217
|
-
debug_test_options: debugTestOptions
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
if (normalized.screeningMode === "llm" && !configResolution.ok) {
|
|
1221
|
-
return {
|
|
1222
|
-
status: "FAILED",
|
|
1223
|
-
error: {
|
|
1224
|
-
code: "SCREEN_CONFIG_ERROR",
|
|
1225
|
-
message: configResolution.error?.message || "screening-config.json is required for LLM screening.",
|
|
1226
|
-
retryable: true
|
|
1227
|
-
},
|
|
1228
|
-
config_path: configResolution.config_path || null,
|
|
1229
|
-
candidate_paths: configResolution.candidate_paths || []
|
|
1374
|
+
}
|
|
1230
1375
|
};
|
|
1231
1376
|
}
|
|
1232
1377
|
|
|
@@ -1260,7 +1405,11 @@ async function startRecommendPipelineRunInternal(args = {}, { workspaceRoot = ""
|
|
|
1260
1405
|
|
|
1261
1406
|
let started;
|
|
1262
1407
|
try {
|
|
1263
|
-
started = recommendRunService.startRecommendRun(
|
|
1408
|
+
started = recommendRunService.startRecommendRun({
|
|
1409
|
+
...getRunOptions(args, parsed, normalized, session, configResolution),
|
|
1410
|
+
runId: fixedRunId || undefined,
|
|
1411
|
+
pid: process.pid
|
|
1412
|
+
});
|
|
1264
1413
|
} catch (error) {
|
|
1265
1414
|
await session.close?.();
|
|
1266
1415
|
return {
|
|
@@ -1311,8 +1460,24 @@ async function startRecommendPipelineRunInternal(args = {}, { workspaceRoot = ""
|
|
|
1311
1460
|
};
|
|
1312
1461
|
}
|
|
1313
1462
|
|
|
1314
|
-
export
|
|
1315
|
-
const
|
|
1463
|
+
export function prepareRecommendPipelineRunTool({ workspaceRoot = "", args = {} } = {}) {
|
|
1464
|
+
const prepared = prepareRecommendPipelineStart(args, { workspaceRoot });
|
|
1465
|
+
if (prepared.response) return prepared.response;
|
|
1466
|
+
const { parsed, normalized } = prepared;
|
|
1467
|
+
return {
|
|
1468
|
+
status: "READY",
|
|
1469
|
+
review: parsed.review,
|
|
1470
|
+
post_action: {
|
|
1471
|
+
requested: normalized.postAction,
|
|
1472
|
+
execute_post_action: args.dry_run_post_action === true ? false : args.execute_post_action !== false,
|
|
1473
|
+
max_greet_count: normalized.maxGreetCount
|
|
1474
|
+
},
|
|
1475
|
+
target_count_semantics: TARGET_COUNT_SEMANTICS
|
|
1476
|
+
};
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
export async function startRecommendPipelineRunTool({ workspaceRoot = "", args = {}, runId = "" } = {}) {
|
|
1480
|
+
const started = await startRecommendPipelineRunInternal(args, { workspaceRoot, runId });
|
|
1316
1481
|
if (started.status !== "ACCEPTED") return started;
|
|
1317
1482
|
return attachMethodEvidence(started, started.run_id);
|
|
1318
1483
|
}
|
|
@@ -1339,12 +1504,14 @@ export function getRecommendPipelineRunTool({ args = {} } = {}) {
|
|
|
1339
1504
|
} catch {
|
|
1340
1505
|
const persisted = readRecommendRunState(runId);
|
|
1341
1506
|
if (persisted) {
|
|
1507
|
+
const reconciled = reconcilePersistedRecommendRunIfNeeded(persisted);
|
|
1342
1508
|
return {
|
|
1343
1509
|
status: "RUN_STATUS",
|
|
1344
|
-
run:
|
|
1510
|
+
run: reconciled,
|
|
1345
1511
|
persistence: {
|
|
1346
1512
|
source: "disk",
|
|
1347
|
-
active_control_available: false
|
|
1513
|
+
active_control_available: false,
|
|
1514
|
+
stale_process_reconciled: reconciled?.state !== persisted.state
|
|
1348
1515
|
},
|
|
1349
1516
|
runtime_evaluate_used: false,
|
|
1350
1517
|
method_summary: {},
|
package/src/run-state.js
CHANGED
|
@@ -160,6 +160,8 @@ function defaultResume(resume = {}) {
|
|
|
160
160
|
checkpoint_path: normalizeMessage(resume?.checkpoint_path || ""),
|
|
161
161
|
pause_control_path: normalizeMessage(resume?.pause_control_path || ""),
|
|
162
162
|
output_csv: normalizeMessage(resume?.output_csv || ""),
|
|
163
|
+
worker_stdout_path: normalizeMessage(resume?.worker_stdout_path || ""),
|
|
164
|
+
worker_stderr_path: normalizeMessage(resume?.worker_stderr_path || ""),
|
|
163
165
|
follow_up_phase: normalizeMessage(resume?.follow_up_phase || ""),
|
|
164
166
|
chat_run_id: normalizeMessage(resume?.chat_run_id || ""),
|
|
165
167
|
chat_state: normalizeMessage(resume?.chat_state || ""),
|