dlw-machine-setup 0.11.1 → 0.12.0-canary.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/bin/installer.js +138 -103
- package/package.json +3 -2
package/bin/installer.js
CHANGED
|
@@ -3123,9 +3123,9 @@ ${page}${helpTipBottom}${choiceDescription}${import_ansi_escapes3.default.cursor
|
|
|
3123
3123
|
});
|
|
3124
3124
|
|
|
3125
3125
|
// src/index.ts
|
|
3126
|
-
var
|
|
3126
|
+
var import_fs18 = require("fs");
|
|
3127
3127
|
var import_readline2 = require("readline");
|
|
3128
|
-
var
|
|
3128
|
+
var import_path18 = require("path");
|
|
3129
3129
|
|
|
3130
3130
|
// src/utils/fetch.ts
|
|
3131
3131
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -4043,8 +4043,8 @@ async function fetchContexts(domains, token, repo, targetDir) {
|
|
|
4043
4043
|
}
|
|
4044
4044
|
|
|
4045
4045
|
// src/steps/resources/fetch-factory.ts
|
|
4046
|
-
var
|
|
4047
|
-
var
|
|
4046
|
+
var import_fs10 = require("fs");
|
|
4047
|
+
var import_path10 = require("path");
|
|
4048
4048
|
|
|
4049
4049
|
// src/bundles/run-bundle.ts
|
|
4050
4050
|
var import_fs8 = require("fs");
|
|
@@ -4557,6 +4557,40 @@ function assertBundleRootExists(ctx) {
|
|
|
4557
4557
|
}
|
|
4558
4558
|
}
|
|
4559
4559
|
|
|
4560
|
+
// src/utils/channel.ts
|
|
4561
|
+
var import_fs9 = require("fs");
|
|
4562
|
+
var import_path9 = require("path");
|
|
4563
|
+
function getChannel() {
|
|
4564
|
+
try {
|
|
4565
|
+
const pkgPath = (0, import_path9.join)(__dirname, "..", "package.json");
|
|
4566
|
+
const { version } = JSON.parse((0, import_fs9.readFileSync)(pkgPath, "utf-8"));
|
|
4567
|
+
if (typeof version === "string" && version.includes("-")) return "test";
|
|
4568
|
+
} catch {
|
|
4569
|
+
}
|
|
4570
|
+
return "prod";
|
|
4571
|
+
}
|
|
4572
|
+
|
|
4573
|
+
// src/utils/resolve-release.ts
|
|
4574
|
+
async function fetchLatestPrerelease(token, repo) {
|
|
4575
|
+
const headers = {
|
|
4576
|
+
"Accept": "application/vnd.github+json",
|
|
4577
|
+
"Authorization": `Bearer ${token}`
|
|
4578
|
+
};
|
|
4579
|
+
const res = await fetchWithRetry(`https://api.github.com/repos/${repo}/releases?per_page=100`, { headers });
|
|
4580
|
+
if (!res.ok) {
|
|
4581
|
+
throw new Error(`GitHub API error (${res.status}): ${getReadableError(res.status)}`);
|
|
4582
|
+
}
|
|
4583
|
+
const releases = await res.json();
|
|
4584
|
+
const match = releases.find((r) => r.prerelease === true);
|
|
4585
|
+
if (!match) {
|
|
4586
|
+
throw new Error(`No pre-release found in ${repo} (test channel)`);
|
|
4587
|
+
}
|
|
4588
|
+
return { tagName: match.tag_name ?? "unknown", assets: match.assets ?? [] };
|
|
4589
|
+
}
|
|
4590
|
+
async function resolveReleaseForChannel(token, repo) {
|
|
4591
|
+
return getChannel() === "test" ? fetchLatestPrerelease(token, repo) : fetchLatestRelease(token, repo);
|
|
4592
|
+
}
|
|
4593
|
+
|
|
4560
4594
|
// src/steps/resources/fetch-factory.ts
|
|
4561
4595
|
var FACTORY_ASSET_NAME = "factory.tar.gz";
|
|
4562
4596
|
var FACTORY_ROOT_FOLDER = "factory";
|
|
@@ -4605,7 +4639,7 @@ var fetch_factory_default = defineStep({
|
|
|
4605
4639
|
const sortedCreated = [...created].sort((a, b) => a.length - b.length);
|
|
4606
4640
|
for (const rel of sortedCreated) {
|
|
4607
4641
|
const abs = resolveProjectPath(rel, projectPath);
|
|
4608
|
-
if (!(0,
|
|
4642
|
+
if (!(0, import_fs10.existsSync)(abs)) continue;
|
|
4609
4643
|
if (isDirectorySafe(abs)) {
|
|
4610
4644
|
deleteDirIfExists(abs);
|
|
4611
4645
|
summary.push(`removed ${rel}`);
|
|
@@ -4633,7 +4667,7 @@ async function fetchFactory(token, repo, targetDir, agent, agentTeams) {
|
|
|
4633
4667
|
};
|
|
4634
4668
|
let release;
|
|
4635
4669
|
try {
|
|
4636
|
-
release = await
|
|
4670
|
+
release = await resolveReleaseForChannel(token, repo);
|
|
4637
4671
|
} catch (err) {
|
|
4638
4672
|
result.failureReason = err instanceof Error ? err.message : String(err);
|
|
4639
4673
|
return result;
|
|
@@ -4646,15 +4680,15 @@ async function fetchFactory(token, repo, targetDir, agent, agentTeams) {
|
|
|
4646
4680
|
let archive = null;
|
|
4647
4681
|
try {
|
|
4648
4682
|
archive = await downloadAndExtractAsset(token, asset, targetDir, ".temp-factory-download");
|
|
4649
|
-
const extractedEntries = (0,
|
|
4683
|
+
const extractedEntries = (0, import_fs10.readdirSync)(archive.extractedRoot);
|
|
4650
4684
|
const extractedFolder = extractedEntries.find((e) => e.toLowerCase() === FACTORY_ROOT_FOLDER.toLowerCase());
|
|
4651
4685
|
if (!extractedFolder) {
|
|
4652
4686
|
result.failureReason = `No ${FACTORY_ROOT_FOLDER}/ folder in archive`;
|
|
4653
4687
|
return result;
|
|
4654
4688
|
}
|
|
4655
|
-
const extractedPath = (0,
|
|
4656
|
-
const manifestPath = (0,
|
|
4657
|
-
if (!(0,
|
|
4689
|
+
const extractedPath = (0, import_path10.join)(archive.extractedRoot, extractedFolder);
|
|
4690
|
+
const manifestPath = (0, import_path10.join)(extractedPath, "install.json");
|
|
4691
|
+
if (!(0, import_fs10.existsSync)(manifestPath)) {
|
|
4658
4692
|
result.failureReason = "Factory archive has no install.json \u2014 upgrade Factory or downgrade installer";
|
|
4659
4693
|
return result;
|
|
4660
4694
|
}
|
|
@@ -4670,7 +4704,7 @@ async function fetchFactory(token, repo, targetDir, agent, agentTeams) {
|
|
|
4670
4704
|
async function installViaBundle(manifestPath, extractedPath, targetDir, agent, agentTeams, result) {
|
|
4671
4705
|
let manifest;
|
|
4672
4706
|
try {
|
|
4673
|
-
manifest = JSON.parse((0,
|
|
4707
|
+
manifest = JSON.parse((0, import_fs10.readFileSync)(manifestPath, "utf-8"));
|
|
4674
4708
|
} catch (e) {
|
|
4675
4709
|
throw new Error(`install.json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
4676
4710
|
}
|
|
@@ -4693,8 +4727,8 @@ async function installViaBundle(manifestPath, extractedPath, targetDir, agent, a
|
|
|
4693
4727
|
}
|
|
4694
4728
|
|
|
4695
4729
|
// src/steps/resources/fetch-abap-hooks.ts
|
|
4696
|
-
var
|
|
4697
|
-
var
|
|
4730
|
+
var import_fs11 = require("fs");
|
|
4731
|
+
var import_path11 = require("path");
|
|
4698
4732
|
var HOOKS_ASSET_NAME = "sap-hooks.tar.gz";
|
|
4699
4733
|
var HOOKS_TAG_PREFIX = "hooks-v";
|
|
4700
4734
|
var HOOKS_ROOT_FOLDER = "hooks";
|
|
@@ -4826,7 +4860,7 @@ async function fetchAbapHooks(token, repo, targetDir, agent) {
|
|
|
4826
4860
|
let archive = null;
|
|
4827
4861
|
try {
|
|
4828
4862
|
archive = await downloadAndExtractAsset(token, asset, targetDir, ".temp-abap-hooks-download");
|
|
4829
|
-
const extractedEntries = (0,
|
|
4863
|
+
const extractedEntries = (0, import_fs11.readdirSync)(archive.extractedRoot);
|
|
4830
4864
|
const innerFolder = extractedEntries.find(
|
|
4831
4865
|
(e) => e.toLowerCase() === HOOKS_ROOT_FOLDER.toLowerCase()
|
|
4832
4866
|
);
|
|
@@ -4834,12 +4868,12 @@ async function fetchAbapHooks(token, repo, targetDir, agent) {
|
|
|
4834
4868
|
result.failureReason = `No ${HOOKS_ROOT_FOLDER}/ folder in archive`;
|
|
4835
4869
|
return result;
|
|
4836
4870
|
}
|
|
4837
|
-
const bundleRoot = (0,
|
|
4838
|
-
if (!(0,
|
|
4871
|
+
const bundleRoot = (0, import_path11.join)(archive.extractedRoot, innerFolder);
|
|
4872
|
+
if (!(0, import_fs11.statSync)(bundleRoot).isDirectory()) {
|
|
4839
4873
|
result.failureReason = `${HOOKS_ROOT_FOLDER}/ entry is not a directory`;
|
|
4840
4874
|
return result;
|
|
4841
4875
|
}
|
|
4842
|
-
const presentDefs = HOOK_DEFINITIONS.filter((d) => (0,
|
|
4876
|
+
const presentDefs = HOOK_DEFINITIONS.filter((d) => (0, import_fs11.existsSync)((0, import_path11.join)(bundleRoot, d.script)));
|
|
4843
4877
|
if (presentDefs.length === 0) {
|
|
4844
4878
|
result.failureReason = "Archive contains no recognized hook scripts";
|
|
4845
4879
|
return result;
|
|
@@ -4893,8 +4927,8 @@ async function fetchAbapHooks(token, repo, targetDir, agent) {
|
|
|
4893
4927
|
}
|
|
4894
4928
|
|
|
4895
4929
|
// src/steps/setup/write-instructions.ts
|
|
4896
|
-
var
|
|
4897
|
-
var
|
|
4930
|
+
var import_fs12 = require("fs");
|
|
4931
|
+
var import_path12 = require("path");
|
|
4898
4932
|
|
|
4899
4933
|
// src/steps/shared.ts
|
|
4900
4934
|
var cached = null;
|
|
@@ -4929,13 +4963,13 @@ var write_instructions_default = defineStep({
|
|
|
4929
4963
|
const projectPath = ctx.config.projectPath;
|
|
4930
4964
|
const content = buildCombinedInstructions(domains, filteredMcpConfig, agent, projectPath);
|
|
4931
4965
|
const target = getAgentTarget(agent);
|
|
4932
|
-
const filePath = (0,
|
|
4933
|
-
const fileDir = (0,
|
|
4934
|
-
if (!(0,
|
|
4935
|
-
const fileExistedBefore = (0,
|
|
4966
|
+
const filePath = (0, import_path12.join)(projectPath, target.instructions);
|
|
4967
|
+
const fileDir = (0, import_path12.dirname)(filePath);
|
|
4968
|
+
if (!(0, import_fs12.existsSync)(fileDir)) (0, import_fs12.mkdirSync)(fileDir, { recursive: true });
|
|
4969
|
+
const fileExistedBefore = (0, import_fs12.existsSync)(filePath);
|
|
4936
4970
|
let cursorFrontmatterWritten = false;
|
|
4937
4971
|
if (agent === "cursor" && !fileExistedBefore) {
|
|
4938
|
-
(0,
|
|
4972
|
+
(0, import_fs12.writeFileSync)(filePath, `---
|
|
4939
4973
|
description: AI development instructions from One-Shot Installer
|
|
4940
4974
|
alwaysApply: true
|
|
4941
4975
|
---
|
|
@@ -5016,16 +5050,16 @@ alwaysApply: true
|
|
|
5016
5050
|
}
|
|
5017
5051
|
});
|
|
5018
5052
|
function collectMdFiles(dir) {
|
|
5019
|
-
if (!(0,
|
|
5020
|
-
const entries = (0,
|
|
5053
|
+
if (!(0, import_fs12.existsSync)(dir)) return [];
|
|
5054
|
+
const entries = (0, import_fs12.readdirSync)(dir, { recursive: true });
|
|
5021
5055
|
return entries.filter((entry) => {
|
|
5022
|
-
const fullPath = (0,
|
|
5023
|
-
return entry.endsWith(".md") && (0,
|
|
5056
|
+
const fullPath = (0, import_path12.join)(dir, entry);
|
|
5057
|
+
return entry.endsWith(".md") && (0, import_fs12.statSync)(fullPath).isFile();
|
|
5024
5058
|
}).map((entry) => entry.replace(/\\/g, "/")).sort();
|
|
5025
5059
|
}
|
|
5026
5060
|
function extractFirstHeading(filePath) {
|
|
5027
5061
|
try {
|
|
5028
|
-
const content = (0,
|
|
5062
|
+
const content = (0, import_fs12.readFileSync)(filePath, "utf-8");
|
|
5029
5063
|
const withoutFrontmatter = content.replace(/^---[\s\S]*?---\s*/, "");
|
|
5030
5064
|
const match = withoutFrontmatter.match(/^#\s+(.+)/m);
|
|
5031
5065
|
if (match) {
|
|
@@ -5043,16 +5077,16 @@ function formatPathRef(contextPath, description, agent) {
|
|
|
5043
5077
|
return `- \`${contextPath}\` \u2014 ${description}`;
|
|
5044
5078
|
}
|
|
5045
5079
|
function resolveDomainFolder(domain, contextsDir) {
|
|
5046
|
-
if ((0,
|
|
5080
|
+
if ((0, import_fs12.existsSync)(contextsDir)) {
|
|
5047
5081
|
try {
|
|
5048
|
-
const entries = (0,
|
|
5082
|
+
const entries = (0, import_fs12.readdirSync)(contextsDir);
|
|
5049
5083
|
const match = entries.find((e) => e.toLowerCase() === domain.toLowerCase());
|
|
5050
|
-
if (match) return { folderName: match, folderPath: (0,
|
|
5084
|
+
if (match) return { folderName: match, folderPath: (0, import_path12.join)(contextsDir, match) };
|
|
5051
5085
|
} catch {
|
|
5052
5086
|
}
|
|
5053
5087
|
}
|
|
5054
5088
|
const fallback = domain.toUpperCase();
|
|
5055
|
-
return { folderName: fallback, folderPath: (0,
|
|
5089
|
+
return { folderName: fallback, folderPath: (0, import_path12.join)(contextsDir, fallback) };
|
|
5056
5090
|
}
|
|
5057
5091
|
function buildContextRefsSection(domains, agent, contextsDir) {
|
|
5058
5092
|
const lines2 = [
|
|
@@ -5064,34 +5098,34 @@ function buildContextRefsSection(domains, agent, contextsDir) {
|
|
|
5064
5098
|
let hasAnyFiles = false;
|
|
5065
5099
|
for (const domain of domains) {
|
|
5066
5100
|
const { folderName, folderPath: domainPath } = resolveDomainFolder(domain, contextsDir);
|
|
5067
|
-
if (!(0,
|
|
5101
|
+
if (!(0, import_fs12.existsSync)(domainPath)) continue;
|
|
5068
5102
|
const domainFiles = [];
|
|
5069
|
-
const ctxInstructions = (0,
|
|
5070
|
-
if ((0,
|
|
5103
|
+
const ctxInstructions = (0, import_path12.join)(domainPath, "context-instructions.md");
|
|
5104
|
+
if ((0, import_fs12.existsSync)(ctxInstructions)) {
|
|
5071
5105
|
const desc = extractFirstHeading(ctxInstructions);
|
|
5072
5106
|
domainFiles.push(formatPathRef(`_ai-context/${folderName}/context-instructions.md`, desc, agent));
|
|
5073
5107
|
}
|
|
5074
|
-
const instructionsMd = (0,
|
|
5075
|
-
if ((0,
|
|
5108
|
+
const instructionsMd = (0, import_path12.join)(domainPath, "core", "instructions.md");
|
|
5109
|
+
if ((0, import_fs12.existsSync)(instructionsMd)) {
|
|
5076
5110
|
const desc = extractFirstHeading(instructionsMd);
|
|
5077
5111
|
domainFiles.push(formatPathRef(`_ai-context/${folderName}/core/instructions.md`, `${desc} (start here)`, agent));
|
|
5078
5112
|
}
|
|
5079
|
-
const coreDir = (0,
|
|
5080
|
-
if ((0,
|
|
5113
|
+
const coreDir = (0, import_path12.join)(domainPath, "core");
|
|
5114
|
+
if ((0, import_fs12.existsSync)(coreDir)) {
|
|
5081
5115
|
const coreFiles = collectMdFiles(coreDir).filter((f) => f !== "instructions.md" && !f.startsWith("instructions/"));
|
|
5082
5116
|
for (const file of coreFiles) {
|
|
5083
|
-
const desc = extractFirstHeading((0,
|
|
5117
|
+
const desc = extractFirstHeading((0, import_path12.join)(coreDir, file));
|
|
5084
5118
|
domainFiles.push(formatPathRef(`_ai-context/${folderName}/core/${file}`, desc, agent));
|
|
5085
5119
|
}
|
|
5086
5120
|
}
|
|
5087
|
-
const refDir = (0,
|
|
5088
|
-
if ((0,
|
|
5121
|
+
const refDir = (0, import_path12.join)(domainPath, "reference");
|
|
5122
|
+
if ((0, import_fs12.existsSync)(refDir)) {
|
|
5089
5123
|
const refFiles = collectMdFiles(refDir);
|
|
5090
5124
|
if (refFiles.length > 0) {
|
|
5091
5125
|
domainFiles.push(``);
|
|
5092
5126
|
domainFiles.push(`**Reference & cheat sheets:**`);
|
|
5093
5127
|
for (const file of refFiles) {
|
|
5094
|
-
const desc = extractFirstHeading((0,
|
|
5128
|
+
const desc = extractFirstHeading((0, import_path12.join)(refDir, file));
|
|
5095
5129
|
domainFiles.push(formatPathRef(`_ai-context/${folderName}/reference/${file}`, desc, agent));
|
|
5096
5130
|
}
|
|
5097
5131
|
}
|
|
@@ -5122,7 +5156,7 @@ function buildMCPSection(mcpConfig) {
|
|
|
5122
5156
|
return lines2.join("\n");
|
|
5123
5157
|
}
|
|
5124
5158
|
function buildCombinedInstructions(domains, mcpConfig, agent, projectPath) {
|
|
5125
|
-
const contextsDir = (0,
|
|
5159
|
+
const contextsDir = (0, import_path12.join)(projectPath, "_ai-context");
|
|
5126
5160
|
const lines2 = [`# AI Development Instructions`, ``, `> Generated by One-Shot Installer`, ``];
|
|
5127
5161
|
lines2.push(buildContextRefsSection(domains, agent, contextsDir));
|
|
5128
5162
|
if (Object.keys(mcpConfig).length > 0) lines2.push(buildMCPSection(mcpConfig));
|
|
@@ -5130,8 +5164,8 @@ function buildCombinedInstructions(domains, mcpConfig, agent, projectPath) {
|
|
|
5130
5164
|
}
|
|
5131
5165
|
|
|
5132
5166
|
// src/steps/setup/write-mcp-config.ts
|
|
5133
|
-
var
|
|
5134
|
-
var
|
|
5167
|
+
var import_fs13 = require("fs");
|
|
5168
|
+
var import_path13 = require("path");
|
|
5135
5169
|
var red2 = (text) => `\x1B[31m${text}\x1B[0m`;
|
|
5136
5170
|
var write_mcp_config_default = defineStep({
|
|
5137
5171
|
name: "write-mcp-config",
|
|
@@ -5143,16 +5177,16 @@ var write_mcp_config_default = defineStep({
|
|
|
5143
5177
|
execute: async (ctx) => {
|
|
5144
5178
|
const filteredMcpConfig = getFilteredMcpConfig(ctx);
|
|
5145
5179
|
const target = getAgentTarget(ctx.config.agent);
|
|
5146
|
-
const mcpJsonPath = (0,
|
|
5147
|
-
const fileExistedBefore = (0,
|
|
5180
|
+
const mcpJsonPath = (0, import_path13.join)(ctx.config.projectPath, target.mcpConfig);
|
|
5181
|
+
const fileExistedBefore = (0, import_fs13.existsSync)(mcpJsonPath);
|
|
5148
5182
|
if (target.mcpDir) {
|
|
5149
|
-
const dir = (0,
|
|
5150
|
-
if (!(0,
|
|
5183
|
+
const dir = (0, import_path13.join)(ctx.config.projectPath, target.mcpDir);
|
|
5184
|
+
if (!(0, import_fs13.existsSync)(dir)) (0, import_fs13.mkdirSync)(dir, { recursive: true });
|
|
5151
5185
|
}
|
|
5152
5186
|
let existingFile = {};
|
|
5153
|
-
if ((0,
|
|
5187
|
+
if ((0, import_fs13.existsSync)(mcpJsonPath)) {
|
|
5154
5188
|
try {
|
|
5155
|
-
existingFile = JSON.parse((0,
|
|
5189
|
+
existingFile = JSON.parse((0, import_fs13.readFileSync)(mcpJsonPath, "utf-8"));
|
|
5156
5190
|
} catch {
|
|
5157
5191
|
const box = [
|
|
5158
5192
|
"",
|
|
@@ -5178,7 +5212,7 @@ var write_mcp_config_default = defineStep({
|
|
|
5178
5212
|
}
|
|
5179
5213
|
const mergedServers = { ...existingServers, ...newServers };
|
|
5180
5214
|
const outputFile = { ...existingFile, [target.mcpRootKey]: mergedServers };
|
|
5181
|
-
(0,
|
|
5215
|
+
(0, import_fs13.writeFileSync)(mcpJsonPath, JSON.stringify(outputFile, null, 2), "utf-8");
|
|
5182
5216
|
ctx.installed.mcpServersAdded = addedServers;
|
|
5183
5217
|
const record = {
|
|
5184
5218
|
filePath: target.mcpConfig,
|
|
@@ -5305,8 +5339,8 @@ function isClaudeCliAvailable() {
|
|
|
5305
5339
|
|
|
5306
5340
|
// src/steps/setup/build-code-index.ts
|
|
5307
5341
|
var import_child_process4 = require("child_process");
|
|
5308
|
-
var
|
|
5309
|
-
var
|
|
5342
|
+
var import_fs14 = require("fs");
|
|
5343
|
+
var import_path14 = require("path");
|
|
5310
5344
|
var CODE_INDEX_RELATIVE_PATH = ".claude/factory/utils/code-index";
|
|
5311
5345
|
var INDEX_OUTPUT_RELATIVE_PATH = ".claude/factory/repo-index.json";
|
|
5312
5346
|
var INDEX_STAMP_RELATIVE_PATH = ".claude/factory/index.stamp";
|
|
@@ -5315,8 +5349,8 @@ var build_code_index_default = defineStep({
|
|
|
5315
5349
|
label: "Building code index",
|
|
5316
5350
|
when: (ctx) => ctx.installed.factoryInstalled === true,
|
|
5317
5351
|
execute: async (ctx) => {
|
|
5318
|
-
const codeIndexDirectory = (0,
|
|
5319
|
-
if (!(0,
|
|
5352
|
+
const codeIndexDirectory = (0, import_path14.join)(ctx.config.projectPath, CODE_INDEX_RELATIVE_PATH);
|
|
5353
|
+
if (!(0, import_fs14.existsSync)(codeIndexDirectory)) {
|
|
5320
5354
|
return {
|
|
5321
5355
|
status: "skipped",
|
|
5322
5356
|
detail: `code-index not found at ${CODE_INDEX_RELATIVE_PATH} \u2014 older Factory release?`,
|
|
@@ -5345,7 +5379,7 @@ var build_code_index_default = defineStep({
|
|
|
5345
5379
|
record: { depsInstalled: false, indexBuilt: false }
|
|
5346
5380
|
};
|
|
5347
5381
|
}
|
|
5348
|
-
const indexerScriptPath = (0,
|
|
5382
|
+
const indexerScriptPath = (0, import_path14.join)(codeIndexDirectory, "index.cjs");
|
|
5349
5383
|
const indexerResult = (0, import_child_process4.spawnSync)(`node "${indexerScriptPath}" "${ctx.config.projectPath}"`, {
|
|
5350
5384
|
shell: true,
|
|
5351
5385
|
stdio: "pipe",
|
|
@@ -5376,21 +5410,21 @@ var build_code_index_default = defineStep({
|
|
|
5376
5410
|
const projectPath = ctx.config.projectPath;
|
|
5377
5411
|
const summaryActions = [];
|
|
5378
5412
|
if (record.indexBuilt) {
|
|
5379
|
-
const indexFilePath = (0,
|
|
5380
|
-
if ((0,
|
|
5381
|
-
(0,
|
|
5413
|
+
const indexFilePath = (0, import_path14.join)(projectPath, INDEX_OUTPUT_RELATIVE_PATH);
|
|
5414
|
+
if ((0, import_fs14.existsSync)(indexFilePath)) {
|
|
5415
|
+
(0, import_fs14.unlinkSync)(indexFilePath);
|
|
5382
5416
|
summaryActions.push(`removed ${INDEX_OUTPUT_RELATIVE_PATH}`);
|
|
5383
5417
|
}
|
|
5384
|
-
const stampFilePath = (0,
|
|
5385
|
-
if ((0,
|
|
5386
|
-
(0,
|
|
5418
|
+
const stampFilePath = (0, import_path14.join)(projectPath, INDEX_STAMP_RELATIVE_PATH);
|
|
5419
|
+
if ((0, import_fs14.existsSync)(stampFilePath)) {
|
|
5420
|
+
(0, import_fs14.unlinkSync)(stampFilePath);
|
|
5387
5421
|
summaryActions.push(`removed ${INDEX_STAMP_RELATIVE_PATH}`);
|
|
5388
5422
|
}
|
|
5389
5423
|
}
|
|
5390
5424
|
if (record.depsInstalled) {
|
|
5391
|
-
const nodeModulesPath = (0,
|
|
5392
|
-
if ((0,
|
|
5393
|
-
(0,
|
|
5425
|
+
const nodeModulesPath = (0, import_path14.join)(projectPath, CODE_INDEX_RELATIVE_PATH, "node_modules");
|
|
5426
|
+
if ((0, import_fs14.existsSync)(nodeModulesPath)) {
|
|
5427
|
+
(0, import_fs14.rmSync)(nodeModulesPath, { recursive: true, force: true });
|
|
5394
5428
|
summaryActions.push("removed code-index node_modules");
|
|
5395
5429
|
}
|
|
5396
5430
|
}
|
|
@@ -5407,8 +5441,8 @@ function isNodeAvailable() {
|
|
|
5407
5441
|
}
|
|
5408
5442
|
|
|
5409
5443
|
// src/steps/setup/update-gitignore.ts
|
|
5410
|
-
var
|
|
5411
|
-
var
|
|
5444
|
+
var import_fs15 = require("fs");
|
|
5445
|
+
var import_path15 = require("path");
|
|
5412
5446
|
var MARKER_START2 = "# one-shot-installer:start";
|
|
5413
5447
|
var MARKER_END2 = "# one-shot-installer:end";
|
|
5414
5448
|
var CORE_GITIGNORE_ENTRIES = [
|
|
@@ -5429,8 +5463,8 @@ var update_gitignore_default = defineStep({
|
|
|
5429
5463
|
name: "update-gitignore",
|
|
5430
5464
|
label: "Updating .gitignore",
|
|
5431
5465
|
execute: async (ctx) => {
|
|
5432
|
-
const gitignorePath = (0,
|
|
5433
|
-
const fileExistedBefore = (0,
|
|
5466
|
+
const gitignorePath = (0, import_path15.join)(ctx.config.projectPath, ".gitignore");
|
|
5467
|
+
const fileExistedBefore = (0, import_fs15.existsSync)(gitignorePath);
|
|
5434
5468
|
upsertMarkerBlock(gitignorePath, MARKER_START2, MARKER_END2, CORE_GITIGNORE_ENTRIES.join("\n"));
|
|
5435
5469
|
const record = {
|
|
5436
5470
|
filePath: ".gitignore",
|
|
@@ -5458,8 +5492,8 @@ var update_gitignore_default = defineStep({
|
|
|
5458
5492
|
});
|
|
5459
5493
|
|
|
5460
5494
|
// src/steps/setup/write-state.ts
|
|
5461
|
-
var
|
|
5462
|
-
var
|
|
5495
|
+
var import_fs16 = require("fs");
|
|
5496
|
+
var import_path16 = require("path");
|
|
5463
5497
|
var import_os2 = require("os");
|
|
5464
5498
|
|
|
5465
5499
|
// package.json
|
|
@@ -5473,7 +5507,8 @@ var package_default = {
|
|
|
5473
5507
|
dev: "tsx src/index.ts",
|
|
5474
5508
|
build: 'esbuild src/index.ts --bundle --platform=node --banner:js="#!/usr/bin/env node" --outfile=wrapper/bin/installer.js',
|
|
5475
5509
|
"build:all": "npm run build",
|
|
5476
|
-
"publish:
|
|
5510
|
+
"publish:test": "cd wrapper && npm publish --tag canary",
|
|
5511
|
+
"publish:prod": "cd wrapper && npm publish --tag latest"
|
|
5477
5512
|
},
|
|
5478
5513
|
dependencies: {
|
|
5479
5514
|
"@inquirer/prompts": "^5.0.0"
|
|
@@ -5493,7 +5528,7 @@ var write_state_default = defineStep({
|
|
|
5493
5528
|
name: "write-state",
|
|
5494
5529
|
label: "Saving installation state",
|
|
5495
5530
|
execute: async (ctx) => {
|
|
5496
|
-
const statePath = (0,
|
|
5531
|
+
const statePath = (0, import_path16.join)(ctx.config.projectPath, ".one-shot-state.json");
|
|
5497
5532
|
const mcpServersAdded = ctx.installed.mcpServersAdded ?? [];
|
|
5498
5533
|
const filteredMcpConfig = Object.fromEntries(
|
|
5499
5534
|
Object.entries(ctx.config.mcpConfig).filter(([name]) => mcpServersAdded.includes(name))
|
|
@@ -5524,13 +5559,13 @@ var write_state_default = defineStep({
|
|
|
5524
5559
|
* mislead the uninstall preview which reads this field. */
|
|
5525
5560
|
factory: ctx.installed.factoryInstalled ? ".claude/" : null,
|
|
5526
5561
|
abapHooks: ctx.installed.abapHooksInstalled ? ".claude/hooks/" : null,
|
|
5527
|
-
globalConfig: (0,
|
|
5562
|
+
globalConfig: (0, import_path16.join)((0, import_os2.homedir)(), ".one-shot-installer")
|
|
5528
5563
|
}
|
|
5529
5564
|
};
|
|
5530
5565
|
if (ctx.journal) {
|
|
5531
5566
|
ctx.journal.setSummary(state);
|
|
5532
5567
|
} else {
|
|
5533
|
-
(0,
|
|
5568
|
+
(0, import_fs16.writeFileSync)(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
5534
5569
|
}
|
|
5535
5570
|
return { status: "success" };
|
|
5536
5571
|
},
|
|
@@ -5545,9 +5580,9 @@ var write_state_default = defineStep({
|
|
|
5545
5580
|
});
|
|
5546
5581
|
|
|
5547
5582
|
// src/uninstall.ts
|
|
5548
|
-
var
|
|
5583
|
+
var import_fs17 = require("fs");
|
|
5549
5584
|
var import_readline = require("readline");
|
|
5550
|
-
var
|
|
5585
|
+
var import_path17 = require("path");
|
|
5551
5586
|
var dim = (text) => `\x1B[2m${text}\x1B[0m`;
|
|
5552
5587
|
var yellow = (text) => `\x1B[33m${text}\x1B[0m`;
|
|
5553
5588
|
var red3 = (text) => `\x1B[31m${text}\x1B[0m`;
|
|
@@ -5567,11 +5602,11 @@ async function uninstall() {
|
|
|
5567
5602
|
try {
|
|
5568
5603
|
const projectInput = await esm_default3({
|
|
5569
5604
|
message: "Project directory to uninstall from:",
|
|
5570
|
-
default: (0,
|
|
5605
|
+
default: (0, import_path17.resolve)(process.cwd())
|
|
5571
5606
|
});
|
|
5572
|
-
const projectPath = (0,
|
|
5573
|
-
const statePath = (0,
|
|
5574
|
-
if (!(0,
|
|
5607
|
+
const projectPath = (0, import_path17.resolve)(projectInput);
|
|
5608
|
+
const statePath = (0, import_path17.join)(projectPath, ".one-shot-state.json");
|
|
5609
|
+
if (!(0, import_fs17.existsSync)(statePath)) {
|
|
5575
5610
|
console.log("");
|
|
5576
5611
|
console.log(red3(" No .one-shot-state.json found at:"));
|
|
5577
5612
|
console.log(` ${statePath}`);
|
|
@@ -5596,7 +5631,7 @@ async function uninstall() {
|
|
|
5596
5631
|
default: false
|
|
5597
5632
|
});
|
|
5598
5633
|
if (proceed2) {
|
|
5599
|
-
(0,
|
|
5634
|
+
(0, import_fs17.unlinkSync)(statePath);
|
|
5600
5635
|
console.log(" Removed .one-shot-state.json");
|
|
5601
5636
|
}
|
|
5602
5637
|
await waitForEnter();
|
|
@@ -5638,7 +5673,7 @@ async function uninstall() {
|
|
|
5638
5673
|
console.log("");
|
|
5639
5674
|
const result = await runRollback(stepList, ctx);
|
|
5640
5675
|
try {
|
|
5641
|
-
if ((0,
|
|
5676
|
+
if ((0, import_fs17.existsSync)(statePath)) (0, import_fs17.unlinkSync)(statePath);
|
|
5642
5677
|
} catch {
|
|
5643
5678
|
}
|
|
5644
5679
|
printSummary(result);
|
|
@@ -5650,7 +5685,7 @@ async function uninstall() {
|
|
|
5650
5685
|
}
|
|
5651
5686
|
function readSummary(statePath) {
|
|
5652
5687
|
try {
|
|
5653
|
-
const raw = JSON.parse((0,
|
|
5688
|
+
const raw = JSON.parse((0, import_fs17.readFileSync)(statePath, "utf-8"));
|
|
5654
5689
|
return raw;
|
|
5655
5690
|
} catch {
|
|
5656
5691
|
return {};
|
|
@@ -5731,19 +5766,19 @@ var dim2 = (text) => `\x1B[2m${text}\x1B[0m`;
|
|
|
5731
5766
|
var yellow2 = (text) => `\x1B[33m${text}\x1B[0m`;
|
|
5732
5767
|
var green2 = (text) => `\x1B[32m${text}\x1B[0m`;
|
|
5733
5768
|
function detectMarkerFileMode(filePath, markerStart) {
|
|
5734
|
-
if (!(0,
|
|
5735
|
-
const content = (0,
|
|
5769
|
+
if (!(0, import_fs18.existsSync)(filePath)) return green2("create");
|
|
5770
|
+
const content = (0, import_fs18.readFileSync)(filePath, "utf-8");
|
|
5736
5771
|
if (content.includes(markerStart)) return yellow2("update");
|
|
5737
5772
|
return yellow2("append");
|
|
5738
5773
|
}
|
|
5739
5774
|
function detectMCPFileMode(filePath) {
|
|
5740
|
-
if (!(0,
|
|
5775
|
+
if (!(0, import_fs18.existsSync)(filePath)) return green2("create");
|
|
5741
5776
|
return yellow2("merge");
|
|
5742
5777
|
}
|
|
5743
5778
|
function detectContextMode(projectPath, domain) {
|
|
5744
|
-
const contextDir = (0,
|
|
5745
|
-
const contextDirLower = (0,
|
|
5746
|
-
if ((0,
|
|
5779
|
+
const contextDir = (0, import_path18.join)(projectPath, "_ai-context", domain.toUpperCase());
|
|
5780
|
+
const contextDirLower = (0, import_path18.join)(projectPath, "_ai-context", domain);
|
|
5781
|
+
if ((0, import_fs18.existsSync)(contextDir) || (0, import_fs18.existsSync)(contextDirLower)) return yellow2("overwrite");
|
|
5747
5782
|
return green2("create");
|
|
5748
5783
|
}
|
|
5749
5784
|
function waitForEnter2() {
|
|
@@ -5789,7 +5824,7 @@ async function main() {
|
|
|
5789
5824
|
await waitForEnter2();
|
|
5790
5825
|
return;
|
|
5791
5826
|
}
|
|
5792
|
-
const statePath = (0,
|
|
5827
|
+
const statePath = (0, import_path18.join)(config.projectPath, ".one-shot-state.json");
|
|
5793
5828
|
const journal = new Journal(statePath);
|
|
5794
5829
|
journal.startFresh();
|
|
5795
5830
|
const ctx = {
|
|
@@ -5873,7 +5908,7 @@ async function collectInputs(options, releaseVersion, factoryAvailable = false,
|
|
|
5873
5908
|
}
|
|
5874
5909
|
const projectInput = await esm_default3({
|
|
5875
5910
|
message: "Project directory:",
|
|
5876
|
-
default: (0,
|
|
5911
|
+
default: (0, import_path18.resolve)(process.cwd())
|
|
5877
5912
|
});
|
|
5878
5913
|
const isAbapSelected = selectedTechnologies.some((t) => t.domains.includes("ABAP"));
|
|
5879
5914
|
const installAbapHooks = abapHooksAvailable && agent === "claude-code" && isAbapSelected;
|
|
@@ -5881,7 +5916,7 @@ async function collectInputs(options, releaseVersion, factoryAvailable = false,
|
|
|
5881
5916
|
technologies: selectedTechnologies,
|
|
5882
5917
|
agent,
|
|
5883
5918
|
azureDevOpsOrg,
|
|
5884
|
-
projectPath: (0,
|
|
5919
|
+
projectPath: (0, import_path18.resolve)(projectInput),
|
|
5885
5920
|
baseMcpServers: options.baseMcpServers,
|
|
5886
5921
|
mcpConfig,
|
|
5887
5922
|
releaseVersion,
|
|
@@ -5897,9 +5932,9 @@ async function previewAndConfirm(config, options) {
|
|
|
5897
5932
|
const instructionFile = target.instructions;
|
|
5898
5933
|
const mcpConfigFile = target.mcpConfig;
|
|
5899
5934
|
const serverEntries = Object.entries(config.mcpConfig);
|
|
5900
|
-
const instructionFilePath = (0,
|
|
5901
|
-
const mcpConfigFilePath = (0,
|
|
5902
|
-
const gitignorePath = (0,
|
|
5935
|
+
const instructionFilePath = (0, import_path18.join)(config.projectPath, instructionFile);
|
|
5936
|
+
const mcpConfigFilePath = (0, import_path18.join)(config.projectPath, mcpConfigFile);
|
|
5937
|
+
const gitignorePath = (0, import_path18.join)(config.projectPath, ".gitignore");
|
|
5903
5938
|
const instructionMode = detectMarkerFileMode(instructionFilePath, "<!-- one-shot-installer:start -->");
|
|
5904
5939
|
const mcpMode = detectMCPFileMode(mcpConfigFilePath);
|
|
5905
5940
|
const gitignoreMode = detectMarkerFileMode(gitignorePath, "# one-shot-installer:start");
|
|
@@ -5929,11 +5964,11 @@ async function previewAndConfirm(config, options) {
|
|
|
5929
5964
|
console.log(` ${mcpConfigFile.padEnd(domainColWidth + 14)}${mcpMode}`);
|
|
5930
5965
|
console.log(` ${".gitignore".padEnd(domainColWidth + 14)}${gitignoreMode}`);
|
|
5931
5966
|
if (config.installFactory || config.installAbapHooks) {
|
|
5932
|
-
const claudeDir = (0,
|
|
5933
|
-
const claudeMode = (0,
|
|
5967
|
+
const claudeDir = (0, import_path18.join)(config.projectPath, ".claude");
|
|
5968
|
+
const claudeMode = (0, import_fs18.existsSync)(claudeDir) ? yellow2("merge") : green2("create");
|
|
5934
5969
|
console.log(` ${".claude/".padEnd(domainColWidth + 14)}${claudeMode}`);
|
|
5935
|
-
const settingsPath = (0,
|
|
5936
|
-
const settingsMode = (0,
|
|
5970
|
+
const settingsPath = (0, import_path18.join)(config.projectPath, ".claude", "settings.json");
|
|
5971
|
+
const settingsMode = (0, import_fs18.existsSync)(settingsPath) ? yellow2("merge") : green2("create");
|
|
5937
5972
|
console.log(` ${".claude/settings.json".padEnd(domainColWidth + 14)}${settingsMode}`);
|
|
5938
5973
|
}
|
|
5939
5974
|
if (serverEntries.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dlw-machine-setup",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0-canary.1",
|
|
4
4
|
"description": "One-shot installer for The Machine toolchain",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dlw-machine-setup": "bin/installer.js"
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"license": "UNLICENSED",
|
|
17
17
|
"publishConfig": {
|
|
18
18
|
"access": "public",
|
|
19
|
-
"registry": "https://registry.npmjs.org"
|
|
19
|
+
"registry": "https://registry.npmjs.org",
|
|
20
|
+
"tag": "canary"
|
|
20
21
|
},
|
|
21
22
|
"engines": {
|
|
22
23
|
"node": ">=18.0.0"
|