imcp 0.1.13 → 0.1.15

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 (25) hide show
  1. package/dist/core/installers/clients/BaseClientInstaller.d.ts +11 -3
  2. package/dist/core/installers/clients/BaseClientInstaller.js +1 -1
  3. package/dist/core/installers/clients/BaseClientInstaller.js.map +1 -1
  4. package/dist/core/installers/clients/ClineInstaller.js +1 -1
  5. package/dist/core/installers/clients/ClineInstaller.js.map +1 -1
  6. package/dist/core/installers/clients/GithubCopilotInstaller.d.ts +8 -0
  7. package/dist/core/installers/clients/GithubCopilotInstaller.js +1 -1
  8. package/dist/core/installers/clients/GithubCopilotInstaller.js.map +1 -1
  9. package/dist/core/installers/clients/MSRooCodeInstaller.js +1 -1
  10. package/dist/core/installers/clients/MSRooCodeInstaller.js.map +1 -1
  11. package/dist/core/installers/clients/VisualStudioInstaller.d.ts +8 -0
  12. package/dist/core/installers/clients/VisualStudioInstaller.js +1 -1
  13. package/dist/core/installers/clients/VisualStudioInstaller.js.map +1 -1
  14. package/dist/core/metadatas/types.d.ts +1 -1
  15. package/dist/core/validators/IServerValidator.d.ts +1 -1
  16. package/dist/core/validators/SSEServerValidator.js +1 -1
  17. package/dist/core/validators/SSEServerValidator.js.map +1 -1
  18. package/dist/core/validators/ServerValidatorFactory.js +1 -1
  19. package/dist/core/validators/ServerValidatorFactory.js.map +1 -1
  20. package/dist/web/contract/serverContract.d.ts +1 -1
  21. package/dist/web/public/js/modal/modalSetup.js +1 -1
  22. package/dist/web/public/js/onboard/formProcessor.js +1 -1
  23. package/dist/web/public/js/onboard/templates.js +1 -1
  24. package/dist/web/public/js/onboard/uiHandlers.js +1 -1
  25. package/package.json +1 -1
