[docs]asyncdefget_installed_plugin_metadata(plugin_name:str)->dict:"""Get metadata from main plugin manifest"""try:manifest_path=Path('data/plugin_manifest.json')logger.debug(f"Reading main plugin manifest from: {manifest_path}")ifnotmanifest_path.exists():raiseValueError(f"Main plugin manifest not found at {manifest_path}")withopen(manifest_path)asf:manifest_data=json.load(f)# Find the plugin in the installed plugins sectioninstalled_plugins=manifest_data.get('plugins',{}).get('installed',{})print("installed_plugins",installed_plugins)plugin_data=installed_plugins.get(plugin_name)ifnotplugin_data:raiseValueError(f"Plugin {plugin_name} not found in manifest")logger.debug(f"Found plugin data in manifest: {plugin_data}")return{'commands':plugin_data.get('commands',[]),'services':plugin_data.get('services',[]),'dependencies':plugin_data.get('dependencies',[])}exceptExceptionase:logger.error(f"Error reading plugin manifest: {str(e)}")raise
[docs]asyncdefcreate_distributable_entry(plugin:PluginEntry)->dict:"""Transform plugin entry to distributable format"""try:# Get metadata from main manifest using display namemetadata=awaitget_installed_plugin_metadata(plugin.name)# Get the remote_source from plugin dataifnotplugin.remote_sourceandplugin.source_path:# Extract from source_path if neededplugin_id=Path(plugin.source_path).parent.nameremote_source=f"runvnc/{plugin_id}"else:remote_source=plugin.remote_sourceor''return{'name':plugin.name,'version':plugin.version,'description':plugin.description,'source':'github','github_url':f"https://github.com/{remote_source}",'commands':metadata['commands'],'services':metadata['services'],'dependencies':metadata['dependencies'],'added_at':datetime.now().isoformat()}exceptExceptionase:logger.error(f"Error creating distributable entry: {str(e)}")raise
[docs]asyncdefadd_plugin(INDEX_DIR:Path,index_name:str,plugin:PluginEntry):"""Add a plugin to an index"""try:logger.debug(f"Adding plugin: {plugin.name} to index: {index_name}")logger.debug(f"Plugin data: {plugin.dict()}")index_dir=INDEX_DIR/index_nameindex_file=index_dir/'index.json'ifnotindex_file.exists():returnJSONResponse({'success':False,'message':'Index not found'})# Early validation - check for required GitHub infohas_github_info=(plugin.remote_sourceorplugin.github_urlorgetattr(plugin,'metadata',{}).get('github_url'))ifnothas_github_info:returnJSONResponse({'success':False,'message':'Plugin missing GitHub repository information. Cannot add to index.'})# Check if plugin is localifplugin.source=='local':returnJSONResponse({'success':False,'message':'Local plugins cannot be added to an index'})withopen(index_file,'r')asf:index_data=json.load(f)ifany(p['name']==plugin.nameforpinindex_data['plugins']):returnJSONResponse({'success':False,'message':'Plugin already in index'})# Transform to distributable formattry:plugin_data=awaitcreate_distributable_entry(plugin)exceptExceptionase:returnJSONResponse({'success':False,'message':f'Failed to create distributable plugin entry: {str(e)}'})index_data['plugins'].append(plugin_data)withopen(index_file,'w')asf:json.dump(index_data,f,indent=2)returnJSONResponse({'success':True,'data':index_data})exceptExceptionase:logger.error(f"Error adding plugin: {str(e)}",exc_info=True)raiseHTTPException(status_code=500,detail=str(e))
[docs]asyncdefremove_plugin(INDEX_DIR:Path,index_name:str,plugin_name:str):"""Remove a plugin from an index"""try:index_dir=INDEX_DIR/index_nameindex_file=index_dir/'index.json'ifnotindex_file.exists():returnJSONResponse({'success':False,'message':'Index not found'})withopen(index_file,'r')asf:index_data=json.load(f)# Remove from index dataindex_data['plugins']=[pforpinindex_data['plugins']ifp['name']!=plugin_name]withopen(index_file,'w')asf:json.dump(index_data,f,indent=2)returnJSONResponse({'success':True,'data':index_data})exceptExceptionase:logger.error(f"Error removing plugin: {str(e)}",exc_info=True)raiseHTTPException(status_code=500,detail=str(e))