mindroot 8.1.0__py3-none-any.whl → 8.2.0__py3-none-any.whl

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.

Potentially problematic release.


This version of mindroot might be problematic. Click here for more details.

@@ -1,5 +1,6 @@
1
- from fastapi import APIRouter, HTTPException
1
+ from fastapi import APIRouter, HTTPException, Request
2
2
  from pydantic import BaseModel
3
+ from sse_starlette.sse import EventSourceResponse
3
4
  import traceback
4
5
  import os
5
6
  import json
@@ -8,6 +9,10 @@ from lib.plugins import (
8
9
  load_plugin_manifest, update_plugin_manifest, plugin_install,
9
10
  save_plugin_manifest, plugin_update, toggle_plugin_state, get_plugin_path
10
11
  )
12
+ from lib.plugins.installation import download_github_files
13
+ from lib.streamcmd import stream_command_as_events
14
+ import asyncio
15
+
11
16
 
12
17
  router = APIRouter()
13
18
 
@@ -30,12 +35,122 @@ class InstallFromIndexRequest(BaseModel):
30
35
  plugin: str
31
36
  index_name: str
32
37
 
38
+ class StreamInstallRequest(BaseModel):
39
+ plugin: str
40
+ source: str
41
+ source_path: str = None
42
+
33
43
  class PluginMetadata(BaseModel):
34
44
  description: Optional[str] = None
35
45
  commands: Optional[List[str]] = None
36
46
  services: Optional[List[str]] = None
37
47
  dependencies: Optional[List[str]] = None
38
48
 
49
+ import sys, os, shlex
50
+
51
+ @router.post("/stream-install-plugin", response_class=EventSourceResponse)
52
+ async def stream_install_plugin(request: StreamInstallRequest):
53
+ """Stream the installation process of a plugin using SSE (POST method)."""
54
+ # Prepare the command based on the source
55
+ if request.source == 'github_direct':
56
+ cmd = [sys.executable, '-m', 'pip', 'install', '-e', request.source_path, '-v', '--no-cache-dir']
57
+ elif request.source == 'local':
58
+ cmd = [sys.executable, '-m', 'pip', 'install', '-e', request.source_path, '-v', '--no-cache-dir']
59
+ elif request.source == 'pypi':
60
+ cmd = [sys.executable, '-m', 'pip', 'install', request.plugin, '-v', '--no-cache-dir']
61
+ else:
62
+ return {"success": False, "message": "Invalid source"}
63
+
64
+ # For GitHub installations, use the plugin_install function which handles the download and extraction
65
+ if request.source == 'github':
66
+ try:
67
+ # Use the streaming approach for GitHub installations
68
+ parts = request.source_path.split(':')
69
+ repo_path = parts[0]
70
+ tag = parts[1] if len(parts) > 1 else None
71
+
72
+ async def stream_github_install():
73
+ yield {"event": "message", "data": f"Downloading GitHub repository {repo_path}..."}
74
+
75
+ try:
76
+ plugin_dir, _, plugin_info = download_github_files(repo_path, tag)
77
+
78
+ cmd = [sys.executable, '-m', 'pip', 'install', '-e', plugin_dir, '-v', '--no-cache-dir']
79
+ async for event in stream_command_as_events(cmd):
80
+ yield event
81
+
82
+ update_plugin_manifest(
83
+ plugin_info['name'], 'github', os.path.abspath(plugin_dir),
84
+ remote_source=repo_path, version=plugin_info.get('version', '0.0.1'),
85
+ metadata=plugin_info
86
+ )
87
+ except Exception as e:
88
+ yield {"event": "error", "data": f"Error installing from GitHub: {str(e)}"}
89
+
90
+ return EventSourceResponse(stream_github_install())
91
+ except Exception as e:
92
+ return {"success": False, "message": f"Error setting up GitHub installation: {str(e)}"}
93
+
94
+ # For other sources, use our streamcmd module to stream the command output
95
+ return EventSourceResponse(stream_command_as_events(cmd))
96
+ @router.get("/stream-install-plugin", response_class=EventSourceResponse)
97
+ async def stream_install_plugin_get(request: Request):
98
+ """Stream the installation process of a plugin using SSE (GET method)."""
99
+ # Extract parameters from query string
100
+ plugin = request.query_params.get("plugin", "")
101
+ source = request.query_params.get("source", "")
102
+ source_path = request.query_params.get("source_path", "")
103
+
104
+ # Use the new simpler approach
105
+ if source == 'github':
106
+ cmd = [sys.executable, '-m', 'pip', 'install', '-e', source_path, '-v', '--no-cache-dir']
107
+ message = f"Installing {plugin} from GitHub repository {source_path}..."
108
+ elif source == 'local':
109
+ cmd = [sys.executable, '-m', 'pip', 'install', '-e', source_path, '-v', '--no-cache-dir']
110
+ message = f"Installing from local path: {source_path}"
111
+ elif source == 'pypi':
112
+ cmd = [sys.executable, '-m', 'pip', 'install', plugin, '-v', '--no-cache-dir']
113
+ message = f"Installing from PyPI: {plugin}"
114
+ else:
115
+ return {"success": False, "message": "Invalid source"}
116
+
117
+ # For GitHub installations, use the plugin_install function which handles the download and extraction
118
+ if source == 'github':
119
+ try:
120
+ # Use the streaming approach for GitHub installations
121
+ parts = source_path.split(':')
122
+ repo_path = parts[0]
123
+ tag = parts[1] if len(parts) > 1 else None
124
+
125
+ # First yield a message about downloading
126
+ async def stream_github_install():
127
+ yield {"event": "message", "data": f"Downloading GitHub repository {repo_path}..."}
128
+
129
+ # Download and extract the GitHub repository
130
+ try:
131
+ plugin_dir, _, plugin_info = download_github_files(repo_path, tag)
132
+
133
+ # Now stream the installation from the local directory
134
+ cmd = [sys.executable, '-m', 'pip', 'install', '-e', plugin_dir, '-v', '--no-cache-dir']
135
+ async for event in stream_command_as_events(cmd):
136
+ yield event
137
+
138
+ # Update the plugin manifest
139
+ update_plugin_manifest(
140
+ plugin_info['name'], 'github', os.path.abspath(plugin_dir),
141
+ remote_source=repo_path, version=plugin_info.get('version', '0.0.1'),
142
+ metadata=plugin_info
143
+ )
144
+ except Exception as e:
145
+ yield {"event": "error", "data": f"Error installing from GitHub: {str(e)}"}
146
+
147
+ return EventSourceResponse(stream_github_install())
148
+ except Exception as e:
149
+ return {"success": False, "message": f"Error installing from GitHub: {str(e)}"}
150
+
151
+ # Use our new streamcmd module
152
+ return EventSourceResponse(stream_command_as_events(cmd))
153
+
39
154
  @router.get("/get-all-plugins")
