dlw-machine-setup 0.5.16 → 0.5.17
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 +83 -45
- 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(
|
|
@@ -3631,7 +3647,7 @@ __export(steps_exports, {
|
|
|
3631
3647
|
// src/steps/resources/fetch-contexts.ts
|
|
3632
3648
|
var import_fs2 = require("fs");
|
|
3633
3649
|
var import_path2 = require("path");
|
|
3634
|
-
var
|
|
3650
|
+
var import_child_process2 = require("child_process");
|
|
3635
3651
|
var MIN_FILE_SIZE = 1024;
|
|
3636
3652
|
var fetch_contexts_default = defineStep({
|
|
3637
3653
|
name: "fetch-contexts",
|
|
@@ -3640,10 +3656,20 @@ var fetch_contexts_default = defineStep({
|
|
|
3640
3656
|
execute: async (ctx) => {
|
|
3641
3657
|
const uniqueDomains = [...new Set(ctx.config.technologies.flatMap((p) => p.domains))];
|
|
3642
3658
|
const domainValues = uniqueDomains.map((d) => d.toLowerCase());
|
|
3643
|
-
|
|
3659
|
+
if (!ctx.contextRepo) {
|
|
3660
|
+
for (const domain of domainValues) {
|
|
3661
|
+
ctx.installed.domainsFailed = domainValues;
|
|
3662
|
+
}
|
|
3663
|
+
return {
|
|
3664
|
+
status: "failed",
|
|
3665
|
+
detail: "Context repo not found (topic: context-data)"
|
|
3666
|
+
};
|
|
3667
|
+
}
|
|
3668
|
+
const downloadResult = await fetchContexts(domainValues, ctx.token, ctx.contextRepo, ctx.config.projectPath);
|
|
3644
3669
|
ctx.installed.domainsInstalled = downloadResult.successful;
|
|
3645
3670
|
ctx.installed.domainsFailed = downloadResult.failed;
|
|
3646
3671
|
ctx.installed.failureReasons = downloadResult.failureReasons;
|
|
3672
|
+
ctx.installed.contextReleaseVersion = downloadResult.releaseVersion;
|
|
3647
3673
|
const domainColWidth = Math.max(...domainValues.map((d) => d.length), 8) + 2;
|
|
3648
3674
|
console.log("");
|
|
3649
3675
|
for (const domain of domainValues) {
|
|
@@ -3667,7 +3693,7 @@ var fetch_contexts_default = defineStep({
|
|
|
3667
3693
|
async function fetchContexts(domains, token, repo, targetDir) {
|
|
3668
3694
|
const result = { successful: [], failed: [], failureReasons: {} };
|
|
3669
3695
|
if (domains.length === 0) return result;
|
|
3670
|
-
const tarCheck = (0,
|
|
3696
|
+
const tarCheck = (0, import_child_process2.spawnSync)("tar", ["--version"], { stdio: "ignore" });
|
|
3671
3697
|
if (tarCheck.status !== 0) {
|
|
3672
3698
|
throw new Error("tar command not found. Please ensure tar is installed and available in your PATH.");
|
|
3673
3699
|
}
|
|
@@ -3683,52 +3709,58 @@ async function fetchContexts(domains, token, repo, targetDir) {
|
|
|
3683
3709
|
throw new Error(`GitHub API error (${releaseResponse.status}): ${getReadableError(releaseResponse.status)}`);
|
|
3684
3710
|
}
|
|
3685
3711
|
const releaseData = await releaseResponse.json();
|
|
3712
|
+
result.releaseVersion = releaseData.tag_name;
|
|
3713
|
+
const asset = releaseData.assets?.find((a) => a.name.endsWith(".tar.gz"));
|
|
3714
|
+
if (!asset) {
|
|
3715
|
+
for (const domain of domains) {
|
|
3716
|
+
result.failed.push(domain);
|
|
3717
|
+
result.failureReasons[domain] = "No tar.gz asset in release";
|
|
3718
|
+
}
|
|
3719
|
+
return result;
|
|
3720
|
+
}
|
|
3686
3721
|
const contextsDir = (0, import_path2.join)(targetDir, "_ai-context");
|
|
3687
3722
|
const tempDir = (0, import_path2.join)(targetDir, ".temp-download");
|
|
3688
3723
|
try {
|
|
3689
3724
|
if (!(0, import_fs2.existsSync)(contextsDir)) (0, import_fs2.mkdirSync)(contextsDir, { recursive: true });
|
|
3690
3725
|
if ((0, import_fs2.existsSync)(tempDir)) (0, import_fs2.rmSync)(tempDir, { recursive: true, force: true });
|
|
3691
3726
|
(0, import_fs2.mkdirSync)(tempDir, { recursive: true });
|
|
3727
|
+
const downloadHeaders = {
|
|
3728
|
+
"Accept": "application/octet-stream",
|
|
3729
|
+
"Authorization": `Bearer ${token}`
|
|
3730
|
+
};
|
|
3731
|
+
const response = await fetchWithRetry(asset.url, { headers: downloadHeaders });
|
|
3732
|
+
if (!response.ok) {
|
|
3733
|
+
throw new Error(`Download failed: ${getReadableError(response.status)}`);
|
|
3734
|
+
}
|
|
3735
|
+
const archivePath = (0, import_path2.join)(tempDir, asset.name);
|
|
3736
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
3737
|
+
(0, import_fs2.writeFileSync)(archivePath, Buffer.from(arrayBuffer));
|
|
3738
|
+
const stats = (0, import_fs2.statSync)(archivePath);
|
|
3739
|
+
if (stats.size < MIN_FILE_SIZE) {
|
|
3740
|
+
throw new Error("File corrupted");
|
|
3741
|
+
}
|
|
3742
|
+
const listResult = (0, import_child_process2.spawnSync)("tar", ["-tzf", archivePath], { encoding: "utf8" });
|
|
3743
|
+
if (listResult.status !== 0) throw new Error("Failed to read archive contents");
|
|
3744
|
+
const resolvedTempDir = (0, import_path2.resolve)(tempDir);
|
|
3745
|
+
for (const entry of listResult.stdout.split("\n").filter(Boolean)) {
|
|
3746
|
+
const entryPath = (0, import_path2.resolve)((0, import_path2.join)(tempDir, entry.replace(/\/$/, "")));
|
|
3747
|
+
if (!entryPath.startsWith(resolvedTempDir + import_path2.sep)) {
|
|
3748
|
+
throw new Error(`Archive contains unsafe path: ${entry}`);
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
const extractResult = (0, import_child_process2.spawnSync)("tar", ["-xzf", archivePath, "-C", tempDir], { stdio: "ignore" });
|
|
3752
|
+
if (extractResult.status !== 0) throw new Error("Archive extraction failed");
|
|
3753
|
+
const extractedFolders = (0, import_fs2.readdirSync)(tempDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
3692
3754
|
for (const domain of domains) {
|
|
3693
3755
|
try {
|
|
3694
|
-
const
|
|
3695
|
-
|
|
3696
|
-
const asset = releaseData.assets?.find((a) => a.name === archiveName);
|
|
3697
|
-
if (!asset) {
|
|
3756
|
+
const match = extractedFolders.find((f) => f.toLowerCase() === domain.toLowerCase());
|
|
3757
|
+
if (!match) {
|
|
3698
3758
|
result.failed.push(domain);
|
|
3699
|
-
result.failureReasons[domain] = "Not found in
|
|
3759
|
+
result.failureReasons[domain] = "Not found in archive";
|
|
3700
3760
|
continue;
|
|
3701
3761
|
}
|
|
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);
|
|
3762
|
+
const domainPath = (0, import_path2.join)(contextsDir, domain);
|
|
3763
|
+
copyDirectory((0, import_path2.join)(tempDir, match), domainPath);
|
|
3732
3764
|
result.successful.push(domain);
|
|
3733
3765
|
} catch (error) {
|
|
3734
3766
|
result.failed.push(domain);
|
|
@@ -3780,7 +3812,7 @@ function getReadableError(status) {
|
|
|
3780
3812
|
// src/steps/resources/fetch-factory.ts
|
|
3781
3813
|
var import_fs3 = require("fs");
|
|
3782
3814
|
var import_path3 = require("path");
|
|
3783
|
-
var
|
|
3815
|
+
var import_child_process3 = require("child_process");
|
|
3784
3816
|
var MIN_FILE_SIZE2 = 1024;
|
|
3785
3817
|
function getFactoryAsset(agent) {
|
|
3786
3818
|
switch (agent) {
|
|
@@ -3805,7 +3837,7 @@ var fetch_factory_default = defineStep({
|
|
|
3805
3837
|
});
|
|
3806
3838
|
async function fetchFactory(token, repo, targetDir, agent) {
|
|
3807
3839
|
const result = { success: false, filesInstalled: [] };
|
|
3808
|
-
const tarCheck = (0,
|
|
3840
|
+
const tarCheck = (0, import_child_process3.spawnSync)("tar", ["--version"], { stdio: "ignore" });
|
|
3809
3841
|
if (tarCheck.status !== 0) {
|
|
3810
3842
|
result.failureReason = "tar command not found";
|
|
3811
3843
|
return result;
|
|
@@ -3848,7 +3880,7 @@ async function fetchFactory(token, repo, targetDir, agent) {
|
|
|
3848
3880
|
result.failureReason = "Downloaded file corrupted (too small)";
|
|
3849
3881
|
return result;
|
|
3850
3882
|
}
|
|
3851
|
-
const listResult = (0,
|
|
3883
|
+
const listResult = (0, import_child_process3.spawnSync)("tar", ["-tzf", archivePath], { encoding: "utf8" });
|
|
3852
3884
|
if (listResult.status !== 0) {
|
|
3853
3885
|
result.failureReason = "Failed to read archive contents";
|
|
3854
3886
|
return result;
|
|
@@ -3861,7 +3893,7 @@ async function fetchFactory(token, repo, targetDir, agent) {
|
|
|
3861
3893
|
return result;
|
|
3862
3894
|
}
|
|
3863
3895
|
}
|
|
3864
|
-
const extractResult = (0,
|
|
3896
|
+
const extractResult = (0, import_child_process3.spawnSync)("tar", ["-xzf", archivePath, "-C", tempDir], { stdio: "ignore" });
|
|
3865
3897
|
if (extractResult.status !== 0) {
|
|
3866
3898
|
result.failureReason = "Archive extraction failed";
|
|
3867
3899
|
return result;
|
|
@@ -4422,7 +4454,7 @@ var update_gitignore_default = defineStep({
|
|
|
4422
4454
|
var import_fs7 = require("fs");
|
|
4423
4455
|
var import_path7 = require("path");
|
|
4424
4456
|
var import_os2 = require("os");
|
|
4425
|
-
var INSTALLER_VERSION = "0.5.
|
|
4457
|
+
var INSTALLER_VERSION = "0.5.17";
|
|
4426
4458
|
var write_state_default = defineStep({
|
|
4427
4459
|
name: "write-state",
|
|
4428
4460
|
label: "Saving installation state",
|
|
@@ -4436,6 +4468,7 @@ var write_state_default = defineStep({
|
|
|
4436
4468
|
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4437
4469
|
installerVersion: INSTALLER_VERSION,
|
|
4438
4470
|
releaseVersion: ctx.config.releaseVersion,
|
|
4471
|
+
contextReleaseVersion: ctx.installed.contextReleaseVersion ?? null,
|
|
4439
4472
|
projectPath: ctx.config.projectPath,
|
|
4440
4473
|
agent: ctx.config.agent,
|
|
4441
4474
|
technologies: ctx.config.technologies.map((p) => p.id),
|
|
@@ -4542,10 +4575,14 @@ async function main() {
|
|
|
4542
4575
|
try {
|
|
4543
4576
|
const token = await getGitHubToken();
|
|
4544
4577
|
console.log(" Locating repositories...");
|
|
4545
|
-
const [repo, factoryRepo] = await Promise.all([
|
|
4578
|
+
const [repo, contextRepo, factoryRepo] = await Promise.all([
|
|
4546
4579
|
discoverRepo(token),
|
|
4580
|
+
discoverRepo(token, "context-data").catch(() => null),
|
|
4547
4581
|
discoverRepo(token, "factory-data").catch(() => null)
|
|
4548
4582
|
]);
|
|
4583
|
+
if (!contextRepo) {
|
|
4584
|
+
console.log(" \u26A0 Context repo not found \u2014 AI contexts will not be installed.");
|
|
4585
|
+
}
|
|
4549
4586
|
if (!factoryRepo) {
|
|
4550
4587
|
console.log(" \u26A0 Factory repo not found \u2014 Factory will not be installed.");
|
|
4551
4588
|
}
|
|
@@ -4566,6 +4603,7 @@ async function main() {
|
|
|
4566
4603
|
config,
|
|
4567
4604
|
token,
|
|
4568
4605
|
repo,
|
|
4606
|
+
contextRepo,
|
|
4569
4607
|
factoryRepo,
|
|
4570
4608
|
installed: {}
|
|
4571
4609
|
};
|