@inspecto-dev/cli 0.3.3 → 0.3.4
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/.turbo/turbo-build.log +6 -6
- package/.turbo/turbo-test.log +5450 -3335
- package/CHANGELOG.md +20 -0
- package/dist/bin.js +5 -2
- package/dist/{chunk-LJOKPCPD.js → chunk-2MOEVONN.js} +481 -49
- package/dist/index.d.ts +7 -0
- package/dist/index.js +1 -1
- package/package.json +3 -3
- package/src/bin.ts +4 -1
- package/src/commands/doctor.ts +27 -0
- package/src/commands/integration-install.ts +99 -4
- package/src/commands/onboard.ts +14 -0
- package/src/detect/build-tool.ts +198 -10
- package/src/onboarding/apply.ts +120 -27
- package/src/onboarding/planner.ts +80 -4
- package/src/onboarding/session.ts +11 -5
- package/src/onboarding/target-resolution.ts +78 -2
- package/src/types.ts +7 -0
- package/tests/apply.test.ts +234 -0
- package/tests/build-tool.test.ts +199 -0
- package/tests/doctor.test.ts +41 -0
- package/tests/install-wrapper.test.ts +56 -0
- package/tests/integration-install.test.ts +128 -0
- package/tests/onboard.test.ts +95 -0
- package/tests/plan.test.ts +102 -0
|
@@ -869,6 +869,34 @@ async function cleanGitignore(root) {
|
|
|
869
869
|
}
|
|
870
870
|
|
|
871
871
|
// src/onboarding/apply.ts
|
|
872
|
+
function normalizeSupportedIde(ide) {
|
|
873
|
+
if (!ide) return void 0;
|
|
874
|
+
return ide.toLowerCase() === "vscode" ? "vscode" : ide.toLowerCase();
|
|
875
|
+
}
|
|
876
|
+
async function readInheritedSettingsDefaults(repoRoot, projectRoot, settingsFileName) {
|
|
877
|
+
if (path6.resolve(repoRoot) === path6.resolve(projectRoot)) {
|
|
878
|
+
return {};
|
|
879
|
+
}
|
|
880
|
+
const inheritedSettingsPath = path6.join(repoRoot, ".inspecto", settingsFileName);
|
|
881
|
+
if (!await exists(inheritedSettingsPath)) {
|
|
882
|
+
return {};
|
|
883
|
+
}
|
|
884
|
+
const inheritedSettings = await readJSON(inheritedSettingsPath);
|
|
885
|
+
if (!inheritedSettings || typeof inheritedSettings !== "object") {
|
|
886
|
+
return {};
|
|
887
|
+
}
|
|
888
|
+
const inheritedDefaults = {};
|
|
889
|
+
if (typeof inheritedSettings.ide === "string") {
|
|
890
|
+
const normalizedIde = normalizeSupportedIde(inheritedSettings.ide);
|
|
891
|
+
if (normalizedIde) {
|
|
892
|
+
inheritedDefaults.ide = normalizedIde;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
if (typeof inheritedSettings["provider.default"] === "string") {
|
|
896
|
+
inheritedDefaults.providerDefault = inheritedSettings["provider.default"];
|
|
897
|
+
}
|
|
898
|
+
return inheritedDefaults;
|
|
899
|
+
}
|
|
872
900
|
function shellQuote(value) {
|
|
873
901
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
874
902
|
}
|
|
@@ -892,11 +920,12 @@ function resolveRuntimePackages() {
|
|
|
892
920
|
function resultStatus(nextSteps) {
|
|
893
921
|
return nextSteps.length > 0 ? "warning" : "ok";
|
|
894
922
|
}
|
|
895
|
-
function manualPlanSteps(plan2) {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
923
|
+
function manualPlanSteps(plan2, includeBlockers = true) {
|
|
924
|
+
const steps = plan2.actions.filter((action) => action.type === "manual_step").map((action) => action.description);
|
|
925
|
+
if (!includeBlockers) {
|
|
926
|
+
return steps;
|
|
927
|
+
}
|
|
928
|
+
return [...plan2.blockers.map((blocker) => blocker.message), ...steps];
|
|
900
929
|
}
|
|
901
930
|
async function applyOnboardingPlan(input) {
|
|
902
931
|
return applyOnboardingPlanInternal(input);
|
|
@@ -960,6 +989,7 @@ function createSpinner(text, quiet = false) {
|
|
|
960
989
|
}
|
|
961
990
|
async function applyOnboardingPlanInternal(input) {
|
|
962
991
|
const reporter = createReporter(input.options.quiet);
|
|
992
|
+
const additiveManualPlan = input.plan?.strategy === "manual" && input.allowManualPlanApply && input.plan.blockers.length === 0;
|
|
963
993
|
if (input.plan && input.plan.strategy !== "supported" && !input.allowManualPlanApply) {
|
|
964
994
|
return {
|
|
965
995
|
status: input.plan.status,
|
|
@@ -968,7 +998,7 @@ async function applyOnboardingPlanInternal(input) {
|
|
|
968
998
|
installFailed: false,
|
|
969
999
|
injectionFailed: false,
|
|
970
1000
|
manualExtensionInstallNeeded: false,
|
|
971
|
-
nextSteps: manualPlanSteps(input.plan)
|
|
1001
|
+
nextSteps: manualPlanSteps(input.plan, true)
|
|
972
1002
|
}
|
|
973
1003
|
};
|
|
974
1004
|
}
|
|
@@ -978,6 +1008,11 @@ async function applyOnboardingPlanInternal(input) {
|
|
|
978
1008
|
const promptsFileName = input.options.shared ? "prompts.json" : "prompts.local.json";
|
|
979
1009
|
const settingsPath = path6.join(settingsDir, settingsFileName);
|
|
980
1010
|
const promptsPath = path6.join(settingsDir, promptsFileName);
|
|
1011
|
+
const inheritedDefaults = await readInheritedSettingsDefaults(
|
|
1012
|
+
input.repoRoot,
|
|
1013
|
+
input.projectRoot,
|
|
1014
|
+
settingsFileName
|
|
1015
|
+
);
|
|
981
1016
|
const runtimePackages = resolveRuntimePackages();
|
|
982
1017
|
const installCmd = getInstallCommand(input.packageManager, runtimePackages.installSpec);
|
|
983
1018
|
const nextSteps = [];
|
|
@@ -1010,17 +1045,19 @@ async function applyOnboardingPlanInternal(input) {
|
|
|
1010
1045
|
}
|
|
1011
1046
|
}
|
|
1012
1047
|
let injectionFailed = Boolean(input.injectionSkippedRequiresManualConfig);
|
|
1013
|
-
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1048
|
+
if (!additiveManualPlan) {
|
|
1049
|
+
for (const target of input.supportedBuildTargets) {
|
|
1050
|
+
const result = await injectPlugin(
|
|
1051
|
+
input.repoRoot,
|
|
1052
|
+
target,
|
|
1053
|
+
input.options.dryRun,
|
|
1054
|
+
input.options.quiet ?? false
|
|
1055
|
+
);
|
|
1056
|
+
if (result.success) {
|
|
1057
|
+
mutations.push(...result.mutations);
|
|
1058
|
+
} else {
|
|
1059
|
+
injectionFailed = true;
|
|
1060
|
+
}
|
|
1024
1061
|
}
|
|
1025
1062
|
}
|
|
1026
1063
|
if (await exists(settingsPath)) {
|
|
@@ -1030,15 +1067,43 @@ async function applyOnboardingPlanInternal(input) {
|
|
|
1030
1067
|
reporter.hint("Please fix the syntax errors manually, or delete it and re-run init");
|
|
1031
1068
|
nextSteps.push(`Fix .inspecto/${settingsFileName} or delete it and rerun Inspecto setup.`);
|
|
1032
1069
|
} else {
|
|
1033
|
-
|
|
1070
|
+
const mergedSettings = existingSettings && typeof existingSettings === "object" ? { ...existingSettings } : {};
|
|
1071
|
+
let settingsChanged = false;
|
|
1072
|
+
const desiredIde = inheritedDefaults.ide ?? (input.selectedIDE?.supported ? normalizeSupportedIde(input.selectedIDE.ide) : void 0);
|
|
1073
|
+
if (desiredIde && !mergedSettings.ide) {
|
|
1074
|
+
mergedSettings.ide = desiredIde;
|
|
1075
|
+
settingsChanged = true;
|
|
1076
|
+
}
|
|
1077
|
+
const desiredProviderDefault = inheritedDefaults.providerDefault ?? input.providerDefault;
|
|
1078
|
+
if (desiredProviderDefault && !mergedSettings["provider.default"]) {
|
|
1079
|
+
mergedSettings["provider.default"] = desiredProviderDefault;
|
|
1080
|
+
settingsChanged = true;
|
|
1081
|
+
}
|
|
1082
|
+
if (settingsChanged) {
|
|
1083
|
+
if (input.options.dryRun) {
|
|
1084
|
+
reporter.dryRun(`Would update .inspecto/${settingsFileName}`);
|
|
1085
|
+
} else {
|
|
1086
|
+
await writeJSON(settingsPath, mergedSettings);
|
|
1087
|
+
reporter.success(`Updated .inspecto/${settingsFileName} with missing defaults`);
|
|
1088
|
+
mutations.push({
|
|
1089
|
+
type: "file_modified",
|
|
1090
|
+
path: `.inspecto/${settingsFileName}`,
|
|
1091
|
+
description: "Merged missing Inspecto defaults into existing settings"
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
} else {
|
|
1095
|
+
reporter.success(`.inspecto/${settingsFileName} already exists (skipped)`);
|
|
1096
|
+
}
|
|
1034
1097
|
}
|
|
1035
1098
|
} else {
|
|
1036
1099
|
const defaultSettings = {};
|
|
1037
|
-
|
|
1038
|
-
|
|
1100
|
+
const desiredIde = inheritedDefaults.ide ?? (input.selectedIDE?.supported ? normalizeSupportedIde(input.selectedIDE.ide) : void 0);
|
|
1101
|
+
const desiredProviderDefault = inheritedDefaults.providerDefault ?? input.providerDefault;
|
|
1102
|
+
if (desiredIde) {
|
|
1103
|
+
defaultSettings.ide = desiredIde;
|
|
1039
1104
|
}
|
|
1040
|
-
if (
|
|
1041
|
-
defaultSettings["provider.default"] =
|
|
1105
|
+
if (desiredProviderDefault) {
|
|
1106
|
+
defaultSettings["provider.default"] = desiredProviderDefault;
|
|
1042
1107
|
}
|
|
1043
1108
|
if (input.options.dryRun) {
|
|
1044
1109
|
reporter.dryRun(`Would create .inspecto/${settingsFileName}`);
|
|
@@ -1117,6 +1182,9 @@ async function applyOnboardingPlanInternal(input) {
|
|
|
1117
1182
|
if (manualExtensionInstallNeeded) {
|
|
1118
1183
|
nextSteps.push("Install the Inspecto IDE extension manually");
|
|
1119
1184
|
}
|
|
1185
|
+
if (additiveManualPlan && input.plan) {
|
|
1186
|
+
nextSteps.push(...manualPlanSteps(input.plan, false));
|
|
1187
|
+
}
|
|
1120
1188
|
if (input.manualConfigRequiredFor === "Nuxt") {
|
|
1121
1189
|
nextSteps.push(
|
|
1122
1190
|
"Nuxt detected\u2014please follow the Nuxt instructions printed above to finish setup."
|
|
@@ -1167,6 +1235,28 @@ async function getResolvedPackageVersion(pkgName, root) {
|
|
|
1167
1235
|
return null;
|
|
1168
1236
|
}
|
|
1169
1237
|
}
|
|
1238
|
+
function parseFirstSemver(version) {
|
|
1239
|
+
if (!version) return null;
|
|
1240
|
+
const match = version.match(/(\d+)\.(\d+)\.(\d+)/);
|
|
1241
|
+
if (!match) {
|
|
1242
|
+
return null;
|
|
1243
|
+
}
|
|
1244
|
+
return {
|
|
1245
|
+
major: Number(match[1]),
|
|
1246
|
+
minor: Number(match[2]),
|
|
1247
|
+
patch: Number(match[3])
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
function isLegacyRspackVersion(version) {
|
|
1251
|
+
const parsed = parseFirstSemver(version);
|
|
1252
|
+
if (!parsed) return false;
|
|
1253
|
+
return parsed.major === 0 && parsed.minor < 4;
|
|
1254
|
+
}
|
|
1255
|
+
function isLegacyWebpackVersion(version) {
|
|
1256
|
+
const parsed = parseFirstSemver(version);
|
|
1257
|
+
if (!parsed) return false;
|
|
1258
|
+
return parsed.major === 4;
|
|
1259
|
+
}
|
|
1170
1260
|
var SUPPORTED_PATTERNS = [
|
|
1171
1261
|
{
|
|
1172
1262
|
tool: "vite",
|
|
@@ -1192,7 +1282,22 @@ var SUPPORTED_PATTERNS = [
|
|
|
1192
1282
|
},
|
|
1193
1283
|
{
|
|
1194
1284
|
tool: "webpack",
|
|
1195
|
-
files: [
|
|
1285
|
+
files: [
|
|
1286
|
+
"webpack.config.js",
|
|
1287
|
+
"webpack.config.ts",
|
|
1288
|
+
"webpack.config.mjs",
|
|
1289
|
+
"webpack.config.cjs",
|
|
1290
|
+
"webpack.config.common.js",
|
|
1291
|
+
"webpack.config.common.ts",
|
|
1292
|
+
"webpack.config.dev.js",
|
|
1293
|
+
"webpack.config.dev.ts",
|
|
1294
|
+
"webpack.config.prod.js",
|
|
1295
|
+
"webpack.config.prod.ts",
|
|
1296
|
+
"webpack.config.esbuild.js",
|
|
1297
|
+
"webpack.config.esbuild.ts",
|
|
1298
|
+
"webpack.config.build-pre.js",
|
|
1299
|
+
"webpack.config.build-pre.ts"
|
|
1300
|
+
],
|
|
1196
1301
|
label: "Webpack"
|
|
1197
1302
|
},
|
|
1198
1303
|
{
|
|
@@ -1337,6 +1442,89 @@ async function detectBuildTools(root, packagePaths) {
|
|
|
1337
1442
|
}
|
|
1338
1443
|
return { supported, unsupported: Array.from(unsupported) };
|
|
1339
1444
|
}
|
|
1445
|
+
function rankScriptCommand(name, command) {
|
|
1446
|
+
const haystack = `${name} ${command}`.toLowerCase();
|
|
1447
|
+
let score = 0;
|
|
1448
|
+
if (/(^|[\s:_-])(start|dev|serve|watch)([\s:_-]|$)/.test(haystack)) score += 8;
|
|
1449
|
+
if (/(^|[\s:_-])(prod|build|release|stats)([\s:_-]|$)/.test(haystack)) score -= 3;
|
|
1450
|
+
if (/(^|[\s:_-])(dll|vendor)([\s:_-]|$)/.test(haystack)) score -= 6;
|
|
1451
|
+
if (haystack.includes("webpack-dev-server")) score += 3;
|
|
1452
|
+
if (haystack.includes("webpack")) score += 1;
|
|
1453
|
+
if (haystack.includes("rspack")) score += 1;
|
|
1454
|
+
return score;
|
|
1455
|
+
}
|
|
1456
|
+
function extractConfigArgs(scriptContent) {
|
|
1457
|
+
return Array.from(scriptContent.matchAll(/(?:-c|--config)\s+([^\s'"`;]+)/g)).map((match) => match[1]).filter((value) => Boolean(value));
|
|
1458
|
+
}
|
|
1459
|
+
async function resolveScriptRelativeCandidate(targetRoot, scriptPath, candidate) {
|
|
1460
|
+
const normalizedCandidate = candidate.replace(/^['"`]|['"`]$/g, "");
|
|
1461
|
+
const normalizedRelativeCandidate = path7.normalize(normalizedCandidate);
|
|
1462
|
+
const possiblePaths = [];
|
|
1463
|
+
if (normalizedRelativeCandidate.startsWith("..")) {
|
|
1464
|
+
possiblePaths.push(
|
|
1465
|
+
path7.normalize(path7.join(path7.dirname(scriptPath), normalizedRelativeCandidate))
|
|
1466
|
+
);
|
|
1467
|
+
} else {
|
|
1468
|
+
possiblePaths.push(normalizedRelativeCandidate);
|
|
1469
|
+
possiblePaths.push(
|
|
1470
|
+
path7.normalize(path7.join(path7.dirname(scriptPath), normalizedRelativeCandidate))
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1473
|
+
for (const possiblePath of possiblePaths) {
|
|
1474
|
+
if (await exists(path7.join(targetRoot, possiblePath))) {
|
|
1475
|
+
return possiblePath.split(path7.sep).join("/");
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
return null;
|
|
1479
|
+
}
|
|
1480
|
+
async function resolveRspackConfigFromScript(targetRoot, scriptPath) {
|
|
1481
|
+
const scriptContent = await readFile(path7.join(targetRoot, scriptPath));
|
|
1482
|
+
if (!scriptContent) {
|
|
1483
|
+
return null;
|
|
1484
|
+
}
|
|
1485
|
+
for (const candidate of extractConfigArgs(scriptContent)) {
|
|
1486
|
+
const resolved = await resolveScriptRelativeCandidate(targetRoot, scriptPath, candidate);
|
|
1487
|
+
if (resolved) {
|
|
1488
|
+
return resolved;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
const matches = scriptContent.matchAll(
|
|
1492
|
+
/['"`]([^'"`\n]*rspack[^'"`\n]*config[^'"`\n]*\.(?:js|ts|mjs|cjs))['"`]/g
|
|
1493
|
+
);
|
|
1494
|
+
for (const match of matches) {
|
|
1495
|
+
const candidate = match[1];
|
|
1496
|
+
if (!candidate) continue;
|
|
1497
|
+
const resolved = await resolveScriptRelativeCandidate(targetRoot, scriptPath, candidate);
|
|
1498
|
+
if (resolved) {
|
|
1499
|
+
return resolved;
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
return null;
|
|
1503
|
+
}
|
|
1504
|
+
async function resolveWebpackBaseConfigFromFile(targetRoot, configPath) {
|
|
1505
|
+
const configContent = await readFile(path7.join(targetRoot, configPath));
|
|
1506
|
+
if (!configContent) {
|
|
1507
|
+
return null;
|
|
1508
|
+
}
|
|
1509
|
+
for (const candidate of extractConfigArgs(configContent)) {
|
|
1510
|
+
const resolved = await resolveScriptRelativeCandidate(targetRoot, configPath, candidate);
|
|
1511
|
+
if (resolved) {
|
|
1512
|
+
return resolved;
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
const matches = configContent.matchAll(
|
|
1516
|
+
/(?:configPath\s*=\s*|require\()\s*['"`]([^'"`\n]*webpack[^'"`\n]*config[^'"`\n]*\.(?:js|ts|mjs|cjs))['"`]/g
|
|
1517
|
+
);
|
|
1518
|
+
for (const match of matches) {
|
|
1519
|
+
const candidate = match[1];
|
|
1520
|
+
if (!candidate) continue;
|
|
1521
|
+
const resolved = await resolveScriptRelativeCandidate(targetRoot, configPath, candidate);
|
|
1522
|
+
if (resolved) {
|
|
1523
|
+
return resolved;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
return null;
|
|
1527
|
+
}
|
|
1340
1528
|
async function detectPattern({
|
|
1341
1529
|
pattern,
|
|
1342
1530
|
workspaceRoot,
|
|
@@ -1376,13 +1564,38 @@ async function detectPattern({
|
|
|
1376
1564
|
}
|
|
1377
1565
|
}
|
|
1378
1566
|
if (hasDep && !detectedFile && (pattern.tool === "esbuild" || pattern.tool === "rollup" || pattern.tool === "webpack" || pattern.tool === "rspack" || pattern.tool === "rsbuild")) {
|
|
1379
|
-
|
|
1567
|
+
const rankedScripts = Object.entries(scripts).sort(
|
|
1568
|
+
([leftName, leftCommand], [rightName, rightCommand]) => rankScriptCommand(rightName, rightCommand) - rankScriptCommand(leftName, leftCommand)
|
|
1569
|
+
);
|
|
1570
|
+
for (const [, cmd] of rankedScripts) {
|
|
1571
|
+
if (pattern.tool === "webpack" || pattern.tool === "rspack") {
|
|
1572
|
+
for (const configArg of extractConfigArgs(cmd)) {
|
|
1573
|
+
const resolvedConfig = await resolveScriptRelativeCandidate(targetRoot, "", configArg);
|
|
1574
|
+
if (resolvedConfig && (cmd.includes(pattern.tool) || cmd.includes(`${pattern.tool}-`))) {
|
|
1575
|
+
if (pattern.tool === "webpack") {
|
|
1576
|
+
detectedFile = await resolveWebpackBaseConfigFromFile(targetRoot, resolvedConfig) ?? resolvedConfig;
|
|
1577
|
+
} else {
|
|
1578
|
+
detectedFile = await resolveRspackConfigFromScript(targetRoot, resolvedConfig) ?? resolvedConfig;
|
|
1579
|
+
}
|
|
1580
|
+
break;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
if (detectedFile) {
|
|
1584
|
+
break;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1380
1587
|
if (cmd.includes("node ")) {
|
|
1381
1588
|
const match = cmd.match(/node\s+([^\s]+\.(js|mjs|cjs|ts))/);
|
|
1382
1589
|
if (match && match[1]) {
|
|
1383
1590
|
if (await exists(path7.join(targetRoot, match[1]))) {
|
|
1384
1591
|
if (cmd.includes(pattern.tool) || match[1].includes(pattern.tool)) {
|
|
1385
|
-
|
|
1592
|
+
if (pattern.tool === "rspack") {
|
|
1593
|
+
detectedFile = await resolveRspackConfigFromScript(targetRoot, match[1]) ?? match[1];
|
|
1594
|
+
} else if (pattern.tool === "webpack") {
|
|
1595
|
+
detectedFile = await resolveWebpackBaseConfigFromFile(targetRoot, match[1]) ?? match[1];
|
|
1596
|
+
} else {
|
|
1597
|
+
detectedFile = match[1];
|
|
1598
|
+
}
|
|
1386
1599
|
break;
|
|
1387
1600
|
}
|
|
1388
1601
|
}
|
|
@@ -1419,13 +1632,11 @@ async function detectPattern({
|
|
|
1419
1632
|
let isLegacyRspack = false;
|
|
1420
1633
|
let isLegacyWebpack = false;
|
|
1421
1634
|
if (pattern.tool === "rspack") {
|
|
1422
|
-
|
|
1423
|
-
if (version && (version.includes("0.3.") || version.includes("0.2.") || version.includes("0.1."))) {
|
|
1635
|
+
if (isLegacyRspackVersion(resolvedVersion)) {
|
|
1424
1636
|
isLegacyRspack = true;
|
|
1425
1637
|
}
|
|
1426
1638
|
} else if (pattern.tool === "webpack") {
|
|
1427
|
-
|
|
1428
|
-
if (version && version.includes("^4") || version?.startsWith("4.")) {
|
|
1639
|
+
if (isLegacyWebpackVersion(resolvedVersion)) {
|
|
1429
1640
|
isLegacyWebpack = true;
|
|
1430
1641
|
}
|
|
1431
1642
|
}
|
|
@@ -1737,6 +1948,28 @@ function buildToolBlockers(context) {
|
|
|
1737
1948
|
}
|
|
1738
1949
|
return [message("missing-build-tool", "No supported build tool detected")];
|
|
1739
1950
|
}
|
|
1951
|
+
function buildToolWarnings(context) {
|
|
1952
|
+
const warnings = [];
|
|
1953
|
+
if (context.buildTools.supported.length === 1) {
|
|
1954
|
+
const buildTool = context.buildTools.supported[0];
|
|
1955
|
+
if (buildTool.tool === "rspack" && buildTool.isLegacyRspack) {
|
|
1956
|
+
warnings.push(
|
|
1957
|
+
message(
|
|
1958
|
+
"legacy-rspack-requires-manual-config",
|
|
1959
|
+
`Legacy Rspack detected at ${buildTool.configPath}. Inspecto must use the legacy Rspack plugin entry and manual config steps.`
|
|
1960
|
+
)
|
|
1961
|
+
);
|
|
1962
|
+
} else if (buildTool.tool === "webpack" && buildTool.isLegacyWebpack) {
|
|
1963
|
+
warnings.push(
|
|
1964
|
+
message(
|
|
1965
|
+
"legacy-webpack4-requires-manual-config",
|
|
1966
|
+
`Webpack 4 detected at ${buildTool.configPath}. Inspecto must use the legacy Webpack 4 plugin entry and manual config steps.`
|
|
1967
|
+
)
|
|
1968
|
+
);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
return warnings;
|
|
1972
|
+
}
|
|
1740
1973
|
function frameworkBlockers(context) {
|
|
1741
1974
|
if (context.frameworks.supported.length > 0) {
|
|
1742
1975
|
return [];
|
|
@@ -1798,6 +2031,35 @@ function manualBuildToolActions(context) {
|
|
|
1798
2031
|
}
|
|
1799
2032
|
];
|
|
1800
2033
|
}
|
|
2034
|
+
const buildTool = context.buildTools.supported[0];
|
|
2035
|
+
if (buildTool?.tool === "rspack" && buildTool.isLegacyRspack) {
|
|
2036
|
+
return [
|
|
2037
|
+
{
|
|
2038
|
+
type: "install_dependency",
|
|
2039
|
+
target: "@inspecto-dev/plugin @inspecto-dev/core",
|
|
2040
|
+
description: `Install the Inspecto runtime packages with ${context.packageManager}.`
|
|
2041
|
+
},
|
|
2042
|
+
{
|
|
2043
|
+
type: "manual_step",
|
|
2044
|
+
target: buildTool.configPath,
|
|
2045
|
+
description: `Update ${buildTool.configPath} to import \`rspackPlugin\` from \`@inspecto-dev/plugin/legacy/rspack\` and add it to the Rspack plugins array.`
|
|
2046
|
+
}
|
|
2047
|
+
];
|
|
2048
|
+
}
|
|
2049
|
+
if (buildTool?.tool === "webpack" && buildTool.isLegacyWebpack) {
|
|
2050
|
+
return [
|
|
2051
|
+
{
|
|
2052
|
+
type: "install_dependency",
|
|
2053
|
+
target: "@inspecto-dev/plugin @inspecto-dev/core",
|
|
2054
|
+
description: `Install the Inspecto runtime packages with ${context.packageManager}.`
|
|
2055
|
+
},
|
|
2056
|
+
{
|
|
2057
|
+
type: "manual_step",
|
|
2058
|
+
target: buildTool.configPath,
|
|
2059
|
+
description: `Update ${buildTool.configPath} to import \`webpackPlugin\` from \`@inspecto-dev/plugin/legacy/webpack4\` and add it to the Webpack plugins array.`
|
|
2060
|
+
}
|
|
2061
|
+
];
|
|
2062
|
+
}
|
|
1801
2063
|
return [
|
|
1802
2064
|
{
|
|
1803
2065
|
type: "manual_step",
|
|
@@ -1826,7 +2088,10 @@ function manualFrameworkActions(context) {
|
|
|
1826
2088
|
}
|
|
1827
2089
|
async function createDetectionResult(root) {
|
|
1828
2090
|
const context = await buildOnboardingContext(root);
|
|
1829
|
-
const warnings = uniqueMessages([
|
|
2091
|
+
const warnings = uniqueMessages([
|
|
2092
|
+
...unsupportedEnvironmentWarnings(context),
|
|
2093
|
+
...buildToolWarnings(context)
|
|
2094
|
+
]);
|
|
1830
2095
|
const buildToolResult = buildToolBlockers(context);
|
|
1831
2096
|
const frameworkResult = frameworkBlockers(context);
|
|
1832
2097
|
const blockers = uniqueMessages([...buildToolResult, ...frameworkResult]);
|
|
@@ -1849,13 +2114,22 @@ async function createDetectionResult(root) {
|
|
|
1849
2114
|
};
|
|
1850
2115
|
}
|
|
1851
2116
|
function createPlanResult(context) {
|
|
1852
|
-
const warnings = uniqueMessages(
|
|
2117
|
+
const warnings = uniqueMessages([
|
|
2118
|
+
...unsupportedEnvironmentWarnings(context),
|
|
2119
|
+
...buildToolWarnings(context)
|
|
2120
|
+
]);
|
|
1853
2121
|
const blockers = uniqueMessages([...buildToolBlockers(context), ...frameworkBlockers(context)]);
|
|
1854
2122
|
const actions = [];
|
|
1855
2123
|
let strategy = "supported";
|
|
1856
|
-
|
|
2124
|
+
const hasLegacyRspackManualPlan = context.buildTools.supported.length === 1 && context.buildTools.supported[0]?.tool === "rspack" && context.buildTools.supported[0]?.isLegacyRspack;
|
|
2125
|
+
const hasLegacyWebpackManualPlan = context.buildTools.supported.length === 1 && context.buildTools.supported[0]?.tool === "webpack" && context.buildTools.supported[0]?.isLegacyWebpack;
|
|
2126
|
+
if (blockers.length > 0 || hasLegacyRspackManualPlan || hasLegacyWebpackManualPlan) {
|
|
1857
2127
|
strategy = "manual";
|
|
1858
|
-
if (context.buildTools.unsupported.length > 0 || context.buildTools.supported.length === 0 || context.buildTools.supported.length > 1
|
|
2128
|
+
if (context.buildTools.unsupported.length > 0 || context.buildTools.supported.length === 0 || context.buildTools.supported.length > 1 || context.buildTools.supported.some(
|
|
2129
|
+
(buildTool) => buildTool.tool === "rspack" && buildTool.isLegacyRspack
|
|
2130
|
+
) || context.buildTools.supported.some(
|
|
2131
|
+
(buildTool) => buildTool.tool === "webpack" && buildTool.isLegacyWebpack
|
|
2132
|
+
)) {
|
|
1859
2133
|
actions.push(...manualBuildToolActions(context));
|
|
1860
2134
|
}
|
|
1861
2135
|
if (frameworkBlockers(context).length > 0) {
|
|
@@ -2040,10 +2314,26 @@ async function detect(json = false) {
|
|
|
2040
2314
|
import path11 from "path";
|
|
2041
2315
|
|
|
2042
2316
|
// src/onboarding/target-resolution.ts
|
|
2317
|
+
function buildCandidateId(candidate) {
|
|
2318
|
+
return [candidate.packagePath || ".", candidate.buildTool, candidate.configPath].join(":");
|
|
2319
|
+
}
|
|
2043
2320
|
function normalizePackagePath(packagePath) {
|
|
2044
2321
|
if (!packagePath || packagePath === ".") return "";
|
|
2045
2322
|
return packagePath.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
2046
2323
|
}
|
|
2324
|
+
function normalizeTargetValue(target) {
|
|
2325
|
+
if (!target) return "";
|
|
2326
|
+
return target.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "");
|
|
2327
|
+
}
|
|
2328
|
+
function buildSelectionPurpose() {
|
|
2329
|
+
return "Choose the build target that runs your local development build so Inspecto can attach the right plugin and settings.";
|
|
2330
|
+
}
|
|
2331
|
+
function buildSelectionInstructions(hasCandidates) {
|
|
2332
|
+
if (!hasCandidates) {
|
|
2333
|
+
return "If auto-detection missed your build entrypoint, rerun with --target <configPath> using the config file or wrapper script your dev command actually starts.";
|
|
2334
|
+
}
|
|
2335
|
+
return "Rerun with --target <candidateId> using one returned candidateId. The CLI also accepts an exact configPath from the candidate list as a compatibility fallback.";
|
|
2336
|
+
}
|
|
2047
2337
|
function looksLikeAppPackage(packagePath) {
|
|
2048
2338
|
if (!packagePath) return true;
|
|
2049
2339
|
return /(^|\/)(app|apps|web|client|frontend|site)(\/|$)/i.test(packagePath);
|
|
@@ -2054,13 +2344,19 @@ function looksLikeAuxiliaryPackage(packagePath) {
|
|
|
2054
2344
|
function buildCandidates(input) {
|
|
2055
2345
|
return input.buildTools.map((buildTool) => {
|
|
2056
2346
|
const packagePath = normalizePackagePath(buildTool.packagePath);
|
|
2057
|
-
|
|
2347
|
+
const candidate = {
|
|
2058
2348
|
packagePath,
|
|
2059
2349
|
configPath: buildTool.configPath,
|
|
2350
|
+
label: buildTool.label,
|
|
2060
2351
|
buildTool: buildTool.tool,
|
|
2352
|
+
isLegacyRspack: buildTool.isLegacyRspack,
|
|
2353
|
+
isLegacyWebpack: buildTool.isLegacyWebpack,
|
|
2061
2354
|
frameworks: input.frameworkSupportByPackage[packagePath] ?? [],
|
|
2062
2355
|
automaticInjection: true
|
|
2063
2356
|
};
|
|
2357
|
+
candidate.id = buildCandidateId(candidate);
|
|
2358
|
+
candidate.candidateId = candidate.id;
|
|
2359
|
+
return candidate;
|
|
2064
2360
|
});
|
|
2065
2361
|
}
|
|
2066
2362
|
function rankCandidate(candidate) {
|
|
@@ -2083,18 +2379,52 @@ function resolveOnboardingTarget(input) {
|
|
|
2083
2379
|
return {
|
|
2084
2380
|
status: "needs_selection",
|
|
2085
2381
|
candidates,
|
|
2086
|
-
reason: "No supported targets were detected."
|
|
2382
|
+
reason: "No supported targets were detected.",
|
|
2383
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2384
|
+
selectionInstructions: buildSelectionInstructions(false)
|
|
2087
2385
|
};
|
|
2088
2386
|
}
|
|
2089
2387
|
const explicitlySelected = normalizePackagePath(input.selectedPackagePath);
|
|
2388
|
+
const explicitlySelectedValue = normalizeTargetValue(input.selectedPackagePath);
|
|
2090
2389
|
if (input.selectedPackagePath !== void 0) {
|
|
2091
|
-
const
|
|
2390
|
+
const selectedById = candidates.find(
|
|
2391
|
+
(candidate) => candidate.id === input.selectedPackagePath || candidate.candidateId === input.selectedPackagePath
|
|
2392
|
+
);
|
|
2393
|
+
if (selectedById) {
|
|
2394
|
+
return {
|
|
2395
|
+
status: "resolved",
|
|
2396
|
+
selected: selectedById,
|
|
2397
|
+
candidates,
|
|
2398
|
+
reason: `Using the explicitly selected target: ${selectedById.configPath}.`,
|
|
2399
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2400
|
+
selectionInstructions: buildSelectionInstructions(true)
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
const selectedByConfigPath = candidates.find(
|
|
2404
|
+
(candidate) => normalizeTargetValue(candidate.configPath) === explicitlySelectedValue
|
|
2405
|
+
);
|
|
2406
|
+
if (selectedByConfigPath) {
|
|
2407
|
+
return {
|
|
2408
|
+
status: "resolved",
|
|
2409
|
+
selected: selectedByConfigPath,
|
|
2410
|
+
candidates,
|
|
2411
|
+
reason: `Using the explicitly selected config path: ${selectedByConfigPath.configPath}.`,
|
|
2412
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2413
|
+
selectionInstructions: buildSelectionInstructions(true)
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
const matchingPackageCandidates = candidates.filter(
|
|
2417
|
+
(candidate) => candidate.packagePath === explicitlySelected
|
|
2418
|
+
);
|
|
2419
|
+
const selected = matchingPackageCandidates.length === 1 ? matchingPackageCandidates[0] : void 0;
|
|
2092
2420
|
if (selected) {
|
|
2093
2421
|
return {
|
|
2094
2422
|
status: "resolved",
|
|
2095
2423
|
selected,
|
|
2096
2424
|
candidates,
|
|
2097
|
-
reason: `Using the explicitly selected target: ${selected.packagePath || "."}
|
|
2425
|
+
reason: `Using the explicitly selected target: ${selected.packagePath || "."}.`,
|
|
2426
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2427
|
+
selectionInstructions: buildSelectionInstructions(true)
|
|
2098
2428
|
};
|
|
2099
2429
|
}
|
|
2100
2430
|
}
|
|
@@ -2103,7 +2433,9 @@ function resolveOnboardingTarget(input) {
|
|
|
2103
2433
|
status: "resolved",
|
|
2104
2434
|
selected: candidates[0],
|
|
2105
2435
|
candidates,
|
|
2106
|
-
reason: "Only one supported target was detected."
|
|
2436
|
+
reason: "Only one supported target was detected.",
|
|
2437
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2438
|
+
selectionInstructions: buildSelectionInstructions(true)
|
|
2107
2439
|
};
|
|
2108
2440
|
}
|
|
2109
2441
|
const ranked = rankCandidates(candidates);
|
|
@@ -2111,14 +2443,18 @@ function resolveOnboardingTarget(input) {
|
|
|
2111
2443
|
return {
|
|
2112
2444
|
status: "needs_selection",
|
|
2113
2445
|
candidates,
|
|
2114
|
-
reason: "Multiple supported targets look equally plausible."
|
|
2446
|
+
reason: "Multiple supported targets look equally plausible.",
|
|
2447
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2448
|
+
selectionInstructions: buildSelectionInstructions(true)
|
|
2115
2449
|
};
|
|
2116
2450
|
}
|
|
2117
2451
|
return {
|
|
2118
2452
|
status: "resolved",
|
|
2119
2453
|
selected: ranked[0].candidate,
|
|
2120
2454
|
candidates,
|
|
2121
|
-
reason: `Preselected ${ranked[0].candidate.packagePath || "."} because it has the strongest supported app signal
|
|
2455
|
+
reason: `Preselected ${ranked[0].candidate.packagePath || "."} because it has the strongest supported app signal.`,
|
|
2456
|
+
selectionPurpose: buildSelectionPurpose(),
|
|
2457
|
+
selectionInstructions: buildSelectionInstructions(true)
|
|
2122
2458
|
};
|
|
2123
2459
|
}
|
|
2124
2460
|
|
|
@@ -2819,6 +3155,25 @@ async function collectDoctorResult(root = process.cwd()) {
|
|
|
2819
3155
|
const settings = await readJSON(targetPath);
|
|
2820
3156
|
if (settings) {
|
|
2821
3157
|
checks.push(createDiagnostic("settings-valid", "ok", `.inspecto/${fileName} valid`));
|
|
3158
|
+
const configuredIde = typeof settings.ide === "string" ? settings.ide : void 0;
|
|
3159
|
+
const detectedIdeCandidates = ideProbe.detected.map((item) => item.ide);
|
|
3160
|
+
if (configuredIde && detectedIdeCandidates.length > 0 && !detectedIdeCandidates.includes(configuredIde)) {
|
|
3161
|
+
checks.push(
|
|
3162
|
+
createDiagnostic(
|
|
3163
|
+
"settings-ide-mismatch",
|
|
3164
|
+
"warning",
|
|
3165
|
+
`.inspecto/${fileName} sets ide=${configuredIde}, but the current environment looks like ${detectedIdeCandidates.join(", ")}. Inspecto will use the configured IDE from ${fileName}.`,
|
|
3166
|
+
[
|
|
3167
|
+
`Update .inspecto/${fileName} if you want Inspecto to target the currently detected IDE instead.`
|
|
3168
|
+
],
|
|
3169
|
+
{
|
|
3170
|
+
configuredIde,
|
|
3171
|
+
detectedIdeCandidates,
|
|
3172
|
+
precedence: `configured ide from ${fileName}`
|
|
3173
|
+
}
|
|
3174
|
+
)
|
|
3175
|
+
);
|
|
3176
|
+
}
|
|
2822
3177
|
} else {
|
|
2823
3178
|
checks.push(
|
|
2824
3179
|
createDiagnostic(
|
|
@@ -2954,7 +3309,8 @@ async function detectFrameworkSupportByPackage2(repoRoot, context) {
|
|
|
2954
3309
|
);
|
|
2955
3310
|
return supportByPackage;
|
|
2956
3311
|
}
|
|
2957
|
-
async function buildTargetedContext(rootContext,
|
|
3312
|
+
async function buildTargetedContext(rootContext, target) {
|
|
3313
|
+
const packagePath = normalizePackagePath2(target.packagePath);
|
|
2958
3314
|
const projectRoot = packagePath ? path13.join(rootContext.root, packagePath) : rootContext.root;
|
|
2959
3315
|
const [frameworks, ides, providers] = await Promise.all([
|
|
2960
3316
|
detectFrameworks(projectRoot),
|
|
@@ -2966,7 +3322,11 @@ async function buildTargetedContext(rootContext, packagePath) {
|
|
|
2966
3322
|
packageManager: rootContext.packageManager,
|
|
2967
3323
|
buildTools: {
|
|
2968
3324
|
supported: rootContext.buildTools.supported.filter((item) => {
|
|
2969
|
-
|
|
3325
|
+
const itemPackagePath = normalizePackagePath2(item.packagePath);
|
|
3326
|
+
if (target.id) {
|
|
3327
|
+
return `${itemPackagePath || "."}:${item.tool}:${item.configPath}` === target.id;
|
|
3328
|
+
}
|
|
3329
|
+
return itemPackagePath === packagePath;
|
|
2970
3330
|
}),
|
|
2971
3331
|
unsupported: []
|
|
2972
3332
|
},
|
|
@@ -3102,7 +3462,7 @@ async function resolveOnboardingSession(root, options = {}) {
|
|
|
3102
3462
|
if (target.status === "needs_selection") {
|
|
3103
3463
|
const plan3 = createPlanResult(rootContext);
|
|
3104
3464
|
const summary2 = {
|
|
3105
|
-
headline: "Inspecto
|
|
3465
|
+
headline: "Inspecto needs one build target selection before setup so it knows which local dev build should receive the plugin and settings.",
|
|
3106
3466
|
changes: [],
|
|
3107
3467
|
risks: [],
|
|
3108
3468
|
manualFollowUp: []
|
|
@@ -3118,8 +3478,7 @@ async function resolveOnboardingSession(root, options = {}) {
|
|
|
3118
3478
|
projectRoot: root
|
|
3119
3479
|
};
|
|
3120
3480
|
}
|
|
3121
|
-
const
|
|
3122
|
-
const context = await buildTargetedContext(rootContext, packagePath);
|
|
3481
|
+
const context = await buildTargetedContext(rootContext, target.selected);
|
|
3123
3482
|
const verification = await buildVerification(context.root, context.packageManager);
|
|
3124
3483
|
const plan2 = createPlanResult(context);
|
|
3125
3484
|
const summary = buildOnboardingSummary(plan2, context.root);
|
|
@@ -3172,7 +3531,8 @@ async function applyResolvedOnboardingSession(session, options = {}) {
|
|
|
3172
3531
|
},
|
|
3173
3532
|
selectedIDE: session.selectedIDE,
|
|
3174
3533
|
providerDefault: session.providerDefault,
|
|
3175
|
-
plan: session.plan
|
|
3534
|
+
plan: session.plan,
|
|
3535
|
+
allowManualPlanApply: session.plan.strategy === "manual" && session.plan.blockers.length === 0
|
|
3176
3536
|
});
|
|
3177
3537
|
const diagnostics = buildExecutionDiagnostics(session, applyResult);
|
|
3178
3538
|
const status = applyResult.postInstall.installFailed && session.context.buildTools.supported.length === 0 ? "error" : diagnostics?.nextSteps.length || diagnostics?.errors.length || diagnostics?.warnings.length ? "partial_success" : "success";
|
|
@@ -3215,6 +3575,19 @@ function printOnboardResult(result) {
|
|
|
3215
3575
|
log.header("Inspecto Onboard");
|
|
3216
3576
|
log.info(`Status: ${result.status}`);
|
|
3217
3577
|
log.info(result.summary.headline);
|
|
3578
|
+
if (result.status === "needs_target_selection") {
|
|
3579
|
+
if (result.target.selectionPurpose) {
|
|
3580
|
+
log.warn(result.target.selectionPurpose);
|
|
3581
|
+
}
|
|
3582
|
+
for (const candidate of result.target.candidates) {
|
|
3583
|
+
const identifier = candidate.candidateId ?? candidate.id ?? candidate.configPath;
|
|
3584
|
+
const label = candidate.label ?? candidate.configPath;
|
|
3585
|
+
log.hint(`${identifier}: ${label}`);
|
|
3586
|
+
}
|
|
3587
|
+
if (result.target.selectionInstructions) {
|
|
3588
|
+
log.hint(result.target.selectionInstructions);
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3218
3591
|
for (const change of result.summary.changes) {
|
|
3219
3592
|
log.hint(change);
|
|
3220
3593
|
}
|
|
@@ -3889,6 +4262,10 @@ function getDispatchModeLabel(assistant, ide, mode) {
|
|
|
3889
4262
|
}
|
|
3890
4263
|
|
|
3891
4264
|
// src/commands/integration-install.ts
|
|
4265
|
+
import {
|
|
4266
|
+
DEFAULT_PROVIDER_MODE,
|
|
4267
|
+
VALID_MODES
|
|
4268
|
+
} from "@inspecto-dev/types";
|
|
3892
4269
|
var REPO_RAW_BASE = "https://raw.githubusercontent.com/inspecto-dev/inspecto/main";
|
|
3893
4270
|
var TOTAL_STEPS2 = 6;
|
|
3894
4271
|
var INTEGRATION_MANIFESTS = [
|
|
@@ -3937,7 +4314,7 @@ var INTEGRATION_MANIFESTS = [
|
|
|
3937
4314
|
{
|
|
3938
4315
|
assistant: "coco",
|
|
3939
4316
|
type: "native-skill",
|
|
3940
|
-
installTarget: ".
|
|
4317
|
+
installTarget: ".trae/skills/inspecto-onboarding/",
|
|
3941
4318
|
preferredInstall: "npx @inspecto-dev/cli integrations install coco --host-ide <vscode|cursor|trae|trae-cn>",
|
|
3942
4319
|
cliSupported: true
|
|
3943
4320
|
}
|
|
@@ -3996,6 +4373,9 @@ ${content}`;
|
|
|
3996
4373
|
}
|
|
3997
4374
|
}
|
|
3998
4375
|
}
|
|
4376
|
+
if (shouldPersistProjectOnboardingDefaults(options)) {
|
|
4377
|
+
await persistProjectOnboardingDefaults(assistant, options);
|
|
4378
|
+
}
|
|
3999
4379
|
const stepOneMessage = options.preview ? formatIntegrationStep2(1, `Previewing ${getAssistantLabel2(assistant)} integration assets`) : formatIntegrationStep2(1, `Installed ${getAssistantLabel2(assistant)} integration assets`);
|
|
4000
4380
|
if (!silent) {
|
|
4001
4381
|
if (options.preview) {
|
|
@@ -4081,6 +4461,46 @@ ${content}`;
|
|
|
4081
4461
|
}
|
|
4082
4462
|
return result;
|
|
4083
4463
|
}
|
|
4464
|
+
function shouldPersistProjectOnboardingDefaults(options) {
|
|
4465
|
+
return !options.preview && !shouldSkipAutomationForInstall(options) && isSupportedHostIde(options.ide);
|
|
4466
|
+
}
|
|
4467
|
+
function isProviderAssistant(value) {
|
|
4468
|
+
return Object.prototype.hasOwnProperty.call(VALID_MODES, value);
|
|
4469
|
+
}
|
|
4470
|
+
async function resolveProviderDefaultForAssistant(assistant, ide) {
|
|
4471
|
+
if (!isProviderAssistant(assistant)) {
|
|
4472
|
+
return void 0;
|
|
4473
|
+
}
|
|
4474
|
+
let mode;
|
|
4475
|
+
if (assistant === "codex" || assistant === "claude-code" || assistant === "gemini") {
|
|
4476
|
+
const dispatchMode = await resolveIntegrationDispatchMode({ assistant, hostIde: ide });
|
|
4477
|
+
mode = dispatchMode.mode ?? DEFAULT_PROVIDER_MODE[assistant];
|
|
4478
|
+
} else {
|
|
4479
|
+
mode = DEFAULT_PROVIDER_MODE[assistant];
|
|
4480
|
+
}
|
|
4481
|
+
if (!mode || !VALID_MODES[assistant].includes(mode)) {
|
|
4482
|
+
return void 0;
|
|
4483
|
+
}
|
|
4484
|
+
return `${assistant}.${mode}`;
|
|
4485
|
+
}
|
|
4486
|
+
async function persistProjectOnboardingDefaults(assistant, options) {
|
|
4487
|
+
const settingsPath = path17.join(process.cwd(), ".inspecto", "settings.local.json");
|
|
4488
|
+
const existingSettings = await readJSON(settingsPath);
|
|
4489
|
+
const resolvedHostIde = await resolveIntegrationHostIde({
|
|
4490
|
+
explicitIde: options.ide,
|
|
4491
|
+
cwd: process.cwd()
|
|
4492
|
+
});
|
|
4493
|
+
const providerDefault = resolvedHostIde.ide && resolvedHostIde.confidence !== "low" ? await resolveProviderDefaultForAssistant(assistant, resolvedHostIde.ide) : void 0;
|
|
4494
|
+
const mergedSettings = existingSettings && typeof existingSettings === "object" ? {
|
|
4495
|
+
...existingSettings,
|
|
4496
|
+
ide: options.ide,
|
|
4497
|
+
...providerDefault ? { "provider.default": providerDefault } : {}
|
|
4498
|
+
} : {
|
|
4499
|
+
ide: options.ide,
|
|
4500
|
+
...providerDefault ? { "provider.default": providerDefault } : {}
|
|
4501
|
+
};
|
|
4502
|
+
await writeJSON(settingsPath, mergedSettings);
|
|
4503
|
+
}
|
|
4084
4504
|
function shouldSkipAutomationForInstall(options) {
|
|
4085
4505
|
return options.scope === "user" && !options.preview;
|
|
4086
4506
|
}
|
|
@@ -4143,6 +4563,12 @@ function resolveInstallPlan(assistant, options) {
|
|
|
4143
4563
|
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-trae/SKILL.md`,
|
|
4144
4564
|
target: ".trae/skills/inspecto-onboarding/SKILL.md",
|
|
4145
4565
|
localSource: "skills/inspecto-onboarding-trae/SKILL.md"
|
|
4566
|
+
},
|
|
4567
|
+
{
|
|
4568
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-trae/scripts/run-inspecto.sh`,
|
|
4569
|
+
target: ".trae/skills/inspecto-onboarding/scripts/run-inspecto.sh",
|
|
4570
|
+
localSource: "skills/inspecto-onboarding-trae/scripts/run-inspecto.sh",
|
|
4571
|
+
executable: true
|
|
4146
4572
|
}
|
|
4147
4573
|
],
|
|
4148
4574
|
successMessage: "Installed Trae skill to .trae/skills/inspecto-onboarding/SKILL.md",
|
|
@@ -4153,11 +4579,17 @@ function resolveInstallPlan(assistant, options) {
|
|
|
4153
4579
|
assets: [
|
|
4154
4580
|
{
|
|
4155
4581
|
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-trae/SKILL.md`,
|
|
4156
|
-
target: ".
|
|
4582
|
+
target: ".trae/skills/inspecto-onboarding/SKILL.md",
|
|
4157
4583
|
localSource: "skills/inspecto-onboarding-trae/SKILL.md"
|
|
4584
|
+
},
|
|
4585
|
+
{
|
|
4586
|
+
source: `${REPO_RAW_BASE}/skills/inspecto-onboarding-trae/scripts/run-inspecto.sh`,
|
|
4587
|
+
target: ".trae/skills/inspecto-onboarding/scripts/run-inspecto.sh",
|
|
4588
|
+
localSource: "skills/inspecto-onboarding-trae/scripts/run-inspecto.sh",
|
|
4589
|
+
executable: true
|
|
4158
4590
|
}
|
|
4159
4591
|
],
|
|
4160
|
-
successMessage: "Installed Coco skill to .
|
|
4592
|
+
successMessage: "Installed Coco skill to .trae/skills/inspecto-onboarding/SKILL.md",
|
|
4161
4593
|
nextStep: "Start a new Coco session."
|
|
4162
4594
|
};
|
|
4163
4595
|
default:
|