dlw-machine-setup 0.5.16 → 0.5.18
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/installer.js +148 -46
- package/package.json +1 -1
package/bin/installer.js
CHANGED
|
@@ -3388,6 +3388,7 @@ async function tryOrgReposList(headers, topic) {
|
|
|
3388
3388
|
var import_fs = require("fs");
|
|
3389
3389
|
var import_path = require("path");
|
|
3390
3390
|
var import_os = require("os");
|
|
3391
|
+
var import_child_process = require("child_process");
|
|
3391
3392
|
var GITHUB_CLIENT_ID = "Ov23liwpMumAhwVufZ7N";
|
|
3392
3393
|
var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
|
|
3393
3394
|
var GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
@@ -3511,11 +3512,26 @@ async function authenticateWithGitHub() {
|
|
|
3511
3512
|
console.log("You'll authenticate once, and the token will be cached for future use.\n");
|
|
3512
3513
|
console.log("Requesting authorization code...");
|
|
3513
3514
|
const deviceCodeData = await requestDeviceCode();
|
|
3515
|
+
let copied = false;
|
|
3516
|
+
try {
|
|
3517
|
+
const os = (0, import_os.platform)();
|
|
3518
|
+
if (os === "win32") {
|
|
3519
|
+
(0, import_child_process.execSync)(`echo ${deviceCodeData.user_code} | clip`, { stdio: "ignore" });
|
|
3520
|
+
copied = true;
|
|
3521
|
+
} else if (os === "darwin") {
|
|
3522
|
+
(0, import_child_process.execSync)(`echo "${deviceCodeData.user_code}" | pbcopy`, { stdio: "ignore" });
|
|
3523
|
+
copied = true;
|
|
3524
|
+
} else {
|
|
3525
|
+
(0, import_child_process.execSync)(`echo "${deviceCodeData.user_code}" | xclip -selection clipboard`, { stdio: "ignore" });
|
|
3526
|
+
copied = true;
|
|
3527
|
+
}
|
|
3528
|
+
} catch {
|
|
3529
|
+
}
|
|
3514
3530
|
console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
|
|
3515
3531
|
console.log("\u2551 GitHub Authentication \u2551");
|
|
3516
3532
|
console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
|
|
3517
3533
|
console.log(`1. Visit: ${deviceCodeData.verification_uri}`);
|
|
3518
|
-
console.log(`2. Enter code: ${deviceCodeData.user_code}`);
|
|
3534
|
+
console.log(`2. Enter code: ${deviceCodeData.user_code}${copied ? " (copied to clipboard!)" : ""}`);
|
|
3519
3535
|
console.log("\nWaiting for authentication...");
|
|
3520
3536
|
console.log("(This window will continue automatically once you approve)\n");
|
|
3521
3537
|
const accessToken = await pollForToken(
|
|
@@ -3622,6 +3638,7 @@ var steps_exports = {};
|
|
|
3622
3638
|
__export(steps_exports, {
|
|
3623
3639
|
fetchContexts: () => fetch_contexts_default,
|
|
3624
3640
|
fetchFactory: () => fetch_factory_default,
|
|
3641
|
+
runMcpInstallCommands: () => run_mcp_install_commands_default,
|
|
3625
3642
|
updateGitignore: () => update_gitignore_default,
|
|
3626
3643
|
writeInstructions: () => write_instructions_default,
|
|
3627
3644
|
writeMcpConfig: () => write_mcp_config_default,
|
|
@@ -3631,7 +3648,7 @@ __export(steps_exports, {
|
|
|
3631
3648
|
// src/steps/resources/fetch-contexts.ts
|
|
3632
3649
|
var import_fs2 = require("fs");
|
|
3633
3650
|
var import_path2 = require("path");
|
|
3634
|
-
var
|
|
3651
|
+
var import_child_process2 = require("child_process");
|
|
3635
3652
|
var MIN_FILE_SIZE = 1024;
|
|
3636
3653
|
var fetch_contexts_default = defineStep({
|
|
3637
3654
|
name: "fetch-contexts",
|
|
@@ -3640,10 +3657,20 @@ var fetch_contexts_default = defineStep({
|
|
|
3640
3657
|
execute: async (ctx) => {
|
|
3641
3658
|
const uniqueDomains = [...new Set(ctx.config.technologies.flatMap((p) => p.domains))];
|
|
3642
3659
|
const domainValues = uniqueDomains.map((d) => d.toLowerCase());
|
|
3643
|
-
|
|
3660
|
+
if (!ctx.contextRepo) {
|
|
3661
|
+
for (const domain of domainValues) {
|
|
3662
|
+
ctx.installed.domainsFailed = domainValues;
|
|
3663
|
+
}
|
|
3664
|
+
return {
|
|
3665
|
+
status: "failed",
|
|
3666
|
+
detail: "Context repo not found (topic: context-data)"
|
|
3667
|
+
};
|
|
3668
|
+
}
|
|
3669
|
+
const downloadResult = await fetchContexts(domainValues, ctx.token, ctx.contextRepo, ctx.config.projectPath);
|
|
3644
3670
|
ctx.installed.domainsInstalled = downloadResult.successful;
|
|
3645
3671
|
ctx.installed.domainsFailed = downloadResult.failed;
|
|
3646
3672
|
ctx.installed.failureReasons = downloadResult.failureReasons;
|
|
3673
|
+
ctx.installed.contextReleaseVersion = downloadResult.releaseVersion;
|
|
3647
3674
|
const domainColWidth = Math.max(...domainValues.map((d) => d.length), 8) + 2;
|
|
3648
3675
|
console.log("");
|
|
3649
3676
|
for (const domain of domainValues) {
|
|
@@ -3667,7 +3694,7 @@ var fetch_contexts_default = defineStep({
|
|
|
3667
3694
|
async function fetchContexts(domains, token, repo, targetDir) {
|
|
3668
3695
|
const result = { successful: [], failed: [], failureReasons: {} };
|
|
3669
3696
|
if (domains.length === 0) return result;
|
|
3670
|
-
const tarCheck = (0,
|
|
3697
|
+
const tarCheck = (0, import_child_process2.spawnSync)("tar", ["--version"], { stdio: "ignore" });
|
|
3671
3698
|
if (tarCheck.status !== 0) {
|
|
3672
3699
|
throw new Error("tar command not found. Please ensure tar is installed and available in your PATH.");
|
|
3673
3700
|
}
|
|
@@ -3683,52 +3710,58 @@ async function fetchContexts(domains, token, repo, targetDir) {
|
|
|
3683
3710
|
throw new Error(`GitHub API error (${releaseResponse.status}): ${getReadableError(releaseResponse.status)}`);
|
|
3684
3711
|
}
|
|
3685
3712
|
const releaseData = await releaseResponse.json();
|
|
3713
|
+
result.releaseVersion = releaseData.tag_name;
|
|
3714
|
+
const asset = releaseData.assets?.find((a) => a.name.endsWith(".tar.gz"));
|
|
3715
|
+
if (!asset) {
|
|
3716
|
+
for (const domain of domains) {
|
|
3717
|
+
result.failed.push(domain);
|
|
3718
|
+
result.failureReasons[domain] = "No tar.gz asset in release";
|
|
3719
|
+
}
|
|
3720
|
+
return result;
|
|
3721
|
+
}
|
|
3686
3722
|
const contextsDir = (0, import_path2.join)(targetDir, "_ai-context");
|
|
3687
3723
|
const tempDir = (0, import_path2.join)(targetDir, ".temp-download");
|
|
3688
3724
|
try {
|
|
3689
3725
|
if (!(0, import_fs2.existsSync)(contextsDir)) (0, import_fs2.mkdirSync)(contextsDir, { recursive: true });
|
|
3690
3726
|
if ((0, import_fs2.existsSync)(tempDir)) (0, import_fs2.rmSync)(tempDir, { recursive: true, force: true });
|
|
3691
3727
|
(0, import_fs2.mkdirSync)(tempDir, { recursive: true });
|
|
3728
|
+
const downloadHeaders = {
|
|
3729
|
+
"Accept": "application/octet-stream",
|
|
3730
|
+
"Authorization": `Bearer ${token}`
|
|
3731
|
+
};
|
|
3732
|
+
const response = await fetchWithRetry(asset.url, { headers: downloadHeaders });
|
|
3733
|
+
if (!response.ok) {
|
|
3734
|
+
throw new Error(`Download failed: ${getReadableError(response.status)}`);
|
|
3735
|
+
}
|
|
3736
|
+
const archivePath = (0, import_path2.join)(tempDir, asset.name);
|
|
3737
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
3738
|
+
(0, import_fs2.writeFileSync)(archivePath, Buffer.from(arrayBuffer));
|
|
3739
|
+
const stats = (0, import_fs2.statSync)(archivePath);
|
|
3740
|
+
if (stats.size < MIN_FILE_SIZE) {
|
|
3741
|
+
throw new Error("File corrupted");
|
|
3742
|
+
}
|
|
3743
|
+
const listResult = (0, import_child_process2.spawnSync)("tar", ["-tzf", archivePath], { encoding: "utf8" });
|
|
3744
|
+
if (listResult.status !== 0) throw new Error("Failed to read archive contents");
|
|
3745
|
+
const resolvedTempDir = (0, import_path2.resolve)(tempDir);
|
|
3746
|
+
for (const entry of listResult.stdout.split("\n").filter(Boolean)) {
|
|
3747
|
+
const entryPath = (0, import_path2.resolve)((0, import_path2.join)(tempDir, entry.replace(/\/$/, "")));
|
|
3748
|
+
if (!entryPath.startsWith(resolvedTempDir + import_path2.sep)) {
|
|
3749
|
+
throw new Error(`Archive contains unsafe path: ${entry}`);
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
const extractResult = (0, import_child_process2.spawnSync)("tar", ["-xzf", archivePath, "-C", tempDir], { stdio: "ignore" });
|
|
3753
|
+
if (extractResult.status !== 0) throw new Error("Archive extraction failed");
|
|
3754
|
+
const extractedFolders = (0, import_fs2.readdirSync)(tempDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
3692
3755
|
for (const domain of domains) {
|
|
3693
3756
|
try {
|
|
3694
|
-
const
|
|
3695
|
-
|
|
3696
|
-
const asset = releaseData.assets?.find((a) => a.name === archiveName);
|
|
3697
|
-
if (!asset) {
|
|
3757
|
+
const match = extractedFolders.find((f) => f.toLowerCase() === domain.toLowerCase());
|
|
3758
|
+
if (!match) {
|
|
3698
3759
|
result.failed.push(domain);
|
|
3699
|
-
result.failureReasons[domain] = "Not found in
|
|
3760
|
+
result.failureReasons[domain] = "Not found in archive";
|
|
3700
3761
|
continue;
|
|
3701
3762
|
}
|
|
3702
|
-
const
|
|
3703
|
-
|
|
3704
|
-
"Authorization": `Bearer ${token}`
|
|
3705
|
-
};
|
|
3706
|
-
const response = await fetchWithRetry(asset.url, { headers: downloadHeaders });
|
|
3707
|
-
if (!response.ok) {
|
|
3708
|
-
throw new Error(`Download failed: ${getReadableError(response.status)}`);
|
|
3709
|
-
}
|
|
3710
|
-
const archivePath = (0, import_path2.join)(tempDir, archiveName);
|
|
3711
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
3712
|
-
(0, import_fs2.writeFileSync)(archivePath, Buffer.from(arrayBuffer));
|
|
3713
|
-
const stats = (0, import_fs2.statSync)(archivePath);
|
|
3714
|
-
if (stats.size < MIN_FILE_SIZE) {
|
|
3715
|
-
throw new Error("File corrupted");
|
|
3716
|
-
}
|
|
3717
|
-
const listResult = (0, import_child_process.spawnSync)("tar", ["-tzf", archivePath], { encoding: "utf8" });
|
|
3718
|
-
if (listResult.status !== 0) throw new Error("Failed to read archive contents");
|
|
3719
|
-
const resolvedTempDir = (0, import_path2.resolve)(tempDir);
|
|
3720
|
-
for (const entry of listResult.stdout.split("\n").filter(Boolean)) {
|
|
3721
|
-
const entryPath = (0, import_path2.resolve)((0, import_path2.join)(tempDir, entry.replace(/\/$/, "")));
|
|
3722
|
-
if (!entryPath.startsWith(resolvedTempDir + import_path2.sep)) {
|
|
3723
|
-
throw new Error(`Archive contains unsafe path: ${entry}`);
|
|
3724
|
-
}
|
|
3725
|
-
}
|
|
3726
|
-
const extractResult = (0, import_child_process.spawnSync)("tar", ["-xzf", archivePath, "-C", tempDir], { stdio: "ignore" });
|
|
3727
|
-
if (extractResult.status !== 0) throw new Error("Archive extraction failed");
|
|
3728
|
-
const extractedEntries = (0, import_fs2.readdirSync)(tempDir);
|
|
3729
|
-
const extractedFolder = extractedEntries.find((e) => e.toLowerCase() === domain.toLowerCase());
|
|
3730
|
-
if (!extractedFolder) throw new Error("Extraction failed");
|
|
3731
|
-
copyDirectory((0, import_path2.join)(tempDir, extractedFolder), domainPath);
|
|
3763
|
+
const domainPath = (0, import_path2.join)(contextsDir, domain);
|
|
3764
|
+
copyDirectory((0, import_path2.join)(tempDir, match), domainPath);
|
|
3732
3765
|
result.successful.push(domain);
|
|
3733
3766
|
} catch (error) {
|
|
3734
3767
|
result.failed.push(domain);
|
|
@@ -3780,7 +3813,7 @@ function getReadableError(status) {
|
|
|
3780
3813
|
// src/steps/resources/fetch-factory.ts
|
|
3781
3814
|
var import_fs3 = require("fs");
|
|
3782
3815
|
var import_path3 = require("path");
|
|
3783
|
-
var
|
|
3816
|
+
var import_child_process3 = require("child_process");
|
|
3784
3817
|
var MIN_FILE_SIZE2 = 1024;
|
|
3785
3818
|
function getFactoryAsset(agent) {
|
|
3786
3819
|
switch (agent) {
|
|
@@ -3805,7 +3838,7 @@ var fetch_factory_default = defineStep({
|
|
|
3805
3838
|
});
|
|
3806
3839
|
async function fetchFactory(token, repo, targetDir, agent) {
|
|
3807
3840
|
const result = { success: false, filesInstalled: [] };
|
|
3808
|
-
const tarCheck = (0,
|
|
3841
|
+
const tarCheck = (0, import_child_process3.spawnSync)("tar", ["--version"], { stdio: "ignore" });
|
|
3809
3842
|
if (tarCheck.status !== 0) {
|
|
3810
3843
|
result.failureReason = "tar command not found";
|
|
3811
3844
|
return result;
|
|
@@ -3848,7 +3881,7 @@ async function fetchFactory(token, repo, targetDir, agent) {
|
|
|
3848
3881
|
result.failureReason = "Downloaded file corrupted (too small)";
|
|
3849
3882
|
return result;
|
|
3850
3883
|
}
|
|
3851
|
-
const listResult = (0,
|
|
3884
|
+
const listResult = (0, import_child_process3.spawnSync)("tar", ["-tzf", archivePath], { encoding: "utf8" });
|
|
3852
3885
|
if (listResult.status !== 0) {
|
|
3853
3886
|
result.failureReason = "Failed to read archive contents";
|
|
3854
3887
|
return result;
|
|
@@ -3861,7 +3894,7 @@ async function fetchFactory(token, repo, targetDir, agent) {
|
|
|
3861
3894
|
return result;
|
|
3862
3895
|
}
|
|
3863
3896
|
}
|
|
3864
|
-
const extractResult = (0,
|
|
3897
|
+
const extractResult = (0, import_child_process3.spawnSync)("tar", ["-xzf", archivePath, "-C", tempDir], { stdio: "ignore" });
|
|
3865
3898
|
if (extractResult.status !== 0) {
|
|
3866
3899
|
result.failureReason = "Archive extraction failed";
|
|
3867
3900
|
return result;
|
|
@@ -4336,7 +4369,7 @@ var write_mcp_config_default = defineStep({
|
|
|
4336
4369
|
const existingServers = existingFile[target.rootKey] ?? {};
|
|
4337
4370
|
const newServers = {};
|
|
4338
4371
|
for (const [serverName, serverConfig] of Object.entries(filteredMcpConfig)) {
|
|
4339
|
-
const { description, useWhen, active, ...mcpFields } = serverConfig;
|
|
4372
|
+
const { description, useWhen, active, installCommand, ...mcpFields } = serverConfig;
|
|
4340
4373
|
newServers[serverName] = mcpFields;
|
|
4341
4374
|
addedServers.push(serverName);
|
|
4342
4375
|
}
|
|
@@ -4362,6 +4395,66 @@ function getAgentMCPTarget(agent) {
|
|
|
4362
4395
|
}
|
|
4363
4396
|
}
|
|
4364
4397
|
|
|
4398
|
+
// src/steps/setup/run-mcp-install-commands.ts
|
|
4399
|
+
var import_child_process4 = require("child_process");
|
|
4400
|
+
var run_mcp_install_commands_default = defineStep({
|
|
4401
|
+
name: "run-mcp-install-commands",
|
|
4402
|
+
label: "Registering MCP servers with Claude Code",
|
|
4403
|
+
when: (ctx) => {
|
|
4404
|
+
if (ctx.config.agent !== "claude-code") return false;
|
|
4405
|
+
const filtered = getFilteredMcpConfig(ctx);
|
|
4406
|
+
return Object.values(filtered).some((s) => typeof s.installCommand === "string" && s.installCommand.length > 0);
|
|
4407
|
+
},
|
|
4408
|
+
execute: async (ctx) => {
|
|
4409
|
+
if (!isClaudeCliAvailable()) {
|
|
4410
|
+
return {
|
|
4411
|
+
status: "skipped",
|
|
4412
|
+
detail: "`claude` CLI not found on PATH \u2014 skipping CLI registration (project .mcp.json was still written)"
|
|
4413
|
+
};
|
|
4414
|
+
}
|
|
4415
|
+
const filtered = getFilteredMcpConfig(ctx);
|
|
4416
|
+
const succeeded = [];
|
|
4417
|
+
const failed = [];
|
|
4418
|
+
for (const [name, cfg] of Object.entries(filtered)) {
|
|
4419
|
+
const cmd = cfg.installCommand;
|
|
4420
|
+
if (typeof cmd !== "string" || cmd.length === 0) continue;
|
|
4421
|
+
const result = (0, import_child_process4.spawnSync)(cmd, {
|
|
4422
|
+
shell: true,
|
|
4423
|
+
stdio: "pipe",
|
|
4424
|
+
encoding: "utf-8",
|
|
4425
|
+
cwd: ctx.config.projectPath
|
|
4426
|
+
});
|
|
4427
|
+
if (result.status === 0) {
|
|
4428
|
+
succeeded.push(name);
|
|
4429
|
+
} else {
|
|
4430
|
+
const stderr = (result.stderr ?? "").trim();
|
|
4431
|
+
const reason = stderr.length > 0 ? stderr.split("\n")[0] : `exit ${result.status}`;
|
|
4432
|
+
failed.push({ name, reason });
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4435
|
+
ctx.installed.mcpInstallCommandsRun = { succeeded, failed };
|
|
4436
|
+
if (failed.length === 0) {
|
|
4437
|
+
return {
|
|
4438
|
+
status: "success",
|
|
4439
|
+
message: succeeded.length > 0 ? succeeded.join(", ") : void 0
|
|
4440
|
+
};
|
|
4441
|
+
}
|
|
4442
|
+
const failedSummary = failed.map((f) => `${f.name} (${f.reason})`).join("; ");
|
|
4443
|
+
if (succeeded.length === 0) {
|
|
4444
|
+
return { status: "failed", detail: failedSummary };
|
|
4445
|
+
}
|
|
4446
|
+
return {
|
|
4447
|
+
status: "success",
|
|
4448
|
+
message: `${succeeded.join(", ")}; failed: ${failed.map((f) => f.name).join(", ")}`,
|
|
4449
|
+
detail: `Some registrations failed: ${failedSummary}`
|
|
4450
|
+
};
|
|
4451
|
+
}
|
|
4452
|
+
});
|
|
4453
|
+
function isClaudeCliAvailable() {
|
|
4454
|
+
const check2 = (0, import_child_process4.spawnSync)("claude --version", { shell: true, stdio: "ignore" });
|
|
4455
|
+
return check2.status === 0;
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4365
4458
|
// src/steps/setup/update-gitignore.ts
|
|
4366
4459
|
var import_fs6 = require("fs");
|
|
4367
4460
|
var import_path6 = require("path");
|
|
@@ -4422,7 +4515,7 @@ var update_gitignore_default = defineStep({
|
|
|
4422
4515
|
var import_fs7 = require("fs");
|
|
4423
4516
|
var import_path7 = require("path");
|
|
4424
4517
|
var import_os2 = require("os");
|
|
4425
|
-
var INSTALLER_VERSION = "0.5.
|
|
4518
|
+
var INSTALLER_VERSION = "0.5.18";
|
|
4426
4519
|
var write_state_default = defineStep({
|
|
4427
4520
|
name: "write-state",
|
|
4428
4521
|
label: "Saving installation state",
|
|
@@ -4436,6 +4529,7 @@ var write_state_default = defineStep({
|
|
|
4436
4529
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4437
4530
|
installerVersion: INSTALLER_VERSION,
|
|
4438
4531
|
releaseVersion: ctx.config.releaseVersion,
|
|
4532
|
+
contextReleaseVersion: ctx.installed.contextReleaseVersion ?? null,
|
|
4439
4533
|
projectPath: ctx.config.projectPath,
|
|
4440
4534
|
agent: ctx.config.agent,
|
|
4441
4535
|
technologies: ctx.config.technologies.map((p) => p.id),
|
|
@@ -4542,10 +4636,14 @@ async function main() {
|
|
|
4542
4636
|
try {
|
|
4543
4637
|
const token = await getGitHubToken();
|
|
4544
4638
|
console.log(" Locating repositories...");
|
|
4545
|
-
const [repo, factoryRepo] = await Promise.all([
|
|
4639
|
+
const [repo, contextRepo, factoryRepo] = await Promise.all([
|
|
4546
4640
|
discoverRepo(token),
|
|
4641
|
+
discoverRepo(token, "context-data").catch(() => null),
|
|
4547
4642
|
discoverRepo(token, "factory-data").catch(() => null)
|
|
4548
4643
|
]);
|
|
4644
|
+
if (!contextRepo) {
|
|
4645
|
+
console.log(" \u26A0 Context repo not found \u2014 AI contexts will not be installed.");
|
|
4646
|
+
}
|
|
4549
4647
|
if (!factoryRepo) {
|
|
4550
4648
|
console.log(" \u26A0 Factory repo not found \u2014 Factory will not be installed.");
|
|
4551
4649
|
}
|
|
@@ -4566,6 +4664,7 @@ async function main() {
|
|
|
4566
4664
|
config,
|
|
4567
4665
|
token,
|
|
4568
4666
|
repo,
|
|
4667
|
+
contextRepo,
|
|
4569
4668
|
factoryRepo,
|
|
4570
4669
|
installed: {}
|
|
4571
4670
|
};
|
|
@@ -4610,6 +4709,9 @@ async function collectInputs(options, releaseVersion, factoryAvailable = false)
|
|
|
4610
4709
|
mcpConfig["azure-devops"].args = mcpConfig["azure-devops"].args?.map(
|
|
4611
4710
|
(arg) => arg === "__AZURE_ORG__" ? azureDevOpsOrg : arg
|
|
4612
4711
|
);
|
|
4712
|
+
if (mcpConfig["azure-devops"].installCommand) {
|
|
4713
|
+
mcpConfig["azure-devops"].installCommand = mcpConfig["azure-devops"].installCommand.replace(/__AZURE_ORG__/g, azureDevOpsOrg);
|
|
4714
|
+
}
|
|
4613
4715
|
}
|
|
4614
4716
|
}
|
|
4615
4717
|
const projectInput = await esm_default4({
|