@@ -30,6 +30,14 @@ export declare abstract class BaseClientInstaller {
30
30
  * Override in child classes to provide custom initialization
31
31
  */
32
32
  protected initializeSettings(settings: any): void;
33
+ /**
34
+ * Set up client settings in the provided settings object
35
+ * Override in child classes to provide custom client settings setup
36
+ * @param settings The settings object to modify
37
+ * @param serverName The name of the server to configure
38
+ * @param installConfig The installation configuration
39
+ */
40
+ protected setupSettings(settings: any, serverName: string, installConfig: any): void;
33
41
  /**
34
42
  * Handle stdio mode configuration
35
43
  * Override in child classes to provide custom stdio configuration
@@ -42,10 +50,10 @@ export declare abstract class BaseClientInstaller {
42
50
  */
43
51
  private isServerReachable;
44
52
  /**
45
- * Handle SSE mode configuration
46
- * Override in child classes to provide custom SSE configuration
53
+ * Handle SSE and Streamable-Http mode configuration
54
+ * Override in child classes to provide custom SSE or Streamable-Http configuration
47
55
  */
48
- protected handleSseMode(settings: any, serverName: string, installConfig: any): Promise<void>;
56
+ protected handleSseAndStreamableMode(settings: any, serverName: string, installConfig: any): Promise<void>;
49
57
  /**
50
58
  * Checks if VS Code or VS Code Insiders is installed and installs the client extension.
51
59
  * @param operationId The operation ID for tracking.
@@ -1,2 +1,2 @@
1
- import{Logger}from"../../../utils/logger.js";import{exec,spawn}from"child_process";import{promisify}from"util";import*as http from"http";import*as https from"https";import{isCommandAvailable,getNpmExecutablePath}from"../../../utils/osUtils.js";import{ExtensionInstaller}from"./ExtensionInstaller.js";import{SUPPORTED_CLIENTS}from"../../metadatas/constants.js";import{MACRO_EXPRESSIONS,MacroResolverFunctions}from"../../../utils/macroExpressionUtils.js";import{InstallOperationManager}from"../../loaders/InstallOperationManager.js";import*as RecordingConstants from"../../metadatas/recordingConstants.js";const execAsync=promisify(exec);export class BaseClientInstaller{generateOperationId(){return`install-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}async setupInstallConfig(e,t){const s={...e.installation};s.mode=e.mode,t.args&&t.args.length>0&&(Logger.debug(`Using args from ServerInstallOptions: ${t.args.join(" ")}`),s.args=t.args);const n=s.env||{},r={};for(const[e,t]of Object.entries(n)){const s=t;s.Default&&(r[e]=s.Default)}return s.env={...r,...t.env||{}},await this._resolveConfigMacros(s,t),Logger.debug(`Final installation config: ${JSON.stringify(s)}`),s}async _resolveConfigMacros(e,t){for(const s of Object.values(MACRO_EXPRESSIONS)){const n=e.args?.some((e=>"string"==typeof e&&e.includes(s))),r=Object.values(e.env||{}).some((e=>"string"==typeof e&&e.includes(s)));if(!n&&!r&&s!==MACRO_EXPRESSIONS.PYTHON_PACKAGE){Logger.debug(`Macro ${s} not found in args or env, skipping resolution.`);continue}const a=MacroResolverFunctions[s];if(a){const n=await a(e,t);if(void 0!==n){if(e.args){const t=e.args.join(" ");e.args=e.args.map((e=>"string"==typeof e&&e.includes(s)?e.replace(new RegExp(s.replace(/[${}]/g,"\\$&"),"g"),n):e)),e.args.join(" ")!==t&&Logger.debug(`Args after ${s} ('${n}') replacement: ${e.args.join(" ")}`)}if(e.env){const t=JSON.stringify(e.env);for(const t in e.env)"string"==typeof e.env[t]&&e.env[t].includes(s)&&(e.env[t]=e.env[t].replace(new RegExp(s.replace(/[${}]/g,"\\$&"),"g"),n));JSON.stringify(e.env)!==t&&Logger.debug(`Env after ${s} ('${n}') replacement: ${JSON.stringify(e.env)}`)}}else Logger.debug(`Could not resolve value for macro: ${s}. It will not be replaced.`)}}}async handleWindowsNpx(e){if("win32"===process.platform&&"npx"===e.command){const t=await getNpmExecutablePath();return{...e,command:"cmd",args:["/c","npx",...e.args],env:{...e.env,APPDATA:t}}}return e}initializeSettings(e){e.mcpServers||(e.mcpServers={})}async handleStdioMode(e,t,s){s.args&&(s.args=s.args.map((e=>"string"==typeof e?e.replace(/\\/g,"/"):e))),e.mcpServers[t]={command:s.command,args:s.args,env:s.env,autoApprove:[],disabled:!1,alwaysAllow:[]}}async isServerReachable(e){return new Promise((t=>{try{const s=new URL(e),n=("https:"===s.protocol?https:http).request(s,{method:"HEAD",timeout:2e3},(e=>{t(!0),e.resume()}));n.on("error",(s=>{Logger.debug(`Server at ${e} is not reachable: ${s.message}`),t(!1)})),n.on("timeout",(()=>{Logger.debug(`Timeout checking server reachability at ${e}`),n.destroy(),t(!1)})),n.end()}catch(s){Logger.error(`Error parsing URL or making request to ${e}: ${s.message}`),t(!1)}}))}async handleSseMode(e,t,s){if(s.url){if(await this.isServerReachable(s.url))Logger.info(`Server at ${s.url} is already running or reachable. Skipping start command.`);else if(s.startingCommand&&"string"==typeof s.startingCommand){Logger.info(`Server at ${s.url} not reachable. Attempting to start server with command: ${s.startingCommand}`);const e=s.startingCommand.split(" "),t=e[0],n=e.slice(1);try{const e=spawn(t,n,{detached:!0,stdio:"ignore",shell:"win32"===process.platform});e.on("error",(e=>{Logger.error(`Failed to start server process with command "${s.startingCommand}": ${e.message}`)})),e.unref(),Logger.info(`Detached server process (PID: ${e.pid}) started with command: "${s.startingCommand}". It will continue running if this main process exits.`)}catch(e){Logger.error(`Exception when trying to spawn server process with command "${s.startingCommand}": ${e.message}`)}}else s.startingCommand?Logger.warn(`startingCommand is present but not a string: ${JSON.stringify(s.startingCommand)}`):Logger.info(`Server at ${s.url} not reachable and no startingCommand provided.`)}else Logger.warn("No URL provided in installConfig for SSE mode. Cannot check reachability or configure server.");e.mcpServers[t]={type:"sse",url:s.url}}async checkVSCodeAndInstallExtension(e){const t=await isCommandAvailable("code"),s=await isCommandAvailable("code-insiders");if(!t&&!s)return{status:"failed",type:"install",target:"server",message:"Failed to install as neither VS Code nor VS Code Insiders are installed on this system. Please run `code` or `code-insiders` to make sure they are installed. Relaunch imcp after installation.",operationId:e};return await ExtensionInstaller.installExtension(this.clientName)?void 0:(Logger.debug(`Failed to install ${this.clientName} extension`),{status:"failed",type:"install",target:"server",message:`Failed to install ${this.clientName} extension`,operationId:e})}async updateVSCodeSettings(e,t){const s=[],n=await isCommandAvailable("code"),r=await isCommandAvailable("code-insiders");if(n)try{const n=SUPPORTED_CLIENTS[this.clientName].codeSettingPath;await this.setupClientSettings(n,e,t),s.push({success:!0,path:n})}catch(e){s.push({success:!1,path:SUPPORTED_CLIENTS[this.clientName].codeSettingPath,error:e instanceof Error?e.message:String(e)})}if(r)try{const n=SUPPORTED_CLIENTS[this.clientName].codeInsiderSettingPath;await this.setupClientSettings(n,e,t),s.push({success:!0,path:n})}catch(e){s.push({success:!1,path:SUPPORTED_CLIENTS[this.clientName].codeInsiderSettingPath,error:e instanceof Error?e.message:String(e)})}return s}async install(e,t,s){const n=this.generateOperationId(),r=InstallOperationManager.getInstance(s||e.name,e.name);return await r.recording((async()=>{await r.recording((()=>this.checkVSCodeAndInstallExtension(n)),{stepName:RecordingConstants.STEP_CHECK_VSCODE_AND_INSTALL_EXTENSION,endMessage:e=>e?.message,onResult:e=>"failed"!==e?.status});const s=await r.recording((()=>this.setupInstallConfig(e,t)),{stepName:RecordingConstants.STEP_SETUP_INSTALLATION_CONFIG});e.mode&&(s.mode=e.mode);const a=await r.recording((()=>this.updateVSCodeSettings(e.name,s)),{stepName:RecordingConstants.STEP_UPDATE_VSCODE_SETTINGS,endMessage:e=>e?.some((e=>e.success))?`Updated settings in: ${e.map((e=>e.path)).join(", ")}`:`Failed to update settings: ${e.map((e=>e.error)).join("; ")}`,onResult:e=>e?.some((e=>e.success))}),o=a.some((e=>e.success)),i=a.filter((e=>e.success)).map((e=>e.path)),l=a.filter((e=>!e.success)).map((e=>e.error));return{status:o?"completed":"failed",type:"install",target:"server",message:o?`Successfully installed ${this.clientName} client. Updated settings in: ${i.join(", ")}`:`Failed to install ${this.clientName} client. Errors: ${l.join("; ")}`,operationId:n,error:o?void 0:l.join("; ")}}),{stepName:RecordingConstants.STEP_INSTALLATION,onResult:e=>"failed"!==e?.status,endMessage:e=>e?.message,onError:e=>{const t=`Unexpected error installing ${this.clientName} client: ${e instanceof Error?e.message:String(e)}`;return{result:{status:"failed",type:"install",target:"server",message:t,operationId:n,error:e instanceof Error?e.message:String(e)},message:t}}})}}
1
+ import{Logger}from"../../../utils/logger.js";import{exec,spawn}from"child_process";import{promisify}from"util";import*as http from"http";import*as https from"https";import{isCommandAvailable,getNpmExecutablePath}from"../../../utils/osUtils.js";import{ExtensionInstaller}from"./ExtensionInstaller.js";import{SUPPORTED_CLIENTS}from"../../metadatas/constants.js";import{MACRO_EXPRESSIONS,MacroResolverFunctions}from"../../../utils/macroExpressionUtils.js";import{InstallOperationManager}from"../../loaders/InstallOperationManager.js";import*as RecordingConstants from"../../metadatas/recordingConstants.js";const execAsync=promisify(exec);export class BaseClientInstaller{generateOperationId(){return`install-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}async setupInstallConfig(e,t){const s={...e.installation};s.mode=e.mode,t.args&&t.args.length>0&&(Logger.debug(`Using args from ServerInstallOptions: ${t.args.join(" ")}`),s.args=t.args);const n=s.env||{},r={};for(const[e,t]of Object.entries(n)){const s=t;s.Default&&(r[e]=s.Default)}return s.env={...r,...t.env||{}},await this._resolveConfigMacros(s,t),Logger.debug(`Final installation config: ${JSON.stringify(s)}`),s}async _resolveConfigMacros(e,t){for(const s of Object.values(MACRO_EXPRESSIONS)){const n=e.args?.some((e=>"string"==typeof e&&e.includes(s))),r=Object.values(e.env||{}).some((e=>"string"==typeof e&&e.includes(s)));if(!n&&!r&&s!==MACRO_EXPRESSIONS.PYTHON_PACKAGE){Logger.debug(`Macro ${s} not found in args or env, skipping resolution.`);continue}const a=MacroResolverFunctions[s];if(a){const n=await a(e,t);if(void 0!==n){if(e.args){const t=e.args.join(" ");e.args=e.args.map((e=>"string"==typeof e&&e.includes(s)?e.replace(new RegExp(s.replace(/[${}]/g,"\\$&"),"g"),n):e)),e.args.join(" ")!==t&&Logger.debug(`Args after ${s} ('${n}') replacement: ${e.args.join(" ")}`)}if(e.env){const t=JSON.stringify(e.env);for(const t in e.env)"string"==typeof e.env[t]&&e.env[t].includes(s)&&(e.env[t]=e.env[t].replace(new RegExp(s.replace(/[${}]/g,"\\$&"),"g"),n));JSON.stringify(e.env)!==t&&Logger.debug(`Env after ${s} ('${n}') replacement: ${JSON.stringify(e.env)}`)}}else Logger.debug(`Could not resolve value for macro: ${s}. It will not be replaced.`)}}}async handleWindowsNpx(e){if("win32"===process.platform&&"npx"===e.command){const t=await getNpmExecutablePath();return{...e,command:"cmd",args:["/c","npx",...e.args],env:{...e.env,APPDATA:t}}}return e}initializeSettings(e){e.mcpServers||(e.mcpServers={})}setupSettings(e,t,s){e.mcpServers[t]={type:s.mode||"sse",url:s.url}}async handleStdioMode(e,t,s){s.args&&(s.args=s.args.map((e=>"string"==typeof e?e.replace(/\\/g,"/"):e))),e.mcpServers[t]={command:s.command,args:s.args,env:s.env,autoApprove:[],disabled:!1,alwaysAllow:[]}}async isServerReachable(e){return new Promise((t=>{try{const s=new URL(e),n=("https:"===s.protocol?https:http).request(s,{method:"HEAD",timeout:2e3},(e=>{t(!0),e.resume()}));n.on("error",(s=>{Logger.debug(`Server at ${e} is not reachable: ${s.message}`),t(!1)})),n.on("timeout",(()=>{Logger.debug(`Timeout checking server reachability at ${e}`),n.destroy(),t(!1)})),n.end()}catch(s){Logger.error(`Error parsing URL or making request to ${e}: ${s.message}`),t(!1)}}))}async handleSseAndStreamableMode(e,t,s){if(s.url){if(await this.isServerReachable(s.url))Logger.info(`Server at ${s.url} is already running or reachable. Skipping start command.`);else if(s.startingCommand&&"string"==typeof s.startingCommand){Logger.info(`Server at ${s.url} not reachable. Attempting to start server with command: ${s.startingCommand}`);const e=s.startingCommand.split(" "),t=e[0],n=e.slice(1);try{const e=spawn(t,n,{detached:!0,stdio:"ignore",shell:"win32"===process.platform});e.on("error",(e=>{Logger.error(`Failed to start server process with command "${s.startingCommand}": ${e.message}`)})),e.unref(),Logger.info(`Detached server process (PID: ${e.pid}) started with command: "${s.startingCommand}". It will continue running if this main process exits.`)}catch(e){Logger.error(`Exception when trying to spawn server process with command "${s.startingCommand}": ${e.message}`)}}else s.startingCommand?Logger.warn(`startingCommand is present but not a string: ${JSON.stringify(s.startingCommand)}`):Logger.info(`Server at ${s.url} not reachable and no startingCommand provided.`)}else Logger.warn("No URL provided in installConfig for SSE mode. Cannot check reachability or configure server.");this.setupSettings(e,t,s)}async checkVSCodeAndInstallExtension(e){const t=await isCommandAvailable("code"),s=await isCommandAvailable("code-insiders");if(!t&&!s)return{status:"failed",type:"install",target:"server",message:"Failed to install as neither VS Code nor VS Code Insiders are installed on this system. Please run `code` or `code-insiders` to make sure they are installed. Relaunch imcp after installation.",operationId:e};return await ExtensionInstaller.installExtension(this.clientName)?void 0:(Logger.debug(`Failed to install ${this.clientName} extension`),{status:"failed",type:"install",target:"server",message:`Failed to install ${this.clientName} extension`,operationId:e})}async updateVSCodeSettings(e,t){const s=[],n=await isCommandAvailable("code"),r=await isCommandAvailable("code-insiders");if(n)try{const n=SUPPORTED_CLIENTS[this.clientName].codeSettingPath;await this.setupClientSettings(n,e,t),s.push({success:!0,path:n})}catch(e){s.push({success:!1,path:SUPPORTED_CLIENTS[this.clientName].codeSettingPath,error:e instanceof Error?e.message:String(e)})}if(r)try{const n=SUPPORTED_CLIENTS[this.clientName].codeInsiderSettingPath;await this.setupClientSettings(n,e,t),s.push({success:!0,path:n})}catch(e){s.push({success:!1,path:SUPPORTED_CLIENTS[this.clientName].codeInsiderSettingPath,error:e instanceof Error?e.message:String(e)})}return s}async install(e,t,s){const n=this.generateOperationId(),r=InstallOperationManager.getInstance(s||e.name,e.name);return await r.recording((async()=>{await r.recording((()=>this.checkVSCodeAndInstallExtension(n)),{stepName:RecordingConstants.STEP_CHECK_VSCODE_AND_INSTALL_EXTENSION,endMessage:e=>e?.message,onResult:e=>"failed"!==e?.status});const s=await r.recording((()=>this.setupInstallConfig(e,t)),{stepName:RecordingConstants.STEP_SETUP_INSTALLATION_CONFIG});e.mode&&(s.mode=e.mode);const a=await r.recording((()=>this.updateVSCodeSettings(e.name,s)),{stepName:RecordingConstants.STEP_UPDATE_VSCODE_SETTINGS,endMessage:e=>e?.some((e=>e.success))?`Updated settings in: ${e.map((e=>e.path)).join(", ")}`:`Failed to update settings: ${e.map((e=>e.error)).join("; ")}`,onResult:e=>e?.some((e=>e.success))}),o=a.some((e=>e.success)),i=a.filter((e=>e.success)).map((e=>e.path)),l=a.filter((e=>!e.success)).map((e=>e.error));return{status:o?"completed":"failed",type:"install",target:"server",message:o?`Successfully installed ${this.clientName} client. Updated settings in: ${i.join(", ")}`:`Failed to install ${this.clientName} client. Errors: ${l.join("; ")}`,operationId:n,error:o?void 0:l.join("; ")}}),{stepName:RecordingConstants.STEP_INSTALLATION,onResult:e=>"failed"!==e?.status,endMessage:e=>e?.message,onError:e=>{const t=`Unexpected error installing ${this.clientName} client: ${e instanceof Error?e.message:String(e)}`;return{result:{status:"failed",type:"install",target:"server",message:t,operationId:n,error:e instanceof Error?e.message:String(e)},message:t}}})}}
2
2
  //# sourceMappingURL=BaseClientInstaller.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Logger","exec","spawn","promisify","http","https","isCommandAvailable","getNpmExecutablePath","ExtensionInstaller","SUPPORTED_CLIENTS","MACRO_EXPRESSIONS","MacroResolverFunctions","InstallOperationManager","RecordingConstants","execAsync","BaseClientInstaller","generateOperationId","Date","now","Math","random","toString","substr","setupInstallConfig","serverConfig","options","finalConfig","installation","mode","args","length","debug","join","baseEnv","env","defaultEnv","key","config","Object","entries","envConfig","Default","this","_resolveConfigMacros","JSON","stringify","macro","values","isMacroInArgs","some","arg","includes","isMacroInEnv","value","PYTHON_PACKAGE","resolver","resolvedValue","undefined","originalArgsString","map","replace","RegExp","originalEnvJson","handleWindowsNpx","process","platform","command","npmPath","APPDATA","initializeSettings","settings","mcpServers","handleStdioMode","serverName","autoApprove","disabled","alwaysAllow","isServerReachable","urlString","Promise","resolve","url","URL","request","protocol","method","timeout","res","resume","on","err","message","destroy","end","error","handleSseMode","installConfig","info","startingCommand","commandParts","split","slice","child","detached","stdio","shell","unref","pid","warn","type","checkVSCodeAndInstallExtension","operationId","isVSCodeInstalled","isVSCodeInsidersInstalled","status","target","installExtension","clientName","updateVSCodeSettings","results","settingPath","codeSettingPath","setupClientSettings","push","success","path","Error","String","codeInsiderSettingPath","install","categoryName","recorder","getInstance","name","recording","async","stepName","STEP_CHECK_VSCODE_AND_INSTALL_EXTENSION","endMessage","result","onResult","STEP_SETUP_INSTALLATION_CONFIG","STEP_UPDATE_VSCODE_SETTINGS","r","anySuccess","successPaths","filter","errors","STEP_INSTALLATION","onError","errorMsg"],"sources":["../../../../src/core/installers/clients/BaseClientInstaller.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["Logger","exec","spawn","promisify","http","https","isCommandAvailable","getNpmExecutablePath","ExtensionInstaller","SUPPORTED_CLIENTS","MACRO_EXPRESSIONS","MacroResolverFunctions","InstallOperationManager","RecordingConstants","execAsync","BaseClientInstaller","generateOperationId","Date","now","Math","random","toString","substr","setupInstallConfig","serverConfig","options","finalConfig","installation","mode","args","length","debug","join","baseEnv","env","defaultEnv","key","config","Object","entries","envConfig","Default","this","_resolveConfigMacros","JSON","stringify","macro","values","isMacroInArgs","some","arg","includes","isMacroInEnv","value","PYTHON_PACKAGE","resolver","resolvedValue","undefined","originalArgsString","map","replace","RegExp","originalEnvJson","handleWindowsNpx","process","platform","command","npmPath","APPDATA","initializeSettings","settings","mcpServers","setupSettings","serverName","installConfig","type","url","handleStdioMode","autoApprove","disabled","alwaysAllow","isServerReachable","urlString","Promise","resolve","URL","request","protocol","method","timeout","res","resume","on","err","message","destroy","end","error","handleSseAndStreamableMode","info","startingCommand","commandParts","split","slice","child","detached","stdio","shell","unref","pid","warn","checkVSCodeAndInstallExtension","operationId","isVSCodeInstalled","isVSCodeInsidersInstalled","status","target","installExtension","clientName","updateVSCodeSettings","results","settingPath","codeSettingPath","setupClientSettings","push","success","path","Error","String","codeInsiderSettingPath","install","categoryName","recorder","getInstance","name","recording","async","stepName","STEP_CHECK_VSCODE_AND_INSTALL_EXTENSION","endMessage","result","onResult","STEP_SETUP_INSTALLATION_CONFIG","STEP_UPDATE_VSCODE_SETTINGS","r","anySuccess","successPaths","filter","errors","STEP_INSTALLATION","onError","errorMsg"],"sources":["../../../../src/core/installers/clients/BaseClientInstaller.ts"],"mappings":"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","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- import{BaseClientInstaller}from"./BaseClientInstaller.js";import{readJsonFile,writeJsonFile}from"../../../utils/clientUtils.js";export class ClineInstaller extends BaseClientInstaller{clientName="Cline";async setupClientSettings(e,i,t){const s=await readJsonFile(e,!0);if(this.initializeSettings(s),"stdio"===t.mode){const e=await this.handleWindowsNpx(t);await this.handleStdioMode(s,i,e)}else"sse"===t.mode&&this.handleSseMode(s,i,t);await writeJsonFile(e,s)}}
1
+ import{BaseClientInstaller}from"./BaseClientInstaller.js";import{readJsonFile,writeJsonFile}from"../../../utils/clientUtils.js";export class ClineInstaller extends BaseClientInstaller{clientName="Cline";async setupClientSettings(e,t,i){const s=await readJsonFile(e,!0);if(this.initializeSettings(s),"stdio"===i.mode){const e=await this.handleWindowsNpx(i);await this.handleStdioMode(s,t,e)}else"sse"!==i.mode&&"streamable-http"!==i.mode||this.handleSseAndStreamableMode(s,t,i);await writeJsonFile(e,s)}}
2
2
  //# sourceMappingURL=ClineInstaller.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BaseClientInstaller","readJsonFile","writeJsonFile","ClineInstaller","clientName","setupClientSettings","settingPath","serverName","installConfig","settings","this","initializeSettings","mode","finalConfig","handleWindowsNpx","handleStdioMode","handleSseMode"],"sources":["../../../../src/core/installers/clients/ClineInstaller.ts"],"mappings":"OAASA,wBAA2B,kCAC3BC,aAAcC,kBAAqB,uCAMtC,MAAOC,uBAAuBH,oBACbI,WAAqB,QAMxC,yBAAMC,CAAoBC,EAAqBC,EAAoBC,GAE/D,MAAMC,QAAiBR,aAAaK,GAAa,GAMjD,GAHAI,KAAKC,mBAAmBF,GAGG,UAAvBD,EAAcI,KAAkB,CAEhC,MAAMC,QAAoBH,KAAKI,iBAAiBN,SAE1CE,KAAKK,gBAAgBN,EAAUF,EAAYM,EACrD,KAAkC,QAAvBL,EAAcI,MACrBF,KAAKM,cAAcP,EAAUF,EAAYC,SAIvCN,cAAcI,EAAaG,EACrC","ignoreList":[]}
1
+ {"version":3,"names":["BaseClientInstaller","readJsonFile","writeJsonFile","ClineInstaller","clientName","setupClientSettings","settingPath","serverName","installConfig","settings","this","initializeSettings","mode","finalConfig","handleWindowsNpx","handleStdioMode","handleSseAndStreamableMode"],"sources":["../../../../src/core/installers/clients/ClineInstaller.ts"],"mappings":"OAASA,wBAA2B,kCAC3BC,aAAcC,kBAAqB,uCAMtC,MAAOC,uBAAuBH,oBACbI,WAAqB,QAMxC,yBAAMC,CAAoBC,EAAqBC,EAAoBC,GAE/D,MAAMC,QAAiBR,aAAaK,GAAa,GAMjD,GAHAI,KAAKC,mBAAmBF,GAGG,UAAvBD,EAAcI,KAAkB,CAEhC,MAAMC,QAAoBH,KAAKI,iBAAiBN,SAE1CE,KAAKK,gBAAgBN,EAAUF,EAAYM,EACrD,KAAkC,QAAvBL,EAAcI,MAAyC,oBAAvBJ,EAAcI,MACrDF,KAAKM,2BAA2BP,EAAUF,EAAYC,SAIpDN,cAAcI,EAAaG,EACrC","ignoreList":[]}
@@ -10,6 +10,14 @@ export declare class GithubCopilotInstaller extends BaseClientInstaller {
10
10
  * Overrides base method to provide custom initialization
11
11
  */
12
12
  protected initializeSettings(settings: any): void;
13
+ /**
14
+ * Set up client settings in the provided settings object for github copilot
15
+ * Override in child classes to provide custom client settings setup
16
+ * @param settings The settings object to modify
17
+ * @param serverName The name of the server to configure
18
+ * @param installConfig The installation configuration
19
+ */
20
+ protected setupSettings(settings: any, serverName: string, installConfig: any): void;
13
21
  /**
14
22
  * Handle stdio mode configuration for GithubCopilot
15
23
  * Overrides base method to provide custom stdio configuration
@@ -1,2 +1,2 @@
1
- import{BaseClientInstaller}from"./BaseClientInstaller.js";import{readJsonFile,writeJsonFile}from"../../../utils/clientUtils.js";export class GithubCopilotInstaller extends BaseClientInstaller{clientName="GithubCopilot";initializeSettings(e){e.mcp||(e.mcp={servers:{},inputs:[]}),e.mcp.servers||(e.mcp.servers={})}async handleStdioMode(e,s,t){t.args&&(t.args=t.args.map((e=>"string"==typeof e?e.replace(/\\/g,"/"):e))),e.mcp.servers[s]={command:t.command,args:t.args,env:t.env}}async setupClientSettings(e,s,t){const i=await readJsonFile(e,!0);this.initializeSettings(i),"stdio"===t.mode?await this.handleStdioMode(i,s,t):"sse"===t.mode&&this.handleSseMode(i,s,t),await writeJsonFile(e,i)}}
1
+ import{BaseClientInstaller}from"./BaseClientInstaller.js";import{readJsonFile,writeJsonFile}from"../../../utils/clientUtils.js";export class GithubCopilotInstaller extends BaseClientInstaller{clientName="GithubCopilot";initializeSettings(e){e.mcp||(e.mcp={servers:{},inputs:[]}),e.mcp.servers||(e.mcp.servers={})}setupSettings(e,s,t){e.mcp.servers[s]={url:t.url}}async handleStdioMode(e,s,t){t.args&&(t.args=t.args.map((e=>"string"==typeof e?e.replace(/\\/g,"/"):e))),e.mcp.servers[s]={command:t.command,args:t.args,env:t.env}}async setupClientSettings(e,s,t){const i=await readJsonFile(e,!0);this.initializeSettings(i),"stdio"===t.mode?await this.handleStdioMode(i,s,t):"sse"!==t.mode&&"streamable-http"!==t.mode||await this.handleSseAndStreamableMode(i,s,t),await writeJsonFile(e,i)}}
2
2
  //# sourceMappingURL=GithubCopilotInstaller.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BaseClientInstaller","readJsonFile","writeJsonFile","GithubCopilotInstaller","clientName","initializeSettings","settings","mcp","servers","inputs","handleStdioMode","serverName","finalConfig","args","map","arg","replace","command","env","setupClientSettings","settingPath","installConfig","this","mode","handleSseMode"],"sources":["../../../../src/core/installers/clients/GithubCopilotInstaller.ts"],"mappings":"OAASA,wBAA2B,kCAC3BC,aAAcC,kBAAqB,uCAMtC,MAAOC,+BAA+BH,oBACrBI,WAAqB,gBAO9B,kBAAAC,CAAmBC,GACpBA,EAASC,MACVD,EAASC,IAAM,CACXC,QAAS,GACTC,OAAQ,KAIXH,EAASC,IAAIC,UACdF,EAASC,IAAIC,QAAU,GAE/B,CAMU,qBAAME,CAAgBJ,EAAeK,EAAoBC,GAC3DA,EAAYC,OACZD,EAAYC,KAAOD,EAAYC,KAAKC,KAAKC,GACtB,iBAARA,EAAmBA,EAAIC,QAAQ,MAAO,KAAOD,KAG5DT,EAASC,IAAIC,QAAQG,GAAc,CAC/BM,QAASL,EAAYK,QACrBJ,KAAMD,EAAYC,KAClBK,IAAKN,EAAYM,IAEzB,CAOA,yBAAMC,CAAoBC,EAAqBT,EAAoBU,GAE/D,MAAMf,QAAiBL,aAAamB,GAAa,GAGjDE,KAAKjB,mBAAmBC,GAGG,UAAvBe,EAAcE,WACRD,KAAKZ,gBAAgBJ,EAAUK,EAAYU,GACnB,QAAvBA,EAAcE,MACrBD,KAAKE,cAAclB,EAAUK,EAAYU,SAIvCnB,cAAckB,EAAad,EACrC","ignoreList":[]}
1
+ {"version":3,"names":["BaseClientInstaller","readJsonFile","writeJsonFile","GithubCopilotInstaller","clientName","initializeSettings","settings","mcp","servers","inputs","setupSettings","serverName","installConfig","url","handleStdioMode","finalConfig","args","map","arg","replace","command","env","setupClientSettings","settingPath","this","mode","handleSseAndStreamableMode"],"sources":["../../../../src/core/installers/clients/GithubCopilotInstaller.ts"],"mappings":"OAASA,wBAA2B,kCAC3BC,aAAcC,kBAAqB,uCAMtC,MAAOC,+BAA+BH,oBACrBI,WAAqB,gBAO9B,kBAAAC,CAAmBC,GACpBA,EAASC,MACVD,EAASC,IAAM,CACXC,QAAS,GACTC,OAAQ,KAIXH,EAASC,IAAIC,UACdF,EAASC,IAAIC,QAAU,GAE/B,CASU,aAAAE,CAAcJ,EAAeK,EAAoBC,GACvDN,EAASC,IAAIC,QAAQG,GAAc,CAC/BE,IAAKD,EAAcC,IAE3B,CAMU,qBAAMC,CAAgBR,EAAeK,EAAoBI,GAC3DA,EAAYC,OACZD,EAAYC,KAAOD,EAAYC,KAAKC,KAAKC,GACtB,iBAARA,EAAmBA,EAAIC,QAAQ,MAAO,KAAOD,KAG5DZ,EAASC,IAAIC,QAAQG,GAAc,CAC/BS,QAASL,EAAYK,QACrBJ,KAAMD,EAAYC,KAClBK,IAAKN,EAAYM,IAEzB,CAOA,yBAAMC,CAAoBC,EAAqBZ,EAAoBC,GAE/D,MAAMN,QAAiBL,aAAasB,GAAa,GAGjDC,KAAKnB,mBAAmBC,GAGG,UAAvBM,EAAca,WACRD,KAAKV,gBAAgBR,EAAUK,EAAYC,GACnB,QAAvBA,EAAca,MAAyC,oBAAvBb,EAAca,YAC/CD,KAAKE,2BAA2BpB,EAAUK,EAAYC,SAI1DV,cAAcqB,EAAajB,EACrC","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- import{BaseClientInstaller}from"./BaseClientInstaller.js";import{readJsonFile,writeJsonFile}from"../../../utils/clientUtils.js";export class MSRooCodeInstaller extends BaseClientInstaller{clientName="MSRooCode";async setupClientSettings(e,t,i){const s=await readJsonFile(e,!0);if(this.initializeSettings(s),"stdio"===i.mode){const e=await this.handleWindowsNpx(i);await this.handleStdioMode(s,t,e)}else"sse"===i.mode&&await this.handleSseMode(s,t,i);await writeJsonFile(e,s)}}
1
+ import{BaseClientInstaller}from"./BaseClientInstaller.js";import{readJsonFile,writeJsonFile}from"../../../utils/clientUtils.js";export class MSRooCodeInstaller extends BaseClientInstaller{clientName="MSRooCode";async setupClientSettings(e,t,i){const s=await readJsonFile(e,!0);if(this.initializeSettings(s),"stdio"===i.mode){const e=await this.handleWindowsNpx(i);await this.handleStdioMode(s,t,e)}else"sse"!==i.mode&&"streamable-http"!==i.mode||await this.handleSseAndStreamableMode(s,t,i);await writeJsonFile(e,s)}}
2
2
  //# sourceMappingURL=MSRooCodeInstaller.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BaseClientInstaller","readJsonFile","writeJsonFile","MSRooCodeInstaller","clientName","setupClientSettings","settingPath","serverName","installConfig","settings","this","initializeSettings","mode","finalConfig","handleWindowsNpx","handleStdioMode","handleSseMode"],"sources":["../../../../src/core/installers/clients/MSRooCodeInstaller.ts"],"mappings":"OAASA,wBAA2B,kCAC3BC,aAAcC,kBAAqB,uCAKtC,MAAOC,2BAA2BH,oBACjBI,WAAqB,YAIxC,yBAAMC,CAAoBC,EAAqBC,EAAoBC,GAE/D,MAAMC,QAAiBR,aAAaK,GAAa,GAMjD,GAHAI,KAAKC,mBAAmBF,GAGG,UAAvBD,EAAcI,KAAkB,CAEhC,MAAMC,QAAoBH,KAAKI,iBAAiBN,SAE1CE,KAAKK,gBAAgBN,EAAUF,EAAYM,EACrD,KAAkC,QAAvBL,EAAcI,YACfF,KAAKM,cAAcP,EAAUF,EAAYC,SAI7CN,cAAcI,EAAaG,EACrC","ignoreList":[]}
1
+ {"version":3,"names":["BaseClientInstaller","readJsonFile","writeJsonFile","MSRooCodeInstaller","clientName","setupClientSettings","settingPath","serverName","installConfig","settings","this","initializeSettings","mode","finalConfig","handleWindowsNpx","handleStdioMode","handleSseAndStreamableMode"],"sources":["../../../../src/core/installers/clients/MSRooCodeInstaller.ts"],"mappings":"OAASA,wBAA2B,kCAC3BC,aAAcC,kBAAqB,uCAKtC,MAAOC,2BAA2BH,oBACjBI,WAAqB,YAIxC,yBAAMC,CAAoBC,EAAqBC,EAAoBC,GAE/D,MAAMC,QAAiBR,aAAaK,GAAa,GAMjD,GAHAI,KAAKC,mBAAmBF,GAGG,UAAvBD,EAAcI,KAAkB,CAEhC,MAAMC,QAAoBH,KAAKI,iBAAiBN,SAE1CE,KAAKK,gBAAgBN,EAAUF,EAAYM,EACrD,KAAkC,QAAvBL,EAAcI,MAAyC,oBAAvBJ,EAAcI,YAC/CF,KAAKM,2BAA2BP,EAAUF,EAAYC,SAI1DN,cAAcI,EAAaG,EACrC","ignoreList":[]}
@@ -30,6 +30,14 @@ export declare class VisualStudioInstaller extends BaseClientInstaller {
30
30
  * Overrides base method to provide custom initialization
31
31
  */
32
32
  protected initializeSettings(settings: any): void;
33
+ /**
34
+ * Set up client settings in the provided settings object for github copilot in visual studio
35
+ * Override in child classes to provide custom client settings setup
36
+ * @param settings The settings object to modify
37
+ * @param serverName The name of the server to configure
38
+ * @param installConfig The installation configuration
39
+ */
40
+ protected setupSettings(settings: any, serverName: string, installConfig: any): void;
33
41
  /**
34
42
  * Handle stdio mode configuration for GithubCopilot
35
43
  * Overrides base method to provide custom stdio configuration
@@ -1,2 +1,2 @@
1
- import{BaseClientInstaller}from"./BaseClientInstaller.js";import{Logger}from"../../../utils/logger.js";import fs from"fs/promises";import path from"path";import{SUPPORTED_CLIENTS}from"../../metadatas/constants.js";import{InstallOperationManager}from"../../loaders/InstallOperationManager.js";import*as RecordingConstants from"../../metadatas/recordingConstants.js";export class VisualStudioInstaller extends BaseClientInstaller{clientName="VisualStudio";async updateVSSettings(e,t){Logger.debug("Updating Visual Studio settings");const s=[];try{const a=SUPPORTED_CLIENTS[this.clientName].codeSettingPath;Logger.debug(`Attempting to update settings at: ${a}`),await this.setupClientSettings(a,e,t),s.push({success:!0,path:a}),Logger.debug("Successfully updated Visual Studio settings")}catch(e){const t=e instanceof Error?e.message:String(e);Logger.error("Failed to update Visual Studio settings:",e),s.push({success:!1,path:SUPPORTED_CLIENTS[this.clientName].codeSettingPath,error:t})}return s}async setupClientSettings(e,t,s){Logger.debug(`Setting up Visual Studio client settings at ${e}`);try{const a=path.dirname(e);await fs.mkdir(a,{recursive:!0});let i={};try{const t=await fs.readFile(e,"utf8");i=JSON.parse(t)}catch(e){Logger.debug("No existing settings file found, creating new one")}this.initializeSettings(i),t=t.replace(/-/g,"_"),"stdio"===s.mode?await this.handleStdioMode(i,t,s):"sse"===s.mode&&this.handleSseMode(i,t,s),await fs.writeFile(e,JSON.stringify(i,null,2),"utf8"),Logger.debug(`Successfully updated Visual Studio settings at ${e}`)}catch(e){throw Logger.error("Failed to setup Visual Studio client settings:",e),e}}initializeSettings(e){e||(e={servers:{},inputs:[]}),e.inputs||(e.inputs=[]),e.servers||(e.servers={})}async handleStdioMode(e,t,s){s.args&&(s.args=s.args.map((e=>"string"==typeof e?e.replace(/\\/g,"/"):e))),e.servers[t]={command:s.command,args:s.args,env:s.env}}async install(e,t,s){const a=this.generateOperationId(),i=InstallOperationManager.getInstance(s||e.name,e.name);return await i.recording((async()=>{const s=await i.recording((()=>this.setupInstallConfig(e,t)),{stepName:RecordingConstants.STEP_SETUP_INSTALLATION_CONFIG});e.mode&&(s.mode=e.mode);const n=await i.recording((()=>this.updateVSSettings(e.name,s)),{stepName:RecordingConstants.STEP_UPDATE_VS_SETTINGS,onResult:e=>e?.some((e=>e.success))}),r=n.some((e=>e.success)),o=n.filter((e=>e.success)).map((e=>e.path)),l=n.filter((e=>!e.success)).map((e=>e.error));return{status:r?"completed":"failed",type:"install",target:"server",message:r?`Successfully installed ${this.clientName} client. Updated settings in: ${o.join(", ")}`:`Failed to install ${this.clientName} client. Errors: ${l.join("; ")}`,operationId:a,error:r?void 0:l.join("; ")}}),{stepName:RecordingConstants.STEP_INSTALLATION,onResult:e=>"failed"!==e?.status,endMessage:e=>e?.message,onError:e=>{const t=`Unexpected error installing ${this.clientName} client: ${e instanceof Error?e.message:String(e)}`;return{result:{status:"failed",type:"install",target:"server",message:t,operationId:a,error:e instanceof Error?e.message:String(e)},message:t}}})}}
1
+ import{BaseClientInstaller}from"./BaseClientInstaller.js";import{Logger}from"../../../utils/logger.js";import fs from"fs/promises";import path from"path";import{SUPPORTED_CLIENTS}from"../../metadatas/constants.js";import{InstallOperationManager}from"../../loaders/InstallOperationManager.js";import*as RecordingConstants from"../../metadatas/recordingConstants.js";export class VisualStudioInstaller extends BaseClientInstaller{clientName="VisualStudio";async updateVSSettings(e,t){Logger.debug("Updating Visual Studio settings");const s=[];try{const a=SUPPORTED_CLIENTS[this.clientName].codeSettingPath;Logger.debug(`Attempting to update settings at: ${a}`),await this.setupClientSettings(a,e,t),s.push({success:!0,path:a}),Logger.debug("Successfully updated Visual Studio settings")}catch(e){const t=e instanceof Error?e.message:String(e);Logger.error("Failed to update Visual Studio settings:",e),s.push({success:!1,path:SUPPORTED_CLIENTS[this.clientName].codeSettingPath,error:t})}return s}async setupClientSettings(e,t,s){Logger.debug(`Setting up Visual Studio client settings at ${e}`);try{const a=path.dirname(e);await fs.mkdir(a,{recursive:!0});let i={};try{const t=await fs.readFile(e,"utf8");i=JSON.parse(t)}catch(e){Logger.debug("No existing settings file found, creating new one")}this.initializeSettings(i),t=t.replace(/-/g,"_"),"stdio"===s.mode?await this.handleStdioMode(i,t,s):"sse"!==s.mode&&"streamable-http"!==s.mode||this.handleSseAndStreamableMode(i,t,s),await fs.writeFile(e,JSON.stringify(i,null,2),"utf8"),Logger.debug(`Successfully updated Visual Studio settings at ${e}`)}catch(e){throw Logger.error("Failed to setup Visual Studio client settings:",e),e}}initializeSettings(e){e||(e={servers:{},inputs:[]}),e.inputs||(e.inputs=[]),e.servers||(e.servers={})}setupSettings(e,t,s){e.servers[t]={url:s.url}}async handleStdioMode(e,t,s){s.args&&(s.args=s.args.map((e=>"string"==typeof e?e.replace(/\\/g,"/"):e))),e.servers[t]={command:s.command,args:s.args,env:s.env}}async install(e,t,s){const a=this.generateOperationId(),i=InstallOperationManager.getInstance(s||e.name,e.name);return await i.recording((async()=>{const s=await i.recording((()=>this.setupInstallConfig(e,t)),{stepName:RecordingConstants.STEP_SETUP_INSTALLATION_CONFIG});e.mode&&(s.mode=e.mode);const n=await i.recording((()=>this.updateVSSettings(e.name,s)),{stepName:RecordingConstants.STEP_UPDATE_VS_SETTINGS,onResult:e=>e?.some((e=>e.success))}),r=n.some((e=>e.success)),o=n.filter((e=>e.success)).map((e=>e.path)),l=n.filter((e=>!e.success)).map((e=>e.error));return{status:r?"completed":"failed",type:"install",target:"server",message:r?`Successfully installed ${this.clientName} client. Updated settings in: ${o.join(", ")}`:`Failed to install ${this.clientName} client. Errors: ${l.join("; ")}`,operationId:a,error:r?void 0:l.join("; ")}}),{stepName:RecordingConstants.STEP_INSTALLATION,onResult:e=>"failed"!==e?.status,endMessage:e=>e?.message,onError:e=>{const t=`Unexpected error installing ${this.clientName} client: ${e instanceof Error?e.message:String(e)}`;return{result:{status:"failed",type:"install",target:"server",message:t,operationId:a,error:e instanceof Error?e.message:String(e)},message:t}}})}}
2
2
  //# sourceMappingURL=VisualStudioInstaller.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["BaseClientInstaller","Logger","fs","path","SUPPORTED_CLIENTS","InstallOperationManager","RecordingConstants","VisualStudioInstaller","clientName","updateVSSettings","serverName","installConfig","debug","results","settingPath","this","codeSettingPath","setupClientSettings","push","success","error","errorMessage","Error","message","String","settingsDir","dirname","mkdir","recursive","settings","existingContent","readFile","JSON","parse","initializeSettings","replace","mode","handleStdioMode","handleSseMode","writeFile","stringify","servers","inputs","finalConfig","args","map","arg","command","env","install","serverConfig","options","categoryName","operationId","generateOperationId","recorder","getInstance","name","recording","async","setupInstallConfig","stepName","STEP_SETUP_INSTALLATION_CONFIG","STEP_UPDATE_VS_SETTINGS","onResult","result","some","r","anySuccess","successPaths","filter","errors","status","type","target","join","undefined","STEP_INSTALLATION","endMessage","onError","errorMsg"],"sources":["../../../../src/core/installers/clients/VisualStudioInstaller.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["BaseClientInstaller","Logger","fs","path","SUPPORTED_CLIENTS","InstallOperationManager","RecordingConstants","VisualStudioInstaller","clientName","updateVSSettings","serverName","installConfig","debug","results","settingPath","this","codeSettingPath","setupClientSettings","push","success","error","errorMessage","Error","message","String","settingsDir","dirname","mkdir","recursive","settings","existingContent","readFile","JSON","parse","initializeSettings","replace","mode","handleStdioMode","handleSseAndStreamableMode","writeFile","stringify","servers","inputs","setupSettings","url","finalConfig","args","map","arg","command","env","install","serverConfig","options","categoryName","operationId","generateOperationId","recorder","getInstance","name","recording","async","setupInstallConfig","stepName","STEP_SETUP_INSTALLATION_CONFIG","STEP_UPDATE_VS_SETTINGS","onResult","result","some","r","anySuccess","successPaths","filter","errors","status","type","target","join","undefined","STEP_INSTALLATION","endMessage","onError","errorMsg"],"sources":["../../../../src/core/installers/clients/VisualStudioInstaller.ts"],"mappings":"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","ignoreList":[]}
@@ -102,7 +102,7 @@ export interface DependencyConfig {
102
102
  export interface McpConfig {
103
103
  name: string;
104
104
  description: string;
105
- mode: 'stdio' | 'sse';
105
+ mode: 'stdio' | 'sse' | 'streamable-http';
106
106
  dependencies?: DependencyConfig;
107
107
  schemas?: string;
108
108
  repository?: string;
@@ -16,4 +16,4 @@ export interface IServerValidator {
16
16
  /**
17
17
  * Valid validator types for MCP servers
18
18
  */
19
- export type ValidatorType = 'stdio' | 'sse';
19
+ export type ValidatorType = 'stdio' | 'sse' | 'streamable-http';
@@ -1,2 +1,2 @@
1
- import{Logger}from"../../utils/logger.js";export class SSEServerValidator{async validateServer(r,e){try{if(Logger.debug(`Validating SSE server configuration: ${r.name}`),!r.installation?.url)throw new Error("SSE server URL is required in installation configuration");try{new URL(r.installation.url)}catch(e){throw new Error(`Invalid SSE server URL: ${r.installation.url}`)}if("sse"!==r.mode)throw new Error(`Invalid server mode for SSE validator: ${r.mode}`);return!0}catch(r){const e=`Server validation failed: ${r instanceof Error?r.message:String(r)}`;throw Logger.error(e),new Error(e)}}}
1
+ import{Logger}from"../../utils/logger.js";export class SSEServerValidator{async validateServer(r,e){try{if(Logger.debug(`Validating SSE server configuration: ${r.name}`),!r.installation?.url)throw new Error("SSE server URL is required in installation configuration");try{new URL(r.installation.url)}catch(e){throw new Error(`Invalid SSE server URL: ${r.installation.url}`)}if("sse"!==r.mode&&"streamable-http"!==r.mode)throw new Error(`Invalid server mode for SSE validator: ${r.mode}`);return!0}catch(r){const e=`Server validation failed: ${r instanceof Error?r.message:String(r)}`;throw Logger.error(e),new Error(e)}}}
2
2
  //# sourceMappingURL=SSEServerValidator.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Logger","SSEServerValidator","validateServer","server","config","debug","name","installation","url","Error","URL","e","mode","error","errorMsg","message","String"],"sources":["../../../src/core/validators/SSEServerValidator.ts"],"mappings":"OAESA,WAAc,+BAKjB,MAAOC,mBAQJ,oBAAMC,CAAeC,EAAmBC,GAC7C,IAGE,GAFAJ,OAAOK,MAAM,wCAAwCF,EAAOG,SAEvDH,EAAOI,cAAcC,IACxB,MAAM,IAAIC,MAAM,4DAGlB,IACE,IAAIC,IAAIP,EAAOI,aAAaC,IAC9B,CAAE,MAAOG,GACP,MAAM,IAAIF,MAAM,2BAA2BN,EAAOI,aAAaC,MACjE,CAGA,GAAoB,QAAhBL,EAAOS,KACT,MAAM,IAAIH,MAAM,0CAA0CN,EAAOS,QAInE,OAAO,CACT,CAAE,MAAOC,GACP,MAAMC,EAAW,6BAA6BD,aAAiBJ,MAAQI,EAAME,QAAUC,OAAOH,KAE9F,MADAb,OAAOa,MAAMC,GACP,IAAIL,MAAMK,EAClB,CACF","ignoreList":[]}
1
+ {"version":3,"names":["Logger","SSEServerValidator","validateServer","server","config","debug","name","installation","url","Error","URL","e","mode","error","errorMsg","message","String"],"sources":["../../../src/core/validators/SSEServerValidator.ts"],"mappings":"OAESA,WAAc,+BAKjB,MAAOC,mBAQJ,oBAAMC,CAAeC,EAAmBC,GAC7C,IAGE,GAFAJ,OAAOK,MAAM,wCAAwCF,EAAOG,SAEvDH,EAAOI,cAAcC,IACxB,MAAM,IAAIC,MAAM,4DAGlB,IACE,IAAIC,IAAIP,EAAOI,aAAaC,IAC9B,CAAE,MAAOG,GACP,MAAM,IAAIF,MAAM,2BAA2BN,EAAOI,aAAaC,MACjE,CAGA,GAAoB,QAAhBL,EAAOS,MAAkC,oBAAhBT,EAAOS,KAClC,MAAM,IAAIH,MAAM,0CAA0CN,EAAOS,QAInE,OAAO,CACT,CAAE,MAAOC,GACP,MAAMC,EAAW,6BAA6BD,aAAiBJ,MAAQI,EAAME,QAAUC,OAAOH,KAE9F,MADAb,OAAOa,MAAMC,GACP,IAAIL,MAAMK,EAClB,CACF","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- import{StdioServerValidator}from"./StdioServerValidator.js";import{SSEServerValidator}from"./SSEServerValidator.js";import{Logger}from"../../utils/logger.js";export class ServerValidatorFactory{static validators=new Map;constructor(){0===ServerValidatorFactory.validators.size&&(Logger.debug("Initializing server validators"),ServerValidatorFactory.validators.set("stdio",new StdioServerValidator),ServerValidatorFactory.validators.set("sse",new SSEServerValidator))}getValidator(r){const e=ServerValidatorFactory.validators.get(r);if(!e){const e=`Unsupported MCP server mode: ${r}`;throw Logger.error(e),new Error(e)}return Logger.debug(`Retrieved ${r} validator`),e}getValidatorForServer(r){return this.getValidator(r.mode)}}export const serverValidatorFactory=new ServerValidatorFactory;
1
+ import{StdioServerValidator}from"./StdioServerValidator.js";import{SSEServerValidator}from"./SSEServerValidator.js";import{Logger}from"../../utils/logger.js";export class ServerValidatorFactory{static validators=new Map;constructor(){0===ServerValidatorFactory.validators.size&&(Logger.debug("Initializing server validators"),ServerValidatorFactory.validators.set("stdio",new StdioServerValidator),ServerValidatorFactory.validators.set("sse",new SSEServerValidator),ServerValidatorFactory.validators.set("streamable-http",new SSEServerValidator))}getValidator(r){const e=ServerValidatorFactory.validators.get(r);if(!e){const e=`Unsupported MCP server mode: ${r}`;throw Logger.error(e),new Error(e)}return Logger.debug(`Retrieved ${r} validator`),e}getValidatorForServer(r){return this.getValidator(r.mode)}}export const serverValidatorFactory=new ServerValidatorFactory;
2
2
  //# sourceMappingURL=ServerValidatorFactory.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["StdioServerValidator","SSEServerValidator","Logger","ServerValidatorFactory","static","Map","constructor","validators","size","debug","set","getValidator","mode","validator","get","error","Error","getValidatorForServer","serverConfig","this","serverValidatorFactory"],"sources":["../../../src/core/validators/ServerValidatorFactory.ts"],"mappings":"OAESA,yBAA4B,mCAC5BC,uBAA0B,iCAC1BC,WAAc,+BAMjB,MAAOC,uBACHC,kBAAoB,IAAIC,IAEhC,WAAAC,GAEiD,IAA3CH,uBAAuBI,WAAWC,OACpCN,OAAOO,MAAM,kCACbN,uBAAuBI,WAAWG,IAAI,QAAS,IAAIV,sBACnDG,uBAAuBI,WAAWG,IAAI,MAAO,IAAIT,oBAErD,CAQO,YAAAU,CAAaC,GAClB,MAAMC,EAAYV,uBAAuBI,WAAWO,IAAIF,GACxD,IAAKC,EAAW,CACd,MAAME,EAAQ,gCAAgCH,IAE9C,MADAV,OAAOa,MAAMA,GACP,IAAIC,MAAMD,EAClB,CAEA,OADAb,OAAOO,MAAM,aAAaG,eACnBC,CACT,CAOO,qBAAAI,CAAsBC,GAC3B,OAAOC,KAAKR,aAAaO,EAAaN,KACxC,SAIK,MAAMQ,uBAAyB,IAAIjB","ignoreList":[]}
1
+ {"version":3,"names":["StdioServerValidator","SSEServerValidator","Logger","ServerValidatorFactory","static","Map","constructor","validators","size","debug","set","getValidator","mode","validator","get","error","Error","getValidatorForServer","serverConfig","this","serverValidatorFactory"],"sources":["../../../src/core/validators/ServerValidatorFactory.ts"],"mappings":"OAESA,yBAA4B,mCAC5BC,uBAA0B,iCAC1BC,WAAc,+BAMjB,MAAOC,uBACHC,kBAAoB,IAAIC,IAEhC,WAAAC,GAEiD,IAA3CH,uBAAuBI,WAAWC,OACpCN,OAAOO,MAAM,kCACbN,uBAAuBI,WAAWG,IAAI,QAAS,IAAIV,sBACnDG,uBAAuBI,WAAWG,IAAI,MAAO,IAAIT,oBACjDE,uBAAuBI,WAAWG,IAAI,kBAAmB,IAAIT,oBAEjE,CAQO,YAAAU,CAAaC,GAClB,MAAMC,EAAYV,uBAAuBI,WAAWO,IAAIF,GACxD,IAAKC,EAAW,CACd,MAAME,EAAQ,gCAAgCH,IAE9C,MADAV,OAAOa,MAAMA,GACP,IAAIC,MAAMD,EAClB,CAEA,OADAb,OAAOO,MAAM,aAAaG,eACnBC,CACT,CAOO,qBAAAI,CAAsBC,GAC3B,OAAOC,KAAKR,aAAaO,EAAaN,KACxC,SAIK,MAAMQ,uBAAyB,IAAIjB","ignoreList":[]}
@@ -2,7 +2,7 @@ import { DependencyConfig, RegistryConfig, ServerInstallOptions } from '../../co
2
2
  export interface OnboardServerConfig {
3
3
  name: string;
4
4
  description: string;
5
- mode: 'stdio' | 'sse';
5
+ mode: 'stdio' | 'sse' | 'streamable-http';
6
6
  schemas?: string;
7
7
  dependencies?: DependencyConfig;
8
8
  repository?: string;
@@ -1,2 +1,2 @@
1
- import{showToast,showConfirm}from"../notifications.js";import{showInstallLoadingModal,updateOverallInstallStatus}from"./loadingModal.js";import{uninstallTools}from"./installation.js";import{handleBulkClientInstall}from"./installation.js";import{compareVersions}from"./versionUtils.js";export function setupClientItems(e,t,n,s,a){e.forEach((e=>{const l=t.installedStatus[e]||{status:"not-installed",type:"check",target:"server"};let o="",i="";"completed"===l.status&&"install"===l.type?(o="Installed",i="installed"):"pending"===l.status?(o="Pending Requirements",i="pending"):"in-progress"===l.status?(o="In Progress",i="pending"):"failed"===l.status&&(o="Failed",i="not-installed");const r="completed"===l.status&&"install"===l.type,d="in-progress"===l.status,c=!r&&!d,m=createClientItem(e,o,i,c,r,d);setupClientItemListeners(m,e,c),setupUninstallButton(m,o,l,e,n,s,i),a.appendChild(m)})),addSectionTitle(a)}export function setupEnvironmentVariables(e,t,n){if("sse"===e.mode)return void(t.style.display="none");const s=e.installation?.env||e.installation?.env||{};addEnvironmentTitle(t),fetch("/api/settings").then((e=>e.json())).then((a=>{const l=a&&a.data&&a.data.userConfigurations?a.data.userConfigurations:{};0===Object.keys(s).length?addNoEnvMessage(t):createEnvironmentInputs(s,t,n.clientMcpSettings,e.name,l)})).catch((()=>{0===Object.keys(s).length?addNoEnvMessage(t):createEnvironmentInputs(s,t,n.clientMcpSettings,e.name,{})}))}export function setupInstallationArguments(e,t,n,s){if(!e)return void(t.style.display="none");if("sse"===s?.mode){t.innerHTML="";let n=!1;return e.url&&(addArgumentsTitle(t),createReadOnlyTextBox(t,"Server URL",e.url,"sse_url"),n=!0),e.startingCommand&&(n||addArgumentsTitle(t),createReadOnlyTextBox(t,"Starting Command",e.startingCommand,"sse_starting_command"),n=!0),void(n||(t.style.display="none"))}addArgumentsTitle(t);const a=createArgumentsContainer();t.appendChild(a),e.args&&Array.isArray(e.args)?e.args.forEach((e=>{a.appendChild(createArgumentInput(e))})):a.appendChild(createArgumentInput()),("python"===e.command||e.command.includes("python"))&&addPythonEnvironmentInput(n,s.name,t)}export function setupServerRequirements(e,t,n,s,a){if("sse"===e.mode)return void(a.style.display="none");const l=e.dependencies?.requirements||[],o=t.data.installationStatus?.requirementsStatus||{};if(l.length>0){const e=renderRequirements(l,o,n,s);a.innerHTML=`\n <h3 class="text-lg font-semibold text-gray-700 mb-3">Dependencies</h3>\n <p class="text-sm text-gray-600 mb-4">These dependencies will be automatically installed when installing the server</p>\n ${e}\n `,setupUpdateToggles(a)}else a.innerHTML='<p class="text-gray-600">No additional dependencies required.</p>'}export function setupFormSubmitHandler(e,t,n,s,a,l,o,i,r){e.onsubmit=e=>{e.preventDefault();const d={},c=[],m=[];let u;if("sse"!==r?.mode){t.querySelectorAll("input").forEach((e=>{e.name&&e.value&&(d[e.name]=e.value)}));const e=n.querySelectorAll(".arg-input");c.push(...Array.from(e).map((e=>e.value.trim())).filter((e=>""!==e)));const a=document.getElementById("python_env");u=a?.value?.trim();s.querySelectorAll(".toggle-update:checked").forEach((e=>{m.push({name:e.dataset.name,version:e.dataset.version})}))}function proceedInstall(){const e=m.length>0,t=document.querySelector(".uninstall-btn");if(!t||!t.matches(":active")){const t=window.selectedClients;if(0===t.length&&!e)return void showToast("Please select at least one client to configure.","error");let n="Starting installation...";const s=o[l]||{installedStatus:{}};if(t.length>0){const e=t[0],a=s.installedStatus?.[e]?.message;a&&(n=a)}const r={targetClients:t,env:d,args:c,settings:u?{pythonEnv:u}:{}};m.length>0&&(r.requirements=m),handleBulkClientInstall(a,l,t,d,n,i,r)}}fetch("/api/settings").then((e=>e.json())).then((e=>{const t=e&&e.data&&e.data.userConfigurations?e.data.userConfigurations:{},n=e&&e.data&&e.data.pythonEnvs?e.data.pythonEnvs:{},s={...t},o={...n};Object.keys(d).forEach((e=>{s[e]=d[e]}));let i=!1;const r=new Set([...Object.keys(t),...Object.keys(d)]);for(const e of r)if(t[e]!==s[e]){i=!0;break}let c=!1;if(void 0!==u&&u!==n[`${a}:${l}`]&&(o[`${a}:${l}`]=u,c=!0),i||c){const e={};i&&(e.userConfigurations=s),c&&(e.pythonEnvs=o),fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).then((()=>{proceedInstall()})).catch((()=>{proceedInstall()}))}else proceedInstall()})).catch((()=>{proceedInstall()}))}}function createClientItem(e,t,n,s,a,l){const o=document.createElement("div");o.className="client-item",o.dataset.target=e,o.dataset.selected="false";const i=document.createElement("div");i.className="client-info";const r=document.createElement("span");return r.className="text-sm font-medium text-gray-900",r.textContent=e,i.appendChild(r),o.appendChild(i),s||(o.classList.add("non-selectable"),a?(o.classList.add("installed-item"),o.title="Already installed"):l&&(o.classList.add("in-progress-item"),o.title="Installation in progress")),o}function setupClientItemListeners(e,t,n){n&&e.addEventListener("click",(()=>{const n="true"===e.dataset.selected;e.dataset.selected=n?"false":"true",n?(e.classList.remove("selected"),window.selectedClients=window.selectedClients.filter((e=>e!==t))):(e.classList.add("selected"),window.selectedClients.includes(t)||window.selectedClients.push(t))}))}function setupUninstallButton(e,t,n,s,a,l,o){if(t){const i=document.createElement("div");i.className="status-container";const r=document.createElement("span");if(r.className=`status-badge ${o}`,r.textContent=t,i.appendChild(r),"completed"===n.status&&"install"===n.type){const e=createUninstallButton(s,a,l);i.appendChild(e)}e.appendChild(i)}}function createUninstallButton(e,t,n){const s=document.createElement("button");return s.className="uninstall-btn text-red-600 hover:text-red-800 ml-2",s.innerHTML='<i class="bx bx-trash"></i>',s.title="Uninstall from this client",s.onclick=async s=>{s.stopPropagation(),s.preventDefault();if(await showConfirm("Uninstall Confirmation",`Are you sure you want to uninstall ${n} from ${e}?`)){window.selectedClients=[e],showInstallLoadingModal("Uninstalling");const s={[n]:{removeData:!0}};try{updateOverallInstallStatus("in-progress",`Uninstalling ${n} from ${e}...`),await uninstallTools(t,s,[e])}catch(e){updateOverallInstallStatus("failed",`Error during uninstall: ${e.message}`)}}return!1},s}function addSectionTitle(e){if(!e.querySelector(".section-title")){const t=document.createElement("h3");t.className="section-title text-lg font-semibold text-gray-700 mb-3",t.textContent="Client Status",e.insertBefore(t,e.firstChild)}}function addEnvironmentTitle(e){if(!e.querySelector(".section-title")){const t=document.createElement("h3");t.className="section-title text-lg font-semibold text-gray-700 mb-3",t.textContent="Environment Variables",e.insertBefore(t,e.firstChild)}}function addNoEnvMessage(e){const t=document.createElement("p");t.className="text-gray-600",t.textContent="No environment variables required for this MCP server.",e.appendChild(t)}function createEnvironmentInputs(e,t,n,s,a={}){Object.keys(e).forEach((l=>{const o=e[l],i=`env_${l}`,r=document.createElement("div");r.className="mb-3";const d=document.createElement("label");d.htmlFor=i,d.className="block text-sm font-medium text-gray-700 mb-1",d.innerHTML=`${l} ${o.Required?'<span class="text-red-500">*</span>':""}`;const c=document.createElement("input");c.type=o.isSecret?"password":"text",c.id=i,c.name=l,c.placeholder=o.Description||l,c.required=o.Required,c.className="input-field";let m=o.Default||"";if(a&&a[l]?m=a[l]:n&&n.MSRooCode&&n.MSRooCode.mcpServers&&n.MSRooCode.mcpServers[s]&&n.MSRooCode.mcpServers[s].env&&n.MSRooCode.mcpServers[s].env[l]&&(m=n.MSRooCode.mcpServers[s].env[l]),c.value=m,r.appendChild(d),r.appendChild(c),o.Description){const e=document.createElement("p");e.className="text-xs text-gray-500 mt-1",e.textContent=o.Description,r.appendChild(e)}t.appendChild(r)}))}function addArgumentsTitle(e){const t=document.createElement("h3");t.className="section-title text-lg font-semibold text-gray-700 mb-3",t.textContent="Arguments",e.appendChild(t)}function createArgumentsContainer(){const e=document.createElement("div");e.className="args-container mb-3";const t=document.createElement("button");return t.type="button",t.className="add-arg-button px-3 py-1 text-sm text-blue-600 hover:text-blue-800 border border-blue-600 hover:border-blue-800 rounded-md mb-2",t.innerHTML='<i class="bx bx-plus"></i> Add Argument',t.onclick=()=>e.appendChild(createArgumentInput()),e.appendChild(t),e}function createArgumentInput(e=""){const t=document.createElement("div");t.className="arg-wrapper flex items-center gap-2 mb-2";const n=document.createElement("input");n.type="text",n.className="arg-input flex-grow",n.value=e,n.placeholder="Enter argument value";const s=document.createElement("button");return s.type="button",s.className="remove-arg-button text-red-600 hover:text-red-800",s.innerHTML='<i class="bx bx-trash"></i>',s.onclick=()=>t.remove(),t.appendChild(n),t.appendChild(s),t}function createReadOnlyTextBox(e,t,n,s){const a=document.createElement("div");a.className="mb-3 sse-info-field";const l=document.createElement("label");l.htmlFor=s,l.className="block text-sm font-medium text-gray-700 mb-1",l.textContent=t;const o=document.createElement("input");o.type="text",o.id=s,o.value=n,o.readOnly=!0,o.className="input-field sse-input-readonly w-full",a.appendChild(l),a.appendChild(o),e.appendChild(a)}function addPythonEnvironmentInput(e,t,n){const s=document.createElement("div");s.className="mt-4";const a=document.createElement("label");a.htmlFor="python_env",a.className="block text-sm font-medium text-gray-700 mb-1",a.textContent="Python Environment";const l=document.createElement("input");l.type="text",l.id="python_env",l.className="input-field",l.placeholder="Enter Python environment path (optional)";const o=document.createElement("p");o.className="text-xs text-gray-500 mt-1",o.textContent="Specify the Python exectable file(e.g. C:/python312/python) to use for installation. Leave empty to use system default. You can specify value in Settings page",s.appendChild(a),s.appendChild(l),s.appendChild(o),n.appendChild(s),fetch("/api/settings").then((e=>e.json())).then((n=>{n&&n.data&&n.data.pythonEnvs&&(l.value=n.data.pythonEnvs[`${e}:${t}`]||n.data.pythonEnvs.system||"")})).catch((()=>{}))}function renderRequirements(e,t,n,s){return e.map((e=>{const a=t[e.name]||{};let l=a.installed?"text-green-600 bg-green-50":"text-yellow-600 bg-yellow-50",o=a.installed?"Installed":"Required",i=a.version?` • <span class="font-medium">${a.version}</span>`:"",r="";return a.installed&&a.availableUpdate&&a.availableUpdate.version&&a.version&&compareVersions(a.availableUpdate.version,a.version)>0&&(l="text-yellow-600 bg-yellow-50",o=`<span style="color: #f59e0b; font-weight: bold; margin-right: 5px;">↑</span>${a.availableUpdate.version}`,r=`\n <label class="inline-flex items-center cursor-pointer ml-2">\n <input type="checkbox" class="toggle-update sr-only"\n data-name="${e.name}"\n data-version="${a.availableUpdate.version}"\n data-category="${n}"\n data-server="${s}">\n <div class="relative w-10 h-5 bg-gray-200 rounded-full toggle-bg">\n <div class="absolute inset-y-0 left-0 w-5 h-5 bg-white rounded-full transition-transform duration-300 transform"></div>\n </div>\n <span class="ml-2 text-sm text-gray-700">Update</span>\n </label>\n `),`\n <div class="border border-gray-200 p-3 rounded-lg mb-2 hover:bg-gray-50">\n <div class="flex justify-between items-center">\n <div>\n <div class="font-semibold text-gray-800">${e.name}</div>\n <div class="text-sm text-gray-600 shadow-sm p-1 rounded bg-gray-50">\n <span class="font-medium">${a.type||"package"}</span>${i}\n </div>\n </div>\n <div class="flex items-center">\n <span class="${l} inline-flex items-center px-3 py-1 rounded-full text-sm">\n ${o}\n </span>\n ${r}\n </div>\n </div>\n </div>\n `})).join("")}function setupUpdateToggles(e){e.querySelectorAll(".toggle-update").forEach((e=>{e.addEventListener("change",(function(){const e=this.parentElement.querySelector(".toggle-bg");this.checked?(e.classList.add("bg-blue-500"),e.querySelector("div").classList.add("translate-x-5")):(e.classList.remove("bg-blue-500"),e.querySelector("div").classList.remove("translate-x-5"))}))}))}
1
+ import{showToast,showConfirm}from"../notifications.js";import{showInstallLoadingModal,updateOverallInstallStatus}from"./loadingModal.js";import{uninstallTools}from"./installation.js";import{handleBulkClientInstall}from"./installation.js";import{compareVersions}from"./versionUtils.js";export function setupClientItems(e,t,n,a,s){e.forEach((e=>{const l=t.installedStatus[e]||{status:"not-installed",type:"check",target:"server"};let o="",i="";"completed"===l.status&&"install"===l.type?(o="Installed",i="installed"):"pending"===l.status?(o="Pending Requirements",i="pending"):"in-progress"===l.status?(o="In Progress",i="pending"):"failed"===l.status&&(o="Failed",i="not-installed");const r="completed"===l.status&&"install"===l.type,d="in-progress"===l.status,c=!r&&!d,m=createClientItem(e,o,i,c,r,d);setupClientItemListeners(m,e,c),setupUninstallButton(m,o,l,e,n,a,i),s.appendChild(m)})),addSectionTitle(s)}export function setupEnvironmentVariables(e,t,n){if("sse"===e.mode||"streamable-http"===e.mode)return void(t.style.display="none");const a=e.installation?.env||e.installation?.env||{};addEnvironmentTitle(t),fetch("/api/settings").then((e=>e.json())).then((s=>{const l=s&&s.data&&s.data.userConfigurations?s.data.userConfigurations:{};0===Object.keys(a).length?addNoEnvMessage(t):createEnvironmentInputs(a,t,n.clientMcpSettings,e.name,l)})).catch((()=>{0===Object.keys(a).length?addNoEnvMessage(t):createEnvironmentInputs(a,t,n.clientMcpSettings,e.name,{})}))}export function setupInstallationArguments(e,t,n,a){if(!e)return void(t.style.display="none");if("sse"===a?.mode||"streamable-http"===a?.mode){t.innerHTML="";let n=!1;return e.url&&(addArgumentsTitle(t),createReadOnlyTextBox(t,"Server URL",e.url,"sse_url"),n=!0),e.startingCommand&&(n||addArgumentsTitle(t),createReadOnlyTextBox(t,"Starting Command",e.startingCommand,"sse_starting_command"),n=!0),void(n||(t.style.display="none"))}addArgumentsTitle(t);const s=createArgumentsContainer();t.appendChild(s),e.args&&Array.isArray(e.args)?e.args.forEach((e=>{s.appendChild(createArgumentInput(e))})):s.appendChild(createArgumentInput()),("python"===e.command||e.command.includes("python"))&&addPythonEnvironmentInput(n,a.name,t)}export function setupServerRequirements(e,t,n,a,s){if("sse"===e.mode||"streamable-http"===e.mode)return void(s.style.display="none");const l=e.dependencies?.requirements||[],o=t.data.installationStatus?.requirementsStatus||{};if(l.length>0){const e=renderRequirements(l,o,n,a);s.innerHTML=`\n <h3 class="text-lg font-semibold text-gray-700 mb-3">Dependencies</h3>\n <p class="text-sm text-gray-600 mb-4">These dependencies will be automatically installed when installing the server</p>\n ${e}\n `,setupUpdateToggles(s)}else s.innerHTML='<p class="text-gray-600">No additional dependencies required.</p>'}export function setupFormSubmitHandler(e,t,n,a,s,l,o,i,r){e.onsubmit=e=>{e.preventDefault();const d={},c=[],m=[];let u;if("sse"!==r?.mode&&"streamable-http"!==r?.mode){t.querySelectorAll("input").forEach((e=>{e.name&&e.value&&(d[e.name]=e.value)}));const e=n.querySelectorAll(".arg-input");c.push(...Array.from(e).map((e=>e.value.trim())).filter((e=>""!==e)));const s=document.getElementById("python_env");u=s?.value?.trim();a.querySelectorAll(".toggle-update:checked").forEach((e=>{m.push({name:e.dataset.name,version:e.dataset.version})}))}function proceedInstall(){const e=m.length>0,t=document.querySelector(".uninstall-btn");if(!t||!t.matches(":active")){const t=window.selectedClients;if(0===t.length&&!e)return void showToast("Please select at least one client to configure.","error");let n="Starting installation...";const a=o[l]||{installedStatus:{}};if(t.length>0){const e=t[0],s=a.installedStatus?.[e]?.message;s&&(n=s)}const r={targetClients:t,env:d,args:c,settings:u?{pythonEnv:u}:{}};m.length>0&&(r.requirements=m),handleBulkClientInstall(s,l,t,d,n,i,r)}}fetch("/api/settings").then((e=>e.json())).then((e=>{const t=e&&e.data&&e.data.userConfigurations?e.data.userConfigurations:{},n=e&&e.data&&e.data.pythonEnvs?e.data.pythonEnvs:{},a={...t},o={...n};Object.keys(d).forEach((e=>{a[e]=d[e]}));let i=!1;const r=new Set([...Object.keys(t),...Object.keys(d)]);for(const e of r)if(t[e]!==a[e]){i=!0;break}let c=!1;if(void 0!==u&&u!==n[`${s}:${l}`]&&(o[`${s}:${l}`]=u,c=!0),i||c){const e={};i&&(e.userConfigurations=a),c&&(e.pythonEnvs=o),fetch("/api/settings",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).then((()=>{proceedInstall()})).catch((()=>{proceedInstall()}))}else proceedInstall()})).catch((()=>{proceedInstall()}))}}function createClientItem(e,t,n,a,s,l){const o=document.createElement("div");o.className="client-item",o.dataset.target=e,o.dataset.selected="false";const i=document.createElement("div");i.className="client-info";const r=document.createElement("span");return r.className="text-sm font-medium text-gray-900",r.textContent=e,i.appendChild(r),o.appendChild(i),a||(o.classList.add("non-selectable"),s?(o.classList.add("installed-item"),o.title="Already installed"):l&&(o.classList.add("in-progress-item"),o.title="Installation in progress")),o}function setupClientItemListeners(e,t,n){n&&e.addEventListener("click",(()=>{const n="true"===e.dataset.selected;e.dataset.selected=n?"false":"true",n?(e.classList.remove("selected"),window.selectedClients=window.selectedClients.filter((e=>e!==t))):(e.classList.add("selected"),window.selectedClients.includes(t)||window.selectedClients.push(t))}))}function setupUninstallButton(e,t,n,a,s,l,o){if(t){const i=document.createElement("div");i.className="status-container";const r=document.createElement("span");if(r.className=`status-badge ${o}`,r.textContent=t,i.appendChild(r),"completed"===n.status&&"install"===n.type){const e=createUninstallButton(a,s,l);i.appendChild(e)}e.appendChild(i)}}function createUninstallButton(e,t,n){const a=document.createElement("button");return a.className="uninstall-btn text-red-600 hover:text-red-800 ml-2",a.innerHTML='<i class="bx bx-trash"></i>',a.title="Uninstall from this client",a.onclick=async a=>{a.stopPropagation(),a.preventDefault();if(await showConfirm("Uninstall Confirmation",`Are you sure you want to uninstall ${n} from ${e}?`)){window.selectedClients=[e],showInstallLoadingModal("Uninstalling");const a={[n]:{removeData:!0}};try{updateOverallInstallStatus("in-progress",`Uninstalling ${n} from ${e}...`),await uninstallTools(t,a,[e])}catch(e){updateOverallInstallStatus("failed",`Error during uninstall: ${e.message}`)}}return!1},a}function addSectionTitle(e){if(!e.querySelector(".section-title")){const t=document.createElement("h3");t.className="section-title text-lg font-semibold text-gray-700 mb-3",t.textContent="Client Status",e.insertBefore(t,e.firstChild)}}function addEnvironmentTitle(e){if(!e.querySelector(".section-title")){const t=document.createElement("h3");t.className="section-title text-lg font-semibold text-gray-700 mb-3",t.textContent="Environment Variables",e.insertBefore(t,e.firstChild)}}function addNoEnvMessage(e){const t=document.createElement("p");t.className="text-gray-600",t.textContent="No environment variables required for this MCP server.",e.appendChild(t)}function createEnvironmentInputs(e,t,n,a,s={}){Object.keys(e).forEach((l=>{const o=e[l],i=`env_${l}`,r=document.createElement("div");r.className="mb-3";const d=document.createElement("label");d.htmlFor=i,d.className="block text-sm font-medium text-gray-700 mb-1",d.innerHTML=`${l} ${o.Required?'<span class="text-red-500">*</span>':""}`;const c=document.createElement("input");c.type=o.isSecret?"password":"text",c.id=i,c.name=l,c.placeholder=o.Description||l,c.required=o.Required,c.className="input-field";let m=o.Default||"";if(s&&s[l]?m=s[l]:n&&n.MSRooCode&&n.MSRooCode.mcpServers&&n.MSRooCode.mcpServers[a]&&n.MSRooCode.mcpServers[a].env&&n.MSRooCode.mcpServers[a].env[l]&&(m=n.MSRooCode.mcpServers[a].env[l]),c.value=m,r.appendChild(d),r.appendChild(c),o.Description){const e=document.createElement("p");e.className="text-xs text-gray-500 mt-1",e.textContent=o.Description,r.appendChild(e)}t.appendChild(r)}))}function addArgumentsTitle(e){const t=document.createElement("h3");t.className="section-title text-lg font-semibold text-gray-700 mb-3",t.textContent="Arguments",e.appendChild(t)}function createArgumentsContainer(){const e=document.createElement("div");e.className="args-container mb-3";const t=document.createElement("button");return t.type="button",t.className="add-arg-button px-3 py-1 text-sm text-blue-600 hover:text-blue-800 border border-blue-600 hover:border-blue-800 rounded-md mb-2",t.innerHTML='<i class="bx bx-plus"></i> Add Argument',t.onclick=()=>e.appendChild(createArgumentInput()),e.appendChild(t),e}function createArgumentInput(e=""){const t=document.createElement("div");t.className="arg-wrapper flex items-center gap-2 mb-2";const n=document.createElement("input");n.type="text",n.className="arg-input flex-grow",n.value=e,n.placeholder="Enter argument value";const a=document.createElement("button");return a.type="button",a.className="remove-arg-button text-red-600 hover:text-red-800",a.innerHTML='<i class="bx bx-trash"></i>',a.onclick=()=>t.remove(),t.appendChild(n),t.appendChild(a),t}function createReadOnlyTextBox(e,t,n,a){const s=document.createElement("div");s.className="mb-3 sse-info-field";const l=document.createElement("label");l.htmlFor=a,l.className="block text-sm font-medium text-gray-700 mb-1",l.textContent=t;const o=document.createElement("input");o.type="text",o.id=a,o.value=n,o.readOnly=!0,o.className="input-field sse-input-readonly w-full",s.appendChild(l),s.appendChild(o),e.appendChild(s)}function addPythonEnvironmentInput(e,t,n){const a=document.createElement("div");a.className="mt-4";const s=document.createElement("label");s.htmlFor="python_env",s.className="block text-sm font-medium text-gray-700 mb-1",s.textContent="Python Environment";const l=document.createElement("input");l.type="text",l.id="python_env",l.className="input-field",l.placeholder="Enter Python environment path (optional)";const o=document.createElement("p");o.className="text-xs text-gray-500 mt-1",o.textContent="Specify the Python exectable file(e.g. C:/python312/python) to use for installation. Leave empty to use system default. You can specify value in Settings page",a.appendChild(s),a.appendChild(l),a.appendChild(o),n.appendChild(a),fetch("/api/settings").then((e=>e.json())).then((n=>{n&&n.data&&n.data.pythonEnvs&&(l.value=n.data.pythonEnvs[`${e}:${t}`]||n.data.pythonEnvs.system||"")})).catch((()=>{}))}function renderRequirements(e,t,n,a){return e.map((e=>{const s=t[e.name]||{};let l=s.installed?"text-green-600 bg-green-50":"text-yellow-600 bg-yellow-50",o=s.installed?"Installed":"Required",i=s.version?` • <span class="font-medium">${s.version}</span>`:"",r="";return s.installed&&s.availableUpdate&&s.availableUpdate.version&&s.version&&compareVersions(s.availableUpdate.version,s.version)>0&&(l="text-yellow-600 bg-yellow-50",o=`<span style="color: #f59e0b; font-weight: bold; margin-right: 5px;">↑</span>${s.availableUpdate.version}`,r=`\n <label class="inline-flex items-center cursor-pointer ml-2">\n <input type="checkbox" class="toggle-update sr-only"\n data-name="${e.name}"\n data-version="${s.availableUpdate.version}"\n data-category="${n}"\n data-server="${a}">\n <div class="relative w-10 h-5 bg-gray-200 rounded-full toggle-bg">\n <div class="absolute inset-y-0 left-0 w-5 h-5 bg-white rounded-full transition-transform duration-300 transform"></div>\n </div>\n <span class="ml-2 text-sm text-gray-700">Update</span>\n </label>\n `),`\n <div class="border border-gray-200 p-3 rounded-lg mb-2 hover:bg-gray-50">\n <div class="flex justify-between items-center">\n <div>\n <div class="font-semibold text-gray-800">${e.name}</div>\n <div class="text-sm text-gray-600 shadow-sm p-1 rounded bg-gray-50">\n <span class="font-medium">${s.type||"package"}</span>${i}\n </div>\n </div>\n <div class="flex items-center">\n <span class="${l} inline-flex items-center px-3 py-1 rounded-full text-sm">\n ${o}\n </span>\n ${r}\n </div>\n </div>\n </div>\n `})).join("")}function setupUpdateToggles(e){e.querySelectorAll(".toggle-update").forEach((e=>{e.addEventListener("change",(function(){const e=this.parentElement.querySelector(".toggle-bg");this.checked?(e.classList.add("bg-blue-500"),e.querySelector("div").classList.add("translate-x-5")):(e.classList.remove("bg-blue-500"),e.querySelector("div").classList.remove("translate-x-5"))}))}))}
2
2
  //# sourceMappingURL=modalSetup.js.map
@@ -1,2 +1,2 @@
1
- import{showToast}from"../notifications.js";import{state,setServerCounter,getServerCounter,clearEnvCountersForTab,clearServerRequirementCountersForTab}from"./state.js";function setupRealTimeValidation(e){const t=document.getElementById(e);if(!t)return;if(!t)return;const r=t.querySelector('input[name="name"]');r&&r.addEventListener("input",(e=>{const t=e.target.value.trim();t?/^[a-zA-Z0-9-_]+$/.test(t)?t.length>50?showValidationMessage(e.target,"Must not exceed 50 characters"):showValidationMessage(e.target,"Valid name",!1):showValidationMessage(e.target,"Only alphanumeric characters, hyphens, and underscores allowed"):showValidationMessage(e.target,"Name is required")}));const s=t.querySelector('input[name="displayName"]');s&&s.addEventListener("input",(e=>{const t=e.target.value.trim();t?t.length>100?showValidationMessage(e.target,"Must not exceed 100 characters"):showValidationMessage(e.target,"Valid display name",!1):showValidationMessage(e.target,"Display name is required")}));const a=t.querySelector('textarea[name="description"]');a&&a.addEventListener("input",(e=>{const t=e.target.value.trim();t.length>500?showValidationMessage(e.target,"Must not exceed 500 characters"):0===t.length?showValidationMessage(e.target,"Description is required"):showValidationMessage(e.target,"Valid description",!1)}));const n=t.querySelector('input[name="repository"]');n&&n.addEventListener("input",(e=>{const t=e.target.value.trim();if(t)try{new URL(t),showValidationMessage(e.target,"Valid URL",!1)}catch(t){showValidationMessage(e.target,"Invalid URL format")}else e.target.nextElementSibling?.remove()})),t.addEventListener("change",(e=>{if(e.target.name?.match(/servers\[\d+\]\.mode/)){const r=e.target.name.match(/servers\[(\d+)\]/)[1],s=t.querySelector(`[name="servers[${r}].installation.command"]`),a=t.querySelector(`[name="servers[${r}].installation.url"]`),n=t.querySelector(`[name="servers[${r}].installation.args"]`);"stdio"===e.target.value?(s&&(s.required=!0,showValidationMessage(s,"Command is required for stdio mode")),a&&(a.required=!1,a.value="",a.nextElementSibling?.remove())):"sse"===e.target.value&&(a&&(a.required=!0,showValidationMessage(a,"URL is required for sse mode")),s&&(s.required=!1,s.value="",s.nextElementSibling?.remove()),n&&(n.value="",n.nextElementSibling?.remove()))}})),t.addEventListener("input",(e=>{if(e.target.name?.includes(".installation.env[")){const t=e.target.name.match(/servers\[(\d+)\]\.installation\.env\[(\d+)\]\.(name|default)/);if(t){const[,r,s,a]=t;if("name"===a){const t=e.target.value.trim();t?/^[A-Z_][A-Z0-9_]*$/.test(t)?t.length>50?showValidationMessage(e.target,"Must not exceed 50 characters"):showValidationMessage(e.target,"Valid name",!1):showValidationMessage(e.target,"Must be uppercase with only letters, numbers, and underscores"):showValidationMessage(e.target,"Environment variable name is required")}}}}))}export async function submitForm(e,t,r=null){e.preventDefault();const s=e.target;let a,n=!1;if("create-category"===t)try{a=formDataToFeedConfiguration(s);const e=new URLSearchParams(window.location.search);n="edit"===e.get("action")&&e.get("category")===a.name}catch(e){return void console.error("Validation error:",e)}else{if("create-server"!==t)return void showToast("Invalid tab context for submission.","error");{if(!r||!r.name)return void showToast("No existing category selected or category data is missing.","error");const e=formDataToFeedConfiguration(s,!0,r);a=JSON.parse(JSON.stringify(r)),a.mcpServers=e.mcpServers||[];const t=new Set((a.requirements||[]).map((e=>`${e.type}|${e.name}|${e.version}`)));(e.requirements||[]).forEach((e=>{const r=`${e.type}|${e.name}|${e.version}`;t.has(r)||(a.requirements.push(e),t.add(r))})),n=!0}}try{const e=await fetch("/api/categories/onboard",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({categoryData:a,isUpdate:n})});if(!e.ok){const t=await e.json().catch((()=>({error:"Failed to parse error response"})));throw new Error(`HTTP error! status: ${e.status}, message: ${t.error||e.statusText}`)}await e.json();showToast("Form submitted successfully! See console for operation details.","success")}catch(e){console.error("Error submitting form:",e),showToast(`Error submitting form: ${e.message}. Please try again.`,"error")}}export function getFormData(e,t=!1,r=null){return formDataToFeedConfiguration(e,t,r)}function validateServerConfig(e){const t=[];if(e.name?/^[a-zA-Z0-9-_]+$/.test(e.name)?e.name.length>50&&t.push("Server name must not exceed 50 characters"):t.push("Server name must only contain alphanumeric characters, hyphens, and underscores"):t.push("Server name is required"),e.description&&""!==e.description.trim()?e.description.length>200&&t.push("Server description must not exceed 200 characters"):t.push("Server description is required"),e.mode?["stdio","sse"].includes(e.mode)||t.push('Server mode must be either "stdio" or "sse"'):t.push("Server mode is required"),"stdio"===e.mode)e.installation?.command?/^[a-zA-Z0-9-_.\\/]+$/.test(e.installation.command)||t.push("Command must only contain alphanumeric characters, hyphens, underscores, dots, and slashes"):t.push("Command is required for stdio server"),e.installation?.args?.length>0&&e.installation.args.forEach(((e,r)=>{/^[a-zA-Z0-9-_./\\]+$/.test(e)||t.push(`Argument ${r+1} must only contain alphanumeric characters, hyphens, underscores, dots, and slashes`)}));else if("sse"===e.mode)if(e.installation?.url)try{new URL(e.installation.url)}catch(e){t.push("Invalid URL format")}else t.push("URL is required for sse server");if(e.installation?.env&&Object.entries(e.installation.env).forEach((([e,r])=>{e?/^[A-Z_][A-Z0-9_]*$/.test(e)?e.length>50&&t.push(`Environment variable name "${e}" must not exceed 50 characters`):t.push(`Environment variable name "${e}" must be uppercase with only letters, numbers, and underscores`):t.push("Environment variable name is required"),r.Required&&!r.Default&&t.push(`Required environment variable "${e}" should have a default value`),r.Description&&r.Description.length>200&&t.push(`Description for environment variable "${e}" must not exceed 200 characters`)})),e.schemas)try{JSON.parse(e.schemas)}catch(e){t.push("Invalid JSON format in schemas")}return t}export function formDataToFeedConfiguration(e,t=!1,r=null){const s=new FormData(e),a={requirements:[],mcpServers:[]};let n;"onboardForm"===e.id?n="serversList":"onboardServerForm"===e.id?n="existingCategoryServersList":console.warn("[formDataToFeedConfiguration] Could not determine serversListId from formElement.id:",e.id),t?r&&(a.name=r.name):(a.name=s.get("name")||"",a.displayName=s.get("displayName")||"",a.description=s.get("description")||"",a.repository=s.get("repository")||void 0);const i=new Map,o=new Map;for(const[e,r]of s.entries()){if(t&&!e.startsWith("servers["))continue;const a=e.match(/^servers\[(\d+)\]\.(.+)$/);if(a){let t=parseInt(a[1],10);const n=a[2];let o=t;i.has(o)||i.set(o,{installation:{env:new Map},dependencies:{requirements:new Map},isNew:!0});const l=i.get(o);if("name"===n)l.name=r;else if("description"===n)l.description=r;else if("mode"===n)l.mode=r;else if("repository"===n)l.repository=r||void 0;else if("schemas"===n)l.schemas=r||void 0;else if("installation.command"===n)l.installation.command=r;else if("installation.args"===n)l.installation.args=r?r.split(",").map((e=>e.trim())).filter((e=>e)):[];else if("installation.url"===n)l.installation.url=r;else if("installation.isLocal"===n)l.installation.isLocal="on"===r;else if("installation.startingCommand"===n)l.installation.startingCommand=r.trim()||void 0;else if(n.startsWith("installation.env[")){const t=n.match(/^installation\.env\[(\d+)\]\.(name|default|required|description)$/);if(t){const a=parseInt(t[1],10),n=t[2];l.installation.env.has(a)||l.installation.env.set(a,{});const i=l.installation.env.get(a);i[n]="required"===n?"on"===s.get(e):r||void 0}}else if(n.startsWith("requirements[")){const e=n.match(/^requirements\[(\d+)\]\.(.+)$/);if(e){const t=parseInt(e[1],10),s=e[2];l.dependencies.requirements.has(t)||l.dependencies.requirements.set(t,{registry:{}});const a=l.dependencies.requirements.get(t);"name"===s?a.name=r:"type"===s?a.type=r:"version"===s?a.version=r:"order"===s?a.order=r?parseInt(r,10):void 0:"alias"===s?a.alias=r||void 0:"registryType"===s?a.registryType=r:s.startsWith("registry.githubRelease.")?(a.registry.githubRelease=a.registry.githubRelease||{},a.registry.githubRelease[s.substring(23)]=r||void 0):s.startsWith("registry.artifacts.")?(a.registry.artifacts=a.registry.artifacts||{},a.registry.artifacts[s.substring(19)]=r||void 0):s.startsWith("registry.local.")&&(a.registry.local=a.registry.local||{},a.registry.local[s.substring(15)]=r||void 0)}}}}i.forEach(((t,r)=>{let s;if("sse"===t.mode)s={name:t.name,description:t.description,mode:t.mode,schemas:t.schemas,repository:t.repository,installation:{url:t.installation.url||""},dependencies:{requirements:[]}},t.installation.isLocal&&t.installation.startingCommand&&(s.installation.startingCommand=t.installation.startingCommand);else{s={name:t.name,description:t.description,mode:t.mode,schemas:t.schemas,repository:t.repository,installation:{command:t.installation.command,args:t.installation.args||[],env:{}},dependencies:{requirements:[]}};const e={};t.installation.env.forEach((t=>{t.name&&(e[t.name]={Required:t.required||!1,Description:t.description||"",Default:t.default||void 0})})),Object.keys(e).length>0?s.installation.env=e:delete s.installation.env}if(t.dependencies.requirements.forEach((e=>{if(!e.name||!e.type||!e.version)return;const t={name:e.name,type:e.type,version:e.version,alias:e.alias,order:e.order};e.registryType&&"public"!==e.registryType&&(t.registry={},"github"===e.registryType&&e.registry.githubRelease?t.registry.githubRelease={repository:e.registry.githubRelease.repository,assetsName:e.registry.githubRelease.assetsName,assetName:e.registry.githubRelease.assetName}:"artifacts"===e.registryType&&e.registry.artifacts?t.registry.artifacts={registryUrl:e.registry.artifacts.registryUrl,registryName:e.registry.artifacts.registryName}:"local"===e.registryType&&e.registry.local&&(t.registry.local={localPath:e.registry.local.localPath,assetName:e.registry.local.assetName}),t.registry.githubRelease&&!t.registry.githubRelease.repository&&delete t.registry.githubRelease,t.registry.artifacts&&!t.registry.artifacts.registryUrl&&delete t.registry.artifacts,t.registry.local&&!t.registry.local.localPath&&delete t.registry.local,0===Object.keys(t.registry).length&&delete t.registry),s.dependencies.requirements.push({name:e.name,version:e.version,order:e.order});const r=`${e.type}|${e.name}|${e.version}`;if(!o.has(r)){const{order:e,...s}=t;o.set(r,s)}})),0===s.dependencies.requirements.length&&delete s.dependencies,"onboardServerForm"===e.id&&n){const t=`#${n} .server-item[data-index="${serverIndex}"]`,r=document.querySelector(t);if(r&&r.dataset.systemTags)try{s.systemTags=JSON.parse(r.dataset.systemTags)}catch(t){console.error(`[formDataToFeedConfiguration] Error parsing systemTags for server index ${serverIndex} ('${s.name}') on ${e.id}:`,t,r.dataset.systemTags),s.systemTags={parseError:!0}}}else delete s.systemTags;a.mcpServers.push(s)})),t&&r&&Array.isArray(r.mcpServers)&&r.mcpServers.forEach((e=>{a.mcpServers.some((t=>t.name===e.name))||e.systemTags&&"true"===e.systemTags.adhoc||(a.mcpServers.push(JSON.parse(JSON.stringify(e))),e.dependencies&&Array.isArray(e.dependencies.requirements)&&e.dependencies.requirements.forEach((t=>{const s=r.requirements?.find((e=>e.name===t.name&&e.type&&e.version===t.version));if(s){const e=`${s.type}|${s.name}|${s.version}`;o.has(e)||o.set(e,JSON.parse(JSON.stringify(s)))}else{const s=r.requirements?.find((e=>e.name===t.name&&e.version===t.version));if(s&&s.type){const e=`${s.type}|${t.name}|${t.version}`;o.has(e)||o.set(e,{name:t.name,version:t.version,type:s.type})}else console.warn(`Could not find full global requirement definition (or type) for ${t.name} v${t.version} from original server ${e.name}`)}})))})),a.requirements=Array.from(o.values());const l=[];if(t||(a.name?/^[a-zA-Z0-9-_]+$/.test(a.name)||l.push("Category name must only contain alphanumeric characters, hyphens, and underscores"):l.push("Category name is required"),a.displayName||l.push("Display name is required")),a.mcpServers.forEach(((e,t)=>{const r=validateServerConfig(e);r.length>0&&l.push(`Server ${t+1} (${e.name||"unnamed"}): ${r.join(", ")}`)})),a.requirements.forEach(((e,t)=>{if(e.name&&e.type&&e.version||l.push(`Requirement ${t+1}: name, type, and version are required`),e.registry){const r=Object.keys(e.registry)[0];["githubRelease","artifacts","local"].includes(r)||l.push(`Requirement ${t+1}: Invalid registry type ${r}`)}})),l.length>0){e.querySelectorAll(".validation-error-message").forEach((e=>e.remove()));l.forEach((t=>{let r=null;if(t.includes("Category name")?r='input[name="name"]':t.includes("Display name")&&(r='input[name="displayName"]'),r){const s=e.querySelector(r);if(s){const e=document.createElement("div");e.className="validation-error-message text-red-500 text-xs mt-1",e.textContent=t,s.insertAdjacentElement("afterend",e)}}}))}return a}export function populateForm(e,t="onboardForm",r=!1,s=null){const a=document.getElementById(t);if(!a)return void console.error(`populateForm: Form with ID "${t}" not found.`);const n=s||("onboardForm"===t?"serversList":"existingCategoryServersList");if(resetOnboardFormDynamicContent(t,n),setupRealTimeValidation(t),e){if("onboardForm"===t){a.querySelector('[name="name"]').value=e.name||"",a.querySelector('[name="displayName"]').value=e.displayName||"",a.querySelector('[name="description"]').value=e.description||"",e.repository&&(a.querySelector('[name="repository"]').value=e.repository);const t=new URLSearchParams(window.location.search);if("edit"===t.get("action")&&t.get("category")===e.name){const e=a.querySelector('[name="name"]');e&&(e.readOnly=!0,e.classList.add("bg-gray-100","cursor-not-allowed"))}}else if("onboardServerForm"===t&&e){a.querySelector('input[name="name"]').value=e.name||"",a.querySelector('input[name="displayName"]').value=e.displayName||"",a.querySelector('textarea[name="description"]').value=e.description||"",a.querySelector('input[name="repository"]').value=e.repository||"";const t=document.getElementById("existingCategoryBasicInfoContainer");t&&t.classList.remove("hidden");const r=document.getElementById("existingCategoryMcpServersContainer");r&&r.classList.remove("hidden")}setServerCounter(n,0),clearEnvCountersForTab(n),clearServerRequirementCountersForTab(n),(e.mcpServers||[]).forEach((s=>{const i=getServerCounter(n);window.addServer(n,r,s);const o=a.querySelector(`#${n} .server-item[data-index="${i}"]`);if(o)if("onboardServerForm"===t)if("true"===s.systemTags?.adhoc)o.dataset.systemTags=JSON.stringify(s.systemTags);else if(state.originalServerNamesForFormPopulation&&s.name&&state.originalServerNamesForFormPopulation.has(s.name))o.dataset.systemTags=JSON.stringify({adhoc:"true"});else if(s.systemTags&&Object.keys(s.systemTags).length>0){const e={...s.systemTags};delete e.adhoc,Object.keys(e).length>0?o.dataset.systemTags=JSON.stringify(e):delete o.dataset.systemTags}else delete o.dataset.systemTags;else s.systemTags?o.dataset.systemTags=JSON.stringify(s.systemTags):delete o.dataset.systemTags;const l=a.querySelector(`[name="servers[${i}].name"]`);l&&(l.value=s.name||"");const m=a.querySelector(`[name="servers[${i}].mode"]`);m&&(m.value=s.mode||"stdio","function"==typeof window.renderInstallationConfig&&window.renderInstallationConfig(i,n,s.mode||"stdio",r,s.installation));const c=a.querySelector(`[name="servers[${i}].description"]`);if(c&&(c.value=s.description||""),s.schemas){const e=document.getElementById(`schema-path-${i}`);e&&(e.value=s.schemas)}if(s.repository){const e=a.querySelector(`[name="servers[${i}].repository"]`);e&&(e.value=s.repository)}if(s.installation)if("sse"===s.mode){const e=a.querySelector(`[name="servers[${i}].installation.url"]`);e&&(e.value=s.installation.url||"")}else{const e=a.querySelector(`[name="servers[${i}].installation.command"]`);if(e&&(e.value=s.installation.command||""),s.installation.args&&Array.isArray(s.installation.args)){const e=a.querySelector(`[name="servers[${i}].installation.args"]`);e&&(e.value=s.installation.args.join(", "))}s.installation.env&&Object.entries(s.installation.env).forEach((([e,t])=>{const s=window.addEnvVariable(i,n,r),o=a.querySelector(`[name="servers[${i}].installation.env[${s}].name"]`);if(o&&(o.value=e),t.Default){const e=a.querySelector(`[name="servers[${i}].installation.env[${s}].default"]`);e&&(e.value=t.Default)}if(t.Required){const e=a.querySelector(`[name="servers[${i}].installation.env[${s}].required"]`);e&&(e.checked=!0)}if(t.Description){const e=a.querySelector(`[name="servers[${i}].installation.env[${s}].description"]`);e&&(e.value=t.Description)}}))}if(s.dependencies&&s.dependencies.requirements){const t=r&&!("true"===s.systemTags?.adhoc);s.dependencies.requirements.forEach((r=>{const s=(e.requirements||[]).find((e=>e.name===r.name));if(!s)return void console.warn(`Could not find full requirement config for dependency name: ${r.name} (version ${r.version} specified by server, but lookup is by name only). Skipping.`);const o=window.addServerRequirement(i,n,t);a.querySelector(`[name="servers[${i}].requirements[${o}].name"]`).value=s.name||"",a.querySelector(`[name="servers[${i}].requirements[${o}].type"]`).value=s.type||"",a.querySelector(`[name="servers[${i}].requirements[${o}].version"]`).value=s.version||"",void 0!==r.order&&(a.querySelector(`[name="servers[${i}].requirements[${o}].order"]`).value=r.order),"command"===s.type&&s.alias&&(a.querySelector(`[name="servers[${i}].requirements[${o}].alias"]`).value=s.alias,window.toggleServerAliasField(i,o,n));let l="public";s.registry&&(s.registry.githubRelease?l="github":s.registry.artifacts?l="artifacts":s.registry.local&&(l="local"));const m=a.querySelector(`[name="servers[${i}].requirements[${o}].registryType"]`);if(m&&(m.value=l,window.toggleServerRegistryConfig(i,o,n)),"github"===l&&s.registry.githubRelease){const e=s.registry.githubRelease;e.repository&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.githubRelease.repository"]`).value=e.repository),e.assetsName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.githubRelease.assetsName"]`).value=e.assetsName),e.assetName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.githubRelease.assetName"]`).value=e.assetName)}else if("artifacts"===l&&s.registry.artifacts){const e=s.registry.artifacts;e.registryUrl&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.artifacts.registryUrl"]`).value=e.registryUrl),e.registryName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.artifacts.registryName"]`).value=e.registryName)}else if("local"===l&&s.registry.local){const e=s.registry.local;e.localPath&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.local.localPath"]`).value=e.localPath),e.assetName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.local.assetName"]`).value=e.assetName)}}))}}))}}export function resetOnboardFormDynamicContent(e="onboardForm",t="serversList"){const r=document.getElementById(e);r&&"onboardServerForm"!==e&&r.reset();const s=document.getElementById(t);let a,n;if(s&&(s.innerHTML=""),setServerCounter(0),state&&state.envCounters&&"function"==typeof state.envCounters.clear&&state.envCounters.clear(),state&&state.serverRequirementCounters&&"function"==typeof state.serverRequirementCounters.clear&&state.serverRequirementCounters.clear(),"onboardForm"===e?(a="validationStatusPanelNewCategory",n="validationStatusContentNewCategory"):"onboardServerForm"===e&&(a="validationStatusPanelExistingCategory",n="validationStatusContentExistingCategoryTab"),a){const e=document.getElementById(a);e&&e.classList.add("hidden")}if(n){const e=document.getElementById(n);e&&(e.innerHTML="")}if("onboardServerForm"===e){const e=document.getElementById("existingCategoryBasicInfoContainer");e&&e.classList.add("hidden");const t=document.getElementById("existingCategoryMcpServersContainer");t&&t.classList.add("hidden")}setupRealTimeValidation(e)}export function showValidationMessage(e,t,r=!0){let s=e.nextElementSibling;s&&s.classList.contains("validation-message")||(s=document.createElement("div"),s.className="validation-message text-xs mt-1 "+(r?"text-red-500":"text-green-500"),e.insertAdjacentElement("afterend",s)),s.textContent=t,s.className="validation-message text-xs mt-1 "+(r?"text-red-500":"text-green-500")}export{setupRealTimeValidation};
1
+ import{showToast}from"../notifications.js";import{state,setServerCounter,getServerCounter,clearEnvCountersForTab,clearServerRequirementCountersForTab}from"./state.js";function setupRealTimeValidation(e){const t=document.getElementById(e);if(!t)return;if(!t)return;const r=t.querySelector('input[name="name"]');r&&r.addEventListener("input",(e=>{const t=e.target.value.trim();t?/^[a-zA-Z0-9-_]+$/.test(t)?t.length>50?showValidationMessage(e.target,"Must not exceed 50 characters"):showValidationMessage(e.target,"Valid name",!1):showValidationMessage(e.target,"Only alphanumeric characters, hyphens, and underscores allowed"):showValidationMessage(e.target,"Name is required")}));const s=t.querySelector('input[name="displayName"]');s&&s.addEventListener("input",(e=>{const t=e.target.value.trim();t?t.length>100?showValidationMessage(e.target,"Must not exceed 100 characters"):showValidationMessage(e.target,"Valid display name",!1):showValidationMessage(e.target,"Display name is required")}));const a=t.querySelector('textarea[name="description"]');a&&a.addEventListener("input",(e=>{const t=e.target.value.trim();t.length>500?showValidationMessage(e.target,"Must not exceed 500 characters"):0===t.length?showValidationMessage(e.target,"Description is required"):showValidationMessage(e.target,"Valid description",!1)}));const n=t.querySelector('input[name="repository"]');n&&n.addEventListener("input",(e=>{const t=e.target.value.trim();if(t)try{new URL(t),showValidationMessage(e.target,"Valid URL",!1)}catch(t){showValidationMessage(e.target,"Invalid URL format")}else e.target.nextElementSibling?.remove()})),t.addEventListener("change",(e=>{if(e.target.name?.match(/servers\[\d+\]\.mode/)){const r=e.target.name.match(/servers\[(\d+)\]/)[1],s=t.querySelector(`[name="servers[${r}].installation.command"]`),a=t.querySelector(`[name="servers[${r}].installation.url"]`),n=t.querySelector(`[name="servers[${r}].installation.args"]`);"stdio"===e.target.value?(s&&(s.required=!0,showValidationMessage(s,"Command is required for stdio mode")),a&&(a.required=!1,a.value="",a.nextElementSibling?.remove())):"sse"!==e.target.value&&"streamable-http"!==e.target.value||(a&&(a.required=!0,showValidationMessage(a,`URL is required for ${e.target.value} mode`)),s&&(s.required=!1,s.value="",s.nextElementSibling?.remove()),n&&(n.value="",n.nextElementSibling?.remove()))}})),t.addEventListener("input",(e=>{if(e.target.name?.includes(".installation.env[")){const t=e.target.name.match(/servers\[(\d+)\]\.installation\.env\[(\d+)\]\.(name|default)/);if(t){const[,r,s,a]=t;if("name"===a){const t=e.target.value.trim();t?/^[A-Z_][A-Z0-9_]*$/.test(t)?t.length>50?showValidationMessage(e.target,"Must not exceed 50 characters"):showValidationMessage(e.target,"Valid name",!1):showValidationMessage(e.target,"Must be uppercase with only letters, numbers, and underscores"):showValidationMessage(e.target,"Environment variable name is required")}}}}))}export async function submitForm(e,t,r=null){e.preventDefault();const s=e.target;let a,n=!1;if("create-category"===t)try{a=formDataToFeedConfiguration(s);const e=new URLSearchParams(window.location.search);n="edit"===e.get("action")&&e.get("category")===a.name}catch(e){return void console.error("Validation error:",e)}else{if("create-server"!==t)return void showToast("Invalid tab context for submission.","error");{if(!r||!r.name)return void showToast("No existing category selected or category data is missing.","error");const e=formDataToFeedConfiguration(s,!0,r);a=JSON.parse(JSON.stringify(r)),a.mcpServers=e.mcpServers||[];const t=new Set((a.requirements||[]).map((e=>`${e.type}|${e.name}|${e.version}`)));(e.requirements||[]).forEach((e=>{const r=`${e.type}|${e.name}|${e.version}`;t.has(r)||(a.requirements.push(e),t.add(r))})),n=!0}}try{const e=await fetch("/api/categories/onboard",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({categoryData:a,isUpdate:n})});if(!e.ok){const t=await e.json().catch((()=>({error:"Failed to parse error response"})));throw new Error(`HTTP error! status: ${e.status}, message: ${t.error||e.statusText}`)}await e.json();showToast("Form submitted successfully! See console for operation details.","success")}catch(e){console.error("Error submitting form:",e),showToast(`Error submitting form: ${e.message}. Please try again.`,"error")}}export function getFormData(e,t=!1,r=null){return formDataToFeedConfiguration(e,t,r)}function validateServerConfig(e){const t=[];if(e.name?/^[a-zA-Z0-9-_]+$/.test(e.name)?e.name.length>50&&t.push("Server name must not exceed 50 characters"):t.push("Server name must only contain alphanumeric characters, hyphens, and underscores"):t.push("Server name is required"),e.description&&""!==e.description.trim()?e.description.length>200&&t.push("Server description must not exceed 200 characters"):t.push("Server description is required"),e.mode?["stdio","sse","streamable-http"].includes(e.mode)||t.push('Server mode must be either "stdio", "sse", or "streamable-http"'):t.push("Server mode is required"),"stdio"===e.mode)e.installation?.command?/^[a-zA-Z0-9-_.\\/]+$/.test(e.installation.command)||t.push("Command must only contain alphanumeric characters, hyphens, underscores, dots, and slashes"):t.push("Command is required for stdio server"),e.installation?.args?.length>0&&e.installation.args.forEach(((e,r)=>{/^[a-zA-Z0-9-_./\\]+$/.test(e)||t.push(`Argument ${r+1} must only contain alphanumeric characters, hyphens, underscores, dots, and slashes`)}));else if("sse"===e.mode||"streamable-http"===e.mode)if(e.installation?.url)try{new URL(e.installation.url)}catch(e){t.push("Invalid URL format")}else t.push("URL is required for sse server");if(e.installation?.env&&Object.entries(e.installation.env).forEach((([e,r])=>{e?/^[A-Z_][A-Z0-9_]*$/.test(e)?e.length>50&&t.push(`Environment variable name "${e}" must not exceed 50 characters`):t.push(`Environment variable name "${e}" must be uppercase with only letters, numbers, and underscores`):t.push("Environment variable name is required"),r.Required&&!r.Default&&t.push(`Required environment variable "${e}" should have a default value`),r.Description&&r.Description.length>200&&t.push(`Description for environment variable "${e}" must not exceed 200 characters`)})),e.schemas)try{JSON.parse(e.schemas)}catch(e){t.push("Invalid JSON format in schemas")}return t}export function formDataToFeedConfiguration(e,t=!1,r=null){const s=new FormData(e),a={requirements:[],mcpServers:[]};let n;"onboardForm"===e.id?n="serversList":"onboardServerForm"===e.id?n="existingCategoryServersList":console.warn("[formDataToFeedConfiguration] Could not determine serversListId from formElement.id:",e.id),t?r&&(a.name=r.name):(a.name=s.get("name")||"",a.displayName=s.get("displayName")||"",a.description=s.get("description")||"",a.repository=s.get("repository")||void 0);const i=new Map,o=new Map;for(const[e,r]of s.entries()){if(t&&!e.startsWith("servers["))continue;const a=e.match(/^servers\[(\d+)\]\.(.+)$/);if(a){let t=parseInt(a[1],10);const n=a[2];let o=t;i.has(o)||i.set(o,{installation:{env:new Map},dependencies:{requirements:new Map},isNew:!0});const l=i.get(o);if("name"===n)l.name=r;else if("description"===n)l.description=r;else if("mode"===n)l.mode=r;else if("repository"===n)l.repository=r||void 0;else if("schemas"===n)l.schemas=r||void 0;else if("installation.command"===n)l.installation.command=r;else if("installation.args"===n)l.installation.args=r?r.split(",").map((e=>e.trim())).filter((e=>e)):[];else if("installation.url"===n)l.installation.url=r;else if("installation.isLocal"===n)l.installation.isLocal="on"===r;else if("installation.startingCommand"===n)l.installation.startingCommand=r.trim()||void 0;else if(n.startsWith("installation.env[")){const t=n.match(/^installation\.env\[(\d+)\]\.(name|default|required|description)$/);if(t){const a=parseInt(t[1],10),n=t[2];l.installation.env.has(a)||l.installation.env.set(a,{});const i=l.installation.env.get(a);i[n]="required"===n?"on"===s.get(e):r||void 0}}else if(n.startsWith("requirements[")){const e=n.match(/^requirements\[(\d+)\]\.(.+)$/);if(e){const t=parseInt(e[1],10),s=e[2];l.dependencies.requirements.has(t)||l.dependencies.requirements.set(t,{registry:{}});const a=l.dependencies.requirements.get(t);"name"===s?a.name=r:"type"===s?a.type=r:"version"===s?a.version=r:"order"===s?a.order=r?parseInt(r,10):void 0:"alias"===s?a.alias=r||void 0:"registryType"===s?a.registryType=r:s.startsWith("registry.githubRelease.")?(a.registry.githubRelease=a.registry.githubRelease||{},a.registry.githubRelease[s.substring(23)]=r||void 0):s.startsWith("registry.artifacts.")?(a.registry.artifacts=a.registry.artifacts||{},a.registry.artifacts[s.substring(19)]=r||void 0):s.startsWith("registry.local.")&&(a.registry.local=a.registry.local||{},a.registry.local[s.substring(15)]=r||void 0)}}}}i.forEach(((t,r)=>{let s;if("sse"===t.mode||"streamable-http"===t.mode)s={name:t.name,description:t.description,mode:t.mode,schemas:t.schemas,repository:t.repository,installation:{url:t.installation.url||""},dependencies:{requirements:[]}},t.installation.isLocal&&t.installation.startingCommand&&(s.installation.startingCommand=t.installation.startingCommand);else{s={name:t.name,description:t.description,mode:t.mode,schemas:t.schemas,repository:t.repository,installation:{command:t.installation.command,args:t.installation.args||[],env:{}},dependencies:{requirements:[]}};const e={};t.installation.env.forEach((t=>{t.name&&(e[t.name]={Required:t.required||!1,Description:t.description||"",Default:t.default||void 0})})),Object.keys(e).length>0?s.installation.env=e:delete s.installation.env}if(t.dependencies.requirements.forEach((e=>{if(!e.name||!e.type||!e.version)return;const t={name:e.name,type:e.type,version:e.version,alias:e.alias,order:e.order};e.registryType&&"public"!==e.registryType&&(t.registry={},"github"===e.registryType&&e.registry.githubRelease?t.registry.githubRelease={repository:e.registry.githubRelease.repository,assetsName:e.registry.githubRelease.assetsName,assetName:e.registry.githubRelease.assetName}:"artifacts"===e.registryType&&e.registry.artifacts?t.registry.artifacts={registryUrl:e.registry.artifacts.registryUrl,registryName:e.registry.artifacts.registryName}:"local"===e.registryType&&e.registry.local&&(t.registry.local={localPath:e.registry.local.localPath,assetName:e.registry.local.assetName}),t.registry.githubRelease&&!t.registry.githubRelease.repository&&delete t.registry.githubRelease,t.registry.artifacts&&!t.registry.artifacts.registryUrl&&delete t.registry.artifacts,t.registry.local&&!t.registry.local.localPath&&delete t.registry.local,0===Object.keys(t.registry).length&&delete t.registry),s.dependencies.requirements.push({name:e.name,version:e.version,order:e.order});const r=`${e.type}|${e.name}|${e.version}`;if(!o.has(r)){const{order:e,...s}=t;o.set(r,s)}})),0===s.dependencies.requirements.length&&delete s.dependencies,"onboardServerForm"===e.id&&n){const t=`#${n} .server-item[data-index="${r}"]`,a=document.querySelector(t);if(a&&a.dataset.systemTags)try{s.systemTags=JSON.parse(a.dataset.systemTags)}catch(t){console.error(`[formDataToFeedConfiguration] Error parsing systemTags for server index ${r} ('${s.name}') on ${e.id}:`,t,a.dataset.systemTags),s.systemTags={parseError:!0}}}else delete s.systemTags;a.mcpServers.push(s)})),t&&r&&Array.isArray(r.mcpServers)&&(r.requirements&&Array.isArray(r.requirements)&&r.requirements.forEach((e=>{const t=`${e.type}|${e.name}|${e.version}`;o.has(t)||o.set(t,JSON.parse(JSON.stringify(e)))})),r.mcpServers.forEach((e=>{a.mcpServers.some((t=>t.name===e.name))||e.systemTags&&"true"===e.systemTags.adhoc||a.mcpServers.push(JSON.parse(JSON.stringify(e)))}))),a.requirements=Array.from(o.values());const l=[];if(t||(a.name?/^[a-zA-Z0-9-_]+$/.test(a.name)||l.push("Category name must only contain alphanumeric characters, hyphens, and underscores"):l.push("Category name is required"),a.displayName||l.push("Display name is required")),a.mcpServers.forEach(((e,t)=>{const r=validateServerConfig(e);r.length>0&&l.push(`Server ${t+1} (${e.name||"unnamed"}): ${r.join(", ")}`)})),a.requirements.forEach(((e,t)=>{if(e.name&&e.type&&e.version||l.push(`Requirement ${t+1}: name, type, and version are required`),e.registry){const r=Object.keys(e.registry)[0];["githubRelease","artifacts","local"].includes(r)||l.push(`Requirement ${t+1}: Invalid registry type ${r}`)}})),l.length>0){e.querySelectorAll(".validation-error-message").forEach((e=>e.remove()));l.forEach((t=>{let r=null;if(t.includes("Category name")?r='input[name="name"]':t.includes("Display name")&&(r='input[name="displayName"]'),r){const s=e.querySelector(r);if(s){const e=document.createElement("div");e.className="validation-error-message text-red-500 text-xs mt-1",e.textContent=t,s.insertAdjacentElement("afterend",e)}}}))}return a}export function populateForm(e,t="onboardForm",r=!1,s=null){const a=document.getElementById(t);if(!a)return void console.error(`populateForm: Form with ID "${t}" not found.`);const n=s||("onboardForm"===t?"serversList":"existingCategoryServersList");if(resetOnboardFormDynamicContent(t,n),setupRealTimeValidation(t),e){if("onboardForm"===t){a.querySelector('[name="name"]').value=e.name||"",a.querySelector('[name="displayName"]').value=e.displayName||"",a.querySelector('[name="description"]').value=e.description||"",e.repository&&(a.querySelector('[name="repository"]').value=e.repository);const t=new URLSearchParams(window.location.search);if("edit"===t.get("action")&&t.get("category")===e.name){const e=a.querySelector('[name="name"]');e&&(e.readOnly=!0,e.classList.add("bg-gray-100","cursor-not-allowed"))}}else if("onboardServerForm"===t&&e){a.querySelector('input[name="name"]').value=e.name||"",a.querySelector('input[name="displayName"]').value=e.displayName||"",a.querySelector('textarea[name="description"]').value=e.description||"",a.querySelector('input[name="repository"]').value=e.repository||"";const t=document.getElementById("existingCategoryBasicInfoContainer");t&&t.classList.remove("hidden");const r=document.getElementById("existingCategoryMcpServersContainer");r&&r.classList.remove("hidden")}setServerCounter(n,0),clearEnvCountersForTab(n),clearServerRequirementCountersForTab(n),(e.mcpServers||[]).forEach((s=>{const i=getServerCounter(n);window.addServer(n,r,s);const o=a.querySelector(`#${n} .server-item[data-index="${i}"]`);if(o)if("onboardServerForm"===t)if("true"===s.systemTags?.adhoc)o.dataset.systemTags=JSON.stringify(s.systemTags);else if(state.originalServerNamesForFormPopulation&&s.name&&state.originalServerNamesForFormPopulation.has(s.name))o.dataset.systemTags=JSON.stringify({adhoc:"true"});else if(s.systemTags&&Object.keys(s.systemTags).length>0){const e={...s.systemTags};delete e.adhoc,Object.keys(e).length>0?o.dataset.systemTags=JSON.stringify(e):delete o.dataset.systemTags}else delete o.dataset.systemTags;else s.systemTags?o.dataset.systemTags=JSON.stringify(s.systemTags):delete o.dataset.systemTags;const l=a.querySelector(`[name="servers[${i}].name"]`);l&&(l.value=s.name||"");const m=a.querySelector(`[name="servers[${i}].mode"]`);m&&(m.value=s.mode||"stdio","function"==typeof window.renderInstallationConfig&&window.renderInstallationConfig(i,n,s.mode||"stdio",r,s.installation));const c=a.querySelector(`[name="servers[${i}].description"]`);if(c&&(c.value=s.description||""),s.schemas){const e=document.getElementById(`schema-path-${i}`);e&&(e.value=s.schemas)}if(s.repository){const e=a.querySelector(`[name="servers[${i}].repository"]`);e&&(e.value=s.repository)}if(s.installation)if("sse"===s.mode||"streamable-http"===s.mode){const e=a.querySelector(`[name="servers[${i}].installation.url"]`);e&&(e.value=s.installation.url||"")}else{const e=a.querySelector(`[name="servers[${i}].installation.command"]`);if(e&&(e.value=s.installation.command||""),s.installation.args&&Array.isArray(s.installation.args)){const e=a.querySelector(`[name="servers[${i}].installation.args"]`);e&&(e.value=s.installation.args.join(", "))}s.installation.env&&Object.entries(s.installation.env).forEach((([e,t])=>{const s=window.addEnvVariable(i,n,r),o=a.querySelector(`[name="servers[${i}].installation.env[${s}].name"]`);if(o&&(o.value=e),t.Default){const e=a.querySelector(`[name="servers[${i}].installation.env[${s}].default"]`);e&&(e.value=t.Default)}if(t.Required){const e=a.querySelector(`[name="servers[${i}].installation.env[${s}].required"]`);e&&(e.checked=!0)}if(t.Description){const e=a.querySelector(`[name="servers[${i}].installation.env[${s}].description"]`);e&&(e.value=t.Description)}}))}if(s.dependencies&&s.dependencies.requirements){const t=r&&!("true"===s.systemTags?.adhoc);s.dependencies.requirements.forEach((r=>{const s=(e.requirements||[]).find((e=>e.name===r.name));if(!s)return void console.warn(`Could not find full requirement config for dependency name: ${r.name} (version ${r.version} specified by server, but lookup is by name only). Skipping.`);const o=window.addServerRequirement(i,n,t);a.querySelector(`[name="servers[${i}].requirements[${o}].name"]`).value=s.name||"",a.querySelector(`[name="servers[${i}].requirements[${o}].type"]`).value=s.type||"",a.querySelector(`[name="servers[${i}].requirements[${o}].version"]`).value=s.version||"",void 0!==r.order&&(a.querySelector(`[name="servers[${i}].requirements[${o}].order"]`).value=r.order),"command"===s.type&&s.alias&&(a.querySelector(`[name="servers[${i}].requirements[${o}].alias"]`).value=s.alias,window.toggleServerAliasField(i,o,n));let l="public";s.registry&&(s.registry.githubRelease?l="github":s.registry.artifacts?l="artifacts":s.registry.local&&(l="local"));const m=a.querySelector(`[name="servers[${i}].requirements[${o}].registryType"]`);if(m&&(m.value=l,window.toggleServerRegistryConfig(i,o,n)),"github"===l&&s.registry.githubRelease){const e=s.registry.githubRelease;e.repository&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.githubRelease.repository"]`).value=e.repository),e.assetsName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.githubRelease.assetsName"]`).value=e.assetsName),e.assetName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.githubRelease.assetName"]`).value=e.assetName)}else if("artifacts"===l&&s.registry.artifacts){const e=s.registry.artifacts;e.registryUrl&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.artifacts.registryUrl"]`).value=e.registryUrl),e.registryName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.artifacts.registryName"]`).value=e.registryName)}else if("local"===l&&s.registry.local){const e=s.registry.local;e.localPath&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.local.localPath"]`).value=e.localPath),e.assetName&&(a.querySelector(`[name="servers[${i}].requirements[${o}].registry.local.assetName"]`).value=e.assetName)}}))}}))}}export function resetOnboardFormDynamicContent(e="onboardForm",t="serversList"){const r=document.getElementById(e);r&&"onboardServerForm"!==e&&r.reset();const s=document.getElementById(t);let a,n;if(s&&(s.innerHTML=""),setServerCounter(0),state&&state.envCounters&&"function"==typeof state.envCounters.clear&&state.envCounters.clear(),state&&state.serverRequirementCounters&&"function"==typeof state.serverRequirementCounters.clear&&state.serverRequirementCounters.clear(),"onboardForm"===e?(a="validationStatusPanelNewCategory",n="validationStatusContentNewCategory"):"onboardServerForm"===e&&(a="validationStatusPanelExistingCategory",n="validationStatusContentExistingCategoryTab"),a){const e=document.getElementById(a);e&&e.classList.add("hidden")}if(n){const e=document.getElementById(n);e&&(e.innerHTML="")}if("onboardServerForm"===e){const e=document.getElementById("existingCategoryBasicInfoContainer");e&&e.classList.add("hidden");const t=document.getElementById("existingCategoryMcpServersContainer");t&&t.classList.add("hidden")}setupRealTimeValidation(e)}export function showValidationMessage(e,t,r=!0){let s=e.nextElementSibling;s&&s.classList.contains("validation-message")||(s=document.createElement("div"),s.className="validation-message text-xs mt-1 "+(r?"text-red-500":"text-green-500"),e.insertAdjacentElement("afterend",s)),s.textContent=t,s.className="validation-message text-xs mt-1 "+(r?"text-red-500":"text-green-500")}export{setupRealTimeValidation};
2
2
  //# sourceMappingURL=formProcessor.js.map
