imcp 0.0.19 → 0.1.2

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 (183) hide show
  1. package/.roo/rules-code/rules.md +88 -0
  2. package/dist/cli/index.js +1 -45
  3. package/dist/core/installers/clients/BaseClientInstaller.d.ts +1 -5
  4. package/dist/core/installers/clients/BaseClientInstaller.js +40 -38
  5. package/dist/core/installers/clients/ClientInstaller.d.ts +9 -9
  6. package/dist/core/installers/clients/ClientInstaller.js +105 -99
  7. package/dist/core/installers/requirements/BaseInstaller.d.ts +9 -1
  8. package/dist/core/installers/requirements/CommandInstaller.d.ts +9 -1
  9. package/dist/core/installers/requirements/CommandInstaller.js +46 -12
  10. package/dist/core/installers/requirements/GeneralInstaller.d.ts +11 -1
  11. package/dist/core/installers/requirements/GeneralInstaller.js +46 -10
  12. package/dist/core/installers/requirements/InstallerFactory.d.ts +3 -1
  13. package/dist/core/installers/requirements/InstallerFactory.js +3 -2
  14. package/dist/core/installers/requirements/NpmInstaller.d.ts +4 -2
  15. package/dist/core/installers/requirements/NpmInstaller.js +38 -22
  16. package/dist/core/installers/requirements/PipInstaller.d.ts +3 -1
  17. package/dist/core/installers/requirements/PipInstaller.js +58 -36
  18. package/dist/core/installers/requirements/RequirementInstaller.d.ts +4 -1
  19. package/dist/core/loaders/InstallOperationManager.d.ts +115 -0
  20. package/dist/core/loaders/InstallOperationManager.js +311 -0
  21. package/dist/core/loaders/SystemSettingsManager.d.ts +54 -0
  22. package/dist/core/loaders/SystemSettingsManager.js +257 -0
  23. package/dist/core/metadatas/constants.d.ts +7 -0
  24. package/dist/core/metadatas/constants.js +7 -0
  25. package/dist/core/metadatas/recordingConstants.d.ts +44 -0
  26. package/dist/core/metadatas/recordingConstants.js +45 -0
  27. package/dist/core/metadatas/types.d.ts +21 -0
  28. package/dist/core/onboard/FeedOnboardService.d.ts +7 -3
  29. package/dist/core/onboard/FeedOnboardService.js +52 -5
  30. package/dist/core/onboard/InstallOperationManager.d.ts +23 -0
  31. package/dist/core/onboard/InstallOperationManager.js +144 -0
  32. package/dist/core/onboard/OnboardStatusManager.js +2 -1
  33. package/dist/core/validators/StdioServerValidator.js +4 -3
  34. package/dist/services/InstallationService.d.ts +2 -37
  35. package/dist/services/InstallationService.js +45 -313
  36. package/dist/services/MCPManager.d.ts +1 -1
  37. package/dist/services/MCPManager.js +53 -47
  38. package/dist/services/RequirementService.d.ts +85 -12
  39. package/dist/services/RequirementService.js +488 -49
  40. package/dist/services/ServerService.d.ts +0 -6
  41. package/dist/services/ServerService.js +0 -74
  42. package/dist/services/TelemetryService.d.ts +15 -0
  43. package/dist/services/TelemetryService.js +54 -0
  44. package/dist/utils/adoUtils.js +6 -3
  45. package/dist/utils/githubAuth.js +65 -0
  46. package/dist/utils/logger.d.ts +16 -0
  47. package/dist/utils/logger.js +78 -1
  48. package/dist/utils/macroExpressionUtils.js +3 -25
  49. package/dist/utils/osUtils.d.ts +22 -1
  50. package/dist/utils/osUtils.js +92 -1
  51. package/dist/utils/versionUtils.d.ts +20 -0
  52. package/dist/utils/versionUtils.js +76 -0
  53. package/dist/web/public/css/modal.css +292 -1
  54. package/dist/web/public/css/serverCategoryList.css +120 -0
  55. package/dist/web/public/css/serverDetails.css +14 -1
  56. package/dist/web/public/index.html +126 -21
  57. package/dist/web/public/js/flights/flights.js +1 -1
  58. package/dist/web/public/js/modal/index.js +8 -14
  59. package/dist/web/public/js/modal/installModal.js +3 -4
  60. package/dist/web/public/js/modal/installation.js +122 -137
  61. package/dist/web/public/js/modal/loadingModal.js +155 -25
  62. package/dist/web/public/js/modal/messageQueue.js +45 -101
  63. package/dist/web/public/js/modal/modalSetup.js +125 -43
  64. package/dist/web/public/js/modal/modalUtils.js +0 -12
  65. package/dist/web/public/js/modal.js +23 -10
  66. package/dist/web/public/js/onboard/formProcessor.js +18 -11
  67. package/dist/web/public/js/onboard/publishHandler.js +35 -3
  68. package/dist/web/public/js/onboard/templates.js +5 -1
  69. package/dist/web/public/js/onboard/uiHandlers.js +266 -39
  70. package/dist/web/public/js/onboard/validationHandlers.js +71 -39
  71. package/dist/web/public/js/serverCategoryDetails.js +60 -11
  72. package/dist/web/public/js/serverCategoryList.js +93 -9
  73. package/dist/web/public/js/settings.js +314 -0
  74. package/dist/web/public/onboard.html +2 -2
  75. package/dist/web/public/settings.html +135 -0
  76. package/dist/web/public/styles.css +32 -0
  77. package/dist/web/server.js +93 -1
  78. package/{src/web/public/js/onboard → docs}/ONBOARDING_PAGE_DESIGN.md +15 -125
  79. package/docs/Telemetry.md +136 -0
  80. package/memory-bank/activeContext.md +26 -0
  81. package/memory-bank/decisionLog.md +91 -0
  82. package/memory-bank/productContext.md +41 -0
  83. package/memory-bank/progress.md +35 -0
  84. package/memory-bank/systemPatterns.md +10 -0
  85. package/package.json +2 -1
  86. package/src/cli/index.ts +1 -48
  87. package/src/core/installers/clients/BaseClientInstaller.ts +64 -50
  88. package/src/core/installers/clients/ClientInstaller.ts +130 -130
  89. package/src/core/installers/requirements/BaseInstaller.ts +9 -1
  90. package/src/core/installers/requirements/CommandInstaller.ts +47 -13
  91. package/src/core/installers/requirements/GeneralInstaller.ts +48 -10
  92. package/src/core/installers/requirements/InstallerFactory.ts +4 -3
  93. package/src/core/installers/requirements/NpmInstaller.ts +90 -68
  94. package/src/core/installers/requirements/PipInstaller.ts +81 -55
  95. package/src/core/installers/requirements/RequirementInstaller.ts +4 -3
  96. package/src/core/loaders/InstallOperationManager.ts +367 -0
  97. package/src/core/loaders/SystemSettingsManager.ts +278 -0
  98. package/src/core/metadatas/constants.ts +9 -0
  99. package/src/core/metadatas/recordingConstants.ts +62 -0
  100. package/src/core/metadatas/types.ts +23 -0
  101. package/src/core/onboard/FeedOnboardService.ts +59 -5
  102. package/src/core/onboard/OnboardStatusManager.ts +2 -1
  103. package/src/core/validators/StdioServerValidator.ts +4 -3
  104. package/src/services/InstallationService.ts +54 -399
  105. package/src/services/MCPManager.ts +61 -64
  106. package/src/services/RequirementService.ts +564 -67
  107. package/src/services/ServerService.ts +0 -90
  108. package/src/services/TelemetryService.ts +59 -0
  109. package/src/utils/adoUtils.ts +6 -4
  110. package/src/utils/githubAuth.ts +84 -1
  111. package/src/utils/logger.ts +83 -1
  112. package/src/utils/macroExpressionUtils.ts +4 -21
  113. package/src/utils/osUtils.ts +92 -1
  114. package/src/utils/versionUtils.ts +98 -13
  115. package/src/web/public/css/modal.css +292 -1
  116. package/src/web/public/css/serverCategoryList.css +120 -0
  117. package/src/web/public/css/serverDetails.css +14 -1
  118. package/src/web/public/index.html +126 -21
  119. package/src/web/public/js/flights/flights.js +1 -1
  120. package/src/web/public/js/modal/index.js +8 -14
  121. package/src/web/public/js/modal/installModal.js +3 -4
  122. package/src/web/public/js/modal/installation.js +122 -137
  123. package/src/web/public/js/modal/loadingModal.js +155 -25
  124. package/src/web/public/js/modal/modalSetup.js +125 -43
  125. package/src/web/public/js/modal/modalUtils.js +0 -12
  126. package/src/web/public/js/modal.js +23 -10
  127. package/src/web/public/js/onboard/formProcessor.js +18 -11
  128. package/src/web/public/js/onboard/publishHandler.js +35 -3
  129. package/src/web/public/js/onboard/templates.js +5 -1
  130. package/src/web/public/js/onboard/uiHandlers.js +266 -39
  131. package/src/web/public/js/onboard/validationHandlers.js +71 -39
  132. package/src/web/public/js/serverCategoryDetails.js +60 -11
  133. package/src/web/public/js/serverCategoryList.js +93 -9
  134. package/src/web/public/js/settings.js +314 -0
  135. package/src/web/public/onboard.html +2 -2
  136. package/src/web/public/settings.html +135 -0
  137. package/src/web/public/styles.css +32 -0
  138. package/src/web/server.ts +96 -1
  139. package/dist/cli/commands/start.d.ts +0 -2
  140. package/dist/cli/commands/start.js +0 -32
  141. package/dist/cli/commands/sync.d.ts +0 -2
  142. package/dist/cli/commands/sync.js +0 -17
  143. package/dist/core/ConfigurationLoader.d.ts +0 -32
  144. package/dist/core/ConfigurationLoader.js +0 -236
  145. package/dist/core/ConfigurationProvider.d.ts +0 -35
  146. package/dist/core/ConfigurationProvider.js +0 -375
  147. package/dist/core/InstallationService.d.ts +0 -50
  148. package/dist/core/InstallationService.js +0 -350
  149. package/dist/core/MCPManager.d.ts +0 -28
  150. package/dist/core/MCPManager.js +0 -188
  151. package/dist/core/RequirementService.d.ts +0 -40
  152. package/dist/core/RequirementService.js +0 -110
  153. package/dist/core/ServerSchemaLoader.d.ts +0 -11
  154. package/dist/core/ServerSchemaLoader.js +0 -43
  155. package/dist/core/ServerSchemaProvider.d.ts +0 -17
  156. package/dist/core/ServerSchemaProvider.js +0 -120
  157. package/dist/core/constants.d.ts +0 -47
  158. package/dist/core/constants.js +0 -94
  159. package/dist/core/installers/BaseInstaller.d.ts +0 -74
  160. package/dist/core/installers/BaseInstaller.js +0 -253
  161. package/dist/core/installers/ClientInstaller.d.ts +0 -23
  162. package/dist/core/installers/ClientInstaller.js +0 -564
  163. package/dist/core/installers/CommandInstaller.d.ts +0 -37
  164. package/dist/core/installers/CommandInstaller.js +0 -173
  165. package/dist/core/installers/GeneralInstaller.d.ts +0 -33
  166. package/dist/core/installers/GeneralInstaller.js +0 -85
  167. package/dist/core/installers/InstallerFactory.d.ts +0 -54
  168. package/dist/core/installers/InstallerFactory.js +0 -97
  169. package/dist/core/installers/NpmInstaller.d.ts +0 -26
  170. package/dist/core/installers/NpmInstaller.js +0 -127
  171. package/dist/core/installers/PipInstaller.d.ts +0 -28
  172. package/dist/core/installers/PipInstaller.js +0 -127
  173. package/dist/core/installers/RequirementInstaller.d.ts +0 -33
  174. package/dist/core/installers/RequirementInstaller.js +0 -3
  175. package/dist/core/types.d.ts +0 -166
  176. package/dist/core/types.js +0 -16
  177. package/dist/services/InstallRequestValidator.d.ts +0 -21
  178. package/dist/services/InstallRequestValidator.js +0 -99
  179. package/dist/web/public/js/modal/installHandler.js +0 -227
  180. package/dist/web/public/js/modal/loadingUI.js +0 -74
  181. package/dist/web/public/js/modal/modalUI.js +0 -214
  182. package/dist/web/public/js/modal/version.js +0 -20
  183. package/src/web/public/js/modal/messageQueue.js +0 -112
