dlw-machine-setup 0.2.5 → 0.3.0

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.
Files changed (2) hide show
  1. package/bin/installer.js +159 -88
  2. package/package.json +1 -1
package/bin/installer.js CHANGED
@@ -3247,9 +3247,9 @@ var import_path5 = require("path");
3247
3247
  // data/wizard-options/agents.json
3248
3248
  var agents_default = {
3249
3249
  agents: [
3250
- { name: "Claude Code", value: "claude-code" },
3251
- { name: "GitHub Copilot", value: "github-copilot" },
3252
- { name: "Cursor", value: "cursor" }
3250
+ { name: "Claude Code", value: "claude-code", active: true },
3251
+ { name: "GitHub Copilot", value: "github-copilot", active: true },
3252
+ { name: "Cursor", value: "cursor", active: false }
3253
3253
  ]
3254
3254
  };
3255
3255
 
@@ -3262,46 +3262,137 @@ var personas_default = {
3262
3262
  name: "SAPUI5 Developer",
3263
3263
  description: "Frontend development with SAP UI5 and Fiori",
3264
3264
  domains: ["SAPUI5"],
3265
- mcpServers: ["azure-devops", "context7", "playwright", "@ui5/mcp-server"]
3265
+ mcpServers: ["azure-devops", "context7", "playwright", "@ui5/mcp-server"],
3266
+ active: true
3266
3267
  },
3267
3268
  {
3268
3269
  id: "cap-developer",
3269
3270
  name: "CAP Developer",
3270
3271
  description: "Backend development with SAP Cloud Application Programming model",
3271
3272
  domains: ["CAP"],
3272
- mcpServers: ["azure-devops", "context7", "cds-mcp"]
3273
+ mcpServers: ["azure-devops", "context7", "cds-mcp"],
3274
+ active: true
3273
3275
  },
3274
3276
  {
3275
3277
  id: "abap-developer",
3276
3278
  name: "ABAP Developer",
3277
3279
  description: "ABAP and SAP backend development",
3278
3280
  domains: ["ABAP"],
3279
- mcpServers: ["azure-devops", "context7", "abap", "sap-researcher"]
3281
+ mcpServers: ["azure-devops", "context7", "abap", "sap-researcher"],
3282
+ active: true
3280
3283
  },
3281
3284
  {
3282
3285
  id: "btp-developer",
3283
3286
  name: "BTP Developer",
3284
3287
  description: "SAP Business Technology Platform development",
3285
3288
  domains: ["BTP"],
3286
- mcpServers: ["azure-devops", "context7"]
3289
+ mcpServers: ["azure-devops", "context7"],
3290
+ active: true
3287
3291
  },
3288
3292
  {
3289
3293
  id: "sap-dm-developer",
3290
3294
  name: "SAP Digital Manufacturing Developer",
3291
3295
  description: "SAP Digital Manufacturing development",
3292
3296
  domains: ["SAP_DM"],
3293
- mcpServers: ["azure-devops", "context7"]
3297
+ mcpServers: ["azure-devops", "context7"],
3298
+ active: true
3294
3299
  },
3295
3300
  {
3296
3301
  id: "forms-developer",
3297
3302
  name: "Forms Developer",
3298
3303
  description: "SAP Forms development",
3299
3304
  domains: ["FORMS"],
3300
- mcpServers: ["azure-devops", "context7"]
3305
+ mcpServers: ["azure-devops", "context7"],
3306
+ active: true
3301
3307
  }
3302
3308
  ]
3303
3309
  };
3304
3310
 