@@ -1,2 +1,2 @@
1
- export const serverTemplate=(e,t=!1,n=null,r="serversList")=>{const s="true"===n?.systemTags?.adhoc,l=!t||s,o=l?"":"disabled",i=l?"":"bg-gray-100 cursor-not-allowed opacity-70",a=l?"":"hidden";return`\n <div class="server-item p-4 border border-gray-300 rounded-lg mb-6 bg-white shadow" data-index="${e}">\n <div id="${r}-server-header-${e}" class="server-header-toggle flex justify-between items-center mb-3 cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-server-content-${e}"\n onclick="window.toggleSectionContent('${r}-server-content-${e}', this.querySelector('i.toggle-icon'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-server-content-${e}', this.querySelector('i.toggle-icon'), this); event.preventDefault(); }">\n <h3 id="${r}-server-title-${e}" class="text-lg font-semibold text-gray-800">MCP Server #${e+1}${s?' <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>':""}</h3>\n <div class="flex items-center">\n <button type="button" onclick="event.stopPropagation(); removeServer(${e}, '${r}')"\n class="action-button-in-server p-1.5 text-sm text-red-600 hover:text-red-800 hover:bg-red-50 rounded-md flex items-center mr-2 ${l?"":"hidden"}" title="Remove Server">\n <i class='bx bx-trash text-lg'></i>\n </button>\n <button type="button" onclick="event.stopPropagation(); window.duplicateServer(${e}, '${r}')"\n class="action-button-in-server duplicate-mcp-server-button p-1.5 text-sm text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-md flex items-center mr-2" title="Duplicate Server">\n <i class='bx bx-copy text-lg'></i>\n </button>\n <i class='bx bxs-chevron-down text-xl toggle-icon'></i>\n </div>\n </div>\n <div id="${r}-server-content-${e}" class="collapsible-content server-content-scrollable hidden" role="region" aria-labelledby="${r}-server-title-${e}">\n\n <div class="grid grid-cols-1 md:grid-cols-2 gap-4">\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Server Name*</label>\n <input type="text" name="servers[${e}].name" required ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="e.g., ado-tools-server">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Mode*</label>\n <select name="servers[${e}].mode" required ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}">\n <option value="stdio">stdio</option>\n <option value="sse">sse</option>\n </select>\n </div>\n <div class="md:col-span-2">\n <label class="block text-sm font-medium text-gray-700 mb-1">Description*</label>\n <textarea name="servers[${e}].description" required rows="3" ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="Detailed description of the server's capabilities"></textarea>\n </div>\n <div class="md:col-span-2 flex gap-x-4 items-end">\n <div class="flex-grow">\n <label class="block text-sm font-medium text-gray-700 mb-1">Schema File Path\n <span class="text-xs text-gray-500 ml-1" title="Optional for listing available tools, please fill full path of the schema file">\n <i class='bx bx-info-circle'></i> Optional\n </span>\n </label>\n <input type="text" name="servers[${e}].schemas" id="schema-path-${e}" ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="e.g., /Users/xxx/schemas/my_server_schema.json">\n </div>\n </div>\n <div class="md:col-span-2">\n <label class="block text-sm font-medium text-gray-700 mb-1">Repository URL</label>\n <input type="url" name="servers[${e}].repository" ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="e.g., https://github.com/org/repo">\n </div>\n </div>\n\n \x3c!-- Package Dependencies --\x3e\n <div class="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200">\n <h4 id="${r}-deps-header-${e}" class="text-md font-semibold text-gray-700 mb-2 flex justify-between items-center cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-server-deps-content-${e}"\n onclick="window.toggleSectionContent('${r}-server-deps-content-${e}', this.querySelector('i'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-server-deps-content-${e}', this.querySelector('i'), this); event.preventDefault(); }">\n <span>Package Dependencies</span>\n <i class='bx bxs-chevron-down text-xl'></i>\n </h4>\n <div id="${r}-server-deps-content-${e}" class="collapsible-content mt-2 hidden" role="region" aria-labelledby="${r}-deps-header-${e}">\n <div id="server-requirements-list-${e}" class="space-y-4">\n \x3c!-- Server requirements will be populated here by serverRequirementTemplate --\x3e\n </div>\n <button type="button" onclick="addServerRequirement(${e}, '${r}', ${!l})"\n class="action-button-in-server mt-3 px-3 py-1.5 text-sm border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100 flex items-center ${a}">\n <i class='bx bx-plus mr-1'></i> Add Dependency\n </button>\n </div>\n </div>\n\n \x3c!-- Startup Configuration --\x3e\n <div class="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200">\n <h4 id="${r}-startup-header-${e}" class="text-md font-semibold text-gray-700 mb-2 flex justify-between items-center cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-installation-content-${e}"\n onclick="window.toggleSectionContent('${r}-installation-content-${e}', this.querySelector('i'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-installation-content-${e}', this.querySelector('i'), this); event.preventDefault(); }">\n <span>Startup Configuration</span>\n <i class='bx bxs-chevron-down text-xl'></i>\n </h4>\n <div id="${r}-installation-content-${e}" class="collapsible-content mt-2 hidden" role="region" aria-labelledby="${r}-startup-header-${e}">\n <div id="installation-config-${e}">\n \x3c!-- Installation fields will be rendered here based on mode by renderInstallationConfig --\x3e\n </div>\n </div>\n </div>\n\n \x3c!-- Environment Variables --\x3e\n <div class="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200" id="env-vars-block-${e}">\n <h4 id="${r}-envars-header-${e}" class="text-md font-semibold text-gray-700 mb-2 flex justify-between items-center cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-env-vars-content-${e}"\n onclick="window.toggleSectionContent('${r}-env-vars-content-${e}', this.querySelector('i'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-env-vars-content-${e}', this.querySelector('i'), this); event.preventDefault(); }">\n <span>Environment Variables</span>\n <i class='bx bxs-chevron-down text-xl'></i>\n </h4>\n <div id="${r}-env-vars-content-${e}" class="collapsible-content mt-2 hidden" role="region" aria-labelledby="${r}-envars-header-${e}">\n <div id="envVarsContainer_${e}" class="space-y-3">\n \x3c!-- Environment variables will be added here by envVariableTemplate --\x3e\n </div>\n <button type="button" onclick="addEnvVariable(${e}, '${r}', ${!l})"\n class="action-button-in-server mt-3 px-3 py-1.5 text-sm border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100 flex items-center ${a}">\n <i class='bx bx-plus mr-1'></i> Add Environment Variable\n </button>\n </div>\n </div>\n </div>\x3c!-- Closing server-content-${e} --\x3e\n </div>\n`};export const envVariableTemplate=(e,t,n=!1,r="serversList")=>{const s=n?"disabled":"",l=n?"bg-gray-100 cursor-not-allowed opacity-70":"";return`\n <div class="env-var-item grid grid-cols-1 gap-2" data-env-index="${t}">\n <div class="grid grid-cols-3 gap-2 items-end">\n <div>\n <label class="block text-sm font-medium text-gray-700">Name*</label>\n <input type="text" name="servers[${e}].installation.env[${t}].name" required ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="ENV_VAR_NAME">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Default Value</label>\n <input type="text" name="servers[${e}].installation.env[${t}].default" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Default value">\n </div>\n <div class="flex items-center gap-2">\n <label class="inline-flex items-center text-sm">\n <input type="checkbox" name="servers[${e}].installation.env[${t}].required" ${s}\n class="text-blue-600 focus:ring-blue-500 ${n?"opacity-70 cursor-not-allowed":""}">\n <span class="ml-1 ${n?"text-gray-500":""}">Required</span>\n </label>\n <button type="button" onclick="removeEnvVariable(${e}, ${t}, '${r}')"\n class="action-button-in-env px-2 py-1 text-red-600 hover:text-red-800 ${n?"hidden":""}">\n <i class='bx bx-trash'></i>\n </button>\n </div>\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Description</label>\n <textarea name="servers[${e}].installation.env[${t}].description" rows="2" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Environment variable description"></textarea>\n </div>\n </div>\n`};export const serverRequirementTemplate=(e,t,n=!1,r="serversList")=>{const s=n?"disabled":"",l=n?"bg-gray-100 cursor-not-allowed opacity-70":"";return`\n <div class="server-requirement-item p-3 border border-gray-200 rounded-lg mb-3" data-req-index="${t}">\n <div class="grid grid-cols-2 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Name*</label>\n <input type="text" name="servers[${e}].requirements[${t}].name" required ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Package or command name">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Type*</label>\n <select name="servers[${e}].requirements[${t}].type" required onchange="toggleServerAliasField(${e}, ${t}, '${r}')" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}">\n <option value="">Select Type</option>\n <option value="npm">NPM Package</option>\n <option value="pip">PIP Package</option>\n <option value="nuget">Nuget Package</option>\n <option value="command">Command</option>\n </select>\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Version*</label>\n <input type="text" name="servers[${e}].requirements[${t}].version" required ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="e.g., latest, v\${latest}, 1.0.0">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Order</label>\n <input type="number" name="servers[${e}].requirements[${t}].order" min="0" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Installation order">\n </div>\n <div id="server-alias-field-${e}-${t}" class="hidden">\n <label class="block text-sm font-medium text-gray-700">Alias</label>\n <input type="text" name="servers[${e}].requirements[${t}].alias" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Command alias">\n </div>\n <div class="col-span-2">\n <label class="block text-sm font-medium text-gray-700">Registry*</label>\n <select name="servers[${e}].requirements[${t}].registryType" onchange="toggleServerRegistryConfig(${e}, ${t}, '${r}')" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}" required>\n <option value="public" selected>Public Registry</option>\n <option value="github">GitHub Release</option>\n <option value="artifacts">Private Artifacts</option>\n </select>\n </div>\n \n <div id="server-registry-config-${e}-${t}" class="col-span-2 registry-configs">\n \x3c!-- GitHub Registry Config --\x3e\n <div id="server-github-config-${e}-${t}" class="registry-config mt-3 p-2 bg-gray-50 rounded-lg hidden">\n <h3 class="text-sm font-medium text-gray-900 mb-2">GitHub Registry Details</h3>\n <div class="grid grid-cols-1 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Repository*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.githubRelease.repository" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="org/repo">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Assets Name Pattern</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.githubRelease.assetsName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="package-\${latest}.zip (e.g. for multiple assets)">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Asset Name Pattern*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.githubRelease.assetName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="package-\${latest}.tgz (specific asset)">\n </div>\n </div>\n </div>\n \n \x3c!-- Artifacts Registry Config --\x3e\n <div id="server-artifacts-config-${e}-${t}" class="registry-config mt-3 p-2 bg-gray-50 rounded-lg hidden">\n <h3 class="text-sm font-medium text-gray-900 mb-2">Private Artifacts Registry Details</h3>\n <div class="grid grid-cols-1 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Registry Name*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.artifacts.registryName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="My-Artifacts-Registry">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Registry URL*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.artifacts.registryUrl" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="https://artifacts.example.com">\n </div>\n </div>\n </div>\n\n \x3c!-- Local Registry Config --\x3e\n <div id="server-local-config-${e}-${t}" class="registry-config mt-3 p-2 bg-gray-50 rounded-lg hidden">\n <h3 class="text-sm font-medium text-gray-900 mb-2">Local Path Details</h3>\n <div class="grid grid-cols-1 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Local Path*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.local.localPath" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="/path/to/local/registry_or_file">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Asset Name Pattern</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.local.assetName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="package-\${latest}.tgz (if localPath is a dir)">\n </div>\n </div>\n </div>\n </div>\n </div>\n <button type="button" onclick="removeServerRequirement(${e}, ${t}, '${r}')"\n class="action-button-in-req mt-2 px-2 py-1 text-red-600 hover:text-red-800 flex items-center text-sm ${n?"hidden":""}">\n <i class='bx bx-trash mr-1'></i>\n Remove\n </button>\n </div>\n`};
1
+ export const serverTemplate=(e,t=!1,n=null,r="serversList")=>{const s="true"===n?.systemTags?.adhoc,l=!t||s,o=l?"":"disabled",i=l?"":"bg-gray-100 cursor-not-allowed opacity-70",a=l?"":"hidden";return`\n <div class="server-item p-4 border border-gray-300 rounded-lg mb-6 bg-white shadow" data-index="${e}">\n <div id="${r}-server-header-${e}" class="server-header-toggle flex justify-between items-center mb-3 cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-server-content-${e}"\n onclick="window.toggleSectionContent('${r}-server-content-${e}', this.querySelector('i.toggle-icon'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-server-content-${e}', this.querySelector('i.toggle-icon'), this); event.preventDefault(); }">\n <h3 id="${r}-server-title-${e}" class="text-lg font-semibold text-gray-800">MCP Server #${e+1}${s?' <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>':""}</h3>\n <div class="flex items-center">\n <button type="button" onclick="event.stopPropagation(); removeServer(${e}, '${r}')"\n class="action-button-in-server p-1.5 text-sm text-red-600 hover:text-red-800 hover:bg-red-50 rounded-md flex items-center mr-2 ${l?"":"hidden"}" title="Remove Server">\n <i class='bx bx-trash text-lg'></i>\n </button>\n <button type="button" onclick="event.stopPropagation(); window.duplicateServer(${e}, '${r}')"\n class="action-button-in-server duplicate-mcp-server-button p-1.5 text-sm text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-md flex items-center mr-2" title="Duplicate Server">\n <i class='bx bx-copy text-lg'></i>\n </button>\n <i class='bx bxs-chevron-down text-xl toggle-icon'></i>\n </div>\n </div>\n <div id="${r}-server-content-${e}" class="collapsible-content server-content-scrollable hidden" role="region" aria-labelledby="${r}-server-title-${e}">\n\n <div class="grid grid-cols-1 md:grid-cols-2 gap-4">\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Server Name*</label>\n <input type="text" name="servers[${e}].name" required ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="e.g., ado-tools-server">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Mode*</label>\n <select name="servers[${e}].mode" required ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}">\n <option value="stdio">stdio</option>\n <option value="sse">sse</option>\n <option value="streamable-http">streamable-http</option>\n </select>\n </div>\n <div class="md:col-span-2">\n <label class="block text-sm font-medium text-gray-700 mb-1">Description*</label>\n <textarea name="servers[${e}].description" required rows="3" ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="Detailed description of the server's capabilities"></textarea>\n </div>\n <div class="md:col-span-2 flex gap-x-4 items-end">\n <div class="flex-grow">\n <label class="block text-sm font-medium text-gray-700 mb-1">Schema File Path\n <span class="text-xs text-gray-500 ml-1" title="Optional for listing available tools, please fill full path of the schema file">\n <i class='bx bx-info-circle'></i> Optional\n </span>\n </label>\n <input type="text" name="servers[${e}].schemas" id="schema-path-${e}" ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="e.g., /Users/xxx/schemas/my_server_schema.json">\n </div>\n </div>\n <div class="md:col-span-2">\n <label class="block text-sm font-medium text-gray-700 mb-1">Repository URL</label>\n <input type="url" name="servers[${e}].repository" ${o}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${i}"\n placeholder="e.g., https://github.com/org/repo">\n </div>\n </div>\n\n \x3c!-- Package Dependencies --\x3e\n <div class="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200">\n <h4 id="${r}-deps-header-${e}" class="text-md font-semibold text-gray-700 mb-2 flex justify-between items-center cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-server-deps-content-${e}"\n onclick="window.toggleSectionContent('${r}-server-deps-content-${e}', this.querySelector('i'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-server-deps-content-${e}', this.querySelector('i'), this); event.preventDefault(); }">\n <span>Package Dependencies</span>\n <i class='bx bxs-chevron-down text-xl'></i>\n </h4>\n <div id="${r}-server-deps-content-${e}" class="collapsible-content mt-2 hidden" role="region" aria-labelledby="${r}-deps-header-${e}">\n <div id="server-requirements-list-${e}" class="space-y-4">\n \x3c!-- Server requirements will be populated here by serverRequirementTemplate --\x3e\n </div>\n <button type="button" onclick="addServerRequirement(${e}, '${r}', ${!l})"\n class="action-button-in-server mt-3 px-3 py-1.5 text-sm border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100 flex items-center ${a}">\n <i class='bx bx-plus mr-1'></i> Add Dependency\n </button>\n </div>\n </div>\n\n \x3c!-- Startup Configuration --\x3e\n <div class="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200">\n <h4 id="${r}-startup-header-${e}" class="text-md font-semibold text-gray-700 mb-2 flex justify-between items-center cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-installation-content-${e}"\n onclick="window.toggleSectionContent('${r}-installation-content-${e}', this.querySelector('i'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-installation-content-${e}', this.querySelector('i'), this); event.preventDefault(); }">\n <span>Startup Configuration</span>\n <i class='bx bxs-chevron-down text-xl'></i>\n </h4>\n <div id="${r}-installation-content-${e}" class="collapsible-content mt-2 hidden" role="region" aria-labelledby="${r}-startup-header-${e}">\n <div id="installation-config-${e}">\n \x3c!-- Installation fields will be rendered here based on mode by renderInstallationConfig --\x3e\n </div>\n </div>\n </div>\n\n \x3c!-- Environment Variables --\x3e\n <div class="mt-4 p-3 bg-gray-50 rounded-lg border border-gray-200" id="env-vars-block-${e}">\n <h4 id="${r}-envars-header-${e}" class="text-md font-semibold text-gray-700 mb-2 flex justify-between items-center cursor-pointer"\n role="button" tabindex="0"\n aria-expanded="false" aria-controls="${r}-env-vars-content-${e}"\n onclick="window.toggleSectionContent('${r}-env-vars-content-${e}', this.querySelector('i'), this)"\n onkeydown="if(event.key==='Enter' || event.key===' ') { window.toggleSectionContent('${r}-env-vars-content-${e}', this.querySelector('i'), this); event.preventDefault(); }">\n <span>Environment Variables</span>\n <i class='bx bxs-chevron-down text-xl'></i>\n </h4>\n <div id="${r}-env-vars-content-${e}" class="collapsible-content mt-2 hidden" role="region" aria-labelledby="${r}-envars-header-${e}">\n <div id="envVarsContainer_${e}" class="space-y-3">\n \x3c!-- Environment variables will be added here by envVariableTemplate --\x3e\n </div>\n <button type="button" onclick="addEnvVariable(${e}, '${r}', ${!l})"\n class="action-button-in-server mt-3 px-3 py-1.5 text-sm border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-100 flex items-center ${a}">\n <i class='bx bx-plus mr-1'></i> Add Environment Variable\n </button>\n </div>\n </div>\n </div>\x3c!-- Closing server-content-${e} --\x3e\n </div>\n`};export const envVariableTemplate=(e,t,n=!1,r="serversList")=>{const s=n?"disabled":"",l=n?"bg-gray-100 cursor-not-allowed opacity-70":"";return`\n <div class="env-var-item grid grid-cols-1 gap-2" data-env-index="${t}">\n <div class="grid grid-cols-3 gap-2 items-end">\n <div>\n <label class="block text-sm font-medium text-gray-700">Name*</label>\n <input type="text" name="servers[${e}].installation.env[${t}].name" required ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="ENV_VAR_NAME">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Default Value</label>\n <input type="text" name="servers[${e}].installation.env[${t}].default" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Default value">\n </div>\n <div class="flex items-center gap-2">\n <label class="inline-flex items-center text-sm">\n <input type="checkbox" name="servers[${e}].installation.env[${t}].required" ${s}\n class="text-blue-600 focus:ring-blue-500 ${n?"opacity-70 cursor-not-allowed":""}">\n <span class="ml-1 ${n?"text-gray-500":""}">Required</span>\n </label>\n <button type="button" onclick="removeEnvVariable(${e}, ${t}, '${r}')"\n class="action-button-in-env px-2 py-1 text-red-600 hover:text-red-800 ${n?"hidden":""}">\n <i class='bx bx-trash'></i>\n </button>\n </div>\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Description</label>\n <textarea name="servers[${e}].installation.env[${t}].description" rows="2" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Environment variable description"></textarea>\n </div>\n </div>\n`};export const serverRequirementTemplate=(e,t,n=!1,r="serversList")=>{const s=n?"disabled":"",l=n?"bg-gray-100 cursor-not-allowed opacity-70":"";return`\n <div class="server-requirement-item p-3 border border-gray-200 rounded-lg mb-3" data-req-index="${t}">\n <div class="grid grid-cols-2 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Name*</label>\n <input type="text" name="servers[${e}].requirements[${t}].name" required ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Package or command name">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Type*</label>\n <select name="servers[${e}].requirements[${t}].type" required onchange="toggleServerAliasField(${e}, ${t}, '${r}')" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}">\n <option value="">Select Type</option>\n <option value="npm">NPM Package</option>\n <option value="pip">PIP Package</option>\n <option value="nuget">Nuget Package</option>\n <option value="command">Command</option>\n </select>\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Version*</label>\n <input type="text" name="servers[${e}].requirements[${t}].version" required ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="e.g., latest, v\${latest}, 1.0.0">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Order</label>\n <input type="number" name="servers[${e}].requirements[${t}].order" min="0" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Installation order">\n </div>\n <div id="server-alias-field-${e}-${t}" class="hidden">\n <label class="block text-sm font-medium text-gray-700">Alias</label>\n <input type="text" name="servers[${e}].requirements[${t}].alias" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="Command alias">\n </div>\n <div class="col-span-2">\n <label class="block text-sm font-medium text-gray-700">Registry*</label>\n <select name="servers[${e}].requirements[${t}].registryType" onchange="toggleServerRegistryConfig(${e}, ${t}, '${r}')" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}" required>\n <option value="public" selected>Public Registry</option>\n <option value="github">GitHub Release</option>\n <option value="artifacts">Private Artifacts</option>\n </select>\n </div>\n \n <div id="server-registry-config-${e}-${t}" class="col-span-2 registry-configs">\n \x3c!-- GitHub Registry Config --\x3e\n <div id="server-github-config-${e}-${t}" class="registry-config mt-3 p-2 bg-gray-50 rounded-lg hidden">\n <h3 class="text-sm font-medium text-gray-900 mb-2">GitHub Registry Details</h3>\n <div class="grid grid-cols-1 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Repository*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.githubRelease.repository" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="org/repo">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Assets Name Pattern</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.githubRelease.assetsName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="package-\${latest}.zip (e.g. for multiple assets)">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Asset Name Pattern*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.githubRelease.assetName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="package-\${latest}.tgz (specific asset)">\n </div>\n </div>\n </div>\n \n \x3c!-- Artifacts Registry Config --\x3e\n <div id="server-artifacts-config-${e}-${t}" class="registry-config mt-3 p-2 bg-gray-50 rounded-lg hidden">\n <h3 class="text-sm font-medium text-gray-900 mb-2">Private Artifacts Registry Details</h3>\n <div class="grid grid-cols-1 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Registry Name*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.artifacts.registryName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="My-Artifacts-Registry">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Registry URL*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.artifacts.registryUrl" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="https://artifacts.example.com">\n </div>\n </div>\n </div>\n\n \x3c!-- Local Registry Config --\x3e\n <div id="server-local-config-${e}-${t}" class="registry-config mt-3 p-2 bg-gray-50 rounded-lg hidden">\n <h3 class="text-sm font-medium text-gray-900 mb-2">Local Path Details</h3>\n <div class="grid grid-cols-1 gap-3">\n <div>\n <label class="block text-sm font-medium text-gray-700">Local Path*</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.local.localPath" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="/path/to/local/registry_or_file">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700">Asset Name Pattern</label>\n <input type="text" name="servers[${e}].requirements[${t}].registry.local.assetName" ${s}\n class="w-full px-2 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${l}"\n placeholder="package-\${latest}.tgz (if localPath is a dir)">\n </div>\n </div>\n </div>\n </div>\n </div>\n <button type="button" onclick="removeServerRequirement(${e}, ${t}, '${r}')"\n class="action-button-in-req mt-2 px-2 py-1 text-red-600 hover:text-red-800 flex items-center text-sm ${n?"hidden":""}">\n <i class='bx bx-trash mr-1'></i>\n Remove\n </button>\n </div>\n`};
2
2
  //# sourceMappingURL=templates.js.map
