@reconcrap/boss-recommend-mcp 1.2.10 → 1.3.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.
- package/README.md +82 -1
- package/package.json +2 -1
- package/skills/boss-chat/README.md +5 -0
- package/skills/boss-chat/SKILL.md +69 -0
- package/skills/boss-recommend-pipeline/SKILL.md +40 -4
- package/src/adapters.js +19 -5
- package/src/boss-chat.js +436 -0
- package/src/cli.js +294 -129
- package/src/index.js +459 -108
- package/src/pipeline.js +605 -8
- package/src/run-state.js +5 -0
- package/src/test-adapters-runtime.js +69 -0
- package/src/test-boss-chat.js +399 -0
- package/src/test-index-async.js +238 -4
- package/src/test-pipeline.js +408 -1
- package/vendor/boss-chat-cli/README.md +134 -0
- package/vendor/boss-chat-cli/package.json +53 -0
- package/vendor/boss-chat-cli/src/app.js +783 -0
- package/vendor/boss-chat-cli/src/browser/chat-page.js +2698 -0
- package/vendor/boss-chat-cli/src/cli.js +1350 -0
- package/vendor/boss-chat-cli/src/mcp/server.js +149 -0
- package/vendor/boss-chat-cli/src/mcp/tool-runtime.js +193 -0
- package/vendor/boss-chat-cli/src/runtime/async-run-state.js +260 -0
- package/vendor/boss-chat-cli/src/runtime/interaction.js +102 -0
- package/vendor/boss-chat-cli/src/runtime/run-control.js +102 -0
- package/vendor/boss-chat-cli/src/services/chrome-client.js +97 -0
- package/vendor/boss-chat-cli/src/services/llm.js +352 -0
- package/vendor/boss-chat-cli/src/services/profile-store.js +157 -0
- package/vendor/boss-chat-cli/src/services/report-store.js +19 -0
- package/vendor/boss-chat-cli/src/services/resume-capture.js +554 -0
- package/vendor/boss-chat-cli/src/services/state-store.js +217 -0
- package/vendor/boss-chat-cli/src/utils/customer-key.js +82 -0
- package/vendor/boss-recommend-screen-cli/boss-recommend-screen-cli.cjs +902 -56
- package/vendor/boss-recommend-screen-cli/test-recoverable-resume-failures.cjs +387 -1
package/src/cli.js
CHANGED
|
@@ -16,6 +16,14 @@ import {
|
|
|
16
16
|
switchRecommendTab,
|
|
17
17
|
waitRecommendFeaturedDetailReady
|
|
18
18
|
} from "./adapters.js";
|
|
19
|
+
import {
|
|
20
|
+
cancelBossChatRun,
|
|
21
|
+
getBossChatHealthCheck,
|
|
22
|
+
getBossChatRun,
|
|
23
|
+
pauseBossChatRun,
|
|
24
|
+
resumeBossChatRun,
|
|
25
|
+
startBossChatRun
|
|
26
|
+
} from "./boss-chat.js";
|
|
19
27
|
import { runRecommendPipeline } from "./pipeline.js";
|
|
20
28
|
|
|
21
29
|
const require = createRequire(import.meta.url);
|
|
@@ -23,7 +31,7 @@ const currentFilePath = fileURLToPath(import.meta.url);
|
|
|
23
31
|
const packageRoot = path.resolve(path.dirname(currentFilePath), "..");
|
|
24
32
|
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
25
33
|
const skillName = "boss-recommend-pipeline";
|
|
26
|
-
const
|
|
34
|
+
const bundledSkillNames = [skillName, "boss-chat"];
|
|
27
35
|
const exampleConfigPath = path.join(packageRoot, "config", "screening-config.example.json");
|
|
28
36
|
const bossUrl = "https://www.zhipin.com/web/chat/recommend";
|
|
29
37
|
const chromeOnboardingUrlPattern = /^chrome:\/\/(welcome|intro|newtab|signin|history-sync|settings\/syncSetup)/i;
|
|
@@ -37,6 +45,10 @@ const autoSyncSkipCommands = new Set(["install", "install-skill", "where", "help
|
|
|
37
45
|
const externalMcpTargetsEnv = "BOSS_RECOMMEND_MCP_CONFIG_TARGETS";
|
|
38
46
|
const externalSkillDirsEnv = "BOSS_RECOMMEND_EXTERNAL_SKILL_DIRS";
|
|
39
47
|
|
|
48
|
+
function getSkillSourceDir(name = skillName) {
|
|
49
|
+
return path.join(packageRoot, "skills", name);
|
|
50
|
+
}
|
|
51
|
+
|
|
40
52
|
function getPackageVersion() {
|
|
41
53
|
try {
|
|
42
54
|
const parsed = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -137,16 +149,16 @@ function getLegacyUserConfigPath() {
|
|
|
137
149
|
return path.join(getCodexHome(), "boss-recommend-mcp", "screening-config.json");
|
|
138
150
|
}
|
|
139
151
|
|
|
140
|
-
function getSkillTargetDir() {
|
|
141
|
-
return path.join(getCodexHome(), "skills",
|
|
152
|
+
function getSkillTargetDir(name = skillName) {
|
|
153
|
+
return path.join(getCodexHome(), "skills", name);
|
|
142
154
|
}
|
|
143
155
|
|
|
144
|
-
function getSkillVersionMarkerPath() {
|
|
145
|
-
return path.join(getSkillTargetDir(), ".installed-version");
|
|
156
|
+
function getSkillVersionMarkerPath(name = skillName) {
|
|
157
|
+
return path.join(getSkillTargetDir(name), ".installed-version");
|
|
146
158
|
}
|
|
147
159
|
|
|
148
|
-
function readInstalledSkillVersion() {
|
|
149
|
-
const markerPath = getSkillVersionMarkerPath();
|
|
160
|
+
function readInstalledSkillVersion(name = skillName) {
|
|
161
|
+
const markerPath = getSkillVersionMarkerPath(name);
|
|
150
162
|
if (!fs.existsSync(markerPath)) return null;
|
|
151
163
|
try {
|
|
152
164
|
return fs.readFileSync(markerPath, "utf8").trim() || null;
|
|
@@ -155,8 +167,8 @@ function readInstalledSkillVersion() {
|
|
|
155
167
|
}
|
|
156
168
|
}
|
|
157
169
|
|
|
158
|
-
function writeInstalledSkillVersion(version) {
|
|
159
|
-
const markerPath = getSkillVersionMarkerPath();
|
|
170
|
+
function writeInstalledSkillVersion(name, version) {
|
|
171
|
+
const markerPath = getSkillVersionMarkerPath(name);
|
|
160
172
|
ensureDir(path.dirname(markerPath));
|
|
161
173
|
fs.writeFileSync(markerPath, `${version}\n`, "utf8");
|
|
162
174
|
}
|
|
@@ -183,6 +195,15 @@ function parsePositivePort(raw) {
|
|
|
183
195
|
return Number.isFinite(port) && port > 0 ? port : null;
|
|
184
196
|
}
|
|
185
197
|
|
|
198
|
+
function parseBooleanOption(raw, fallback = undefined) {
|
|
199
|
+
if (raw === undefined || raw === null || raw === "") return fallback;
|
|
200
|
+
if (raw === true) return true;
|
|
201
|
+
const normalized = String(raw).trim().toLowerCase();
|
|
202
|
+
if (["true", "1", "yes", "y", "on"].includes(normalized)) return true;
|
|
203
|
+
if (["false", "0", "no", "n", "off"].includes(normalized)) return false;
|
|
204
|
+
return fallback;
|
|
205
|
+
}
|
|
206
|
+
|
|
186
207
|
function normalizePageScope(value) {
|
|
187
208
|
const normalized = String(value || "").trim().toLowerCase();
|
|
188
209
|
if (!normalized) return null;
|
|
@@ -259,6 +280,13 @@ function getRunOverrides(options) {
|
|
|
259
280
|
return parseJsonOption(options["overrides-json"], "overrides");
|
|
260
281
|
}
|
|
261
282
|
|
|
283
|
+
function getRunFollowUp(options) {
|
|
284
|
+
if (typeof options["follow-up-file"] === "string" && options["follow-up-file"].trim()) {
|
|
285
|
+
return parseJsonOption(readTextFile(options["follow-up-file"], "follow_up"), "follow_up");
|
|
286
|
+
}
|
|
287
|
+
return parseJsonOption(options["follow-up-json"], "follow_up");
|
|
288
|
+
}
|
|
289
|
+
|
|
262
290
|
function normalizeMcpClientName(value) {
|
|
263
291
|
const raw = String(value || "").trim().toLowerCase();
|
|
264
292
|
if (!raw) return "";
|
|
@@ -542,13 +570,15 @@ function mirrorSkillToExternalDirs(options = {}) {
|
|
|
542
570
|
const mirrored = [];
|
|
543
571
|
const skipped = [];
|
|
544
572
|
for (const baseDir of baseDirs) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
573
|
+
for (const bundledSkillName of bundledSkillNames) {
|
|
574
|
+
try {
|
|
575
|
+
const targetDir = path.join(baseDir, bundledSkillName);
|
|
576
|
+
ensureDir(path.dirname(targetDir));
|
|
577
|
+
fs.cpSync(getSkillSourceDir(bundledSkillName), targetDir, { recursive: true, force: true });
|
|
578
|
+
mirrored.push({ base_dir: baseDir, target_dir: targetDir, skill: bundledSkillName });
|
|
579
|
+
} catch (error) {
|
|
580
|
+
skipped.push({ base_dir: baseDir, skill: bundledSkillName, reason: error.message });
|
|
581
|
+
}
|
|
552
582
|
}
|
|
553
583
|
}
|
|
554
584
|
return { baseDirs, mirrored, skipped };
|
|
@@ -556,17 +586,29 @@ function mirrorSkillToExternalDirs(options = {}) {
|
|
|
556
586
|
|
|
557
587
|
function syncSkillAssets(options = {}) {
|
|
558
588
|
const force = options.force === true;
|
|
559
|
-
const
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
589
|
+
const results = [];
|
|
590
|
+
for (const bundledSkillName of bundledSkillNames) {
|
|
591
|
+
const targetDir = getSkillTargetDir(bundledSkillName);
|
|
592
|
+
const skillEntry = path.join(targetDir, "SKILL.md");
|
|
593
|
+
const installedVersion = readInstalledSkillVersion(bundledSkillName);
|
|
594
|
+
const needsSync = force || !fs.existsSync(skillEntry) || installedVersion !== packageVersion;
|
|
595
|
+
if (needsSync) {
|
|
596
|
+
ensureDir(path.dirname(targetDir));
|
|
597
|
+
fs.cpSync(getSkillSourceDir(bundledSkillName), targetDir, { recursive: true, force: true });
|
|
598
|
+
writeInstalledSkillVersion(bundledSkillName, packageVersion);
|
|
599
|
+
}
|
|
600
|
+
results.push({
|
|
601
|
+
skill: bundledSkillName,
|
|
602
|
+
targetDir,
|
|
603
|
+
updated: needsSync,
|
|
604
|
+
installedVersion,
|
|
605
|
+
packageVersion
|
|
606
|
+
});
|
|
565
607
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
608
|
+
return {
|
|
609
|
+
primaryTargetDir: results[0]?.targetDir || null,
|
|
610
|
+
results
|
|
611
|
+
};
|
|
570
612
|
}
|
|
571
613
|
|
|
572
614
|
function ensureAssetsUpToDate(command) {
|
|
@@ -579,7 +621,7 @@ function ensureAssetsUpToDate(command) {
|
|
|
579
621
|
}
|
|
580
622
|
|
|
581
623
|
function installSkill() {
|
|
582
|
-
return syncSkillAssets({ force: true }).
|
|
624
|
+
return syncSkillAssets({ force: true }).results;
|
|
583
625
|
}
|
|
584
626
|
|
|
585
627
|
function pathStartsWith(filePath, rootPath) {
|
|
@@ -1163,10 +1205,10 @@ function printPaths() {
|
|
|
1163
1205
|
const stateHome = getStateHome();
|
|
1164
1206
|
const calibrationResolution = getFeaturedCalibrationResolution(process.cwd());
|
|
1165
1207
|
console.log(`package_root=${packageRoot}`);
|
|
1166
|
-
console.log(`
|
|
1208
|
+
console.log(`skill_sources=${bundledSkillNames.map((name) => getSkillSourceDir(name)).join(" | ")}`);
|
|
1167
1209
|
console.log(`codex_home=${codexHome}`);
|
|
1168
1210
|
console.log(`state_home=${stateHome}`);
|
|
1169
|
-
console.log(`
|
|
1211
|
+
console.log(`skill_targets=${bundledSkillNames.map((name) => path.join(codexHome, "skills", name)).join(" | ")}`);
|
|
1170
1212
|
console.log(`config_target=${getUserConfigPath()}`);
|
|
1171
1213
|
console.log(`legacy_config_target=${getLegacyUserConfigPath()}`);
|
|
1172
1214
|
console.log(`calibration_target=${calibrationResolution.calibration_path}`);
|
|
@@ -1181,8 +1223,9 @@ function printHelp() {
|
|
|
1181
1223
|
console.log(" boss-recommend-mcp Start the MCP server");
|
|
1182
1224
|
console.log(" boss-recommend-mcp start Start the MCP server");
|
|
1183
1225
|
console.log(" boss-recommend-mcp run Run the recommend pipeline once via CLI and print JSON");
|
|
1226
|
+
console.log(" boss-recommend-mcp chat <subcommand> Run bundled boss-chat commands via the recommend package");
|
|
1184
1227
|
console.log(" boss-recommend-mcp install Install skill/MCP templates and auto-init screening-config.json (supports --agent trae-cn/cursor/...)");
|
|
1185
|
-
console.log(" boss-recommend-mcp install-skill Install
|
|
1228
|
+
console.log(" boss-recommend-mcp install-skill Install bundled Codex skills");
|
|
1186
1229
|
console.log(" boss-recommend-mcp init-config Create screening-config.json if missing (prefer workspace config/, fallback ~/.boss-recommend-mcp)");
|
|
1187
1230
|
console.log(" boss-recommend-mcp config set Write baseUrl/apiKey/model (prefer workspace config/, fallback ~/.boss-recommend-mcp)");
|
|
1188
1231
|
console.log(" boss-recommend-mcp set-port Persist preferred Chrome debug port to screening-config.json");
|
|
@@ -1193,7 +1236,8 @@ function printHelp() {
|
|
|
1193
1236
|
console.log(" boss-recommend-mcp where Print installed package, skill, and config paths");
|
|
1194
1237
|
console.log("");
|
|
1195
1238
|
console.log("Run command:");
|
|
1196
|
-
console.log(" boss-recommend-mcp run --instruction \"推荐页上筛选211男生,近14天没有,有大模型平台经验\" [--confirmation-json '{...}'] [--overrides-json '{...}']");
|
|
1239
|
+
console.log(" boss-recommend-mcp run --instruction \"推荐页上筛选211男生,近14天没有,有大模型平台经验\" [--confirmation-json '{...}'] [--overrides-json '{...}'] [--follow-up-json '{...}']");
|
|
1240
|
+
console.log(" boss-recommend-mcp chat run --job \"算法工程师\" --start-from unread --criteria \"有 AI Agent 经验\" --targetCount 20 # 后台启动,不自动轮询");
|
|
1197
1241
|
console.log(" boss-recommend-mcp config set --base-url <url> --api-key <key> --model <model> [--openai-organization <id>] [--openai-project <id>]");
|
|
1198
1242
|
console.log(" boss-recommend-mcp install --agent trae-cn");
|
|
1199
1243
|
console.log(" boss-recommend-mcp doctor --agent trae-cn --page-scope featured");
|
|
@@ -1214,12 +1258,15 @@ function printMcpConfig(options = {}) {
|
|
|
1214
1258
|
}
|
|
1215
1259
|
|
|
1216
1260
|
function installAll(options = {}) {
|
|
1217
|
-
const
|
|
1261
|
+
const skillResults = installSkill();
|
|
1218
1262
|
const configResult = ensureUserConfig(options);
|
|
1219
1263
|
const mcpTemplateResult = writeMcpConfigFiles({ client: "all" });
|
|
1220
1264
|
const externalMcpResult = installExternalMcpConfigs(options);
|
|
1221
1265
|
const externalSkillResult = mirrorSkillToExternalDirs(options);
|
|
1222
|
-
console.log(`
|
|
1266
|
+
console.log(`Bundled skills installed: ${skillResults.length}`);
|
|
1267
|
+
for (const item of skillResults) {
|
|
1268
|
+
console.log(`- ${item.skill}: ${item.targetDir}`);
|
|
1269
|
+
}
|
|
1223
1270
|
console.log(
|
|
1224
1271
|
configResult.created
|
|
1225
1272
|
? `screening-config.json created: ${configResult.path}`
|
|
@@ -1256,6 +1303,7 @@ async function runPipelineOnce(options) {
|
|
|
1256
1303
|
const instruction = getRunInstruction(options);
|
|
1257
1304
|
const confirmation = getRunConfirmation(options);
|
|
1258
1305
|
const overrides = getRunOverrides(options);
|
|
1306
|
+
const followUp = getRunFollowUp(options);
|
|
1259
1307
|
const workspaceRoot = getWorkspaceRoot(options);
|
|
1260
1308
|
const explicitPort = parsePositivePort(options.port);
|
|
1261
1309
|
if (explicitPort) {
|
|
@@ -1267,78 +1315,168 @@ async function runPipelineOnce(options) {
|
|
|
1267
1315
|
workspaceRoot,
|
|
1268
1316
|
instruction,
|
|
1269
1317
|
confirmation,
|
|
1270
|
-
overrides
|
|
1318
|
+
overrides,
|
|
1319
|
+
followUp
|
|
1271
1320
|
});
|
|
1272
1321
|
printJson(result);
|
|
1273
1322
|
}
|
|
1274
1323
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1324
|
+
function buildBossChatCliInput(options = {}) {
|
|
1325
|
+
return {
|
|
1326
|
+
profile: typeof options.profile === "string" ? options.profile.trim() : undefined,
|
|
1327
|
+
job: typeof options.job === "string" ? options.job.trim() : undefined,
|
|
1328
|
+
start_from: String(options["start-from"] || options.start_from || "").trim().toLowerCase() || undefined,
|
|
1329
|
+
criteria: typeof options.criteria === "string" ? options.criteria.trim() : undefined,
|
|
1330
|
+
target_count: parsePositivePort(options.targetCount || options["target-count"] || options.target_count),
|
|
1331
|
+
port: parsePositivePort(options.port),
|
|
1332
|
+
dry_run: options["dry-run"] === true || options.dryRun === true,
|
|
1333
|
+
no_state: options["no-state"] === true || options.noState === true,
|
|
1334
|
+
safe_pacing: parseBooleanOption(options["safe-pacing"] ?? options.safe_pacing),
|
|
1335
|
+
batch_rest_enabled: parseBooleanOption(options["batch-rest"] ?? options.batch_rest_enabled)
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1278
1338
|
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
}
|
|
1294
|
-
});
|
|
1295
|
-
process.exitCode = 1;
|
|
1296
|
-
}
|
|
1297
|
-
break;
|
|
1298
|
-
case "install":
|
|
1299
|
-
try {
|
|
1300
|
-
installAll(options);
|
|
1301
|
-
} catch (error) {
|
|
1302
|
-
console.error(error.message || "Install failed.");
|
|
1303
|
-
process.exitCode = 1;
|
|
1304
|
-
}
|
|
1305
|
-
break;
|
|
1306
|
-
case "install-skill":
|
|
1307
|
-
console.log(`Skill installed to: ${installSkill()}`);
|
|
1308
|
-
break;
|
|
1309
|
-
case "init-config": {
|
|
1310
|
-
const result = ensureUserConfig(options);
|
|
1311
|
-
console.log(result.created ? `Config template created at: ${result.path}` : `Config already exists at: ${result.path}`);
|
|
1312
|
-
break;
|
|
1313
|
-
}
|
|
1314
|
-
case "set-port": {
|
|
1315
|
-
try {
|
|
1316
|
-
const result = setDebugPort(options);
|
|
1317
|
-
console.log(`Preferred debug port saved: ${result.port}`);
|
|
1318
|
-
console.log(`Updated config: ${result.configPath}`);
|
|
1319
|
-
console.log("Port priority for runtime commands: --port > BOSS_RECOMMEND_CHROME_PORT > screening-config.json.debugPort > 9222");
|
|
1320
|
-
} catch (error) {
|
|
1321
|
-
console.error(error.message || "Failed to persist debug port.");
|
|
1322
|
-
process.exitCode = 1;
|
|
1323
|
-
}
|
|
1324
|
-
break;
|
|
1339
|
+
function getBossChatCliRunTarget(options = {}) {
|
|
1340
|
+
return {
|
|
1341
|
+
profile: typeof options.profile === "string" ? options.profile.trim() : undefined,
|
|
1342
|
+
run_id: String(options["run-id"] || options.runId || options.run_id || "").trim()
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
async function runBossChatCliCommand(subcommand, options = {}) {
|
|
1347
|
+
const workspaceRoot = getWorkspaceRoot(options);
|
|
1348
|
+
if (subcommand === "health-check") {
|
|
1349
|
+
printJson(getBossChatHealthCheck(workspaceRoot, {
|
|
1350
|
+
port: parsePositivePort(options.port)
|
|
1351
|
+
}));
|
|
1352
|
+
return;
|
|
1325
1353
|
}
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1354
|
+
|
|
1355
|
+
if (subcommand === "run") {
|
|
1356
|
+
printJson(await startBossChatRun({
|
|
1357
|
+
workspaceRoot,
|
|
1358
|
+
input: buildBossChatCliInput(options)
|
|
1359
|
+
}));
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
if (subcommand === "start-run") {
|
|
1364
|
+
printJson(await startBossChatRun({
|
|
1365
|
+
workspaceRoot,
|
|
1366
|
+
input: buildBossChatCliInput(options)
|
|
1367
|
+
}));
|
|
1368
|
+
return;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
if (subcommand === "get-run") {
|
|
1372
|
+
printJson(await getBossChatRun({
|
|
1373
|
+
workspaceRoot,
|
|
1374
|
+
input: getBossChatCliRunTarget(options)
|
|
1375
|
+
}));
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
if (subcommand === "pause-run") {
|
|
1380
|
+
printJson(await pauseBossChatRun({
|
|
1381
|
+
workspaceRoot,
|
|
1382
|
+
input: getBossChatCliRunTarget(options)
|
|
1383
|
+
}));
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
if (subcommand === "resume-run") {
|
|
1388
|
+
printJson(await resumeBossChatRun({
|
|
1389
|
+
workspaceRoot,
|
|
1390
|
+
input: getBossChatCliRunTarget(options)
|
|
1391
|
+
}));
|
|
1392
|
+
return;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
if (subcommand === "cancel-run") {
|
|
1396
|
+
printJson(await cancelBossChatRun({
|
|
1397
|
+
workspaceRoot,
|
|
1398
|
+
input: getBossChatCliRunTarget(options)
|
|
1399
|
+
}));
|
|
1400
|
+
return;
|
|
1335
1401
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1402
|
+
|
|
1403
|
+
throw new Error(`Unknown chat subcommand: ${subcommand || ""}`);
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
export async function runCli(argv = process.argv) {
|
|
1407
|
+
const command = argv[2] || "start";
|
|
1408
|
+
const options = parseOptions(argv.slice(3));
|
|
1409
|
+
ensureAssetsUpToDate(command);
|
|
1410
|
+
|
|
1411
|
+
switch (command) {
|
|
1412
|
+
case "start":
|
|
1413
|
+
startServer();
|
|
1414
|
+
break;
|
|
1415
|
+
case "run":
|
|
1416
|
+
try {
|
|
1417
|
+
await runPipelineOnce(options);
|
|
1418
|
+
} catch (error) {
|
|
1419
|
+
printJson({
|
|
1420
|
+
status: "FAILED",
|
|
1421
|
+
error: {
|
|
1422
|
+
code: "INVALID_CLI_INPUT",
|
|
1423
|
+
message: error.message || "Invalid CLI input",
|
|
1424
|
+
retryable: false
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
process.exitCode = 1;
|
|
1428
|
+
}
|
|
1429
|
+
break;
|
|
1430
|
+
case "chat":
|
|
1340
1431
|
try {
|
|
1341
|
-
const
|
|
1432
|
+
const chatSubcommand = String(argv[3] || "").trim().toLowerCase();
|
|
1433
|
+
const chatOptions = parseOptions(argv.slice(4));
|
|
1434
|
+
await runBossChatCliCommand(chatSubcommand, chatOptions);
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
printJson({
|
|
1437
|
+
status: "FAILED",
|
|
1438
|
+
error: {
|
|
1439
|
+
code: "INVALID_CHAT_CLI_INPUT",
|
|
1440
|
+
message: error.message || "Invalid chat CLI input",
|
|
1441
|
+
retryable: false
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1444
|
+
process.exitCode = 1;
|
|
1445
|
+
}
|
|
1446
|
+
break;
|
|
1447
|
+
case "install":
|
|
1448
|
+
try {
|
|
1449
|
+
installAll(options);
|
|
1450
|
+
} catch (error) {
|
|
1451
|
+
console.error(error.message || "Install failed.");
|
|
1452
|
+
process.exitCode = 1;
|
|
1453
|
+
}
|
|
1454
|
+
break;
|
|
1455
|
+
case "install-skill":
|
|
1456
|
+
for (const item of installSkill()) {
|
|
1457
|
+
console.log(`Skill installed: ${item.skill} -> ${item.targetDir}`);
|
|
1458
|
+
}
|
|
1459
|
+
break;
|
|
1460
|
+
case "init-config": {
|
|
1461
|
+
const result = ensureUserConfig(options);
|
|
1462
|
+
console.log(result.created ? `Config template created at: ${result.path}` : `Config already exists at: ${result.path}`);
|
|
1463
|
+
break;
|
|
1464
|
+
}
|
|
1465
|
+
case "set-port": {
|
|
1466
|
+
try {
|
|
1467
|
+
const result = setDebugPort(options);
|
|
1468
|
+
console.log(`Preferred debug port saved: ${result.port}`);
|
|
1469
|
+
console.log(`Updated config: ${result.configPath}`);
|
|
1470
|
+
console.log("Port priority for runtime commands: --port > BOSS_RECOMMEND_CHROME_PORT > screening-config.json.debugPort > 9222");
|
|
1471
|
+
} catch (error) {
|
|
1472
|
+
console.error(error.message || "Failed to persist debug port.");
|
|
1473
|
+
process.exitCode = 1;
|
|
1474
|
+
}
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1477
|
+
case "set-config": {
|
|
1478
|
+
try {
|
|
1479
|
+
const result = setScreeningConfig(options);
|
|
1342
1480
|
console.log(`screening-config.json updated: ${result.path}`);
|
|
1343
1481
|
} catch (error) {
|
|
1344
1482
|
console.error(error.message || "Failed to write screening-config.json.");
|
|
@@ -1346,37 +1484,64 @@ switch (command) {
|
|
|
1346
1484
|
}
|
|
1347
1485
|
break;
|
|
1348
1486
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1487
|
+
case "config": {
|
|
1488
|
+
const sub = String(argv[3] || "").trim().toLowerCase();
|
|
1489
|
+
if (!sub || sub.startsWith("--") || sub === "set") {
|
|
1490
|
+
const configOptions = sub === "set" ? parseOptions(argv.slice(4)) : options;
|
|
1491
|
+
try {
|
|
1492
|
+
const result = setScreeningConfig(configOptions);
|
|
1493
|
+
console.log(`screening-config.json updated: ${result.path}`);
|
|
1494
|
+
} catch (error) {
|
|
1495
|
+
console.error(error.message || "Failed to write screening-config.json.");
|
|
1496
|
+
process.exitCode = 1;
|
|
1497
|
+
}
|
|
1498
|
+
break;
|
|
1499
|
+
}
|
|
1500
|
+
console.error(`Unknown config subcommand: ${sub}`);
|
|
1358
1501
|
process.exitCode = 1;
|
|
1502
|
+
break;
|
|
1359
1503
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1504
|
+
case "mcp-config":
|
|
1505
|
+
try {
|
|
1506
|
+
printMcpConfig(options);
|
|
1507
|
+
} catch (error) {
|
|
1508
|
+
console.error(error.message || "Failed to generate MCP config template.");
|
|
1509
|
+
process.exitCode = 1;
|
|
1510
|
+
}
|
|
1511
|
+
break;
|
|
1512
|
+
case "doctor":
|
|
1513
|
+
await printDoctor(options);
|
|
1514
|
+
break;
|
|
1515
|
+
case "calibrate":
|
|
1516
|
+
await calibrate(options);
|
|
1517
|
+
break;
|
|
1518
|
+
case "launch-chrome":
|
|
1519
|
+
await launchChrome(options);
|
|
1520
|
+
break;
|
|
1521
|
+
case "where":
|
|
1522
|
+
printPaths();
|
|
1523
|
+
break;
|
|
1524
|
+
case "help":
|
|
1525
|
+
case "--help":
|
|
1526
|
+
case "-h":
|
|
1527
|
+
printHelp();
|
|
1528
|
+
break;
|
|
1529
|
+
default:
|
|
1530
|
+
console.error(`Unknown command: ${command}`);
|
|
1531
|
+
console.error("Run `boss-recommend-mcp --help` for usage.");
|
|
1532
|
+
process.exitCode = 1;
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
export const __testables = {
|
|
1537
|
+
buildBossChatCliInput,
|
|
1538
|
+
getBossChatCliRunTarget,
|
|
1539
|
+
getRunFollowUp,
|
|
1540
|
+
installSkill,
|
|
1541
|
+
runBossChatCliCommand,
|
|
1542
|
+
runPipelineOnce
|
|
1543
|
+
};
|
|
1544
|
+
|
|
1545
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === currentFilePath) {
|
|
1546
|
+
await runCli(process.argv);
|
|
1547
|
+
}
|