imcp 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/dist/cli/commands/install.js +2 -2
  2. package/dist/cli/commands/list.js +2 -2
  3. package/dist/cli/commands/serve.js +3 -2
  4. package/dist/core/RequirementService.d.ts +0 -12
  5. package/dist/core/RequirementService.js +0 -24
  6. package/dist/core/installers/clients/BaseClientInstaller.d.ts +26 -3
  7. package/dist/core/installers/clients/BaseClientInstaller.js +121 -0
  8. package/dist/core/installers/clients/ClientInstaller.d.ts +1 -1
  9. package/dist/core/installers/clients/ClientInstaller.js +1 -1
  10. package/dist/core/installers/clients/ClientInstallerFactory.js +1 -1
  11. package/dist/core/installers/clients/ClineInstaller.d.ts +1 -6
  12. package/dist/core/installers/clients/ClineInstaller.js +1 -94
  13. package/dist/core/installers/clients/ExtensionInstaller.js +1 -1
  14. package/dist/core/installers/clients/GithubCopilotInstaller.d.ts +1 -6
  15. package/dist/core/installers/clients/GithubCopilotInstaller.js +1 -94
  16. package/dist/core/installers/clients/MSRooCodeInstaller.d.ts +1 -5
  17. package/dist/core/installers/clients/MSRooCodeInstaller.js +1 -94
  18. package/dist/core/installers/requirements/BaseInstaller.d.ts +1 -1
  19. package/dist/core/installers/requirements/BaseInstaller.js +1 -1
  20. package/dist/core/installers/requirements/CommandInstaller.d.ts +1 -1
  21. package/dist/core/installers/requirements/CommandInstaller.js +1 -1
  22. package/dist/core/installers/requirements/GeneralInstaller.d.ts +1 -1
  23. package/dist/core/installers/requirements/InstallerFactory.d.ts +1 -1
  24. package/dist/core/installers/requirements/NpmInstaller.d.ts +1 -1
  25. package/dist/core/installers/requirements/NpmInstaller.js +1 -1
  26. package/dist/core/installers/requirements/PipInstaller.d.ts +1 -1
  27. package/dist/core/installers/requirements/RequirementInstaller.d.ts +1 -1
  28. package/dist/core/loaders/ConfigurationLoader.d.ts +35 -0
  29. package/dist/core/loaders/ConfigurationLoader.js +257 -0
  30. package/dist/core/loaders/ConfigurationProvider.d.ts +38 -0
  31. package/dist/core/loaders/ConfigurationProvider.js +384 -0
  32. package/dist/core/loaders/ServerSchemaLoader.d.ts +22 -0
  33. package/dist/core/loaders/ServerSchemaLoader.js +109 -0
  34. package/dist/core/loaders/ServerSchemaProvider.d.ts +14 -0
  35. package/dist/core/loaders/ServerSchemaProvider.js +90 -0
  36. package/dist/core/metadatas/constants.d.ts +47 -0
  37. package/dist/core/metadatas/constants.js +94 -0
  38. package/dist/core/metadatas/types.d.ts +167 -0
  39. package/dist/core/metadatas/types.js +16 -0
  40. package/dist/core/onboard/FeedOnboardService.d.ts +15 -8
  41. package/dist/core/onboard/FeedOnboardService.js +215 -130
  42. package/dist/core/onboard/OnboardProcessor.d.ts +8 -2
  43. package/dist/core/onboard/OnboardProcessor.js +53 -9
  44. package/dist/core/onboard/OnboardStatus.d.ts +7 -2
  45. package/dist/core/onboard/OnboardStatusManager.d.ts +71 -25
  46. package/dist/core/onboard/OnboardStatusManager.js +231 -47
  47. package/dist/core/validators/FeedValidator.d.ts +8 -3
  48. package/dist/core/validators/FeedValidator.js +61 -7
  49. package/dist/core/validators/IServerValidator.d.ts +1 -1
  50. package/dist/core/validators/SSEServerValidator.d.ts +1 -1
  51. package/dist/core/validators/ServerValidatorFactory.d.ts +1 -1
  52. package/dist/core/validators/StdioServerValidator.d.ts +1 -1
  53. package/dist/core/validators/StdioServerValidator.js +85 -33
  54. package/dist/index.d.ts +3 -3
  55. package/dist/index.js +3 -3
  56. package/dist/services/InstallationService.d.ts +50 -0
  57. package/dist/services/InstallationService.js +350 -0
  58. package/dist/services/MCPManager.d.ts +29 -0
  59. package/dist/services/MCPManager.js +192 -0
  60. package/dist/services/RequirementService.d.ts +40 -0
  61. package/dist/services/RequirementService.js +110 -0
  62. package/dist/services/ServerService.d.ts +2 -2
  63. package/dist/services/ServerService.js +6 -6
  64. package/dist/utils/adoUtils.d.ts +2 -2
  65. package/dist/utils/adoUtils.js +1 -1
  66. package/dist/utils/feedUtils.js +1 -1
  67. package/dist/utils/githubUtils.d.ts +1 -1
  68. package/dist/utils/githubUtils.js +1 -1
  69. package/dist/utils/logger.d.ts +2 -0
  70. package/dist/utils/logger.js +11 -1
  71. package/dist/utils/macroExpressionUtils.d.ts +1 -1
  72. package/dist/utils/osUtils.d.ts +1 -1
  73. package/dist/utils/osUtils.js +1 -1
  74. package/dist/web/contract/serverContract.d.ts +1 -1
  75. package/dist/web/public/index.html +1 -3
  76. package/dist/web/public/js/api.js +2 -80
  77. package/dist/web/public/js/modal/installation.js +1 -1
  78. package/dist/web/public/js/onboard/ONBOARDING_PAGE_DESIGN.md +41 -9
  79. package/dist/web/public/js/onboard/formProcessor.js +200 -34
  80. package/dist/web/public/js/onboard/index.js +2 -2
  81. package/dist/web/public/js/onboard/publishHandler.js +30 -22
  82. package/dist/web/public/js/onboard/templates.js +34 -40
  83. package/dist/web/public/js/onboard/uiHandlers.js +175 -84
  84. package/dist/web/public/js/onboard/validationHandlers.js +147 -64
  85. package/dist/web/public/js/serverCategoryDetails.js +19 -4
  86. package/dist/web/public/js/serverCategoryList.js +13 -1
  87. package/dist/web/public/onboard.html +1 -1
  88. package/dist/web/server.js +21 -8
  89. package/package.json +1 -1
  90. package/src/cli/commands/install.ts +3 -3
  91. package/src/cli/commands/list.ts +2 -2
  92. package/src/cli/commands/serve.ts +3 -2
  93. package/src/cli/index.ts +1 -1
  94. package/src/core/installers/clients/BaseClientInstaller.ts +134 -3
  95. package/src/core/installers/clients/ClientInstaller.ts +3 -3
  96. package/src/core/installers/clients/ClientInstallerFactory.ts +1 -1
  97. package/src/core/installers/clients/ClineInstaller.ts +1 -101
  98. package/src/core/installers/clients/ExtensionInstaller.ts +1 -1
  99. package/src/core/installers/clients/GithubCopilotInstaller.ts +1 -101
  100. package/src/core/installers/clients/MSRooCodeInstaller.ts +1 -102
  101. package/src/core/installers/requirements/BaseInstaller.ts +2 -2
  102. package/src/core/installers/requirements/CommandInstaller.ts +1 -1
  103. package/src/core/installers/requirements/GeneralInstaller.ts +1 -1
  104. package/src/core/installers/requirements/InstallerFactory.ts +1 -1
  105. package/src/core/installers/requirements/NpmInstaller.ts +12 -12
  106. package/src/core/installers/requirements/PipInstaller.ts +1 -1
  107. package/src/core/installers/requirements/RequirementInstaller.ts +1 -1
  108. package/src/core/{ConfigurationLoader.ts → loaders/ConfigurationLoader.ts} +31 -7
  109. package/src/core/{ConfigurationProvider.ts → loaders/ConfigurationProvider.ts} +18 -10
  110. package/src/core/loaders/ServerSchemaLoader.ts +117 -0
  111. package/src/core/loaders/ServerSchemaProvider.ts +99 -0
  112. package/src/core/{types.ts → metadatas/types.ts} +3 -2
  113. package/src/core/onboard/FeedOnboardService.ts +270 -146
  114. package/src/core/onboard/OnboardProcessor.ts +60 -11
  115. package/src/core/onboard/OnboardStatus.ts +7 -2
  116. package/src/core/onboard/OnboardStatusManager.ts +270 -43
  117. package/src/core/validators/FeedValidator.ts +65 -9
  118. package/src/core/validators/IServerValidator.ts +1 -1
  119. package/src/core/validators/SSEServerValidator.ts +2 -2
  120. package/src/core/validators/ServerValidatorFactory.ts +1 -1
  121. package/src/core/validators/StdioServerValidator.ts +86 -34
  122. package/src/index.ts +3 -3
  123. package/src/{core → services}/InstallationService.ts +5 -5
  124. package/src/{core → services}/MCPManager.ts +10 -5
  125. package/src/{core → services}/RequirementService.ts +2 -31
  126. package/src/services/ServerService.ts +7 -7
  127. package/src/utils/adoUtils.ts +3 -3
  128. package/src/utils/feedUtils.ts +2 -2
  129. package/src/utils/githubUtils.ts +2 -2
  130. package/src/utils/logger.ts +13 -1
  131. package/src/utils/macroExpressionUtils.ts +1 -1
  132. package/src/utils/osUtils.ts +4 -4
  133. package/src/web/contract/serverContract.ts +2 -2
  134. package/src/web/public/index.html +1 -3
  135. package/src/web/public/js/api.js +2 -80
  136. package/src/web/public/js/modal/installation.js +1 -1
  137. package/src/web/public/js/onboard/ONBOARDING_PAGE_DESIGN.md +41 -9
  138. package/src/web/public/js/onboard/formProcessor.js +200 -34
  139. package/src/web/public/js/onboard/index.js +2 -2
  140. package/src/web/public/js/onboard/publishHandler.js +30 -22
  141. package/src/web/public/js/onboard/templates.js +34 -40
  142. package/src/web/public/js/onboard/uiHandlers.js +175 -84
  143. package/src/web/public/js/onboard/validationHandlers.js +147 -64
  144. package/src/web/public/js/serverCategoryDetails.js +19 -4
  145. package/src/web/public/js/serverCategoryList.js +13 -1
  146. package/src/web/public/onboard.html +1 -1
  147. package/src/web/server.ts +30 -14
  148. package/src/core/ServerSchemaLoader.ts +0 -48
  149. package/src/core/ServerSchemaProvider.ts +0 -137
  150. package/src/services/InstallRequestValidator.ts +0 -112
  151. /package/src/core/{constants.ts → metadatas/constants.ts} +0 -0