3311
+ // data/wizard-options/mcp-servers.json
3312
+ var mcp_servers_default = {
3313
+ "azure-devops": {
3314
+ command: "npx",
3315
+ args: ["-y", "@azure-devops/mcp", "__AZURE_ORG__"],
3316
+ description: "Access Azure DevOps work items, boards, pipelines and repositories",
3317
+ useWhen: "User asks about work items, sprints, pipelines, pull requests or Azure DevOps tasks",
3318
+ active: true
3319
+ },
3320
+ context7: {
3321
+ type: "stdio",
3322
+ command: "npx",
3323
+ args: ["-y", "@upstash/context7-mcp"],
3324
+ description: "Fetch up-to-date library and framework documentation",
3325
+ useWhen: "User asks how something works in a specific library or framework (e.g. 'how does X work in SAPUI5?')",
3326
+ active: true
3327
+ },
3328
+ "@ui5/mcp-server": {
3329
+ type: "stdio",
3330
+ command: "npx",
3331
+ args: ["@ui5/mcp-server"],
3332
+ description: "SAPUI5-specific tooling for views, controllers, manifest and OData",
3333
+ useWhen: "User asks to create or modify SAPUI5 views, controllers, fragments or manifest.json",
3334
+ active: true
3335
+ },
3336
+ playwright: {
3337
+ command: "npx",
3338
+ args: ["@playwright/mcp@latest"],
3339
+ description: "Browser automation and end-to-end testing",
3340
+ useWhen: "User asks to write or run browser tests, or automate browser interactions",
3341
+ active: true
3342
+ },
3343
+ "cds-mcp": {
3344
+ command: "npx",
3345
+ args: ["-y", "@cap-js/mcp-server"],
3346
+ description: "SAP CAP/CDS tooling for service definitions, handlers and CQL",
3347
+ useWhen: "User asks about CAP services, CDS models, handlers or CQL queries",
3348
+ active: true
3349
+ },
3350
+ abap: {
3351
+ type: "http",
3352
+ url: "http://localhost:5001/mcp",
3353
+ description: "ABAP development assistant for SAP backend development",
3354
+ useWhen: "User asks about ABAP code, RAP objects, CDS views or SAP backend logic",
3355
+ active: true
3356
+ },
3357
+ "sap-researcher": {
3358
+ command: "npx",
3359
+ args: ["mcp-remote", "http://gsi-em-az1-0057/successormcp/mcp", "--allow-http"],
3360
+ description: "Internal SAP knowledge base and documentation search",
3361
+ useWhen: "User asks about SAP-specific topics, best practices or internal documentation",
3362
+ active: true
3363
+ }
3364
+ };
3365
+
3366
+ // src/utils/data/fetch-wizard-options.ts
3367
+ var GITHUB_REPO = "DLW-INT-SAP-DEV/DBE_DLWR_AI_WORKSPACE_SETUP_client";
3368
+ async function fetchWizardOptions(token) {
3369
+ try {
3370
+ const headers = {
3371
+ "Accept": "application/vnd.github+json",
3372
+ "Authorization": `Bearer ${token}`
3373
+ };
3374
+ const releaseRes = await fetch(
3375
+ `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`,
3376
+ { headers }
3377
+ );
3378
+ if (!releaseRes.ok) return null;
3379
+ const release = await releaseRes.json();
3380
+ const asset = release.assets?.find((a) => a.name === "wizard-options.json");
3381
+ if (!asset) return null;
3382
+ const assetRes = await fetch(asset.url, {
3383
+ headers: { ...headers, "Accept": "application/octet-stream" }
3384
+ });
3385
+ if (!assetRes.ok) return null;
3386
+ const data = await assetRes.json();
3387
+ if (!Array.isArray(data.agents) || !Array.isArray(data.personas?.personas)) {
3388
+ return null;
3389
+ }
3390
+ return data;
3391
+ } catch {
3392
+ return null;
3393
+ }
3394
+ }
3395
+
3305
3396
  // src/utils/data/fetch-contexts.ts
3306
3397
  var import_fs2 = require("fs");
3307
3398
  var import_path2 = require("path");
@@ -3463,12 +3554,12 @@ async function getGitHubToken() {
3463
3554
  }
3464
3555
 
3465
3556
  // src/utils/data/fetch-contexts.ts
3466
- var GITHUB_REPO = "DLW-INT-SAP-DEV/DBE_DLWR_AI_WORKSPACE_SETUP_client";
3557
+ var GITHUB_REPO2 = "DLW-INT-SAP-DEV/DBE_DLWR_AI_WORKSPACE_SETUP_client";
3467
3558
  var MAX_RETRIES = 3;
3468
3559
  var RETRY_DELAY_MS = 2e3;
3469
3560
  var MIN_FILE_SIZE = 1024;