40
155
  async def get_all_plugins():
41
156
  try:
@@ -87,7 +202,7 @@ async def scan_directory(request: DirectoryRequest):
87
202
  # Update installed plugins from discovered ones
88
203
  for plugin_name, plugin_info in discovered_plugins.items():
89
204
  plugin_info['source'] = 'local'
90
- plugin_info['metadata'] = {
205
+ plugin_info['metadata'] = plugin_info.get('metadata', {}) or {
91
206
  "description": plugin_info.get('description', ''),
92
207
  "install_date": plugin_info.get('install_date', ''),
93
208
  "commands": plugin_info.get('commands', []),
@@ -96,8 +211,16 @@ async def scan_directory(request: DirectoryRequest):
96
211
  print(plugin_info)
97
212
  manifest['plugins']['installed'][plugin_name] = plugin_info
98
213
 
214
+ # Prepare plugin list for response
215
+ plugins_list = [{
216
+ "name": name,
217
+ "description": info.get('metadata', {}).get('description', info.get('description', ''))
218
+ } for name, info in discovered_plugins.items()]
219
+
99
220
  save_plugin_manifest(manifest)
100
- return {"success": True, "message": f"Scanned {len(discovered_plugins)} plugins in {directory}"}
221
+ return {"success": True,
222
+ "message": f"Scanned {len(discovered_plugins)} plugins in {directory}",
223
+ "plugins": plugins_list}
101
224
  except Exception as e:
102
225
  trace = traceback.format_exc()
103
226
  return {"success": False, "message": f"Error during scan: {str(e)}\n\n{trace}"}