@@ -0,0 +1,110 @@
1
+ import { createInstallerFactory } from '../core/installers/index.js';
2
+ import { exec } from 'child_process';
3
+ import util from 'util';
4
+ /**
5
+ * Service responsible for managing requirements installation and status
6
+ */
7
+ export class RequirementService {
8
+ static instance;
9
+ installerFactory = createInstallerFactory(util.promisify(exec));
10
+ constructor() { }
11
+ /**
12
+ * Get the singleton instance of RequirementService
13
+ * @returns The RequirementService instance
14
+ */
15
+ static getInstance() {
16
+ if (!RequirementService.instance) {
17
+ RequirementService.instance = new RequirementService();
18
+ }
19
+ return RequirementService.instance;
20
+ }
21
+ /**
22
+ * Check the installation status of a requirement
23
+ * @param requirement The requirement to check
24
+ * @returns The installation status
25
+ */
26
+ async checkRequirementStatus(requirement, options) {
27
+ // Validate requirement
28
+ this.validateRequirement(requirement);
29
+ // Check the installation status
30
+ return await this.installerFactory.checkInstallation(requirement, options);
31
+ }
32
+ /**
33
+ * Check if updates are available for a requirement
34
+ * @param requirement The requirement to check for updates
35
+ * @returns Updated status with available updates information
36
+ */
37
+ async checkRequirementForUpdates(requirement, currentStatus) {
38
+ // Validate requirement
39
+ this.validateRequirement(requirement);
40
+ // Get current status
41
+ // Check for updates using the appropriate installer
42
+ const installer = this.installerFactory.getInstaller(requirement);
43
+ if (!installer || !installer.supportCheckUpdates()) {
44
+ return currentStatus;
45
+ }
46
+ // Pass pythonEnv from currentStatus if it exists for pip packages
47
+ const options = requirement.type === 'pip' && currentStatus.pythonEnv
48
+ ? { settings: { pythonEnv: currentStatus.pythonEnv } }
49
+ : undefined;
50
+ const status = await this.checkRequirementStatus(requirement, options);
51
+ return await installer.checkForUpdates(requirement, status);
52
+ }
53
+ /**
54
+ * Update a requirement to a new version
55
+ * @param requirement The requirement configuration
56
+ * @param updateVersion The version to update to
57
+ * @returns The updated requirement status
58
+ */
59
+ async updateRequirement(requirement, updateVersion, options) {
60
+ // Validate requirement
61
+ this.validateRequirement(requirement);
62
+ // Create an updated requirement with the new version
63
+ const updatedRequirement = {
64
+ ...requirement,
65
+ version: requirement.version.includes('latest') ? requirement.version : updateVersion,
66
+ };
67
+ // Install the updated version
68
+ return await this.installerFactory.install(updatedRequirement, options);
69
+ }
70
+ /**
71
+ * Validate a requirement configuration
72
+ * @param requirement The requirement to validate
73
+ * @throws Error if the requirement is invalid
74
+ */
75
+ validateRequirement(requirement) {
76
+ // Ensure requirement has required fields
77
+ if (!requirement.name) {
78
+ throw new Error('Requirement name is required');
79
+ }
80
+ if (!requirement.type) {
81
+ throw new Error('Requirement type is required');
82
+ }
83
+ // For type 'other', registry must be specified
84
+ if (requirement.type === 'other' && !requirement.registry) {
85
+ throw new Error('Registry must be specified for requirement type "other"');
86
+ }
87
+ // Validate registry configuration if provided
88
+ if (requirement.registry) {
89
+ const { githubRelease, artifacts } = requirement.registry;
90
+ // Validate GitHub release configuration
91
+ if (githubRelease) {
92
+ if (!githubRelease.repository) {
93
+ throw new Error('Repository is required for GitHub release registry');
94
+ }
95
+ if (!githubRelease.assetName) {
96
+ throw new Error('Asset name is required for GitHub release registry');
97
+ }
98
+ }
99
+ // Validate artifacts registry configuration
100
+ if (artifacts) {
101
+ if (!artifacts.registryUrl) {
102
+ throw new Error('Registry URL is required for artifacts registry');
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ // Export a singleton instance
109
+ export const requirementService = RequirementService.getInstance();
110
+ //# sourceMappingURL=RequirementService.js.map
@@ -1,5 +1,5 @@
1
- import { ServerSchema } from '../core/ServerSchemaProvider.js';
2
- import { MCPServerCategory, ServerInstallOptions, ServerCategoryListOptions, ServerOperationResult, ServerUninstallOptions, FeedConfiguration } from '../core/types.js';
1
+ import { ServerSchema } from '../core/loaders/ServerSchemaProvider.js';
2
+ import { MCPServerCategory, ServerInstallOptions, ServerCategoryListOptions, ServerOperationResult, ServerUninstallOptions, FeedConfiguration } from '../core/metadatas/types.js';
3
3
  import { OperationStatus } from '../core/onboard/OnboardStatus.js';
4
4
  /**
5
5
  * ServerService provides a unified interface for server management operations.
@@ -1,9 +1,9 @@
1
1
  import path from 'path';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { Logger } from '../utils/logger.js';
4
- import { getServerSchemaProvider } from '../core/ServerSchemaProvider.js';
5
- import { mcpManager } from '../core/MCPManager.js';
6
- import { UPDATE_CHECK_INTERVAL_MS } from '../core/constants.js';
4
+ import { ServerSchemaProvider } from '../core/loaders/ServerSchemaProvider.js';
5
+ import { mcpManager } from './MCPManager.js';
6
+ import { UPDATE_CHECK_INTERVAL_MS } from '../core/metadatas/constants.js';
7
7
  import { updateCheckTracker } from '../utils/UpdateCheckTracker.js';
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
9
  /**
@@ -53,8 +53,8 @@ export class ServerService {
53
53
  return;
54
54
  }
55
55
  try {
56
- const { requirementService } = await import('../core/RequirementService.js');
57
- const { configProvider } = await import('../core/ConfigurationProvider.js');
56
+ const { requirementService } = await import('./RequirementService.js');
57
+ const { configProvider } = await import('../core/loaders/ConfigurationProvider.js');
58
58
  for (const requirement of serverCategory.feedConfiguration.requirements) {
59
59
  if (requirement.version.includes('latest')) {
60
60
  // Get current status if available
@@ -102,7 +102,7 @@ export class ServerService {
102
102
  */
103
103
  async getServerSchema(categoryName, serverName) {
104
104
  try {
105
- const provider = await getServerSchemaProvider();
105
+ const provider = ServerSchemaProvider.getInstance();
106
106
  const serverMcpConfig = await mcpManager.getServerMcpConfig(categoryName, serverName);
107
107
  return await provider.getSchema(categoryName, serverMcpConfig?.schemas || `${serverName}.json`);
108
108
  }
@@ -1,4 +1,4 @@
1
- import { RequirementConfig, RegistryConfig } from '../core/types.js';
1
+ import { RequirementConfig, RegistryConfig } from '../core/metadatas/types.js';
2
2
  export interface AdoArtifactResult {
3
3
  type: 'npm' | 'pip';
4
4
  package: string;
@@ -25,5 +25,5 @@ targetDir?: string): Promise<AdoArtifactResult>;
25
25
  * @param options Optional server install options (e.g., for pythonCommand).
26
26
  * @returns The latest version string, or undefined if not found or an error occurs.
27
27
  */
28
- export declare function getArtifactLatestVersion(requirement: RequirementConfig, registry: RegistryConfig['artifacts'], options?: import('../core/types.js').ServerInstallOptions, // Added import for ServerInstallOptions
28
+ export declare function getArtifactLatestVersion(requirement: RequirementConfig, registry: RegistryConfig['artifacts'], options?: import('../core/metadatas/types.js').ServerInstallOptions, // Added import for ServerInstallOptions
29
29
  targetDir?: string): Promise<string | undefined>;
@@ -1,4 +1,4 @@
1
- import { SETTINGS_DIR } from '../core/constants.js';
1
+ import { SETTINGS_DIR } from '../core/metadatas/constants.js';
2
2
  import { Logger } from './logger.js';
3
3
  import { exec } from 'child_process';
4
4
  import util from 'util';
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs/promises';
2
2
  import { Logger } from './logger.js';
3
- import { LOCAL_FEEDS_DIR } from '../core/constants.js';
3
+ import { LOCAL_FEEDS_DIR } from '../core/metadatas/constants.js';
4
4
  /**
5
5
  * Checks if local feeds exist in the LOCAL_FEEDS_DIR
6
6
  * Returns true if the directory exists and contains at least one .json file
@@ -1,4 +1,4 @@
1
- import { RegistryConfig, RequirementConfig } from '../core/types.js';
1
+ import { RegistryConfig, RequirementConfig } from '../core/metadatas/types.js';
2
2
  /**
3
3
  * Get the latest version available for a GitHub repository
4
4
  * @param execPromise The promise-based exec function
@@ -3,7 +3,7 @@ import util from 'util';
3
3
  import fs from 'fs/promises';
4
4
  import path from 'path';
5
5
  import { extractZipFile } from './clientUtils.js';
6
- import { SETTINGS_DIR } from '../core/constants.js';
6
+ import { SETTINGS_DIR } from '../core/metadatas/constants.js';
7
7
  const execAsync = util.promisify(exec);
8
8
  /**
9
9
  * Get the latest version available for a GitHub repository
@@ -9,6 +9,8 @@ export declare class Logger {
9
9
  private static getTimestamp;
10
10
  private static writeToLogFile;
11
11
  static log(message: string): Promise<void>;
12
+ static info(message: string): Promise<void>;
13
+ static warn(message: string): Promise<void>;
12
14
  static debug(message: string | object): Promise<void>;
13
15
  static error(message: string, error?: unknown): Promise<void>;
14
16
  }
@@ -1,6 +1,6 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
- import { SETTINGS_DIR } from '../core/constants.js';
3
+ import { SETTINGS_DIR } from '../core/metadatas/constants.js';
4
4
  export class Logger {
5
5
  static verbose = false;
6
6
  static fileLoggingEnabled = true;
@@ -48,6 +48,16 @@ export class Logger {
48
48
  console.log(message);
49
49
  await this.writeToLogFile('INFO', message);
50
50
  }
51
+ static async info(message) {
52
+ console.info(message);
53
+ await this.writeToLogFile('INFO', message);
54
+ }
55
+ static async warn(message) {
56
+ const yellowColor = '\x1b[33m';
57
+ const resetColor = '\x1b[0m';
58
+ console.warn(`${yellowColor}${message}${resetColor}`);
59
+ await this.writeToLogFile('WARN', message);
60
+ }
51
61
  static async debug(message) {
52
62
  let formattedMessage;
53
63
  if (typeof message === 'object') {
@@ -1,4 +1,4 @@
1
- import { ServerInstallOptions } from '../core/types.js';
1
+ import { ServerInstallOptions } from '../core/metadatas/types.js';
2
2
  export declare const MACRO_EXPRESSIONS: {
3
3
  readonly PYTHON_PACKAGE: "${PYTHON_PACKAGE}";
4
4
  readonly NPMPATH: "${NPMPATH}";
@@ -1,4 +1,4 @@
1
- import { OSType } from '../core/types.js';
1
+ import { OSType } from '../core/metadatas/types.js';
2
2
  export declare function getOSType(): OSType;
3
3
  export declare function installCLI(tool: 'gh' | 'git'): Promise<void>;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { OSType } from '../core/types.js';
1
+ import { OSType } from '../core/metadatas/types.js';
2
2
  import os from 'os';
3
3
  import { exec } from 'child_process';
4
4
  import util from 'util';
@@ -1,4 +1,4 @@
1
- import { DependencyConfig, RegistryConfig, ServerInstallOptions } from '../../core/types.js';
1
+ import { DependencyConfig, RegistryConfig, ServerInstallOptions } from '../../core/metadatas/types.js';
2
2
  export interface OnboardServerConfig {
3
3
  name: string;
4
4
  description: string;
@@ -167,7 +167,7 @@
167
167
 
168
168
  <!-- Module scripts -->
169
169
  <script type="module">
170
- import { fetchServerCategories, handleInstallServer, installRequirement, upgradeRequirement, uninstallTool } from './js/api.js';
170
+ import { fetchServerCategories, handleInstallServer, uninstallTool } from './js/api.js';
171
171
  import { setupSearch } from './js/serverCategoryList.js';
172
172
  import { showServerDetails } from './js/serverCategoryDetails.js';
173
173
  import { showInstallModal, closeModal, setupModalOutsideClick } from './js/modal.js';
@@ -182,8 +182,6 @@
182
182
  // If other parts of the app call window.showOnboardModal, they'll need updating too.
183
183
  window.closeModal = closeModal;
184
184
  window.handleInstallServer = handleInstallServer;
185
- window.installRequirement = installRequirement;
186
- window.upgradeRequirement = upgradeRequirement;
187
185
  window.uninstallTool = uninstallTool;
188
186
 
189
187
  // Initialize
@@ -42,7 +42,7 @@ async function fetchServerCategories() {
42
42
  async function handleInstallServer(event, categoryName, serverName, callback, options = {}) {
43
43
  event.preventDefault(); // Prevent page reload
44
44
  console.log("Handling install for:", categoryName, serverName);
45
-
45
+
46
46
  // Get selected targets from the form if not provided in options
47
47
  const selectedTargets = options.targets || [...document.querySelectorAll('input[name="targets"]:checked')]
48
48
  .map(cb => cb.value);
@@ -71,7 +71,7 @@ async function handleInstallServer(event, categoryName, serverName, callback, op
71
71
  const response = await fetch(`/api/categories/${categoryName}/install`, {
72
72
  method: 'POST',
73
73
  headers: { 'Content-Type': 'application/json' },
74
- body: JSON.stringify({serverList: serverList})
74
+ body: JSON.stringify({ serverList: serverList })
75
75
  });
76
76
 
77
77
  if (!response.ok) {
@@ -90,82 +90,6 @@ async function handleInstallServer(event, categoryName, serverName, callback, op
90
90
  }
91
91
  }
92
92
 
93
- // Install requirement handler
94
- async function installRequirement(reqName) {
95
- const detailsDiv = document.getElementById('serverCategoryDetails');
96
- const serverTitle = detailsDiv.querySelector('h3');
97
- if (!serverTitle) {
98
- showToast('No server selected.', 'error');
99
- return;
100
- }
101
- let serverName = serverTitle.textContent;
102
- if (serverName.includes(' for ')) {
103
- serverName = serverName.split(' for ')[0];
104
- }
105
- const confirmed = await showConfirm(`Do you want to install requirement '${reqName}' for ${serverName}?`);
106
- if (!confirmed) {
107
- return;
108
- }
109
-
110
- const btn = Array.from(document.querySelectorAll('button')).find(b => b.textContent.trim() === 'Install' && b.onclick?.toString().includes(reqName));
111
- if (btn) btn.disabled = true;
112
-
113
- try {
114
- const response = await fetch(`/api/categories/${serverName}/install-requirement`, {
115
- method: 'POST',
116
- headers: { 'Content-Type': 'application/json' },
117
- body: JSON.stringify({ requirementName: reqName })
118
- });
119
- if (!response.ok) {
120
- const errorData = await response.text();
121
- throw new Error(`Installation failed: ${errorData || response.statusText}`);
122
- }
123
- showToast(`Requirement '${reqName}' installation initiated successfully!`, 'success');
124
- setTimeout(() => {
125
- fetchServerCategories();
126
- window.showServerDetails(serverName);
127
- }, 1000);
128
- } catch (error) {
129
- console.error('Error installing requirement:', error);
130
- showToast(`Error installing requirement: ${error.message}. Please check console.`, 'error');
131
- } finally {
132
- if (btn) btn.disabled = false;
133
- }
134
- }
135
-
136
- // Handle upgrade/uninstall actions
137
- async function upgradeRequirement(name) {
138
- const serverTitle = document.querySelector('#serverCategoryDetails h3')?.textContent;
139
- if (!serverTitle) {
140
- showToast('No server selected.', 'error');
141
- return;
142
- }
143
-
144
- const upgradeConfirmed = await showConfirm(`Do you want to upgrade requirement '${name}' for ${serverTitle}?`);
145
- if (!upgradeConfirmed) {
146
- return;
147
- }
148
-
149
- try {
150
- const response = await fetch(`/api/categories/${serverTitle}/upgrade-requirement`, {
151
- method: 'POST',
152
- headers: { 'Content-Type': 'application/json' },
153
- body: JSON.stringify({ requirementName: name })
154
- });
155
-
156
- if (!response.ok) {
157
- const errorData = await response.text();
158
- throw new Error(`Upgrade failed: ${errorData || response.statusText}`);
159
- }
160
-
161
- showToast(`Requirement '${name}' upgrade initiated successfully!`, 'success');
162
- fetchServerCategories();
163
- window.showServerDetails(serverTitle);
164
- } catch (error) {
165
- console.error('Error upgrading requirement:', error);
166
- showToast(`Error upgrading requirement: ${error.message}`, 'error');
167
- }
168
- }
169
93
 
170
94
  async function uninstallTool(name) {
171
95
  const serverTitle = document.querySelector('#serverCategoryDetails h3')?.textContent;
@@ -204,7 +128,5 @@ export {
204
128
  allServerCategoriesData,
205
129
  fetchServerCategories,
206
130
  handleInstallServer,
207
- installRequirement,
208
- upgradeRequirement,
209
131
  uninstallTool
210
132
  };
@@ -175,7 +175,7 @@ async function pollInstallStatus(categoryName, serverName, targets, interval = 2
175
175
  delayedAppendInstallLoadingMessage(`${target}: ${msg}`);
176
176
  lastMessages[target] = msg;
177
177
  }
178
- if (status !== "completed") {
178
+ if (status !== "completed" && status !== "failed") {
179
179
  allTargetsCompleted = false;
180
180
  }
181
181
  }
@@ -168,9 +168,9 @@ A toggle switch allows users to switch between the standard form view and a raw
168
168
  - Calls `getFormData()` (from `formProcessor.js`) to get the current form data as `FeedConfiguration`.
169
169
  - Sends an initial POST request to `/api/categories/onboard` with the `FeedConfiguration` object and an `isUpdate` flag.
170
170
  - The "Publish" button shows a spinning loader icon and its text changes to "Publishing...". Both "Validate" and "Publish" buttons are disabled.
171
- - **Polling for Status**: If the initial publish request is successful and the operation is not immediately completed or failed, `handlePublish` initiates polling using the shared `pollOperationStatus` function (from `validationHandlers.js`). This function periodically calls `GET /api/categories/:categoryName/onboard/status`.
172
- - **Displaying Results**: The shared `updateOperationDisplay` function (from `validationHandlers.js`) formats and displays the results from both the initial publish call and subsequent status polls in the relevant status panel. It shows overall status, messages, PR info (if available), and detailed validation results if included in the publish response.
173
- - **Completion/Failure**: Polling stops when the status is 'COMPLETED', 'FAILED', or 'succeeded'. Upon completion or failure, the "Publish" button reverts to its original state, and both "Validate" and "Publish" buttons are re-enabled. Success and error messages are displayed using `showToast()`.
171
+ - **Polling for Status**: If the initial publish request is successful and the operation is not immediately completed or failed, `handlePublish` initiates polling. The shared `pollOperationStatus` function (from `validationHandlers.js`) is called, which periodically queries `GET /api/categories/:categoryName/onboard/status?operationType=FULL_ONBOARDING`. `pollOperationStatus` now returns a boolean to manage polling continuation.
172
+ - **Displaying Results**: The shared `updateOperationDisplay` function (from `validationHandlers.js`) formats and displays detailed progress, including individual steps, from both the initial publish call and subsequent status polls.
173
+ - **Completion/Failure**: Polling stops based on the status returned by `pollOperationStatus`. Upon completion or failure, buttons are reset, and `showToast()` displays messages. For detailed information on recent changes to polling and status display, see Section 9: "Enhanced Operation Status Polling and Display".
174
174
  - **Validation (`handleValidation` in `validationHandlers.js`)**:
175
175
  - **Validation (`handleValidation` in `validationHandlers.js`)**:
176
176
  - The `validationStatusPanel` (unique per tab) is located under the "MCP Servers" section (or equivalent) and above the main action buttons ("Validate", "Publish"). It is a foldable panel.
@@ -179,14 +179,14 @@ A toggle switch allows users to switch between the standard form view and a raw
179
179
  - Sends an initial POST request to `/api/categories/onboard/validate`.
180
180
  - The "Validate" button shows a spinning loader icon and its text changes to "Validating...". Both "Validate" and "Publish" buttons are disabled.
181
181
  - **Polling for Status**:
182
- - If the initial validation request is successful and the operation is not immediately completed or failed, `handleValidation` initiates polling using the shared `pollOperationStatus` function (from `validationHandlers.js`).
183
- - This function uses the `onboardingId` (category name) from the validation response to periodically call `GET /api/categories/:categoryName/onboard/status`.
182
+ - If the initial validation request is successful and the operation is not immediately completed or failed, `handleValidation` initiates polling.
183
+ - The shared `pollOperationStatus` function (from `validationHandlers.js`) is called, which periodically queries `GET /api/categories/:categoryName/onboard/status?operationType=VALIDATION_ONLY` (using the category name from the form). `pollOperationStatus` now returns a boolean to manage polling continuation.
184
184
  - **Displaying Results**:
185
- - The shared `updateOperationDisplay` function (from `validationHandlers.js`) formats and displays the results from both the initial validation call and subsequent status polls in the relevant status panel.
186
- - It handles different structures of the `validationStatus` object in the response, including displaying overall status, messages, and detailed results for each server if `validationStatus.serverResults` is present.
185
+ - The shared `updateOperationDisplay` function (from `validationHandlers.js`) formats and displays detailed progress, including individual steps, from both the initial validation call and subsequent status polls.
186
+ - It handles different structures of the `validationStatus` object and overall operation status.
187
187
  - **Completion/Failure**:
188
- - Polling stops when the status is 'COMPLETED', 'FAILED', or 'succeeded'.
189
- - Upon completion or failure, the "Validate" button reverts to its original state ("Validate" text and icon), and both "Validate" and "Publish" buttons are re-enabled.
188
+ - Polling stops based on the status returned by `pollOperationStatus`.
189
+ - Upon completion or failure, buttons are reset. For detailed information on recent changes to polling and status display, see Section 9: "Enhanced Operation Status Polling and Display".
190
190
  - **Copy JSON (`copyJsonToClipboard` in `uiHandlers.js`)**: Copies the content of `jsonEditorTextarea` to the clipboard. Uses `showToast()` for feedback.
191
191
  - **Global Function Exposure**: Necessary UI handler functions (like `addServer`, `removeServer`, `toggleSectionContent`, etc.) are attached to the `window` object so they can be called from `onclick` attributes in the HTML templates.
192
192
  - **Custom Notifications**: Standard browser `alert()` calls have been replaced with a custom toast notification system (`showToast()` from `../notifications.js`). This system requires an `.alert-container` div in the host HTML (`onboard.html`) and uses CSS from `css/notifications.css` for styling. The `notifications.js` module handles the creation, display, and dismissal (manual and automatic) of these toasts without relying on Bootstrap's JavaScript.
@@ -290,6 +290,38 @@ This section documents significant fixes and behavior changes implemented recent
290
290
  - **Outcome:** The "Publish" and "Validate" buttons now reliably revert to their default active states when an operation (validation or publish) concludes with a failure, regardless of the casing of the status string from the backend or whether the failure occurs immediately or during polling.
291
291
  - **Overall Outcome:** These changes improve the reliability of data submission and provide more accurate UI feedback for asynchronous operations on the "Create Server in Existing Category" tab.
292
292
 
293
+ - **Enhanced Operation Status Polling and Display (May 2025 - Current Session):**
294
+ - **Context:** Significant improvements were made to the handling of asynchronous operations (validation and publishing), including more detailed progress display, robust polling, and clearer API interactions.
295
+ - **Issues Addressed & Solutions:**
296
+ 1. **Server-Side API (`server.ts` - `/api/categories/:categoryName/onboard/status`):**
297
+ - The endpoint now requires an `operationType` query parameter (e.g., `VALIDATION_ONLY`, `FULL_ONBOARDING`).
298
+ - The response payload (`OperationStatus`) was enhanced to include:
299
+ - `steps`: An array of objects detailing each step of the operation (name, serverName, timestamp, status, errorMessage).
300
+ - `operationType`: Reflects the type of operation being tracked, taken from the status object.
301
+ - `feedConfiguration`: Conditionally included for successful `VALIDATION_ONLY` operations if present in the result.
302
+ - The `onboardingId` in the response is `categoryName_operationType`.
303
+ - The `message` field in the response now prioritizes the last step's name or an overall error message.
304
+ 2. **Client-Side Polling Logic (`validationHandlers.js` - `pollOperationStatus`):**
305
+ - The function now accepts an `operationType` parameter, which is passed to the API.
306
+ - It returns a boolean promise (`Promise<boolean>`) indicating whether polling should continue, allowing the caller (`handleValidation` or `handlePublish`) to manage `clearInterval`.
307
+ - Calls `ensureProgressToggleListener` to ensure the UI for displaying progress steps is interactive.
308
+ - Status comparisons (`COMPLETED`, `FAILED`, `SUCCEEDED`) are now case-insensitive.
309
+ 3. **Operation Initiation (`publishHandler.js` - `handlePublish`, `validationHandlers.js` - `handleValidation`):**
310
+ - When initiating polling, these functions now pass the correct `operationType` (`FULL_ONBOARDING` for publish, `VALIDATION_ONLY` for validate) and use the original `finalFeedConfiguration.name` as the `categoryName` for the polling request.
311
+ - They now manage `clearInterval` based on the boolean returned by `pollOperationStatus`.
312
+ - Both handlers call `ensureProgressToggleListener` at the beginning to prepare the UI for status updates.
313
+ - `handlePublish` includes improved error handling for the initial publish request, ensuring UI elements are correctly updated even if the initial call fails or returns a terminal status.
314
+ 4. **UI Display (`validationHandlers.js` - `updateOperationDisplay`):**
315
+ - A new collapsible "Progress" section is displayed, showing detailed `steps` from the API response. Each step includes:
316
+ - A status icon (error, in-progress spinner, success).
317
+ - The step name, server name (if applicable), and timestamp.
318
+ - An error message for the step, if any.
319
+ - The visibility of the "Progress" section is managed by `ensureProgressToggleListener` (which attaches a click handler to the section header) and the `toggleSectionContent` utility.
320
+ - The `operationType` is now displayed.
321
+ - The logic for displaying the overall status spinner has been updated to cover more in-progress states (e.g., `PENDING`, `VALIDATING`, `PRCREATING`, `PUBLISHING`) and uses case-insensitive comparisons.
322
+ 5. **Progress Section Toggling (`validationHandlers.js` - `ensureProgressToggleListener`):**
323
+ - A new exported utility function, `ensureProgressToggleListener`, was added. It attaches a click event listener to the status content element. This listener delegates to `toggleSectionContent` (from `uiHandlers.js`) when the progress section header is clicked, allowing users to expand or collapse the detailed list of progress steps. The listener is attached only once per status content element.
324
+ - **Outcome:** These changes provide users with more granular and interactive feedback on long-running operations, improve the robustness and accuracy of status polling, and align client-server communication for tracking asynchronous onboarding tasks.
293
325
  ---
294
326
 
295
327
  ## 10. Server Validation System