3470
3561
  async function fetchContexts(options = {}) {
3471
- const { domains = [], targetDir = process.cwd(), force = false } = options;
3562
+ const { domains = [], targetDir = process.cwd(), force = false, token } = options;
3472
3563
  const result = {
3473
3564
  successful: [],
3474
3565
  failed: [],
@@ -3479,9 +3570,9 @@ async function fetchContexts(options = {}) {
3479
3570
  return result;
3480
3571
  }
3481
3572
  await checkPrerequisites();
3482
- const githubToken = await getGitHubToken();
3573
+ const githubToken = token ?? await getGitHubToken();
3483
3574
  try {
3484
- const releaseUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
3575
+ const releaseUrl = `https://api.github.com/repos/${GITHUB_REPO2}/releases/latest`;
3485
3576
  const headers = {
3486
3577
  "Accept": "application/vnd.github+json",
3487
3578
  "Authorization": `Bearer ${githubToken}`
@@ -3656,56 +3747,6 @@ function mergeDirectories(source, target) {
3656
3747
  // src/utils/setup/setup-mcp.ts
3657
3748
  var import_fs3 = require("fs");
3658
3749
  var import_path3 = require("path");
3659
-
3660
- // data/wizard-options/mcp-servers.json
3661
- var mcp_servers_default = {
3662
- "azure-devops": {
3663
- command: "npx",
3664
- args: ["-y", "@azure-devops/mcp", "__AZURE_ORG__"],
3665
- description: "Access Azure DevOps work items, boards, pipelines and repositories",
3666
- useWhen: "User asks about work items, sprints, pipelines, pull requests or Azure DevOps tasks"
3667
- },
3668
- context7: {
3669
- type: "stdio",
3670
- command: "npx",
3671
- args: ["-y", "@upstash/context7-mcp"],
3672
- description: "Fetch up-to-date library and framework documentation",
3673
- useWhen: "User asks how something works in a specific library or framework (e.g. 'how does X work in SAPUI5?')"
3674
- },
3675
- "@ui5/mcp-server": {
3676
- type: "stdio",
3677
- command: "npx",
3678
- args: ["@ui5/mcp-server"],
3679
- description: "SAPUI5-specific tooling for views, controllers, manifest and OData",
3680
- useWhen: "User asks to create or modify SAPUI5 views, controllers, fragments or manifest.json"
3681
- },
3682
- playwright: {
3683
- command: "npx",
3684
- args: ["@playwright/mcp@latest"],
3685
- description: "Browser automation and end-to-end testing",
3686
- useWhen: "User asks to write or run browser tests, or automate browser interactions"
3687
- },
3688
- "cds-mcp": {
3689
- command: "npx",
3690
- args: ["-y", "@cap-js/mcp-server"],
3691
- description: "SAP CAP/CDS tooling for service definitions, handlers and CQL",
3692
- useWhen: "User asks about CAP services, CDS models, handlers or CQL queries"
3693
- },
3694
- abap: {
3695
- type: "http",
3696
- url: "http://localhost:5001/mcp",
3697
- description: "ABAP development assistant for SAP backend development",
3698
- useWhen: "User asks about ABAP code, RAP objects, CDS views or SAP backend logic"
3699
- },
3700
- "sap-researcher": {
3701
- command: "npx",
3702
- args: ["mcp-remote", "http://gsi-em-az1-0057/successormcp/mcp", "--allow-http"],
3703
- description: "Internal SAP knowledge base and documentation search",
3704
- useWhen: "User asks about SAP-specific topics, best practices or internal documentation"
3705
- }
3706
- };
3707
-
3708
- // src/utils/setup/setup-mcp.ts
3709
3750
  function getAgentMCPTarget(agent) {
3710
3751
  switch (agent) {
3711
3752
  case "claude-code":
@@ -3717,7 +3758,9 @@ function getAgentMCPTarget(agent) {
3717
3758
  return { filePath: ".vscode/mcp.json", rootKey: "servers", dir: ".vscode" };
3718
3759
  }
3719
3760
  }
3720
- var ALL_MCP_SERVERS = mcp_servers_default;
3761
+ var ALL_MCP_SERVERS = Object.fromEntries(
3762
+ Object.entries(mcp_servers_default).filter(([, config]) => config.active !== false)
3763
+ );
3721
3764
  async function setupMCPConfiguration(projectPath, mcpConfig, agent) {
3722
3765
  const target = getAgentMCPTarget(agent);
3723
3766
  const mcpJsonPath = (0, import_path3.join)(projectPath, target.filePath);
@@ -3743,7 +3786,7 @@ async function setupMCPConfiguration(projectPath, mcpConfig, agent) {
3743
3786
  if (mergedServers[serverName]) {
3744
3787
  skippedServers.push(serverName);
3745
3788
  } else {
3746
- const { description, useWhen, ...mcpFields } = serverConfig;
3789
+ const { description, useWhen, active, ...mcpFields } = serverConfig;
3747
3790
  mergedServers[serverName] = mcpFields;
3748
3791
  addedServers.push(serverName);
3749
3792
  }
@@ -3752,17 +3795,18 @@ async function setupMCPConfiguration(projectPath, mcpConfig, agent) {
3752
3795
  (0, import_fs3.writeFileSync)(mcpJsonPath, JSON.stringify(outputFile, null, 2), "utf-8");
3753
3796
  return { addedServers, skippedServers };
3754
3797
  }
3755
- function buildMCPConfiguration(selectedItems, baseMcpServers2) {
3798
+ function buildMCPConfiguration(selectedItems, baseMcpServers2, allMcpServers) {
3799
+ const servers = allMcpServers ?? ALL_MCP_SERVERS;
3756
3800
  const config = {};
3757
3801
  for (const serverName of baseMcpServers2) {
3758
- if (ALL_MCP_SERVERS[serverName]) {
3759
- config[serverName] = ALL_MCP_SERVERS[serverName];
3802
+ if (servers[serverName]) {
3803
+ config[serverName] = servers[serverName];
3760
3804
  }
3761
3805
  }
3762
3806
  for (const item of selectedItems) {
3763
3807
  for (const serverName of item.mcpServers) {
3764
- if (ALL_MCP_SERVERS[serverName] && !config[serverName]) {
3765
- config[serverName] = ALL_MCP_SERVERS[serverName];
3808
+ if (servers[serverName] && !config[serverName]) {
3809
+ config[serverName] = servers[serverName];
3766
3810
  }
3767
3811
  }
3768
3812
  }
@@ -3868,15 +3912,15 @@ async function setupInstructions(config) {
3868
3912
  break;
3869
3913
  }
3870
3914
  case "github-copilot": {
3871
- const instructionsDir = (0, import_path4.join)(process.cwd(), ".github", "instructions");
3872
- if (!(0, import_fs4.existsSync)(instructionsDir)) (0, import_fs4.mkdirSync)(instructionsDir, { recursive: true });
3915
+ const agentsDir = (0, import_path4.join)(process.cwd(), ".github", "agents");
3916
+ if (!(0, import_fs4.existsSync)(agentsDir)) (0, import_fs4.mkdirSync)(agentsDir, { recursive: true });
3873
3917
  const body = buildCombinedInstructions(domains, mcpConfig);
3874
3918
  const withFrontmatter = `---
3875
3919
  applyTo: "**"
3876
3920
  ---
3877
3921
 
3878
3922
  ${body}`;
3879
- upsertBlock((0, import_path4.join)(instructionsDir, `instructions.instructions.md`), withFrontmatter);
3923
+ upsertBlock((0, import_path4.join)(agentsDir, `instructions.md`), withFrontmatter);
3880
3924
  break;
3881
3925
  }
3882
3926
  case "cursor": {
@@ -3892,9 +3936,33 @@ ${body}`;
3892
3936
  }
3893
3937
 
3894
3938
  // src/utils/mod.ts
3895
- var personas = personas_default.personas;
3939
+ var personas = personas_default.personas.filter((p) => p.active !== false);
3896
3940
  var baseMcpServers = personas_default.baseMcpServers;
3897
- var agents = agents_default.agents;
3941
+ var agents = agents_default.agents.filter((a) => a.active !== false);
3942
+ async function loadWizardOptions(token) {
3943
+ const remote = await fetchWizardOptions(token);
3944
+ if (remote) {
3945
+ const filteredMcpServers = Object.fromEntries(
3946
+ Object.entries(remote.mcpServers).filter(([, config]) => config.active !== false)
3947
+ );
3948
+ return {
3949
+ personas: remote.personas.personas.filter((p) => p.active !== false),
3950
+ agents: remote.agents.filter((a) => a.active !== false),
3951
+ baseMcpServers: remote.personas.baseMcpServers,
3952
+ mcpServers: filteredMcpServers
3953
+ };
3954
+ }
3955
+ console.log(" (Using bundled configuration)");
3956
+ const fallbackMcpServers = Object.fromEntries(
3957
+ Object.entries(mcp_servers_default).filter(([, c]) => c.active !== false)
3958
+ );
3959
+ return {
3960
+ personas,
3961
+ agents,
3962
+ baseMcpServers,
3963
+ mcpServers: fallbackMcpServers
3964
+ };
3965
+ }
3898
3966
 
3899
3967
  // src/index.ts
3900
3968
  function getInstructionFilePath(agent) {
@@ -3902,7 +3970,7 @@ function getInstructionFilePath(agent) {
3902
3970
  case "claude-code":
3903
3971
  return "CLAUDE.md";
3904
3972
  case "github-copilot":
3905
- return ".github/instructions/instructions.instructions.md";
3973
+ return ".github/agents/instructions.md";
3906
3974
  case "cursor":
3907
3975
  return ".cursor/rules/instructions.mdc";
3908
3976
  default:
@@ -3938,18 +4006,21 @@ async function main() {
3938
4006
  console.clear();
3939
4007
  console.log("One-Shot Setup Installer\n");
3940
4008
  try {
3941
- const config = await collectInputs();
4009
+ const token = await getGitHubToken();
4010
+ console.log(" Loading configuration...");
4011
+ const options = await loadWizardOptions(token);
4012
+ const config = await collectInputs(options);
3942
4013
  if (!config) {
3943
4014
  await waitForEnter();
3944
4015
  return;
3945
4016
  }
3946
- const proceed = await previewAndConfirm(config);
4017
+ const proceed = await previewAndConfirm(config, options);
3947
4018
  if (!proceed) {
3948
4019
  console.log("\nNo changes made.");
3949
4020
  await waitForEnter();
3950
4021
  return;
3951
4022
  }
3952
- const result = await execute(config);
4023
+ const result = await execute(config, token);
3953
4024
  printSummary(result);
3954
4025
  return;
3955
4026
  } catch (error) {
@@ -3957,22 +4028,22 @@ async function main() {
3957
4028
  await waitForEnter();
3958
4029
  }
3959
4030
  }
3960
- async function collectInputs() {
4031
+ async function collectInputs(options) {
3961
4032
  const selectedIds = await esm_default2({
3962
4033
  message: "Personas:",
3963
4034
  instructions: " Space to select \xB7 Enter to confirm",
3964
- choices: personas.map((p) => ({
4035
+ choices: options.personas.map((p) => ({
3965
4036
  name: p.name.replace(/ Developer$/, ""),
3966
4037
  value: p.id
3967
4038
  })),
3968
4039
  required: true
3969
4040
  });
3970
- const selectedPersonas = personas.filter((p) => selectedIds.includes(p.id));
4041
+ const selectedPersonas = options.personas.filter((p) => selectedIds.includes(p.id));
3971
4042
  const agent = await esm_default5({
3972
4043
  message: "AI coding tool:",
3973
- choices: agents
4044
+ choices: options.agents
3974
4045
  });
3975
- const mcpConfig = buildMCPConfiguration(selectedPersonas, baseMcpServers);
4046
+ const mcpConfig = buildMCPConfiguration(selectedPersonas, options.baseMcpServers, options.mcpServers);
3976
4047
  let azureDevOpsOrg = "";
3977
4048
  if (mcpConfig["azure-devops"]) {
3978
4049
  const org = await esm_default4({
@@ -3999,9 +4070,9 @@ async function collectInputs() {
3999
4070
  mcpConfig
4000
4071
  };
4001
4072
  }
4002
- async function previewAndConfirm(config) {
4073
+ async function previewAndConfirm(config, options) {
4003
4074
  const personaNames = config.personas.map((p) => p.name.replace(/ Developer$/, "")).join(", ");
4004
- const agentDisplay = agents.find((a) => a.value === config.agent)?.name ?? config.agent;
4075
+ const agentDisplay = options.agents.find((a) => a.value === config.agent)?.name ?? config.agent;
4005
4076
  const instructionFile = getInstructionFilePath(config.agent);
4006
4077
  const mcpConfigFile = getMCPConfigPath(config.agent);
4007
4078
  const serverEntries = Object.entries(config.mcpConfig);
@@ -4029,7 +4100,7 @@ async function previewAndConfirm(config) {
4029
4100
  console.log("\n" + "\u2500".repeat(48));
4030
4101
  return esm_default3({ message: "Proceed?", default: true });
4031
4102
  }
4032
- async function execute(config) {
4103
+ async function execute(config, token) {
4033
4104
  const instructionFilePath = getInstructionFilePath(config.agent);
4034
4105
  const mcpConfigPath = getMCPConfigPath(config.agent);
4035
4106
  const result = {
@@ -4048,7 +4119,7 @@ async function execute(config) {
4048
4119
  const domainValues = uniqueDomains.map((d) => d.toLowerCase());
4049
4120
  console.log(` Downloading contexts...`);
4050
4121
  try {
4051
- const downloadResult = await fetchContexts({ domains: domainValues });
4122
+ const downloadResult = await fetchContexts({ domains: domainValues, token });
4052
4123
  result.domainsInstalled = downloadResult.successful;
4053
4124
  result.domainsFailed = downloadResult.failed;
4054
4125
  result.failureReasons = downloadResult.failureReasons;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dlw-machine-setup",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "description": "One-shot installer for The Machine toolchain",
5
5
  "bin": {
6
6
  "dlw-machine-setup": "bin/installer.js"