@@ -1,2 +1,2 @@
1
- import{serverTemplate,envVariableTemplate,serverRequirementTemplate}from"./templates.js";import{state,setServerCounter,getServerCounter,setEnvCounter,getEnvCounter,deleteEnvCounter,clearEnvCountersForTab,setServerRequirementCounter,getServerRequirementCounter,deleteServerRequirementCounter,clearServerRequirementCountersForTab}from"./state.js";import{getFormData,populateForm,resetOnboardFormDynamicContent}from"./formProcessor.js";import{showToast}from"../notifications.js";function reindexElements(e,t,r,n){n.forEach((({selector:n,idBase:s,namePattern:o})=>{const a=e.querySelector(n);if(a&&(s&&(a.id=`${s}${r}`),o&&a.getAttribute("name"))){const e=a.getAttribute("name").replace(new RegExp(o.replace("INDEX",t)),`$1${r}$2`);a.setAttribute("name",e)}}))}function reindexServers(e="serversList"){const t=document.getElementById(e);if(!t)return;const r=t.querySelectorAll(".server-item"),n=new Map,s=new Map;r.forEach(((t,r)=>{const o=parseInt(t.dataset.index,10);t.dataset.index=r;const a=t.querySelector("h3");if(a){const e=a.textContent||"",t=`MCP Server #${r+1}`;let n="";e.includes("(Adhoc - Editable)")?n=' <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>':e.includes("(Read-only)")&&(n=" (Read-only)"),a.innerHTML=`${t}${n}`}const i=t.querySelector(`#${e}-server-header-${o}`);if(i){i.id=`${e}-server-header-${r}`;const t=`${e}-server-content-${o}`,n=`${e}-server-content-${r}`;let s=i.getAttribute("onclick");s&&(s=s.replace(new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),n),i.setAttribute("onclick",s));let a=i.getAttribute("onkeydown");a&&(a=a.replace(new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),n),i.setAttribute("onkeydown",a)),i.setAttribute("aria-controls",n)}const l=t.querySelector(`#${e}-server-title-${o}`);l&&(l.id=`${e}-server-title-${r}`);const c=t.querySelector(`#${e}-server-content-${o}`);c&&c.setAttribute("aria-labelledby",`${e}-server-title-${r}`),t.querySelectorAll("[onclick]").forEach((t=>{const n=t.getAttribute("onclick");if(!n)return;if(t.id===`${e}-server-header-${r}`)return;const s=n.replace(new RegExp(`\\((\\s*)${o}(\\s*[,\\)])`,"g"),`($1${r}$2`).replace(new RegExp(`${e}-server-deps-content-${o}`.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),`${e}-server-deps-content-${r}`).replace(new RegExp(`${e}-installation-content-${o}`.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),`${e}-installation-content-${r}`).replace(new RegExp(`${e}-env-vars-content-${o}`.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),`${e}-env-vars-content-${r}`);t.setAttribute("onclick",s)})),reindexElements(t,o,r,[{selector:`#${e}-server-content-${o}`,idBase:`${e}-server-content-`},{selector:`#${e}-server-deps-content-${o}`,idBase:`${e}-server-deps-content-`},{selector:`#${e}-installation-content-${o}`,idBase:`${e}-installation-content-`},{selector:`#${e}-env-vars-content-${o}`,idBase:`${e}-env-vars-content-`},{selector:`#schema-path-${o}`,idBase:"schema-path-"},{selector:`#envVarsContainer_${o}`,idBase:"envVarsContainer_"}]);const d=t.querySelector(`#envVarsContainer_${r}`);let u=0;d&&d.querySelectorAll(".env-var-item").forEach(((e,t)=>{const n=parseInt(e.dataset.envIndex,10);e.dataset.envIndex=t,reindexElements(e,n,t,[{selector:"[name]",namePattern:`(servers\\[${r}\\]\\.installation\\.env\\[)\\d+(\\]\\..+)`}]),u++})),n.set(r,u);const m=t.querySelector(`#server-requirements-list-${r}`);let v=0;m&&m.querySelectorAll(".server-requirement-item").forEach(((e,t)=>{const n=parseInt(e.dataset.reqIndex,10);e.dataset.reqIndex=t,reindexElements(e,n,t,[{selector:"[name]",namePattern:`(servers\\[${r}\\]\\.requirements\\[)\\d+(\\]\\..+)`}]),v++})),s.set(r,v)})),clearEnvCountersForTab(e),n.forEach(((t,r)=>setEnvCounter(e,r,t))),clearServerRequirementCountersForTab(e),s.forEach(((t,r)=>setServerRequirementCounter(e,r,t))),setServerCounter(e,r.length)}export function addServer(e="serversList",t=!1,r=null){const n=document.getElementById(e);if(!n)return-1;0===n.children.length&&(setServerCounter(e,0),clearEnvCountersForTab(e),clearServerRequirementCountersForTab(e));const s=getServerCounter(e);let o;o=!("true"===r?.systemTags?.adhoc)&&(!!t&&(state.originalServerNamesForFormPopulation?!!(r&&r.name&&state.originalServerNamesForFormPopulation.has(r.name)):!!r)),n.insertAdjacentHTML("beforeend",serverTemplate(s,t,r,e)),setEnvCounter(e,s,0),setServerRequirementCounter(e,s,0),setServerCounter(e,s+1);const a=n.querySelector(`.server-item[data-index="${s}"]`);if(a){r&&r.systemTags?a.dataset.systemTags=JSON.stringify(r.systemTags):r&&!r.systemTags?delete a.dataset.systemTags:r||delete a.dataset.systemTags,r&&r.name?a.dataset.originalName=r.name:delete a.dataset.originalName,setupServerMode(a,s,e,o,r),setupReadOnlyState(a,o,r,e,s);if([{contentId:`${e}-server-deps-content-${s}`,iconSelector:`#${e}-deps-header-${s} i`},{contentId:`${e}-installation-content-${s}`,iconSelector:`#${e}-startup-header-${s} i`},{contentId:`${e}-env-vars-content-${s}`,iconSelector:`#${e}-envars-header-${s} i`}].forEach((({contentId:e,iconSelector:t})=>{const r=document.getElementById(e),n=a.querySelector(t);r&&n&&(r.classList.remove("hidden"),n.classList.remove("bxs-chevron-down"),n.classList.add("bxs-chevron-up"))})),!o){n.querySelectorAll(".server-item").forEach((t=>{const r=parseInt(t.dataset.index,10);if(t.parentElement!==n)return;const o=`${e}-server-content-${r}`,a=t.querySelector(".server-header-toggle i.toggle-icon"),i=document.getElementById(o);i&&a&&(r===s?(i.classList.contains("hidden")&&toggleSectionContent(o,a),setTimeout((()=>{t.scrollIntoView({behavior:"smooth",block:"nearest"})}),0)):i.classList.contains("hidden")||toggleSectionContent(o,a))}))}}return s}function setupServerMode(e,t,r,n,s){const o=e.querySelector(`select[name="servers[${t}].mode"]`);o&&(n&&s&&(o.value=s.mode||"stdio"),o.addEventListener("change",(()=>renderInstallationConfig(t,r))),renderInstallationConfig(t,r,o.value,n,s?.installation))}function setupReadOnlyState(e,t,r,n,s){const o=e.querySelector(`#${n}-server-title-${s}`),a=`MCP Server #${s+1}`;let i="true"===r?.systemTags?.adhoc;if(!i&&e.dataset.systemTags)try{"true"===JSON.parse(e.dataset.systemTags).adhoc&&(i=!0)}catch(e){}if(t){if(o)if(i)if(o.querySelector("span.text-blue-600")){const e=o.querySelector("span.text-blue-600").outerHTML;o.innerHTML=`${a} ${e}`}else o.innerHTML=`${a} <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>`;else o.innerHTML=`${a} (Read-only)`;e.querySelectorAll("input, select, textarea").forEach((e=>{e.closest(".env-var-item")||e.closest(".server-requirement-item")||(e.disabled=!0,e.classList.add("bg-gray-100","cursor-not-allowed","opacity-70"))})),e.querySelectorAll(".action-button-in-server").forEach((e=>{e.classList.contains("duplicate-mcp-server-button")?(e.style.display="flex",e.classList.remove("hidden"),e.disabled=!1):(e.style.display="none",e.classList.add("hidden"))}));[{contentId:`${n}-server-content-${s}`,iconSelector:".server-header-toggle i.toggle-icon"},{contentId:`${n}-server-deps-content-${s}`,iconSelector:`#${n}-deps-header-${s} i`},{contentId:`${n}-installation-content-${s}`,iconSelector:`#${n}-startup-header-${s} i`},{contentId:`${n}-env-vars-content-${s}`,iconSelector:`#${n}-envars-header-${s} i`}].forEach((({contentId:t,iconSelector:r})=>{const n=document.getElementById(t),s=e.querySelector(r);n&&s&&(n.classList.remove("hidden"),s.classList.remove("bxs-chevron-down"),s.classList.add("bxs-chevron-up"))}))}else{if(o)if(i)if(o.querySelector("span.text-blue-600")){const e=o.querySelector("span.text-blue-600").outerHTML;o.innerHTML=`${a} ${e}`}else o.innerHTML=`${a} <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>`;else o.innerHTML=a;setTimeout((()=>{e.querySelectorAll("input, select, textarea").forEach((e=>{e.closest(".env-var-item")||e.closest(".server-requirement-item")||(e.disabled=!1,e.removeAttribute("readonly"),e.classList.remove("bg-gray-100","cursor-not-allowed","opacity-70"))})),e.querySelectorAll(".action-button-in-server").forEach((e=>{e.style.display="flex",e.disabled=!1,e.classList.remove("hidden","opacity-50","cursor-not-allowed")}))}),0)}}export function renderInstallationConfig(e,t="serversList",r=null,n=!1,s=null){const o=document.querySelector(`#${t} .server-item[data-index="${e}"]`);if(!o)return;const a=o.querySelector(`select[name="servers[${e}].mode"]`),i=r||(a?a.value:"stdio"),l=o.querySelector(`#installation-config-${e}`),c=o.querySelector(`#env-vars-block-${e}`);if(!l)return;const d=n?"disabled":"",u=n?"bg-gray-100 cursor-not-allowed opacity-70":"";if(l.innerHTML="sse"===i?generateSSETemplate(e,d,u,s):generateStdioTemplate(e,d,u,s),"sse"===i){const t=o.querySelector(`#isLocalCheckbox-${e}`),r=o.querySelector(`#startingCommandContainer-${e}`),s=o.querySelector(`#startingCommandInput-${e}`);t&&r&&s&&t.addEventListener("change",(e=>{e.target.checked?(r.style.display="",n||(s.disabled=!1,s.classList.remove("bg-gray-100","cursor-not-allowed","opacity-70"))):(r.style.display="none",s.disabled=!0,s.classList.add("bg-gray-100","cursor-not-allowed","opacity-70"))}))}c&&(c.style.display="sse"===i?"none":"")}function generateSSETemplate(e,t,r,n){const s=t.includes("disabled"),o=!!n?.startingCommand,a=n?.startingCommand||"",i=s?"disabled":"",l=o?"checked":"",c=s||!o?"disabled":"",d=o?"":"display: none;",u=s||!o||s?r:"";return`\n <div class="space-y-4">\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1" for="server-url-${e}">Server URL*</label>\n <input type="text" id="server-url-${e}" name="servers[${e}].installation.url" required ${t}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${r}"\n placeholder="e.g., http://localhost:8000 or https://remote-server.com/api"\n value="${n?.url||""}">\n </div>\n\n <div class="flex items-center">\n <input type="checkbox" id="isLocalCheckbox-${e}" name="servers[${e}].installation.isLocal" ${i} ${l}\n class="h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 ${s?"cursor-not-allowed opacity-70":""}">\n <label for="isLocalCheckbox-${e}" class="ml-2 block text-sm text-gray-900 ${s?"cursor-not-allowed opacity-70":""}">\n Is Local Server (requires starting command)\n </label>\n </div>\n\n <div id="startingCommandContainer-${e}" style="${d}">\n <label class="block text-sm font-medium text-gray-700 mb-1" for="startingCommandInput-${e}">Starting Command</label>\n <input type="text" id="startingCommandInput-${e}" name="servers[${e}].installation.startingCommand"\n ${c}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${u}"\n placeholder="e.g., python -m my_server --port 8000"\n value="${a}">\n <p class="mt-1 text-xs text-gray-500">Command to run if the local server is not already running. Will be ignored if 'Is Local Server' is unchecked.</p>\n </div>\n </div>\n `}function generateStdioTemplate(e,t,r,n){return`\n <div class="grid grid-cols-1 md:grid-cols-2 gap-4">\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Command*</label>\n <input type="text" name="servers[${e}].installation.command" required ${t}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${r}"\n placeholder="e.g., node, python3"\n value="${n?.command||""}">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Arguments (comma-separated)</label>\n <input type="text" name="servers[${e}].installation.args" ${t}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${r}"\n placeholder="arg1, path/to/script.js, --flag"\n value="${n?.args?n.args.join(", "):""}">\n </div>\n </div>\n `}export function removeServer(e,t="serversList"){const r=document.getElementById(t);if(!r)return;const n=r.querySelector(`.server-item[data-index="${e}"]`);n&&(n.remove(),deleteEnvCounter(t,e),deleteServerRequirementCounter(t,e),reindexServers(t))}export function addEnvVariable(e,t="serversList",r=!1){const n=document.querySelector(`#${t} .server-item[data-index="${e}"] #envVarsContainer_${e}`);if(!n)return-1;const s=getEnvCounter(t,e);return n.insertAdjacentHTML("beforeend",envVariableTemplate(e,s,r,t)),setEnvCounter(t,e,s+1),s}export function removeEnvVariable(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .env-var-item[data-env-index="${t}"]`);n&&n.remove()}export function addServerRequirement(e,t="serversList",r=!1){console.log(`[addServerRequirement] ServerIndex: ${e}, isServerEffectivelyReadOnly received: ${r}`);const n=document.querySelector(`#${t} .server-item[data-index="${e}"] #server-requirements-list-${e}`);if(!n)return-1;const s=getServerRequirementCounter(t,e);return n.insertAdjacentHTML("beforeend",serverRequirementTemplate(e,s,r,t)),setServerRequirementCounter(t,e,s+1),toggleServerAliasField(e,s,t),toggleServerRegistryConfig(e,s,t),s}export function removeServerRequirement(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .server-requirement-item[data-req-index="${t}"]`);n&&n.remove()}export function toggleServerAliasField(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .server-requirement-item[data-req-index="${t}"]`);if(!n)return;const s=n.querySelector(`select[name="servers[${e}].requirements[${t}].type"]`),o=n.querySelector(`#server-alias-field-${e}-${t}`);s&&o&&o.classList.toggle("hidden","command"!==s.value)}export function toggleServerRegistryConfig(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .server-requirement-item[data-req-index="${t}"]`);if(!n)return;const s=n.querySelector(`select[name="servers[${e}].requirements[${t}].registryType"]`);s&&["github","artifacts"].forEach((r=>{const o=n.querySelector(`#server-${r}-config-${e}-${t}`);o&&o.classList.toggle("hidden",s.value!==r)}))}export function toggleSectionContent(e,t,r=null){const n=document.getElementById(e);if(!n)return;r=r||t?.parentElement||null;const s=n.classList.toggle("hidden");t&&(t.classList.toggle("bxs-chevron-up",!s),t.classList.toggle("bxs-chevron-down",s)),r&&r.setAttribute("aria-expanded",(!s).toString())}export function toggleViewMode(e,t,r,n=null,s=!1){const o={createCategory:document.getElementById("panel-create-category"),createServer:document.getElementById("panel-create-server"),jsonEditor:document.getElementById("panel-json-editor"),textarea:document.getElementById("jsonEditorTextarea"),activeForm:document.getElementById(t),viewModeToggle:document.getElementById("viewModeToggle"),actionButtons:{json:document.getElementById("jsonEditorActionsContainer"),main:document.querySelector(`#${t} ~ .flex.justify-end.space-x-4.pt-6.border-t`)}};if(!isViewAlreadyActive(e,o,t)){state.originalServerNamesForFormPopulation&&(state.originalServerNamesForFormPopulation=null);try{e?handleJsonView(o,t,r,n,s):(s&&n&&n.mcpServers&&"onboardServerForm"===t&&(state.originalServerNamesForFormPopulation=new Set(n.mcpServers.map((e=>e.name)).filter((e=>e)))),handleFormView(o,t,r,n,s),state.originalServerNamesForFormPopulation&&(state.originalServerNamesForFormPopulation=null))}catch(t){console.error("Error in view mode toggle:",t),showToast(`Error: ${t.message}`,"error"),o.viewModeToggle&&(o.viewModeToggle.checked=e),state.originalServerNamesForFormPopulation&&(state.originalServerNamesForFormPopulation=null)}}}function isViewAlreadyActive(e,t,r){if(e&&t.jsonEditor&&!t.jsonEditor.classList.contains("hidden"))return!0;if(!e&&t.jsonEditor?.classList.contains("hidden")){if("onboardForm"===r&&t.createCategory&&!t.createCategory.classList.contains("hidden"))return!0;if("onboardServerForm"===r&&t.createServer&&!t.createServer.classList.contains("hidden"))return!0}return!1}function handleJsonView(e,t,r,n,s){const o=getFeedConfiguration(e.activeForm,n,s);e.textarea.value=JSON.stringify(o,null,2),e.textarea.readOnly=s&&n?.mcpServers?.length>0,e.textarea.readOnly?(e.textarea.classList.add("bg-gray-100","cursor-not-allowed"),showToast("JSON view is read-only for existing servers in this category.","info")):e.textarea.classList.remove("bg-gray-100","cursor-not-allowed"),togglePanels(e,!0),toggleButtons(e.actionButtons,!0)}function handleFormView(e,t,r,n,s){const o=JSON.parse(e.textarea.value),a=document.getElementById(r);a&&(a.innerHTML=""),resetOnboardFormDynamicContent(t,r),populateForm(o,t,s&&n?.mcpServers?.length>0,r),togglePanels(e,!1,t),toggleButtons(e.actionButtons,!1)}function getFeedConfiguration(e,t,r){if(!r||!t)return e?getFormData(e):{};const n=getFormData(e,!0,t),s=JSON.parse(JSON.stringify(t));return s.mcpServers=n.mcpServers||[],s.requirements=n.requirements||[],s}function togglePanels(e,t,r=null){e.createCategory?.classList.add("hidden"),e.createServer?.classList.add("hidden"),e.jsonEditor?.classList.add("hidden"),t?e.jsonEditor?.classList.remove("hidden"):r&&("onboardForm"===r?e.createCategory?.classList.remove("hidden"):"onboardServerForm"===r&&e.createServer?.classList.remove("hidden"))}function toggleButtons(e,t){e.main?.classList.toggle("hidden",t),e.json?.classList.toggle("hidden",t)}export async function saveJsonData(e,t=null){const r=document.getElementById("jsonEditorTextarea");if(r.readOnly)showToast("Cannot save, JSON editor is in read-only mode for existing servers.","warning");else try{const n=prepareConfiguration(e,JSON.parse(r.value),t);if(!n)return;await saveConfiguration(n)}catch(e){console.error("Error saving JSON data:",e),showToast(`Error saving JSON data: ${e.message}`,"error")}}function prepareConfiguration(e,t,r){return"create-category"===e?t.name?{data:t,isUpdate:isUpdateOperation(t.name)}:(showToast("Category Name is required in JSON.","error"),null):"create-server"===e?r?.name?{data:mergeConfigurations(r,t),isUpdate:!0}:(showToast("No existing category context for saving JSON.","error"),null):(showToast("Invalid tab context for saving JSON.","error"),null)}function isUpdateOperation(e){const t=new URLSearchParams(window.location.search);return"edit"===t.get("action")&&t.get("category")===e}function mergeConfigurations(e,t){const r=JSON.parse(JSON.stringify(e)),n=new Set(r.mcpServers?.map((e=>e.name))||[]),s=(t.mcpServers||[]).filter((e=>!n.has(e.name)));r.mcpServers=(r.mcpServers||[]).concat(s);const o=new Set(r.requirements?.map((e=>`${e.type}|${e.name}|${e.version}`))||[]);return(t.requirements||[]).forEach((e=>{const t=`${e.type}|${e.name}|${e.version}`,n=s.some((t=>t.dependencies?.requirements?.some((t=>t.name===e.name&&t.version===e.version))));!o.has(t)&&n&&(r.requirements=r.requirements||[],r.requirements.push(e))})),r}async function saveConfiguration({data:e,isUpdate:t}){const r=await fetch("/api/categories/onboard",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({categoryData:e,isUpdate:t})});if(!r.ok){const e=await r.json();throw new Error(e.error||`HTTP error! status: ${r.status}`)}showToast("JSON data submitted successfully!","success")}export async function copyJsonToClipboard(){const e=document.getElementById("jsonEditorTextarea");if(e)try{await navigator.clipboard.writeText(e.value),showToast("JSON copied to clipboard!","success")}catch(e){console.error("Failed to copy JSON:",e),showToast("Failed to copy JSON. See console for details.","error")}else showToast("JSON content not found.","error")}export function duplicateServer(e,t){const r="serversList"===t?"onboardForm":"onboardServerForm",n=document.getElementById(r);if(!n)return void showToast(`Form with ID ${r} not found. Cannot duplicate server.`,"error");const s="existingCategoryServersList"===t;let o=null;s&&(o=window.currentSelectedCategoryData||null);if(!n.querySelector(`.server-item[data-index="${e}"]`))return void showToast("Could not find the server item to duplicate in the DOM.","error");const a=[];n.querySelectorAll("input, select, textarea").forEach((e=>{e.disabled&&(a.push({element:e,wasDisabled:!0}),e.disabled=!1)}));const i=getFormData(n,s,o);if(a.forEach((({element:e,wasDisabled:t})=>{e.disabled=t})),!i||!i.mcpServers||i.mcpServers.length<=e)return void showToast("Could not retrieve data for the server to duplicate after attempting to enable fields.","error");let l=JSON.parse(JSON.stringify(i.mcpServers[e]));l.systemTags&&delete l.systemTags;let c=!1;s&&(c=window.isExistingCategoryReadOnly||!1);const d=addServer(t,c,null);if(-1===d)return void showToast("Failed to add a new server item for duplication.","error");const u=document.getElementById(t).querySelector(`.server-item[data-index="${d}"]`);u?(populateServerManually(u,d,l,t),showToast(`Server #${e+1} duplicated to Server #${d+1}.`,"success")):showToast("Failed to find the new server item after duplication.","error")}function populateServerManually(e,t,r,n){e.querySelector(`input[name="servers[${t}].name"]`).value=r.name||"",e.querySelector(`textarea[name="servers[${t}].description"]`).value=r.description||"",e.querySelector(`select[name="servers[${t}].mode"]`).value=r.mode||"stdio",e.querySelector(`input[name="servers[${t}].schemas"]`).value=r.schemas||"",e.querySelector(`input[name="servers[${t}].repository"]`).value=r.repository||"";const s=e.querySelector(`select[name="servers[${t}].mode"]`);if(s&&s.dispatchEvent(new Event("change")),"stdio"===r.mode&&r.installation){const n=e.querySelector(`input[name="servers[${t}].installation.command"]`);n&&(n.value=r.installation.command||"");const s=e.querySelector(`input[name="servers[${t}].installation.args"]`);s&&(s.value=r.installation.args?r.installation.args.join(", "):"")}else if("sse"===r.mode&&r.installation){const n=e.querySelector(`input[name="servers[${t}].installation.url"]`);n&&(n.value=r.installation.url||"")}const o=e.querySelector(`#envVarsContainer_${t}`);o&&r.installation&&r.installation.env&&Object.entries(r.installation.env).forEach((([e,r])=>{const s=addEnvVariable(t,n,!1),a=o.querySelector(`.env-var-item[data-env-index="${s}"]`);a&&(a.querySelector(`input[name="servers[${t}].installation.env[${s}].name"]`).value=e,a.querySelector(`input[name="servers[${t}].installation.env[${s}].default"]`).value=r.Default||"",a.querySelector(`input[name="servers[${t}].installation.env[${s}].required"]`).checked=r.Required||!1,a.querySelector(`textarea[name="servers[${t}].installation.env[${s}].description"]`).value=r.Description||"")}));const a=e.querySelector(`#server-requirements-list-${t}`);a&&r.dependencies&&r.dependencies.requirements&&r.dependencies.requirements.forEach((e=>{const r=addServerRequirement(t,n,!1),s=a.querySelector(`.server-requirement-item[data-req-index="${r}"]`);if(s){s.querySelector(`input[name="servers[${t}].requirements[${r}].name"]`).value=e.name||"",s.querySelector(`select[name="servers[${t}].requirements[${r}].type"]`).value=e.type||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].version"]`).value=e.version||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].order"]`).value=e.order||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].alias"]`).value=e.alias||"";const n=s.querySelector(`select[name="servers[${t}].requirements[${r}].type"]`);n&&n.dispatchEvent(new Event("change"));const o=s.querySelector(`select[name="servers[${t}].requirements[${r}].registryType"]`);o&&(o.value=e.registryType||"public",o.dispatchEvent(new Event("change")),e.registry&&("github"===e.registryType&&e.registry.githubRelease?(s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.githubRelease.repository"]`).value=e.registry.githubRelease.repository||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.githubRelease.assetsName"]`).value=e.registry.githubRelease.assetsName||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.githubRelease.assetName"]`).value=e.registry.githubRelease.assetName||""):"artifacts"===e.registryType&&e.registry.artifacts?(s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.artifacts.registryName"]`).value=e.registry.artifacts.registryName||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.artifacts.registryUrl"]`).value=e.registry.artifacts.registryUrl||""):"local"===e.registryType&&e.registry.local&&(s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.local.localPath"]`).value=e.registry.local.localPath||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.local.assetName"]`).value=e.registry.local.assetName||"")))}})),setupReadOnlyState(e,!1,null,n,t)}window.duplicateServer=duplicateServer,Object.entries({addServer:addServer,removeServer:removeServer,addEnvVariable:addEnvVariable,removeEnvVariable:removeEnvVariable,addServerRequirement:addServerRequirement,removeServerRequirement:removeServerRequirement,toggleServerAliasField:toggleServerAliasField,toggleServerRegistryConfig:toggleServerRegistryConfig,renderInstallationConfig:renderInstallationConfig,toggleSectionContent:toggleSectionContent,copyJsonToClipboard:copyJsonToClipboard}).forEach((([e,t])=>{window[e]=t}));
1
+ import{serverTemplate,envVariableTemplate,serverRequirementTemplate}from"./templates.js";import{state,setServerCounter,getServerCounter,setEnvCounter,getEnvCounter,deleteEnvCounter,clearEnvCountersForTab,setServerRequirementCounter,getServerRequirementCounter,deleteServerRequirementCounter,clearServerRequirementCountersForTab}from"./state.js";import{getFormData,populateForm,resetOnboardFormDynamicContent}from"./formProcessor.js";import{showToast}from"../notifications.js";function reindexElements(e,t,r,n){n.forEach((({selector:n,idBase:s,namePattern:o})=>{const a=e.querySelector(n);if(a&&(s&&(a.id=`${s}${r}`),o&&a.getAttribute("name"))){const e=a.getAttribute("name").replace(new RegExp(o.replace("INDEX",t)),`$1${r}$2`);a.setAttribute("name",e)}}))}function reindexServers(e="serversList"){const t=document.getElementById(e);if(!t)return;const r=t.querySelectorAll(".server-item"),n=new Map,s=new Map;r.forEach(((t,r)=>{const o=parseInt(t.dataset.index,10);t.dataset.index=r;const a=t.querySelector("h3");if(a){const e=a.textContent||"",t=`MCP Server #${r+1}`;let n="";e.includes("(Adhoc - Editable)")?n=' <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>':e.includes("(Read-only)")&&(n=" (Read-only)"),a.innerHTML=`${t}${n}`}const i=t.querySelector(`#${e}-server-header-${o}`);if(i){i.id=`${e}-server-header-${r}`;const t=`${e}-server-content-${o}`,n=`${e}-server-content-${r}`;let s=i.getAttribute("onclick");s&&(s=s.replace(new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),n),i.setAttribute("onclick",s));let a=i.getAttribute("onkeydown");a&&(a=a.replace(new RegExp(t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),n),i.setAttribute("onkeydown",a)),i.setAttribute("aria-controls",n)}const l=t.querySelector(`#${e}-server-title-${o}`);l&&(l.id=`${e}-server-title-${r}`);const c=t.querySelector(`#${e}-server-content-${o}`);c&&c.setAttribute("aria-labelledby",`${e}-server-title-${r}`),t.querySelectorAll("[onclick]").forEach((t=>{const n=t.getAttribute("onclick");if(!n)return;if(t.id===`${e}-server-header-${r}`)return;const s=n.replace(new RegExp(`\\((\\s*)${o}(\\s*[,\\)])`,"g"),`($1${r}$2`).replace(new RegExp(`${e}-server-deps-content-${o}`.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),`${e}-server-deps-content-${r}`).replace(new RegExp(`${e}-installation-content-${o}`.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),`${e}-installation-content-${r}`).replace(new RegExp(`${e}-env-vars-content-${o}`.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),"g"),`${e}-env-vars-content-${r}`);t.setAttribute("onclick",s)})),reindexElements(t,o,r,[{selector:`#${e}-server-content-${o}`,idBase:`${e}-server-content-`},{selector:`#${e}-server-deps-content-${o}`,idBase:`${e}-server-deps-content-`},{selector:`#${e}-installation-content-${o}`,idBase:`${e}-installation-content-`},{selector:`#${e}-env-vars-content-${o}`,idBase:`${e}-env-vars-content-`},{selector:`#schema-path-${o}`,idBase:"schema-path-"},{selector:`#envVarsContainer_${o}`,idBase:"envVarsContainer_"}]);const d=t.querySelector(`#envVarsContainer_${r}`);let u=0;d&&d.querySelectorAll(".env-var-item").forEach(((e,t)=>{const n=parseInt(e.dataset.envIndex,10);e.dataset.envIndex=t,reindexElements(e,n,t,[{selector:"[name]",namePattern:`(servers\\[${r}\\]\\.installation\\.env\\[)\\d+(\\]\\..+)`}]),u++})),n.set(r,u);const m=t.querySelector(`#server-requirements-list-${r}`);let v=0;m&&m.querySelectorAll(".server-requirement-item").forEach(((e,t)=>{const n=parseInt(e.dataset.reqIndex,10);e.dataset.reqIndex=t,reindexElements(e,n,t,[{selector:"[name]",namePattern:`(servers\\[${r}\\]\\.requirements\\[)\\d+(\\]\\..+)`}]),v++})),s.set(r,v)})),clearEnvCountersForTab(e),n.forEach(((t,r)=>setEnvCounter(e,r,t))),clearServerRequirementCountersForTab(e),s.forEach(((t,r)=>setServerRequirementCounter(e,r,t))),setServerCounter(e,r.length)}export function addServer(e="serversList",t=!1,r=null){const n=document.getElementById(e);if(!n)return-1;0===n.children.length&&(setServerCounter(e,0),clearEnvCountersForTab(e),clearServerRequirementCountersForTab(e));const s=getServerCounter(e);let o;o=!("true"===r?.systemTags?.adhoc)&&(!!t&&(state.originalServerNamesForFormPopulation?!!(r&&r.name&&state.originalServerNamesForFormPopulation.has(r.name)):!!r)),n.insertAdjacentHTML("beforeend",serverTemplate(s,t,r,e)),setEnvCounter(e,s,0),setServerRequirementCounter(e,s,0),setServerCounter(e,s+1);const a=n.querySelector(`.server-item[data-index="${s}"]`);if(a){r&&r.systemTags?a.dataset.systemTags=JSON.stringify(r.systemTags):r&&!r.systemTags?delete a.dataset.systemTags:r||delete a.dataset.systemTags,r&&r.name?a.dataset.originalName=r.name:delete a.dataset.originalName,setupServerMode(a,s,e,o,r),setupReadOnlyState(a,o,r,e,s);if([{contentId:`${e}-server-deps-content-${s}`,iconSelector:`#${e}-deps-header-${s} i`},{contentId:`${e}-installation-content-${s}`,iconSelector:`#${e}-startup-header-${s} i`},{contentId:`${e}-env-vars-content-${s}`,iconSelector:`#${e}-envars-header-${s} i`}].forEach((({contentId:e,iconSelector:t})=>{const r=document.getElementById(e),n=a.querySelector(t);r&&n&&(r.classList.remove("hidden"),n.classList.remove("bxs-chevron-down"),n.classList.add("bxs-chevron-up"))})),!o){n.querySelectorAll(".server-item").forEach((t=>{const r=parseInt(t.dataset.index,10);if(t.parentElement!==n)return;const o=`${e}-server-content-${r}`,a=t.querySelector(".server-header-toggle i.toggle-icon"),i=document.getElementById(o);i&&a&&(r===s?(i.classList.contains("hidden")&&toggleSectionContent(o,a),setTimeout((()=>{t.scrollIntoView({behavior:"smooth",block:"nearest"})}),0)):i.classList.contains("hidden")||toggleSectionContent(o,a))}))}}return s}function setupServerMode(e,t,r,n,s){const o=e.querySelector(`select[name="servers[${t}].mode"]`);o&&(n&&s&&(o.value=s.mode||"stdio"),o.addEventListener("change",(()=>renderInstallationConfig(t,r))),renderInstallationConfig(t,r,o.value,n,s?.installation))}function setupReadOnlyState(e,t,r,n,s){const o=e.querySelector(`#${n}-server-title-${s}`),a=`MCP Server #${s+1}`;let i="true"===r?.systemTags?.adhoc;if(!i&&e.dataset.systemTags)try{"true"===JSON.parse(e.dataset.systemTags).adhoc&&(i=!0)}catch(e){}if(t){if(o)if(i)if(o.querySelector("span.text-blue-600")){const e=o.querySelector("span.text-blue-600").outerHTML;o.innerHTML=`${a} ${e}`}else o.innerHTML=`${a} <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>`;else o.innerHTML=`${a} (Read-only)`;e.querySelectorAll("input, select, textarea").forEach((e=>{e.closest(".env-var-item")||e.closest(".server-requirement-item")||(e.disabled=!0,e.classList.add("bg-gray-100","cursor-not-allowed","opacity-70"))})),e.querySelectorAll(".action-button-in-server").forEach((e=>{e.classList.contains("duplicate-mcp-server-button")?(e.style.display="flex",e.classList.remove("hidden"),e.disabled=!1):(e.style.display="none",e.classList.add("hidden"))}));[{contentId:`${n}-server-content-${s}`,iconSelector:".server-header-toggle i.toggle-icon"},{contentId:`${n}-server-deps-content-${s}`,iconSelector:`#${n}-deps-header-${s} i`},{contentId:`${n}-installation-content-${s}`,iconSelector:`#${n}-startup-header-${s} i`},{contentId:`${n}-env-vars-content-${s}`,iconSelector:`#${n}-envars-header-${s} i`}].forEach((({contentId:t,iconSelector:r})=>{const n=document.getElementById(t),s=e.querySelector(r);n&&s&&(n.classList.remove("hidden"),s.classList.remove("bxs-chevron-down"),s.classList.add("bxs-chevron-up"))}))}else{if(o)if(i)if(o.querySelector("span.text-blue-600")){const e=o.querySelector("span.text-blue-600").outerHTML;o.innerHTML=`${a} ${e}`}else o.innerHTML=`${a} <span class="text-sm text-blue-600 ml-1">(Adhoc - Editable)</span>`;else o.innerHTML=a;setTimeout((()=>{e.querySelectorAll("input, select, textarea").forEach((e=>{e.closest(".env-var-item")||e.closest(".server-requirement-item")||(e.disabled=!1,e.removeAttribute("readonly"),e.classList.remove("bg-gray-100","cursor-not-allowed","opacity-70"))})),e.querySelectorAll(".action-button-in-server").forEach((e=>{e.style.display="flex",e.disabled=!1,e.classList.remove("hidden","opacity-50","cursor-not-allowed")}))}),0)}}export function renderInstallationConfig(e,t="serversList",r=null,n=!1,s=null){const o=document.querySelector(`#${t} .server-item[data-index="${e}"]`);if(!o)return;const a=o.querySelector(`select[name="servers[${e}].mode"]`),i=r||(a?a.value:"stdio"),l=o.querySelector(`#installation-config-${e}`),c=o.querySelector(`#env-vars-block-${e}`);if(!l)return;const d=n?"disabled":"",u=n?"bg-gray-100 cursor-not-allowed opacity-70":"";if(l.innerHTML="sse"===i||"streamable-http"===i?generateSSETemplate(e,d,u,s):generateStdioTemplate(e,d,u,s),"sse"===i||"streamable-http"===i){const t=o.querySelector(`#isLocalCheckbox-${e}`),r=o.querySelector(`#startingCommandContainer-${e}`),s=o.querySelector(`#startingCommandInput-${e}`);t&&r&&s&&t.addEventListener("change",(e=>{e.target.checked?(r.style.display="",n||(s.disabled=!1,s.classList.remove("bg-gray-100","cursor-not-allowed","opacity-70"))):(r.style.display="none",s.disabled=!0,s.classList.add("bg-gray-100","cursor-not-allowed","opacity-70"))}))}c&&(c.style.display="sse"===i||"streamable-http"===i?"none":"")}function generateSSETemplate(e,t,r,n){const s=t.includes("disabled"),o=!!n?.startingCommand,a=n?.startingCommand||"",i=s?"disabled":"",l=o?"checked":"",c=s||!o?"disabled":"",d=o?"":"display: none;",u=s||!o||s?r:"";return`\n <div class="space-y-4">\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1" for="server-url-${e}">Server URL*</label>\n <input type="text" id="server-url-${e}" name="servers[${e}].installation.url" required ${t}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${r}"\n placeholder="e.g., http://localhost:8000 or https://remote-server.com/api"\n value="${n?.url||""}">\n </div>\n\n <div class="flex items-center">\n <input type="checkbox" id="isLocalCheckbox-${e}" name="servers[${e}].installation.isLocal" ${i} ${l}\n class="h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500 ${s?"cursor-not-allowed opacity-70":""}">\n <label for="isLocalCheckbox-${e}" class="ml-2 block text-sm text-gray-900 ${s?"cursor-not-allowed opacity-70":""}">\n Is Local Server (requires starting command)\n </label>\n </div>\n\n <div id="startingCommandContainer-${e}" style="${d}">\n <label class="block text-sm font-medium text-gray-700 mb-1" for="startingCommandInput-${e}">Starting Command</label>\n <input type="text" id="startingCommandInput-${e}" name="servers[${e}].installation.startingCommand"\n ${c}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${u}"\n placeholder="e.g., python -m my_server --port 8000"\n value="${a}">\n <p class="mt-1 text-xs text-gray-500">Command to run if the local server is not already running. Will be ignored if 'Is Local Server' is unchecked.</p>\n </div>\n </div>\n `}function generateStdioTemplate(e,t,r,n){return`\n <div class="grid grid-cols-1 md:grid-cols-2 gap-4">\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Command*</label>\n <input type="text" name="servers[${e}].installation.command" required ${t}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${r}"\n placeholder="e.g., node, python3"\n value="${n?.command||""}">\n </div>\n <div>\n <label class="block text-sm font-medium text-gray-700 mb-1">Arguments (comma-separated)</label>\n <input type="text" name="servers[${e}].installation.args" ${t}\n class="w-full px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${r}"\n placeholder="arg1, path/to/script.js, --flag"\n value="${n?.args?n.args.join(", "):""}">\n </div>\n </div>\n `}export function removeServer(e,t="serversList"){const r=document.getElementById(t);if(!r)return;const n=r.querySelector(`.server-item[data-index="${e}"]`);n&&(n.remove(),deleteEnvCounter(t,e),deleteServerRequirementCounter(t,e),reindexServers(t))}export function addEnvVariable(e,t="serversList",r=!1){const n=document.querySelector(`#${t} .server-item[data-index="${e}"] #envVarsContainer_${e}`);if(!n)return-1;const s=getEnvCounter(t,e);return n.insertAdjacentHTML("beforeend",envVariableTemplate(e,s,r,t)),setEnvCounter(t,e,s+1),s}export function removeEnvVariable(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .env-var-item[data-env-index="${t}"]`);n&&n.remove()}export function addServerRequirement(e,t="serversList",r=!1){console.log(`[addServerRequirement] ServerIndex: ${e}, isServerEffectivelyReadOnly received: ${r}`);const n=document.querySelector(`#${t} .server-item[data-index="${e}"] #server-requirements-list-${e}`);if(!n)return-1;const s=getServerRequirementCounter(t,e);return n.insertAdjacentHTML("beforeend",serverRequirementTemplate(e,s,r,t)),setServerRequirementCounter(t,e,s+1),toggleServerAliasField(e,s,t),toggleServerRegistryConfig(e,s,t),s}export function removeServerRequirement(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .server-requirement-item[data-req-index="${t}"]`);n&&n.remove()}export function toggleServerAliasField(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .server-requirement-item[data-req-index="${t}"]`);if(!n)return;const s=n.querySelector(`select[name="servers[${e}].requirements[${t}].type"]`),o=n.querySelector(`#server-alias-field-${e}-${t}`);s&&o&&o.classList.toggle("hidden","command"!==s.value)}export function toggleServerRegistryConfig(e,t,r="serversList"){const n=document.querySelector(`#${r} .server-item[data-index="${e}"] .server-requirement-item[data-req-index="${t}"]`);if(!n)return;const s=n.querySelector(`select[name="servers[${e}].requirements[${t}].registryType"]`);s&&["github","artifacts"].forEach((r=>{const o=n.querySelector(`#server-${r}-config-${e}-${t}`);o&&o.classList.toggle("hidden",s.value!==r)}))}export function toggleSectionContent(e,t,r=null){const n=document.getElementById(e);if(!n)return;r=r||t?.parentElement||null;const s=n.classList.toggle("hidden");t&&(t.classList.toggle("bxs-chevron-up",!s),t.classList.toggle("bxs-chevron-down",s)),r&&r.setAttribute("aria-expanded",(!s).toString())}export function toggleViewMode(e,t,r,n=null,s=!1){const o={createCategory:document.getElementById("panel-create-category"),createServer:document.getElementById("panel-create-server"),jsonEditor:document.getElementById("panel-json-editor"),textarea:document.getElementById("jsonEditorTextarea"),activeForm:document.getElementById(t),viewModeToggle:document.getElementById("viewModeToggle"),actionButtons:{json:document.getElementById("jsonEditorActionsContainer"),main:document.querySelector(`#${t} ~ .flex.justify-end.space-x-4.pt-6.border-t`)}};if(!isViewAlreadyActive(e,o,t)){state.originalServerNamesForFormPopulation&&(state.originalServerNamesForFormPopulation=null);try{e?handleJsonView(o,t,r,n,s):(s&&n&&n.mcpServers&&"onboardServerForm"===t&&(state.originalServerNamesForFormPopulation=new Set(n.mcpServers.map((e=>e.name)).filter((e=>e)))),handleFormView(o,t,r,n,s),state.originalServerNamesForFormPopulation&&(state.originalServerNamesForFormPopulation=null))}catch(t){console.error("Error in view mode toggle:",t),showToast(`Error: ${t.message}`,"error"),o.viewModeToggle&&(o.viewModeToggle.checked=e),state.originalServerNamesForFormPopulation&&(state.originalServerNamesForFormPopulation=null)}}}function isViewAlreadyActive(e,t,r){if(e&&t.jsonEditor&&!t.jsonEditor.classList.contains("hidden"))return!0;if(!e&&t.jsonEditor?.classList.contains("hidden")){if("onboardForm"===r&&t.createCategory&&!t.createCategory.classList.contains("hidden"))return!0;if("onboardServerForm"===r&&t.createServer&&!t.createServer.classList.contains("hidden"))return!0}return!1}function handleJsonView(e,t,r,n,s){const o=getFeedConfiguration(e.activeForm,n,s);e.textarea.value=JSON.stringify(o,null,2),e.textarea.readOnly=s&&n?.mcpServers?.length>0,e.textarea.readOnly?(e.textarea.classList.add("bg-gray-100","cursor-not-allowed"),showToast("JSON view is read-only for existing servers in this category.","info")):e.textarea.classList.remove("bg-gray-100","cursor-not-allowed"),togglePanels(e,!0),toggleButtons(e.actionButtons,!0)}function handleFormView(e,t,r,n,s){const o=JSON.parse(e.textarea.value),a=document.getElementById(r);a&&(a.innerHTML=""),resetOnboardFormDynamicContent(t,r),populateForm(o,t,s&&n?.mcpServers?.length>0,r),togglePanels(e,!1,t),toggleButtons(e.actionButtons,!1)}function getFeedConfiguration(e,t,r){if(!r||!t)return e?getFormData(e):{};const n=getFormData(e,!0,t),s=JSON.parse(JSON.stringify(t));return s.mcpServers=n.mcpServers||[],s.requirements=n.requirements||[],s}function togglePanels(e,t,r=null){e.createCategory?.classList.add("hidden"),e.createServer?.classList.add("hidden"),e.jsonEditor?.classList.add("hidden"),t?e.jsonEditor?.classList.remove("hidden"):r&&("onboardForm"===r?e.createCategory?.classList.remove("hidden"):"onboardServerForm"===r&&e.createServer?.classList.remove("hidden"))}function toggleButtons(e,t){e.main?.classList.toggle("hidden",t),e.json?.classList.toggle("hidden",t)}export async function saveJsonData(e,t=null){const r=document.getElementById("jsonEditorTextarea");if(r.readOnly)showToast("Cannot save, JSON editor is in read-only mode for existing servers.","warning");else try{const n=prepareConfiguration(e,JSON.parse(r.value),t);if(!n)return;await saveConfiguration(n)}catch(e){console.error("Error saving JSON data:",e),showToast(`Error saving JSON data: ${e.message}`,"error")}}function prepareConfiguration(e,t,r){return"create-category"===e?t.name?{data:t,isUpdate:isUpdateOperation(t.name)}:(showToast("Category Name is required in JSON.","error"),null):"create-server"===e?r?.name?{data:mergeConfigurations(r,t),isUpdate:!0}:(showToast("No existing category context for saving JSON.","error"),null):(showToast("Invalid tab context for saving JSON.","error"),null)}function isUpdateOperation(e){const t=new URLSearchParams(window.location.search);return"edit"===t.get("action")&&t.get("category")===e}function mergeConfigurations(e,t){const r=JSON.parse(JSON.stringify(e)),n=new Set(r.mcpServers?.map((e=>e.name))||[]),s=(t.mcpServers||[]).filter((e=>!n.has(e.name)));r.mcpServers=(r.mcpServers||[]).concat(s);const o=new Set(r.requirements?.map((e=>`${e.type}|${e.name}|${e.version}`))||[]);return(t.requirements||[]).forEach((e=>{const t=`${e.type}|${e.name}|${e.version}`,n=s.some((t=>t.dependencies?.requirements?.some((t=>t.name===e.name&&t.version===e.version))));!o.has(t)&&n&&(r.requirements=r.requirements||[],r.requirements.push(e))})),r}async function saveConfiguration({data:e,isUpdate:t}){const r=await fetch("/api/categories/onboard",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({categoryData:e,isUpdate:t})});if(!r.ok){const e=await r.json();throw new Error(e.error||`HTTP error! status: ${r.status}`)}showToast("JSON data submitted successfully!","success")}export async function copyJsonToClipboard(){const e=document.getElementById("jsonEditorTextarea");if(e)try{await navigator.clipboard.writeText(e.value),showToast("JSON copied to clipboard!","success")}catch(e){console.error("Failed to copy JSON:",e),showToast("Failed to copy JSON. See console for details.","error")}else showToast("JSON content not found.","error")}export function duplicateServer(e,t){const r="serversList"===t?"onboardForm":"onboardServerForm",n=document.getElementById(r);if(!n)return void showToast(`Form with ID ${r} not found. Cannot duplicate server.`,"error");const s="existingCategoryServersList"===t;let o=null;s&&(o=window.currentSelectedCategoryData||null);if(!n.querySelector(`.server-item[data-index="${e}"]`))return void showToast("Could not find the server item to duplicate in the DOM.","error");const a=[];n.querySelectorAll("input, select, textarea").forEach((e=>{e.disabled&&(a.push({element:e,wasDisabled:!0}),e.disabled=!1)}));const i=getFormData(n,s,o);if(a.forEach((({element:e,wasDisabled:t})=>{e.disabled=t})),!i||!i.mcpServers||i.mcpServers.length<=e)return void showToast("Could not retrieve data for the server to duplicate after attempting to enable fields.","error");let l=JSON.parse(JSON.stringify(i.mcpServers[e]));l.systemTags&&delete l.systemTags;let c=!1;s&&(c=window.isExistingCategoryReadOnly||!1);const d=addServer(t,c,null);if(-1===d)return void showToast("Failed to add a new server item for duplication.","error");const u=document.getElementById(t).querySelector(`.server-item[data-index="${d}"]`);u?(populateServerManually(u,d,l,t),showToast(`Server #${e+1} duplicated to Server #${d+1}.`,"success")):showToast("Failed to find the new server item after duplication.","error")}function populateServerManually(e,t,r,n){e.querySelector(`input[name="servers[${t}].name"]`).value=r.name||"",e.querySelector(`textarea[name="servers[${t}].description"]`).value=r.description||"",e.querySelector(`select[name="servers[${t}].mode"]`).value=r.mode||"stdio",e.querySelector(`input[name="servers[${t}].schemas"]`).value=r.schemas||"",e.querySelector(`input[name="servers[${t}].repository"]`).value=r.repository||"";const s=e.querySelector(`select[name="servers[${t}].mode"]`);if(s&&s.dispatchEvent(new Event("change")),"stdio"===r.mode&&r.installation){const n=e.querySelector(`input[name="servers[${t}].installation.command"]`);n&&(n.value=r.installation.command||"");const s=e.querySelector(`input[name="servers[${t}].installation.args"]`);s&&(s.value=r.installation.args?r.installation.args.join(", "):"")}else if(("sse"===r.mode||"streamable-http"===r.mode)&&r.installation){const n=e.querySelector(`input[name="servers[${t}].installation.url"]`);n&&(n.value=r.installation.url||"")}const o=e.querySelector(`#envVarsContainer_${t}`);o&&r.installation&&r.installation.env&&Object.entries(r.installation.env).forEach((([e,r])=>{const s=addEnvVariable(t,n,!1),a=o.querySelector(`.env-var-item[data-env-index="${s}"]`);a&&(a.querySelector(`input[name="servers[${t}].installation.env[${s}].name"]`).value=e,a.querySelector(`input[name="servers[${t}].installation.env[${s}].default"]`).value=r.Default||"",a.querySelector(`input[name="servers[${t}].installation.env[${s}].required"]`).checked=r.Required||!1,a.querySelector(`textarea[name="servers[${t}].installation.env[${s}].description"]`).value=r.Description||"")}));const a=e.querySelector(`#server-requirements-list-${t}`);a&&r.dependencies&&r.dependencies.requirements&&r.dependencies.requirements.forEach((e=>{const r=addServerRequirement(t,n,!1),s=a.querySelector(`.server-requirement-item[data-req-index="${r}"]`);if(s){s.querySelector(`input[name="servers[${t}].requirements[${r}].name"]`).value=e.name||"",s.querySelector(`select[name="servers[${t}].requirements[${r}].type"]`).value=e.type||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].version"]`).value=e.version||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].order"]`).value=e.order||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].alias"]`).value=e.alias||"";const n=s.querySelector(`select[name="servers[${t}].requirements[${r}].type"]`);n&&n.dispatchEvent(new Event("change"));const o=s.querySelector(`select[name="servers[${t}].requirements[${r}].registryType"]`);o&&(o.value=e.registryType||"public",o.dispatchEvent(new Event("change")),e.registry&&("github"===e.registryType&&e.registry.githubRelease?(s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.githubRelease.repository"]`).value=e.registry.githubRelease.repository||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.githubRelease.assetsName"]`).value=e.registry.githubRelease.assetsName||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.githubRelease.assetName"]`).value=e.registry.githubRelease.assetName||""):"artifacts"===e.registryType&&e.registry.artifacts?(s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.artifacts.registryName"]`).value=e.registry.artifacts.registryName||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.artifacts.registryUrl"]`).value=e.registry.artifacts.registryUrl||""):"local"===e.registryType&&e.registry.local&&(s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.local.localPath"]`).value=e.registry.local.localPath||"",s.querySelector(`input[name="servers[${t}].requirements[${r}].registry.local.assetName"]`).value=e.registry.local.assetName||"")))}})),setupReadOnlyState(e,!1,null,n,t)}window.duplicateServer=duplicateServer,Object.entries({addServer:addServer,removeServer:removeServer,addEnvVariable:addEnvVariable,removeEnvVariable:removeEnvVariable,addServerRequirement:addServerRequirement,removeServerRequirement:removeServerRequirement,toggleServerAliasField:toggleServerAliasField,toggleServerRegistryConfig:toggleServerRegistryConfig,renderInstallationConfig:renderInstallationConfig,toggleSectionContent:toggleSectionContent,copyJsonToClipboard:copyJsonToClipboard}).forEach((([e,t])=>{window[e]=t}));
2
2
  //# sourceMappingURL=uiHandlers.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imcp",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Node.js SDK for Model Context Protocol (MCP)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",