sirchmunk 0.0.1__py3-none-any.whl → 0.0.2__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.
- sirchmunk/api/__init__.py +1 -0
- sirchmunk/api/chat.py +1123 -0
- sirchmunk/api/components/__init__.py +0 -0
- sirchmunk/api/components/history_storage.py +402 -0
- sirchmunk/api/components/monitor_tracker.py +518 -0
- sirchmunk/api/components/settings_storage.py +353 -0
- sirchmunk/api/history.py +254 -0
- sirchmunk/api/knowledge.py +411 -0
- sirchmunk/api/main.py +120 -0
- sirchmunk/api/monitor.py +219 -0
- sirchmunk/api/run_server.py +54 -0
- sirchmunk/api/search.py +230 -0
- sirchmunk/api/settings.py +309 -0
- sirchmunk/api/tools.py +315 -0
- sirchmunk/cli/__init__.py +11 -0
- sirchmunk/cli/cli.py +789 -0
- sirchmunk/learnings/knowledge_base.py +5 -2
- sirchmunk/llm/prompts.py +12 -1
- sirchmunk/retrieve/text_retriever.py +186 -2
- sirchmunk/scan/file_scanner.py +2 -2
- sirchmunk/schema/knowledge.py +119 -35
- sirchmunk/search.py +384 -26
- sirchmunk/storage/__init__.py +2 -2
- sirchmunk/storage/{knowledge_manager.py → knowledge_storage.py} +265 -60
- sirchmunk/utils/constants.py +7 -5
- sirchmunk/utils/embedding_util.py +217 -0
- sirchmunk/utils/tokenizer_util.py +36 -1
- sirchmunk/version.py +1 -1
- {sirchmunk-0.0.1.dist-info → sirchmunk-0.0.2.dist-info}/METADATA +196 -14
- sirchmunk-0.0.2.dist-info/RECORD +69 -0
- {sirchmunk-0.0.1.dist-info → sirchmunk-0.0.2.dist-info}/WHEEL +1 -1
- sirchmunk-0.0.2.dist-info/top_level.txt +2 -0
- sirchmunk_mcp/__init__.py +25 -0
- sirchmunk_mcp/cli.py +478 -0
- sirchmunk_mcp/config.py +276 -0
- sirchmunk_mcp/server.py +355 -0
- sirchmunk_mcp/service.py +327 -0
- sirchmunk_mcp/setup.py +15 -0
- sirchmunk_mcp/tools.py +410 -0
- sirchmunk-0.0.1.dist-info/RECORD +0 -45
- sirchmunk-0.0.1.dist-info/top_level.txt +0 -1
- {sirchmunk-0.0.1.dist-info → sirchmunk-0.0.2.dist-info}/entry_points.txt +0 -0
- {sirchmunk-0.0.1.dist-info → sirchmunk-0.0.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Copyright (c) ModelScope Contributors. All rights reserved.
|
|
2
|
+
"""
|
|
3
|
+
Settings API endpoints with persistent storage
|
|
4
|
+
Provides UI settings and environment variable management
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException
|
|
8
|
+
from typing import Dict, Any, Optional
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
|
|
11
|
+
from sirchmunk.api.components.settings_storage import SettingsStorage
|
|
12
|
+
from sirchmunk.utils.constants import (
|
|
13
|
+
GREP_CONCURRENT_LIMIT,
|
|
14
|
+
LLM_BASE_URL,
|
|
15
|
+
LLM_API_KEY,
|
|
16
|
+
LLM_MODEL_NAME,
|
|
17
|
+
SIRCHMUNK_WORK_PATH
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
router = APIRouter(prefix="/api/v1/settings", tags=["settings"])
|
|
21
|
+
|
|
22
|
+
# Initialize settings storage (with error handling)
|
|
23
|
+
try:
|
|
24
|
+
settings_storage = SettingsStorage()
|
|
25
|
+
except Exception as e:
|
|
26
|
+
print(f"[ERROR] Failed to initialize SettingsStorage: {e}")
|
|
27
|
+
settings_storage = None
|
|
28
|
+
|
|
29
|
+
# === Request/Response Models ===
|
|
30
|
+
|
|
31
|
+
class UISettings(BaseModel):
|
|
32
|
+
theme: str = "light"
|
|
33
|
+
language: str = "en"
|
|
34
|
+
|
|
35
|
+
class EnvironmentVariables(BaseModel):
|
|
36
|
+
SIRCHMUNK_WORK_PATH: Optional[str] = None
|
|
37
|
+
LLM_BASE_URL: Optional[str] = None
|
|
38
|
+
LLM_API_KEY: Optional[str] = None
|
|
39
|
+
LLM_MODEL_NAME: Optional[str] = None
|
|
40
|
+
GREP_CONCURRENT_LIMIT: Optional[int] = None
|
|
41
|
+
|
|
42
|
+
class SaveSettingsRequest(BaseModel):
|
|
43
|
+
ui: Optional[UISettings] = None
|
|
44
|
+
environment: Optional[Dict[str, str]] = None
|
|
45
|
+
|
|
46
|
+
# === Helper Functions ===
|
|
47
|
+
|
|
48
|
+
def get_default_ui_settings() -> Dict[str, Any]:
|
|
49
|
+
"""Get default UI settings"""
|
|
50
|
+
return {
|
|
51
|
+
"theme": settings_storage.get_setting("ui.theme", "light"),
|
|
52
|
+
"language": settings_storage.get_setting("ui.language", "en"),
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
def get_current_env_variables() -> Dict[str, Any]:
|
|
56
|
+
"""Get current environment variables with saved overrides"""
|
|
57
|
+
# Get saved values from storage
|
|
58
|
+
saved_work_path = settings_storage.get_env_variable("SIRCHMUNK_WORK_PATH")
|
|
59
|
+
saved_llm_base_url = settings_storage.get_env_variable("LLM_BASE_URL")
|
|
60
|
+
saved_llm_api_key = settings_storage.get_env_variable("LLM_API_KEY")
|
|
61
|
+
saved_llm_model = settings_storage.get_env_variable("LLM_MODEL_NAME")
|
|
62
|
+
saved_grep_limit = settings_storage.get_env_variable("GREP_CONCURRENT_LIMIT")
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
"SIRCHMUNK_WORK_PATH": {
|
|
66
|
+
"value": saved_work_path or str(SIRCHMUNK_WORK_PATH),
|
|
67
|
+
"default": str(SIRCHMUNK_WORK_PATH),
|
|
68
|
+
"description": "Working directory for Sirchmunk data",
|
|
69
|
+
"category": "system"
|
|
70
|
+
},
|
|
71
|
+
"LLM_BASE_URL": {
|
|
72
|
+
"value": saved_llm_base_url or LLM_BASE_URL,
|
|
73
|
+
"default": LLM_BASE_URL,
|
|
74
|
+
"description": "Base URL for LLM API (OpenAI-compatible endpoint)",
|
|
75
|
+
"category": "llm"
|
|
76
|
+
},
|
|
77
|
+
"LLM_API_KEY": {
|
|
78
|
+
"value": "***" if (saved_llm_api_key or LLM_API_KEY) else "",
|
|
79
|
+
"default": "***" if LLM_API_KEY else "",
|
|
80
|
+
"description": "API key for LLM service",
|
|
81
|
+
"category": "llm",
|
|
82
|
+
"sensitive": True
|
|
83
|
+
},
|
|
84
|
+
"LLM_MODEL_NAME": {
|
|
85
|
+
"value": saved_llm_model or LLM_MODEL_NAME,
|
|
86
|
+
"default": LLM_MODEL_NAME,
|
|
87
|
+
"description": "Model name for LLM",
|
|
88
|
+
"category": "llm"
|
|
89
|
+
},
|
|
90
|
+
"GREP_CONCURRENT_LIMIT": {
|
|
91
|
+
"value": saved_grep_limit or str(GREP_CONCURRENT_LIMIT),
|
|
92
|
+
"default": str(GREP_CONCURRENT_LIMIT),
|
|
93
|
+
"description": "Maximum concurrent grep requests",
|
|
94
|
+
"category": "system"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# === API Endpoints ===
|
|
99
|
+
|
|
100
|
+
@router.get("")
|
|
101
|
+
async def get_all_settings():
|
|
102
|
+
"""Get all settings including UI and environment variables"""
|
|
103
|
+
if settings_storage is None:
|
|
104
|
+
raise HTTPException(status_code=503, detail="Settings storage not available")
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
ui_settings = get_default_ui_settings()
|
|
108
|
+
env_variables = get_current_env_variables()
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
"success": True,
|
|
112
|
+
"data": {
|
|
113
|
+
"ui": ui_settings,
|
|
114
|
+
"environment": env_variables
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
119
|
+
|
|
120
|
+
@router.get("/ui")
|
|
121
|
+
async def get_ui_settings():
|
|
122
|
+
"""Get UI settings"""
|
|
123
|
+
if settings_storage is None:
|
|
124
|
+
# Return default settings if storage not available
|
|
125
|
+
return {
|
|
126
|
+
"success": True,
|
|
127
|
+
"data": {
|
|
128
|
+
"theme": "light",
|
|
129
|
+
"language": "en"
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
ui_settings = get_default_ui_settings()
|
|
135
|
+
return {
|
|
136
|
+
"success": True,
|
|
137
|
+
"data": ui_settings
|
|
138
|
+
}
|
|
139
|
+
except Exception as e:
|
|
140
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
141
|
+
|
|
142
|
+
@router.get("/environment")
|
|
143
|
+
async def get_environment_variables():
|
|
144
|
+
"""Get environment variables"""
|
|
145
|
+
if settings_storage is None:
|
|
146
|
+
raise HTTPException(status_code=503, detail="Settings storage not available")
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
env_variables = get_current_env_variables()
|
|
150
|
+
return {
|
|
151
|
+
"success": True,
|
|
152
|
+
"data": env_variables
|
|
153
|
+
}
|
|
154
|
+
except Exception as e:
|
|
155
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
156
|
+
|
|
157
|
+
@router.post("")
|
|
158
|
+
async def save_settings(request: SaveSettingsRequest):
|
|
159
|
+
"""Save settings (UI and/or environment variables)"""
|
|
160
|
+
if settings_storage is None:
|
|
161
|
+
raise HTTPException(status_code=503, detail="Settings storage not available")
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
saved_items = []
|
|
165
|
+
|
|
166
|
+
# Save UI settings
|
|
167
|
+
if request.ui:
|
|
168
|
+
if request.ui.theme:
|
|
169
|
+
settings_storage.save_setting("ui.theme", request.ui.theme, "ui")
|
|
170
|
+
saved_items.append("theme")
|
|
171
|
+
|
|
172
|
+
if request.ui.language:
|
|
173
|
+
settings_storage.save_setting("ui.language", request.ui.language, "ui")
|
|
174
|
+
saved_items.append("language")
|
|
175
|
+
|
|
176
|
+
# Save environment variables
|
|
177
|
+
if request.environment:
|
|
178
|
+
for key, value in request.environment.items():
|
|
179
|
+
if value: # Only save non-empty values
|
|
180
|
+
# For sensitive fields, store the actual value (not masked)
|
|
181
|
+
settings_storage.save_env_variable(
|
|
182
|
+
key,
|
|
183
|
+
value,
|
|
184
|
+
description=f"User-configured {key}",
|
|
185
|
+
category="llm" if "LLM" in key else "system"
|
|
186
|
+
)
|
|
187
|
+
saved_items.append(key)
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
"success": True,
|
|
191
|
+
"message": f"Settings saved successfully: {', '.join(saved_items)}",
|
|
192
|
+
"saved_items": saved_items
|
|
193
|
+
}
|
|
194
|
+
except Exception as e:
|
|
195
|
+
raise HTTPException(status_code=500, detail=f"Failed to save settings: {str(e)}")
|
|
196
|
+
|
|
197
|
+
@router.post("/ui")
|
|
198
|
+
async def update_ui_settings(ui: UISettings):
|
|
199
|
+
"""Update UI settings"""
|
|
200
|
+
if settings_storage is None:
|
|
201
|
+
raise HTTPException(status_code=503, detail="Settings storage not available")
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
settings_storage.save_setting("ui.theme", ui.theme, "ui")
|
|
205
|
+
settings_storage.save_setting("ui.language", ui.language, "ui")
|
|
206
|
+
|
|
207
|
+
return {
|
|
208
|
+
"success": True,
|
|
209
|
+
"message": "UI settings updated successfully",
|
|
210
|
+
"data": {
|
|
211
|
+
"theme": ui.theme,
|
|
212
|
+
"language": ui.language
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
except Exception as e:
|
|
216
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
217
|
+
|
|
218
|
+
@router.get("/test/llm")
|
|
219
|
+
async def test_llm_connection():
|
|
220
|
+
"""Test LLM connection"""
|
|
221
|
+
from sirchmunk.llm import OpenAIChat
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
# Get current LLM settings
|
|
225
|
+
base_url = settings_storage.get_env_variable("LLM_BASE_URL") or LLM_BASE_URL
|
|
226
|
+
api_key = settings_storage.get_env_variable("LLM_API_KEY") or LLM_API_KEY
|
|
227
|
+
model = settings_storage.get_env_variable("LLM_MODEL_NAME") or LLM_MODEL_NAME
|
|
228
|
+
|
|
229
|
+
print(f"[DEBUG] Testing LLM connection with base_url={base_url}, model={model}, api_key={'***' if api_key else '(not set)'}")
|
|
230
|
+
|
|
231
|
+
# Simple validation
|
|
232
|
+
if not api_key:
|
|
233
|
+
return {
|
|
234
|
+
"success": False,
|
|
235
|
+
"status": "error",
|
|
236
|
+
"message": "LLM API key is not configured",
|
|
237
|
+
"model": None
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if not base_url:
|
|
241
|
+
return {
|
|
242
|
+
"success": False,
|
|
243
|
+
"status": "error",
|
|
244
|
+
"message": "LLM base URL is not configured",
|
|
245
|
+
"model": None
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
llm = OpenAIChat(
|
|
250
|
+
base_url=base_url,
|
|
251
|
+
api_key=api_key,
|
|
252
|
+
model=model
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
messages = [
|
|
256
|
+
{"role": "system",
|
|
257
|
+
"content": "You are a helpful AI assistant."},
|
|
258
|
+
{"role": "user", "content": "Output the word: 'test'."}
|
|
259
|
+
]
|
|
260
|
+
resp = await llm.achat(
|
|
261
|
+
messages=messages,
|
|
262
|
+
stream=False
|
|
263
|
+
)
|
|
264
|
+
print(f"[DEBUG] LLM response: {resp.content}")
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
"success": True,
|
|
268
|
+
"status": "configured",
|
|
269
|
+
"message": "LLM connection successful",
|
|
270
|
+
"model": model,
|
|
271
|
+
"base_url": base_url
|
|
272
|
+
}
|
|
273
|
+
except Exception as e:
|
|
274
|
+
return {
|
|
275
|
+
"success": False,
|
|
276
|
+
"status": "error",
|
|
277
|
+
"message": str(e),
|
|
278
|
+
"model": None
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@router.get("/status")
|
|
282
|
+
async def get_settings_status():
|
|
283
|
+
"""Get settings status for quick overview"""
|
|
284
|
+
try:
|
|
285
|
+
ui_settings = get_default_ui_settings()
|
|
286
|
+
|
|
287
|
+
# Check LLM configuration
|
|
288
|
+
llm_api_key = settings_storage.get_env_variable("LLM_API_KEY") or LLM_API_KEY
|
|
289
|
+
llm_base_url = settings_storage.get_env_variable("LLM_BASE_URL") or LLM_BASE_URL
|
|
290
|
+
llm_model = settings_storage.get_env_variable("LLM_MODEL_NAME") or LLM_MODEL_NAME
|
|
291
|
+
|
|
292
|
+
llm_configured = bool(llm_api_key and llm_base_url and llm_model)
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
"success": True,
|
|
296
|
+
"data": {
|
|
297
|
+
"ui": {
|
|
298
|
+
"theme": ui_settings.get("theme", "light"),
|
|
299
|
+
"language": ui_settings.get("language", "en")
|
|
300
|
+
},
|
|
301
|
+
"llm": {
|
|
302
|
+
"configured": llm_configured,
|
|
303
|
+
"model": llm_model if llm_configured else None,
|
|
304
|
+
"status": "ready" if llm_configured else "not_configured"
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
except Exception as e:
|
|
309
|
+
raise HTTPException(status_code=500, detail=str(e))
|
sirchmunk/api/tools.py
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# Copyright (c) ModelScope Contributors. All rights reserved.
|
|
2
|
+
"""
|
|
3
|
+
Tools API endpoints for Sirchmunk
|
|
4
|
+
Handles quick actions like file export, PPT generation, document conversion, etc.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, HTTPException
|
|
8
|
+
from typing import Dict, List, Any, Optional
|
|
9
|
+
import uuid
|
|
10
|
+
from datetime import datetime, timedelta
|
|
11
|
+
import random
|
|
12
|
+
|
|
13
|
+
router = APIRouter(prefix="/api/v1/tools", tags=["tools"])
|
|
14
|
+
|
|
15
|
+
# Mock tool configurations
|
|
16
|
+
TOOL_CONFIGS = {
|
|
17
|
+
"export-pdf": {
|
|
18
|
+
"name": "PDF Export",
|
|
19
|
+
"description": "Export conversation or content to PDF format",
|
|
20
|
+
"processing_time": (2, 5), # seconds range
|
|
21
|
+
"output_format": "pdf"
|
|
22
|
+
},
|
|
23
|
+
"generate-ppt": {
|
|
24
|
+
"name": "PPT Generation",
|
|
25
|
+
"description": "Generate PowerPoint presentation from content",
|
|
26
|
+
"processing_time": (5, 10),
|
|
27
|
+
"output_format": "pptx"
|
|
28
|
+
},
|
|
29
|
+
"convert-doc": {
|
|
30
|
+
"name": "Document Conversion",
|
|
31
|
+
"description": "Convert documents between different formats",
|
|
32
|
+
"processing_time": (3, 7),
|
|
33
|
+
"output_format": "various"
|
|
34
|
+
},
|
|
35
|
+
"generate-video": {
|
|
36
|
+
"name": "Video Generation",
|
|
37
|
+
"description": "Create video content from text or images",
|
|
38
|
+
"processing_time": (15, 30),
|
|
39
|
+
"output_format": "mp4"
|
|
40
|
+
},
|
|
41
|
+
"create-image": {
|
|
42
|
+
"name": "Image Creation",
|
|
43
|
+
"description": "Generate images using AI",
|
|
44
|
+
"processing_time": (3, 8),
|
|
45
|
+
"output_format": "png"
|
|
46
|
+
},
|
|
47
|
+
"export-excel": {
|
|
48
|
+
"name": "Excel Export",
|
|
49
|
+
"description": "Export data to Excel spreadsheet",
|
|
50
|
+
"processing_time": (2, 4),
|
|
51
|
+
"output_format": "xlsx"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@router.get("/")
|
|
56
|
+
async def list_available_tools():
|
|
57
|
+
"""List all available tools and their configurations"""
|
|
58
|
+
try:
|
|
59
|
+
tools = []
|
|
60
|
+
for tool_id, config in TOOL_CONFIGS.items():
|
|
61
|
+
tools.append({
|
|
62
|
+
"id": tool_id,
|
|
63
|
+
"name": config["name"],
|
|
64
|
+
"description": config["description"],
|
|
65
|
+
"output_format": config["output_format"],
|
|
66
|
+
"estimated_time": f"{config['processing_time'][0]}-{config['processing_time'][1]}s"
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
"success": True,
|
|
71
|
+
"data": tools,
|
|
72
|
+
"timestamp": datetime.now().isoformat()
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
except Exception as e:
|
|
76
|
+
raise HTTPException(status_code=500, detail=f"Failed to list tools: {str(e)}")
|
|
77
|
+
|
|
78
|
+
@router.post("/{tool_id}")
|
|
79
|
+
async def execute_tool(tool_id: str, request: Dict[str, Any]):
|
|
80
|
+
"""
|
|
81
|
+
Execute a specific tool
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
tool_id: ID of the tool to execute
|
|
85
|
+
request: Tool execution parameters
|
|
86
|
+
"""
|
|
87
|
+
try:
|
|
88
|
+
if tool_id not in TOOL_CONFIGS:
|
|
89
|
+
raise HTTPException(status_code=404, detail=f"Tool '{tool_id}' not found")
|
|
90
|
+
|
|
91
|
+
config = TOOL_CONFIGS[tool_id]
|
|
92
|
+
|
|
93
|
+
# Simulate processing time
|
|
94
|
+
processing_time = random.randint(*config["processing_time"])
|
|
95
|
+
|
|
96
|
+
# Generate mock result based on tool type
|
|
97
|
+
result = await _generate_tool_result(tool_id, config, request)
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
"success": True,
|
|
101
|
+
"data": result,
|
|
102
|
+
"message": f"{config['name']} completed successfully",
|
|
103
|
+
"timestamp": datetime.now().isoformat()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
except HTTPException:
|
|
107
|
+
raise
|
|
108
|
+
except Exception as e:
|
|
109
|
+
raise HTTPException(status_code=500, detail=f"Failed to execute tool: {str(e)}")
|
|
110
|
+
|
|
111
|
+
async def _generate_tool_result(tool_id: str, config: Dict[str, Any], request: Dict[str, Any]) -> Dict[str, Any]:
|
|
112
|
+
"""Generate mock result for tool execution"""
|
|
113
|
+
|
|
114
|
+
base_result = {
|
|
115
|
+
"task_id": str(uuid.uuid4()),
|
|
116
|
+
"tool_id": tool_id,
|
|
117
|
+
"tool_name": config["name"],
|
|
118
|
+
"started_at": datetime.now().isoformat(),
|
|
119
|
+
"completed_at": (datetime.now() + timedelta(seconds=random.randint(*config["processing_time"]))).isoformat(),
|
|
120
|
+
"status": "completed"
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if tool_id == "export-pdf":
|
|
124
|
+
return {
|
|
125
|
+
**base_result,
|
|
126
|
+
"output": {
|
|
127
|
+
"file_name": f"conversation_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf",
|
|
128
|
+
"file_size": f"{random.randint(500, 2000)} KB",
|
|
129
|
+
"pages": random.randint(3, 15),
|
|
130
|
+
"download_url": f"https://example.com/downloads/pdf_{base_result['task_id']}.pdf"
|
|
131
|
+
},
|
|
132
|
+
"metadata": {
|
|
133
|
+
"format": "PDF",
|
|
134
|
+
"quality": "high",
|
|
135
|
+
"includes_images": True,
|
|
136
|
+
"includes_formatting": True
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
elif tool_id == "generate-ppt":
|
|
141
|
+
return {
|
|
142
|
+
**base_result,
|
|
143
|
+
"output": {
|
|
144
|
+
"file_name": f"presentation_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pptx",
|
|
145
|
+
"file_size": f"{random.randint(2, 8)} MB",
|
|
146
|
+
"slides": random.randint(8, 20),
|
|
147
|
+
"download_url": f"https://example.com/downloads/ppt_{base_result['task_id']}.pptx"
|
|
148
|
+
},
|
|
149
|
+
"metadata": {
|
|
150
|
+
"template": "professional",
|
|
151
|
+
"theme": "modern",
|
|
152
|
+
"includes_charts": True,
|
|
153
|
+
"includes_animations": False
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
elif tool_id == "convert-doc":
|
|
158
|
+
source_format = request.get("source_format", "docx")
|
|
159
|
+
target_format = request.get("target_format", "pdf")
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
**base_result,
|
|
163
|
+
"output": {
|
|
164
|
+
"file_name": f"converted_document_{datetime.now().strftime('%Y%m%d_%H%M%S')}.{target_format}",
|
|
165
|
+
"file_size": f"{random.randint(800, 3000)} KB",
|
|
166
|
+
"download_url": f"https://example.com/downloads/converted_{base_result['task_id']}.{target_format}"
|
|
167
|
+
},
|
|
168
|
+
"metadata": {
|
|
169
|
+
"source_format": source_format,
|
|
170
|
+
"target_format": target_format,
|
|
171
|
+
"conversion_quality": "high",
|
|
172
|
+
"preserved_formatting": True
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
elif tool_id == "generate-video":
|
|
177
|
+
return {
|
|
178
|
+
**base_result,
|
|
179
|
+
"output": {
|
|
180
|
+
"file_name": f"generated_video_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4",
|
|
181
|
+
"file_size": f"{random.randint(10, 50)} MB",
|
|
182
|
+
"duration": f"{random.randint(30, 180)} seconds",
|
|
183
|
+
"download_url": f"https://example.com/downloads/video_{base_result['task_id']}.mp4"
|
|
184
|
+
},
|
|
185
|
+
"metadata": {
|
|
186
|
+
"resolution": "1920x1080",
|
|
187
|
+
"fps": 30,
|
|
188
|
+
"codec": "H.264",
|
|
189
|
+
"audio": True
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
elif tool_id == "create-image":
|
|
194
|
+
return {
|
|
195
|
+
**base_result,
|
|
196
|
+
"output": {
|
|
197
|
+
"file_name": f"generated_image_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png",
|
|
198
|
+
"file_size": f"{random.randint(500, 2000)} KB",
|
|
199
|
+
"dimensions": "1024x1024",
|
|
200
|
+
"download_url": f"https://example.com/downloads/image_{base_result['task_id']}.png"
|
|
201
|
+
},
|
|
202
|
+
"metadata": {
|
|
203
|
+
"format": "PNG",
|
|
204
|
+
"quality": "high",
|
|
205
|
+
"style": "photorealistic",
|
|
206
|
+
"ai_model": "DALL-E 3"
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
elif tool_id == "export-excel":
|
|
211
|
+
return {
|
|
212
|
+
**base_result,
|
|
213
|
+
"output": {
|
|
214
|
+
"file_name": f"data_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx",
|
|
215
|
+
"file_size": f"{random.randint(200, 1500)} KB",
|
|
216
|
+
"sheets": random.randint(1, 5),
|
|
217
|
+
"rows": random.randint(100, 5000),
|
|
218
|
+
"download_url": f"https://example.com/downloads/excel_{base_result['task_id']}.xlsx"
|
|
219
|
+
},
|
|
220
|
+
"metadata": {
|
|
221
|
+
"format": "Excel 2019",
|
|
222
|
+
"includes_charts": True,
|
|
223
|
+
"includes_formulas": True,
|
|
224
|
+
"data_types": ["text", "numbers", "dates"]
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
else:
|
|
229
|
+
return {
|
|
230
|
+
**base_result,
|
|
231
|
+
"output": {
|
|
232
|
+
"message": "Tool executed successfully",
|
|
233
|
+
"result": "Generic tool result"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@router.get("/{tool_id}/status")
|
|
238
|
+
async def get_tool_status(tool_id: str):
|
|
239
|
+
"""Get the current status of a tool"""
|
|
240
|
+
try:
|
|
241
|
+
if tool_id not in TOOL_CONFIGS:
|
|
242
|
+
raise HTTPException(status_code=404, detail=f"Tool '{tool_id}' not found")
|
|
243
|
+
|
|
244
|
+
config = TOOL_CONFIGS[tool_id]
|
|
245
|
+
|
|
246
|
+
status_data = {
|
|
247
|
+
"tool_id": tool_id,
|
|
248
|
+
"name": config["name"],
|
|
249
|
+
"status": "available",
|
|
250
|
+
"description": config["description"],
|
|
251
|
+
"output_format": config["output_format"],
|
|
252
|
+
"estimated_processing_time": f"{config['processing_time'][0]}-{config['processing_time'][1]} seconds",
|
|
253
|
+
"usage_stats": {
|
|
254
|
+
"total_executions": random.randint(50, 500),
|
|
255
|
+
"success_rate": round(random.uniform(0.85, 0.99), 2),
|
|
256
|
+
"average_processing_time": f"{random.randint(config['processing_time'][0], config['processing_time'][1])} seconds"
|
|
257
|
+
},
|
|
258
|
+
"last_used": (datetime.now() - timedelta(hours=random.randint(1, 48))).isoformat()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
"success": True,
|
|
263
|
+
"data": status_data,
|
|
264
|
+
"timestamp": datetime.now().isoformat()
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
except HTTPException:
|
|
268
|
+
raise
|
|
269
|
+
except Exception as e:
|
|
270
|
+
raise HTTPException(status_code=500, detail=f"Failed to get tool status: {str(e)}")
|
|
271
|
+
|
|
272
|
+
@router.get("/history")
|
|
273
|
+
async def get_tool_execution_history(
|
|
274
|
+
tool_id: Optional[str] = None,
|
|
275
|
+
limit: int = 20,
|
|
276
|
+
offset: int = 0
|
|
277
|
+
):
|
|
278
|
+
"""Get tool execution history"""
|
|
279
|
+
try:
|
|
280
|
+
# Generate mock history
|
|
281
|
+
history = []
|
|
282
|
+
|
|
283
|
+
for i in range(limit):
|
|
284
|
+
if tool_id and tool_id not in TOOL_CONFIGS:
|
|
285
|
+
continue
|
|
286
|
+
|
|
287
|
+
selected_tool_id = tool_id or random.choice(list(TOOL_CONFIGS.keys()))
|
|
288
|
+
config = TOOL_CONFIGS[selected_tool_id]
|
|
289
|
+
|
|
290
|
+
execution = {
|
|
291
|
+
"id": str(uuid.uuid4()),
|
|
292
|
+
"tool_id": selected_tool_id,
|
|
293
|
+
"tool_name": config["name"],
|
|
294
|
+
"status": random.choice(["completed", "completed", "completed", "failed"]),
|
|
295
|
+
"started_at": (datetime.now() - timedelta(hours=random.randint(1, 168))).isoformat(),
|
|
296
|
+
"completed_at": (datetime.now() - timedelta(hours=random.randint(1, 168))).isoformat(),
|
|
297
|
+
"processing_time": f"{random.randint(*config['processing_time'])} seconds",
|
|
298
|
+
"output_size": f"{random.randint(100, 5000)} KB"
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
history.append(execution)
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
"success": True,
|
|
305
|
+
"data": history,
|
|
306
|
+
"pagination": {
|
|
307
|
+
"limit": limit,
|
|
308
|
+
"offset": offset,
|
|
309
|
+
"total": random.randint(100, 1000)
|
|
310
|
+
},
|
|
311
|
+
"timestamp": datetime.now().isoformat()
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
except Exception as e:
|
|
315
|
+
raise HTTPException(status_code=500, detail=f"Failed to get tool history: {str(e)}")
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Copyright (c) ModelScope Contributors. All rights reserved.
|
|
2
|
+
"""
|
|
3
|
+
Sirchmunk Command Line Interface.
|
|
4
|
+
|
|
5
|
+
Provides CLI commands for initialization, configuration, server management,
|
|
6
|
+
and search operations.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .cli import run_cmd
|
|
10
|
+
|
|
11
|
+
__all__ = ["run_cmd"]
|