@@ -2,6 +2,7 @@ import { OSType } from '../../metadatas/types.js';
2
2
  import { BaseInstaller } from './BaseInstaller.js';
3
3
  import { getOSType, refreshPathEnv } from '../../../utils/osUtils.js';
4
4
  import { Logger } from '../../../utils/logger.js';
5
+ import * as RecordingConstants from '../../metadatas/recordingConstants.js';
5
6
  /**
6
7
  * Installer implementation for command-line tools
7
8
  */
@@ -122,8 +123,15 @@ export class CommandInstaller extends BaseInstaller {
122
123
  * @param requirement The requirement to install
123
124
  * @returns The status of the installation
124
125
  */
125
- async install(requirement) {
126
- try {
126
+ /**
127
+ * Install the command
128
+ * @param requirement The requirement to install
129
+ * @param options Optional install options
130
+ * @param recorder Optional InstallOperationManager for recording steps
131
+ * @returns The status of the installation
132
+ */
133
+ async install(requirement, recorder, options) {
134
+ const doInstall = async () => {
127
135
  const status = await this.checkInstallation(requirement);
128
136
  if (status.installed) {
129
137
  return status;
@@ -132,20 +140,20 @@ export class CommandInstaller extends BaseInstaller {
132
140
  const osType = getOSType();
133
141
  let installCommand;
134
142
  if (osType === OSType.Windows) {
135
- // Windows installation using winget
136
143
  installCommand = `winget install --id ${packageId}`;
137
144
  if (requirement.version && requirement.version !== 'latest') {
138
145
  installCommand += ` --version ${requirement.version}`;
139
146
  }
140
147
  }
141
148
  else if (osType === OSType.MacOS) {
142
- // macOS installation using Homebrew
143
149
  installCommand = `brew install ${packageId}`;
144
150
  if (requirement.version && requirement.version !== 'latest') {
145
151
  installCommand += `@${requirement.version}`;
146
152
  }
147
153
  }
148
154
  else {
155
+ if (recorder)
156
+ await recorder.recordStep('CommandInstaller:UnsupportedOS', 'failed', `Unsupported OS for ${requirement.name}`);
149
157
  throw new Error(`Unsupported operating system for installing ${requirement.name}`);
150
158
  }
151
159
  // Execute the installation command
@@ -165,15 +173,41 @@ export class CommandInstaller extends BaseInstaller {
165
173
  version: updatedStatus.version || requirement.version,
166
174
  inProgress: false
167
175
  };
176
+ };
177
+ if (recorder) {
178
+ return recorder.recording(doInstall, {
179
+ stepName: RecordingConstants.STEP_COMMAND_INSTALLER_INSTALL,
180
+ inProgressMessage: `Installing command: ${requirement.name}`,
181
+ endMessage: (result) => result.installed
182
+ ? `Install completed for ${requirement.name}`
183
+ : `Install failed for ${requirement.name}`,
184
+ onError: (error) => {
185
+ return {
186
+ result: {
187
+ name: requirement.name,
188
+ type: 'command',
189
+ installed: false,
190
+ error: error instanceof Error ? error.message : String(error),
191
+ inProgress: false,
192
+ },
193
+ message: error instanceof Error ? error.message : String(error),
194
+ };
195
+ },
196
+ });
168
197
  }
169
- catch (error) {
170
- return {
171
- name: requirement.name,
172
- type: 'command',
173
- installed: false,
174
- error: error instanceof Error ? error.message : String(error),
175
- inProgress: false
176
- };
198
+ else {
199
+ try {
200
+ return await doInstall();
201
+ }
202
+ catch (error) {
203
+ return {
204
+ name: requirement.name,
205
+ type: 'command',
206
+ installed: false,
207
+ error: error instanceof Error ? error.message : String(error),
208
+ inProgress: false,
209
+ };
210
+ }
177
211
  }
178
212
  }
179
213
  }
@@ -1,5 +1,6 @@
1
1
  import { RequirementConfig, RequirementStatus, ServerInstallOptions } from '../../metadatas/types.js';
2
2
  import { BaseInstaller } from './BaseInstaller.js';
3
+ import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
3
4
  /**
4
5
  * Installer implementation for general requirements (type 'other')
5
6
  * This installer handles requirements that don't fit into specific package manager categories
@@ -34,5 +35,14 @@ export declare class GeneralInstaller extends BaseInstaller {
34
35
  * @param requirement The requirement to install
35
36
  * @returns The status of the installation, including the install path in updateInfo
36
37
  */
37
- install(requirement: RequirementConfig): Promise<RequirementStatus>;
38
+ /**
39
+ * Install the general requirement
40
+ * For type 'other', this doesn't actually install anything, but downloads
41
+ * or locates the asset and returns the path for the caller to use
42
+ * @param requirement The requirement to install
43
+ * @param options Optional install options
44
+ * @param recorder Optional InstallOperationManager for recording steps
45
+ * @returns The status of the installation, including the install path in updateInfo
46
+ */
47
+ install(requirement: RequirementConfig, recorder: InstallOperationManager, options?: ServerInstallOptions): Promise<RequirementStatus>;
38
48
  }
@@ -1,6 +1,7 @@
1
1
  import { BaseInstaller } from './BaseInstaller.js';
2
2
  import { handleGitHubRelease } from '../../../utils/githubUtils.js';
3
3
  import { handleArtifact } from '../../../utils/adoUtils.js';
4
+ import * as RecordingConstants from '../../metadatas/recordingConstants.js';
4
5
  /**
5
6
  * Installer implementation for general requirements (type 'other')
6
7
  * This installer handles requirements that don't fit into specific package manager categories
@@ -50,8 +51,17 @@ export class GeneralInstaller extends BaseInstaller {
50
51
  * @param requirement The requirement to install
51
52
  * @returns The status of the installation, including the install path in updateInfo
52
53
  */
53
- async install(requirement) {
54
- try {
54
+ /**
55
+ * Install the general requirement
56
+ * For type 'other', this doesn't actually install anything, but downloads
57
+ * or locates the asset and returns the path for the caller to use
58
+ * @param requirement The requirement to install
59
+ * @param options Optional install options
60
+ * @param recorder Optional InstallOperationManager for recording steps
61
+ * @returns The status of the installation, including the install path in updateInfo
62
+ */
63
+ async install(requirement, recorder, options) {
64
+ const doInstall = async () => {
55
65
  // For type 'other', a registry must be specified
56
66
  if (!requirement.registry) {
57
67
  throw new Error('Registry must be specified for requirement type "other"');
@@ -76,15 +86,41 @@ export class GeneralInstaller extends BaseInstaller {
76
86
  version: requirement.version,
77
87
  inProgress: false,
78
88
  };
89
+ };
90
+ if (recorder) {
91
+ return recorder.recording(doInstall, {
92
+ stepName: RecordingConstants.STEP_GENERAL_INSTALLER_INSTALL,
93
+ inProgressMessage: `Installing general requirement: ${requirement.name}`,
94
+ endMessage: (result) => result.installed
95
+ ? `Install completed for ${requirement.name}`
96
+ : `Install failed for ${requirement.name}`,
97
+ onError: (error) => {
98
+ return {
99
+ result: {
100
+ name: requirement.name,
101
+ type: 'other',
102
+ installed: false,
103
+ error: error instanceof Error ? error.message : String(error),
104
+ inProgress: false,
105
+ },
106
+ message: error instanceof Error ? error.message : String(error),
107
+ };
108
+ },
109
+ });
79
110
  }
80
- catch (error) {
81
- return {
82
- name: requirement.name,
83
- type: 'other',
84
- installed: false,
85
- error: error instanceof Error ? error.message : String(error),
86
- inProgress: false
87
- };
111
+ else {
112
+ try {
113
+ return await doInstall();
114
+ }
115
+ catch (error) {
116
+ return {
117
+ name: requirement.name,
118
+ type: 'other',
119
+ installed: false,
120
+ error: error instanceof Error ? error.message : String(error),
121
+ inProgress: false,
122
+ };
123
+ }
88
124
  }
89
125
  }
90
126
  }
@@ -1,6 +1,7 @@
1
1
  import { RequirementConfig, RequirementStatus, ServerInstallOptions } from '../../metadatas/types.js';
2
2
  import { RequirementInstaller } from './RequirementInstaller.js';
3
3
  import { exec } from 'child_process';
4
+ import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
4
5
  /**
5
6
  * Factory for creating the appropriate installer for a requirement
6
7
  */
@@ -34,10 +35,11 @@ export declare class InstallerFactory {
34
35
  /**
35
36
  * Install a requirement using the appropriate installer
36
37
  * @param requirement The requirement to install
38
+ * @param recorder Optional InstallOperationManager for recording steps
37
39
  * @param options Installation options including python environment
38
40
  * @returns The installation status
39
41
  */
40
- install(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
42
+ install(requirement: RequirementConfig, recorder: InstallOperationManager, options?: ServerInstallOptions): Promise<RequirementStatus>;
41
43
  /**
42
44
  * Check the installation status of a requirement
43
45
  * @param requirement The requirement to check
@@ -50,10 +50,11 @@ export class InstallerFactory {
50
50
  /**
51
51
  * Install a requirement using the appropriate installer
52
52
  * @param requirement The requirement to install
53
+ * @param recorder Optional InstallOperationManager for recording steps
53
54
  * @param options Installation options including python environment
54
55
  * @returns The installation status
55
56
  */
56
- async install(requirement, options) {
57
+ async install(requirement, recorder, options) {
57
58
  const installer = this.getInstaller(requirement);
58
59
  if (!installer) {
59
60
  return {
@@ -64,7 +65,7 @@ export class InstallerFactory {
64
65
  inProgress: false
65
66
  };
66
67
  }
67
- return await installer.install(requirement, options);
68
+ return await installer.install(requirement, recorder, options);
68
69
  }
69
70
  /**
70
71
  * Check the installation status of a requirement
@@ -1,5 +1,6 @@
1
1
  import { RequirementConfig, RequirementStatus, ServerInstallOptions } from '../../metadatas/types.js';
2
2
  import { BaseInstaller } from './BaseInstaller.js';
3
+ import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
3
4
  /**
4
5
  * Installer implementation for NPM packages
5
6
  */
@@ -58,8 +59,9 @@ export declare class NpmInstaller extends BaseInstaller {
58
59
  /**
59
60
  * Install the NPM package.
60
61
  * @param requirement The requirement to install.
61
- * @param options Installation options, including pythonCommand for ADO (though not used by npm) and folderName.
62
+ * @param recorder Optional InstallOperationManager for recording steps.
63
+ * @param options Installation options.
62
64
  * @returns The status of the installation.
63
65
  */
64
- install(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
66
+ install(requirement: RequirementConfig, recorder: InstallOperationManager, options?: ServerInstallOptions): Promise<RequirementStatus>;
65
67
  }
@@ -7,6 +7,7 @@ import path from 'path';
7
7
  import fs from 'fs/promises';
8
8
  import { SETTINGS_DIR } from '../../metadatas/constants.js'; // Corrected path
9
9
  import { Logger } from '../../../utils/logger.js';
10
+ import * as RecordingConstants from '../../metadatas/recordingConstants.js';
10
11
  /**
11
12
  * Installer implementation for NPM packages
12
13
  */
@@ -136,13 +137,13 @@ export class NpmInstaller extends BaseInstaller {
136
137
  * @param targetDir Target directory for installation.
137
138
  * @returns The installed version of the package.
138
139
  */
139
- async _installPackage(requirement, packageSource, targetDir) {
140
+ async _installPackage(requirement, packageSource, targetDir, recorder) {
140
141
  Logger.debug(`Installing NPM package from "${packageSource}" into "${targetDir}"`);
141
142
  await fs.mkdir(targetDir, { recursive: true });
142
143
  const installCommand = `npm install ${packageSource} --prefix "${targetDir}"`;
143
144
  Logger.debug(`Executing install command: ${installCommand}`);
144
145
  const requirementName = this._getRequirementName(requirement);
145
- try {
146
+ return await recorder.recording(async () => {
146
147
  const { stdout: installStdout, stderr: installStderr } = await this.execPromise(installCommand);
147
148
  Logger.debug(`NPM install stdout for ${packageSource} in ${targetDir}: ${installStdout}`);
148
149
  if (installStderr && !installStderr.toLowerCase().includes('added') && !installStderr.toLowerCase().includes('updated') && !installStderr.toLowerCase().includes('found 0 vulnerabilities')) {
@@ -155,24 +156,28 @@ export class NpmInstaller extends BaseInstaller {
155
156
  return { version: installedVersion };
156
157
  }
157
158
  else {
158
- throw new Error(`Successfully ran npm install for ${packageSource}, but ${requirement.name} version could not be determined via npm list in ${targetDir}.`);
159
+ throw new Error(`Successfully ran npm install for ${packageSource}, but ${requirement.name} version could not be determined via npm list in ${targetDir}, stderr: ${installStderr}`);
159
160
  }
160
- }
161
- catch (error) {
162
- Logger.error(`Failed to install or verify NPM package ${packageSource} into ${targetDir}`, error);
163
- throw error;
164
- }
161
+ }, {
162
+ stepName: RecordingConstants.STEP_INSTALLATION_COMMAND_EXECUTION,
163
+ inProgressMessage: `Running: ${installCommand}`,
164
+ onError: (error) => {
165
+ Logger.error(`Error during NPM installation: ${error instanceof Error ? error.message : String(error)}`);
166
+ throw error;
167
+ }
168
+ });
165
169
  }
166
170
  /**
167
171
  * Install the NPM package.
168
172
  * @param requirement The requirement to install.
169
- * @param options Installation options, including pythonCommand for ADO (though not used by npm) and folderName.
173
+ * @param recorder Optional InstallOperationManager for recording steps.
174
+ * @param options Installation options.
170
175
  * @returns The status of the installation.
171
176
  */
172
- async install(requirement, options) {
177
+ async install(requirement, recorder, options) {
173
178
  const targetDir = options?.settings?.folderName || this._getRequirementFolderPath(requirement);
174
179
  await fs.mkdir(targetDir, { recursive: true });
175
- try {
180
+ return recorder.recording(async () => {
176
181
  const status = await this.checkInstallation(requirement, { settings: { folderName: targetDir } });
177
182
  if (status.installed && status.version && compareVersions(status.version, requirement.version) === 0 && !requirement.version.toLowerCase().includes('latest')) {
178
183
  Logger.log(`${requirement.name}@${status.version} already installed in ${targetDir}.`);
@@ -192,10 +197,12 @@ export class NpmInstaller extends BaseInstaller {
192
197
  resolvedVersion = adoResult.version;
193
198
  }
194
199
  else {
200
+ if (recorder)
201
+ await recorder.recordStep('NpmInstaller:RegistryConfig', 'failed', 'Invalid registry configuration for npm.');
195
202
  throw new Error('Invalid registry configuration for npm.');
196
203
  }
197
204
  }
198
- const finalInstallResult = await this._installPackage(requirement, packageToInstall, targetDir);
205
+ const finalInstallResult = await this._installPackage(requirement, packageToInstall, targetDir, recorder);
199
206
  resolvedVersion = finalInstallResult.version;
200
207
  return {
201
208
  name: requirement.name,
@@ -205,16 +212,25 @@ export class NpmInstaller extends BaseInstaller {
205
212
  inProgress: false,
206
213
  npmPath: targetDir
207
214
  };
208
- }
209
- catch (error) {
210
- return {
211
- name: requirement.name,
212
- type: 'npm',
213
- installed: false,
214
- error: error instanceof Error ? error.message : String(error),
215
- inProgress: false
216
- };
217
- }
215
+ }, {
216
+ stepName: RecordingConstants.STEP_NPM_INSTALLER_INSTALL,
217
+ inProgressMessage: `Installing npm package: ${requirement.name}`,
218
+ endMessage: (result) => result.installed
219
+ ? `Install completed for ${requirement.name}`
220
+ : `Install failed for ${requirement.name}`,
221
+ onError: (error) => {
222
+ return {
223
+ result: {
224
+ name: requirement.name,
225
+ type: 'npm',
226
+ installed: false,
227
+ error: error instanceof Error ? error.message : String(error),
228
+ inProgress: false
229
+ },
230
+ message: error instanceof Error ? error.message : String(error),
231
+ };
232
+ },
233
+ });
218
234
  }
219
235
  }
220
236
  //# sourceMappingURL=NpmInstaller.js.map
@@ -1,5 +1,6 @@
1
1
  import { RequirementConfig, RequirementStatus, ServerInstallOptions } from '../../metadatas/types.js';
2
2
  import { BaseInstaller } from './BaseInstaller.js';
3
+ import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
3
4
  /**
4
5
  * Installer implementation for Python packages using pip
5
6
  */
@@ -30,8 +31,9 @@ export declare class PipInstaller extends BaseInstaller {
30
31
  /**
31
32
  * Install the Python package
32
33
  * @param requirement The requirement to install
34
+ * @param recorder Optional InstallOperationManager for recording steps
33
35
  * @param options Optional server install options
34
36
  * @returns The status of the installation
35
37
  */
36
- install(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
38
+ install(requirement: RequirementConfig, recorder: InstallOperationManager, options?: ServerInstallOptions): Promise<RequirementStatus>;
37
39
  }
@@ -1,9 +1,9 @@
1
1
  import { BaseInstaller } from './BaseInstaller.js';
2
2
  import { handleGitHubRelease, getGitHubLatestVersion } from '../../../utils/githubUtils.js';
3
- // Assuming getArtifactLatestVersion will be available in adoUtils.ts
4
3
  import { handleArtifact as handleAdoArtifact, getArtifactLatestVersion } from '../../../utils/adoUtils.js';
5
4
  import { compareVersions } from '../../../utils/versionUtils.js';
6
5
  import { Logger } from '../../../utils/logger.js';
6
+ import * as RecordingConstants from '../../metadatas/recordingConstants.js';
7
7
  /**
8
8
  * Installer implementation for Python packages using pip
9
9
  */
@@ -105,21 +105,25 @@ export class PipInstaller extends BaseInstaller {
105
105
  /**
106
106
  * Install the Python package
107
107
  * @param requirement The requirement to install
108
+ * @param recorder Optional InstallOperationManager for recording steps
108
109
  * @param options Optional server install options
109
110
  * @returns The status of the installation
110
111
  */
111
- async install(requirement, options) {
112
- try {
112
+ async install(requirement, recorder, options) {
113
+ return await recorder.recording(async () => {
113
114
  const status = await this.checkInstallation(requirement, options);
114
115
  if (status.installed && status.version && compareVersions(status.version, requirement.version) === 0 && !requirement.version.toLowerCase().includes('latest')) {
115
116
  Logger.log(`${requirement.name}==${status.version} already installed for ${this.getPythonCommand}.`);
116
117
  return status;
117
118
  }
118
119
  const pipCmd = this.getPipCommand(options);
120
+ let command;
119
121
  if (!requirement.registry) {
120
- const { stderr } = await this.execPromise(`${pipCmd} install ${requirement.name}==${requirement.version}`);
121
- if (stderr && stderr.toLowerCase().includes('error')) {
122
- throw new Error(stderr);
122
+ if (requirement.version && !requirement.version.includes('latest')) {
123
+ command = `${pipCmd} install ${requirement.name}==${requirement.version}`;
124
+ }
125
+ else {
126
+ command = `${pipCmd} install --upgrade ${requirement.name}`;
123
127
  }
124
128
  }
125
129
  else {
@@ -127,45 +131,63 @@ export class PipInstaller extends BaseInstaller {
127
131
  if (requirement.registry.githubRelease) {
128
132
  const result = await handleGitHubRelease(requirement, requirement.registry.githubRelease);
129
133
  packageSource = result.resolvedPath;
130
- const { stderr } = await this.execPromise(`${pipCmd} install "${packageSource}"`);
131
- if (stderr && stderr.toLowerCase().includes('error')) {
132
- throw new Error(stderr);
133
- }
134
+ command = `${pipCmd} install "${packageSource}"`;
134
135
  }
135
136
  else if (requirement.registry.artifacts) {
136
137
  const pythonCmd = this.getPythonCommand(options);
137
138
  const adoArtifactResult = await handleAdoArtifact(requirement, requirement.registry.artifacts, pythonCmd);
138
- const { stderr } = await this.execPromise(`${pipCmd} install ${adoArtifactResult.package} --extra-index-url ${adoArtifactResult.registryUrl}`);
139
- if (stderr && stderr.toLowerCase().includes('error')) {
140
- const checkStatus = await this.checkInstallation(requirement, options);
141
- if (!checkStatus.installed) {
142
- throw new Error(`Pip installation failed with: ${stderr}`);
143
- }
144
- }
139
+ command = `${pipCmd} install ${adoArtifactResult.package} --extra-index-url ${adoArtifactResult.registryUrl}`;
145
140
  }
146
141
  else {
142
+ await recorder.recordStep('PipInstaller:RegistryConfig', 'failed', 'Invalid registry configuration');
147
143
  throw new Error('Invalid registry configuration');
148
144
  }
149
145
  }
150
- return {
151
- name: requirement.name,
152
- type: 'pip',
153
- installed: true,
154
- version: requirement.version, // This might need to be updated to actual installed version
155
- inProgress: false,
156
- pythonEnv: this.getPythonCommand(options)
157
- };
158
- }
159
- catch (error) {
160
- return {
161
- name: requirement.name,
162
- type: 'pip',
163
- installed: false,
164
- error: error instanceof Error ? error.message : String(error),
165
- inProgress: false,
166
- pythonEnv: this.getPythonCommand(options)
167
- };
168
- }
146
+ return await recorder.recording(async () => {
147
+ const { stderr } = await this.execPromise(command);
148
+ if (stderr && stderr.toLowerCase().includes('error')) {
149
+ Logger.debug(`Pip installation error: ${stderr}`);
150
+ // wait for 5 seconds as python pip would be little delayed
151
+ await new Promise(resolve => setTimeout(resolve, 5000));
152
+ const checkStatus = await this.checkInstallation(requirement, options);
153
+ if (!checkStatus.installed) {
154
+ Logger.error(`Package not found after the command, ${stderr}`);
155
+ throw new Error(`Pip installation failed with: ${stderr}`);
156
+ }
157
+ }
158
+ return {
159
+ name: requirement.name,
160
+ type: 'pip',
161
+ installed: true,
162
+ version: requirement.version, // This might need to be updated to actual installed version
163
+ inProgress: false,
164
+ pythonEnv: this.getPythonCommand(options)
165
+ };
166
+ }, {
167
+ stepName: `${RecordingConstants.STEP_INSTALL_COMMAND_PREFIX}: ${requirement.name} : ${requirement.version}`,
168
+ inProgressMessage: `Running: ${command}`,
169
+ endMessage: (result) => result.installed ? `Succeeded: ${command}` : `Failed: ${command}`,
170
+ });
171
+ }, {
172
+ stepName: RecordingConstants.STEP_PIP_INSTALLER_INSTALL,
173
+ inProgressMessage: `Installing pip package: ${requirement.name}`,
174
+ endMessage: (result) => result.installed
175
+ ? `Install completed for ${requirement.name} with version ${result.version}`
176
+ : `Install failed for ${requirement.name}`,
177
+ onError: (error) => {
178
+ return {
179
+ result: {
180
+ name: requirement.name,
181
+ type: 'pip',
182
+ installed: false,
183
+ error: error instanceof Error ? error.message : String(error),
184
+ inProgress: false,
185
+ pythonEnv: this.getPythonCommand(options)
186
+ },
187
+ message: error instanceof Error ? error.message : String(error),
188
+ };
189
+ },
190
+ });
169
191
  }
170
192
  }
171
193
  //# sourceMappingURL=PipInstaller.js.map
@@ -1,4 +1,5 @@
1
1
  import { RequirementConfig, RequirementStatus, ServerInstallOptions } from '../../metadatas/types.js';
2
+ import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
2
3
  /**
3
4
  * Interface for requirement installers.
4
5
  * Implementations should handle specific requirement types.
@@ -14,9 +15,11 @@ export interface RequirementInstaller {
14
15
  /**
15
16
  * Install the requirement
16
17
  * @param requirement The requirement to install
18
+ * @param options Optional install options
19
+ * @param recorder Optional InstallOperationManager for recording steps
17
20
  * @returns The status of the installation
18
21
  */
19
- install(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
22
+ install(requirement: RequirementConfig, recorder: InstallOperationManager, options?: ServerInstallOptions): Promise<RequirementStatus>;
20
23
  /**
21
24
  * Check if the requirement is already installed
22
25
  * @param requirement The requirement to check