cloneloop 0.1.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.
Files changed (118) hide show
  1. cloneloop-0.1.0.dist-info/METADATA +392 -0
  2. cloneloop-0.1.0.dist-info/RECORD +118 -0
  3. cloneloop-0.1.0.dist-info/WHEEL +4 -0
  4. cloneloop-0.1.0.dist-info/entry_points.txt +5 -0
  5. mcp_ai_supervisor/__init__.py +52 -0
  6. mcp_ai_supervisor/__main__.py +551 -0
  7. mcp_ai_supervisor/debug.py +15 -0
  8. mcp_ai_supervisor/desktop_app/__init__.py +29 -0
  9. mcp_ai_supervisor/desktop_app/desktop_app.py +390 -0
  10. mcp_ai_supervisor/helpers/__init__.py +4 -0
  11. mcp_ai_supervisor/helpers/feedback_helpers.py +140 -0
  12. mcp_ai_supervisor/helpers/image_helpers.py +73 -0
  13. mcp_ai_supervisor/i18n.py +14 -0
  14. mcp_ai_supervisor/log_writer.py +16 -0
  15. mcp_ai_supervisor/logging/__init__.py +8 -0
  16. mcp_ai_supervisor/logging/log_parser.py +293 -0
  17. mcp_ai_supervisor/logging/log_tailer.py +367 -0
  18. mcp_ai_supervisor/py.typed +0 -0
  19. mcp_ai_supervisor/server.py +654 -0
  20. mcp_ai_supervisor/utils/__init__.py +28 -0
  21. mcp_ai_supervisor/utils/error_handler.py +10 -0
  22. mcp_ai_supervisor/utils/memory_monitor.py +11 -0
  23. mcp_ai_supervisor/utils/paths.py +7 -0
  24. mcp_ai_supervisor/utils/resource_manager.py +15 -0
  25. mcp_ai_supervisor/utils/structure_checker.py +291 -0
  26. mcp_ai_supervisor/web/__init__.py +26 -0
  27. mcp_ai_supervisor/web/constants/__init__.py +8 -0
  28. mcp_ai_supervisor/web/constants/message_codes.py +173 -0
  29. mcp_ai_supervisor/web/core/__init__.py +30 -0
  30. mcp_ai_supervisor/web/core/agent_bridge.py +957 -0
  31. mcp_ai_supervisor/web/core/auto_responder.py +332 -0
  32. mcp_ai_supervisor/web/core/context_collector.py +124 -0
  33. mcp_ai_supervisor/web/core/conversation_recorder.py +751 -0
  34. mcp_ai_supervisor/web/core/delegate_manager.py +1193 -0
  35. mcp_ai_supervisor/web/core/feedback_mediator.py +259 -0
  36. mcp_ai_supervisor/web/core/message_channel.py +551 -0
  37. mcp_ai_supervisor/web/core/response_builder.py +333 -0
  38. mcp_ai_supervisor/web/core/scene_detector.py +184 -0
  39. mcp_ai_supervisor/web/core/task_state.py +194 -0
  40. mcp_ai_supervisor/web/locales/en/translation.json +643 -0
  41. mcp_ai_supervisor/web/locales/zh-CN/translation.json +629 -0
  42. mcp_ai_supervisor/web/locales/zh-TW/translation.json +648 -0
  43. mcp_ai_supervisor/web/main.py +747 -0
  44. mcp_ai_supervisor/web/managers/__init__.py +8 -0
  45. mcp_ai_supervisor/web/managers/desktop_manager.py +228 -0
  46. mcp_ai_supervisor/web/managers/server_manager.py +170 -0
  47. mcp_ai_supervisor/web/managers/session_manager.py +515 -0
  48. mcp_ai_supervisor/web/managers/workbench_connector.py +186 -0
  49. mcp_ai_supervisor/web/models/__init__.py +13 -0
  50. mcp_ai_supervisor/web/models/feedback_result.py +16 -0
  51. mcp_ai_supervisor/web/models/feedback_session.py +938 -0
  52. mcp_ai_supervisor/web/models/session_cleaner.py +245 -0
  53. mcp_ai_supervisor/web/models/session_commands.py +213 -0
  54. mcp_ai_supervisor/web/models/session_resolver.py +158 -0
  55. mcp_ai_supervisor/web/models/session_timer.py +242 -0
  56. mcp_ai_supervisor/web/routes/__init__.py +12 -0
  57. mcp_ai_supervisor/web/routes/main_routes.py +965 -0
  58. mcp_ai_supervisor/web/routes/settings_routes.py +195 -0
  59. mcp_ai_supervisor/web/routes/ws_handlers.py +270 -0
  60. mcp_ai_supervisor/web/static/css/audio-management.css +545 -0
  61. mcp_ai_supervisor/web/static/css/notification-settings.css +152 -0
  62. mcp_ai_supervisor/web/static/css/prompt-management.css +566 -0
  63. mcp_ai_supervisor/web/static/css/session-management.css +1428 -0
  64. mcp_ai_supervisor/web/static/css/styles.css +2267 -0
  65. mcp_ai_supervisor/web/static/favicon.ico +0 -0
  66. mcp_ai_supervisor/web/static/icon-192.png +0 -0
  67. mcp_ai_supervisor/web/static/icon.svg +11 -0
  68. mcp_ai_supervisor/web/static/index.html +37 -0
  69. mcp_ai_supervisor/web/static/js/app.js +1721 -0
  70. mcp_ai_supervisor/web/static/js/i18n.js +376 -0
  71. mcp_ai_supervisor/web/static/js/modules/audio/audio-manager.js +610 -0
  72. mcp_ai_supervisor/web/static/js/modules/audio/audio-settings-ui.js +732 -0
  73. mcp_ai_supervisor/web/static/js/modules/connection-monitor.js +435 -0
  74. mcp_ai_supervisor/web/static/js/modules/constants/message-codes.js +168 -0
  75. mcp_ai_supervisor/web/static/js/modules/countdown-manager.js +273 -0
  76. mcp_ai_supervisor/web/static/js/modules/drag-drop-handler.js +677 -0
  77. mcp_ai_supervisor/web/static/js/modules/file-upload-manager.js +555 -0
  78. mcp_ai_supervisor/web/static/js/modules/image-handler.js +199 -0
  79. mcp_ai_supervisor/web/static/js/modules/logger.js +404 -0
  80. mcp_ai_supervisor/web/static/js/modules/notification/notification-manager.js +360 -0
  81. mcp_ai_supervisor/web/static/js/modules/notification/notification-settings.js +344 -0
  82. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-input-buttons.js +427 -0
  83. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-manager.js +414 -0
  84. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-modal.js +458 -0
  85. mcp_ai_supervisor/web/static/js/modules/prompt/prompt-settings-ui.js +524 -0
  86. mcp_ai_supervisor/web/static/js/modules/session/session-data-manager.js +1042 -0
  87. mcp_ai_supervisor/web/static/js/modules/session/session-details-modal.js +594 -0
  88. mcp_ai_supervisor/web/static/js/modules/session/session-ui-renderer.js +836 -0
  89. mcp_ai_supervisor/web/static/js/modules/session-manager.js +1059 -0
  90. mcp_ai_supervisor/web/static/js/modules/settings-manager.js +1002 -0
  91. mcp_ai_supervisor/web/static/js/modules/tab-manager.js +235 -0
  92. mcp_ai_supervisor/web/static/js/modules/textarea-height-manager.js +267 -0
  93. mcp_ai_supervisor/web/static/js/modules/ui-manager.js +578 -0
  94. mcp_ai_supervisor/web/static/js/modules/utils/dom-utils.js +392 -0
  95. mcp_ai_supervisor/web/static/js/modules/utils/status-utils.js +403 -0
  96. mcp_ai_supervisor/web/static/js/modules/utils/time-utils.js +440 -0
  97. mcp_ai_supervisor/web/static/js/modules/utils.js +557 -0
  98. mcp_ai_supervisor/web/static/js/modules/websocket-manager.js +875 -0
  99. mcp_ai_supervisor/web/static/js/modules/workbench-notification.js +103 -0
  100. mcp_ai_supervisor/web/static/js/vendor/marked.min.js +6 -0
  101. mcp_ai_supervisor/web/static/js/vendor/purify.min.js +3 -0
  102. mcp_ai_supervisor/web/templates/components/image-upload.html +43 -0
  103. mcp_ai_supervisor/web/templates/components/settings-card.html +58 -0
  104. mcp_ai_supervisor/web/templates/components/status-indicator.html +31 -0
  105. mcp_ai_supervisor/web/templates/components/toggle-switch.html +19 -0
  106. mcp_ai_supervisor/web/templates/feedback.html +1198 -0
  107. mcp_ai_supervisor/web/templates/index.html +378 -0
  108. mcp_ai_supervisor/web/utils/__init__.py +12 -0
  109. mcp_ai_supervisor/web/utils/browser.py +35 -0
  110. mcp_ai_supervisor/web/utils/compression_config.py +195 -0
  111. mcp_ai_supervisor/web/utils/compression_monitor.py +314 -0
  112. mcp_ai_supervisor/web/utils/ide_opener.py +286 -0
  113. mcp_ai_supervisor/web/utils/network.py +66 -0
  114. mcp_ai_supervisor/web/utils/port_manager.py +340 -0
  115. mcp_ai_supervisor/web/utils/session_cleanup_manager.py +543 -0
  116. mcp_ai_supervisor/web/utils/workbench_client.py +899 -0
  117. mcp_ai_supervisor/workbench/__init__.py +5 -0
  118. mcp_ai_supervisor/workbench/__main__.py +5 -0
@@ -0,0 +1,11 @@
1
+ """代理模块:重定向到 mcp_supervisor_core.memory_monitor
2
+
3
+ 重构过渡期保持向后兼容。
4
+ Phase 3 删除 src/ 时此文件一并删除。
5
+ """
6
+ from mcp_supervisor_core.memory_monitor import * # noqa: F401,F403
7
+ from mcp_supervisor_core.memory_monitor import ( # noqa: F401
8
+ MemoryMonitor,
9
+ MemorySnapshot,
10
+ get_memory_monitor,
11
+ )
@@ -0,0 +1,7 @@
1
+ """代理模块:重定向到 mcp_supervisor_core.paths
2
+
3
+ 重构过渡期保持向后兼容。
4
+ Phase 3 删除 src/ 时此文件一并删除。
5
+ """
6
+ from mcp_supervisor_core.paths import * # noqa: F401,F403
7
+ from mcp_supervisor_core.paths import normalize_path, project_hash # noqa: F401
@@ -0,0 +1,15 @@
1
+ """代理模块:重定向到 mcp_supervisor_core.resource_manager
2
+
3
+ 重构过渡期保持向后兼容。
4
+ Phase 3 删除 src/ 时此文件一并删除。
5
+ """
6
+ from mcp_supervisor_core.resource_manager import * # noqa: F401,F403
7
+ from mcp_supervisor_core.resource_manager import ( # noqa: F401
8
+ ResourceManager,
9
+ ResourceType,
10
+ cleanup_all_resources,
11
+ create_temp_dir,
12
+ create_temp_file,
13
+ get_resource_manager,
14
+ register_process,
15
+ )
@@ -0,0 +1,291 @@
1
+ """代码结构检查模块 — 检查变更文件所在目录的结构健康度。
2
+
3
+ AI 每次编码完成后调用,只扫描变更文件所在的目录(不递归子目录),
4
+ 产出结构摘要帮助 PM 判断代码组织是否需要关注。
5
+
6
+ 用法:
7
+ from mcp_ai_supervisor.utils.structure_checker import check_changed_dirs
8
+ report = check_changed_dirs("/project/root", ["src/a.py", "src/b.py"])
9
+ """
10
+
11
+ import json
12
+ import os
13
+ from collections import defaultdict
14
+ from fnmatch import fnmatch
15
+ from pathlib import Path
16
+
17
+ DEFAULT_CONFIG = {
18
+ "max_files_per_dir": 15,
19
+ "file_size_warning": 300,
20
+ "file_size_critical": 500,
21
+ "file_size_severe": 1000,
22
+ "ignore_files": [
23
+ "*.pyc", "*.pyo", "*.min.js", "*.min.css", "*.bundle.js",
24
+ "*.map", "*.lock",
25
+ "*.ico", "*.png", "*.jpg", "*.jpeg", "*.gif", "*.svg", "*.webp",
26
+ "*.woff", "*.woff2", "*.ttf", "*.eot",
27
+ "*.zip", "*.tar", "*.gz", "*.bz2", "*.whl",
28
+ "*.so", "*.dylib", "*.dll", "*.o", "*.obj", "*.class",
29
+ "*.DS_Store",
30
+ ],
31
+ "ignore_dirs": [
32
+ "node_modules", "__pycache__", ".git", ".tox", ".mypy_cache",
33
+ ".pytest_cache", "dist", "build", "*.egg-info", ".eggs",
34
+ ".venv", "venv", "env",
35
+ ],
36
+ "related_extensions": [
37
+ [".tsx", ".module.css"],
38
+ [".jsx", ".module.css"],
39
+ [".vue", ".module.css"],
40
+ [".ts", ".module.css"],
41
+ [".py", ".pyi"],
42
+ ],
43
+ }
44
+
45
+ CODE_EXTENSIONS = {
46
+ ".py", ".pyi", ".ts", ".tsx", ".js", ".jsx", ".css", ".scss", ".less",
47
+ ".html", ".htm", ".sh", ".bash", ".sql", ".rs", ".go", ".java", ".rb",
48
+ ".vue", ".svelte",
49
+ ".c", ".cpp", ".h", ".hpp", ".cc", ".cxx",
50
+ ".swift", ".kt", ".kts", ".dart", ".php",
51
+ ".scala", ".lua", ".r",
52
+ ".graphql", ".gql", ".proto",
53
+ ".ex", ".exs", ".erl",
54
+ ".cs",
55
+ }
56
+ DOC_EXTENSIONS = {".md", ".txt", ".rst", ".adoc", ".tex"}
57
+
58
+ ROLE_KEYWORDS = {
59
+ "model": "数据模型", "models": "数据模型", "schema": "数据模型", "schemas": "数据模型",
60
+ "route": "路由接口", "routes": "路由接口", "router": "路由接口", "api": "路由接口",
61
+ "endpoint": "路由接口", "endpoints": "路由接口",
62
+ "controller": "控制器", "controllers": "控制器",
63
+ "service": "业务逻辑", "services": "业务逻辑", "manager": "业务逻辑",
64
+ "handler": "业务逻辑", "handlers": "业务逻辑",
65
+ "middleware": "中间件", "middlewares": "中间件",
66
+ "util": "工具类", "utils": "工具类", "helper": "工具类", "helpers": "工具类",
67
+ "config": "配置", "settings": "配置", "constants": "配置", "const": "配置",
68
+ "test": "测试", "tests": "测试", "spec": "测试",
69
+ "mock": "测试", "mocks": "测试", "fixture": "测试", "fixtures": "测试",
70
+ "component": "UI组件", "components": "UI组件",
71
+ "view": "视图", "views": "视图", "template": "模板", "templates": "模板",
72
+ "hook": "钩子", "hooks": "钩子",
73
+ "store": "状态管理", "stores": "状态管理",
74
+ "type": "类型定义", "types": "类型定义", "interface": "类型定义", "interfaces": "类型定义",
75
+ "dto": "数据传输",
76
+ "migration": "数据迁移", "migrations": "数据迁移",
77
+ "plugin": "插件", "plugins": "插件",
78
+ "adapter": "适配器", "adapters": "适配器",
79
+ "validator": "校验", "validators": "校验",
80
+ "serializer": "序列化", "serializers": "序列化",
81
+ "command": "命令", "commands": "命令",
82
+ "task": "异步任务", "tasks": "异步任务", "worker": "异步任务", "workers": "异步任务",
83
+ "provider": "提供者", "providers": "提供者",
84
+ "repository": "仓储", "repositories": "仓储",
85
+ "factory": "工厂", "factories": "工厂",
86
+ "decorator": "装饰器", "decorators": "装饰器",
87
+ }
88
+
89
+
90
+ def _load_config(project_root: str) -> dict:
91
+ config = dict(DEFAULT_CONFIG)
92
+ config_path = os.path.join(project_root, ".structure-check.json")
93
+ if os.path.isfile(config_path):
94
+ try:
95
+ with open(config_path, "r", encoding="utf-8") as f:
96
+ config.update(json.load(f))
97
+ except (json.JSONDecodeError, OSError):
98
+ pass
99
+ return config
100
+
101
+
102
+ def _should_ignore(filename: str, config: dict) -> bool:
103
+ return any(fnmatch(filename, p) for p in config["ignore_files"])
104
+
105
+
106
+ def _count_lines(filepath: str) -> int:
107
+ try:
108
+ with open(filepath, "rb") as f:
109
+ if b"\x00" in f.read(1024):
110
+ return -1
111
+ with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
112
+ return sum(1 for _ in f)
113
+ except (OSError, UnicodeDecodeError):
114
+ return -1
115
+
116
+
117
+ def _infer_role(filename: str) -> str | None:
118
+ stem = Path(filename).stem.lower()
119
+ for keyword, role in ROLE_KEYWORDS.items():
120
+ if keyword in stem.split("_") or keyword in stem.split("-") or stem == keyword:
121
+ return role
122
+ if stem.startswith("test_") or stem.endswith("_test") or stem.endswith("_spec"):
123
+ return "测试"
124
+ return None
125
+
126
+
127
+ def _is_ignored_dir(dirname: str, config: dict) -> bool:
128
+ return any(fnmatch(dirname, p) for p in config.get("ignore_dirs", []))
129
+
130
+
131
+ def _scan_dir(dirpath: str, config: dict) -> dict:
132
+ info = {
133
+ "path": dirpath,
134
+ "files": [],
135
+ "file_count": 0,
136
+ "code_file_count": 0,
137
+ "total_lines": 0,
138
+ "roles": defaultdict(int),
139
+ }
140
+
141
+ if not os.path.isdir(dirpath):
142
+ return info
143
+
144
+ dirname = os.path.basename(dirpath)
145
+ if _is_ignored_dir(dirname, config):
146
+ return info
147
+
148
+ for fname in os.listdir(dirpath):
149
+ fpath = os.path.join(dirpath, fname)
150
+ if not os.path.isfile(fpath) or _should_ignore(fname, config):
151
+ continue
152
+
153
+ ext = os.path.splitext(fname)[1].lower()
154
+ lines = _count_lines(fpath)
155
+ if lines < 0:
156
+ continue
157
+
158
+ is_code = ext in CODE_EXTENSIONS
159
+ role = _infer_role(fname)
160
+
161
+ info["files"].append({
162
+ "name": fname, "ext": ext, "lines": lines,
163
+ "is_code": is_code, "role": role,
164
+ })
165
+ info["file_count"] += 1
166
+ if is_code:
167
+ info["code_file_count"] += 1
168
+ info["total_lines"] += lines
169
+ if role:
170
+ info["roles"][role] += 1
171
+
172
+ return info
173
+
174
+
175
+ def _analyze_dir(dir_info: dict, config: dict) -> list[str]:
176
+ concerns = []
177
+
178
+ for f in sorted(
179
+ (f for f in dir_info["files"] if f["is_code"] and f["lines"] >= config["file_size_warning"]),
180
+ key=lambda x: -x["lines"],
181
+ ):
182
+ lines = f["lines"]
183
+ if lines >= config["file_size_severe"]:
184
+ level = "严重过大"
185
+ elif lines >= config["file_size_critical"]:
186
+ level = "过大"
187
+ else:
188
+ level = "较大"
189
+ concerns.append(f" {f['name']} ({lines} 行, {level})")
190
+
191
+ if dir_info["file_count"] > config["max_files_per_dir"]:
192
+ concerns.append(f" 目录文件数: {dir_info['file_count']} 个 (超过 {config['max_files_per_dir']})")
193
+
194
+ code_files = [f for f in dir_info["files"] if f["is_code"]]
195
+ doc_files = [
196
+ f for f in dir_info["files"]
197
+ if f["ext"] in DOC_EXTENSIONS and f["name"].upper() != "README.MD"
198
+ ]
199
+ if code_files and doc_files:
200
+ doc_names = ", ".join(f["name"] for f in doc_files[:5])
201
+ concerns.append(f" 文档混入代码目录: {doc_names}")
202
+
203
+ roles = dict(dir_info["roles"])
204
+ if len(roles) >= 3:
205
+ role_summary = ", ".join(f"{r}({c})" for r, c in sorted(roles.items(), key=lambda x: -x[1]))
206
+ concerns.append(f" 职责混杂: {role_summary}")
207
+
208
+ return concerns
209
+
210
+
211
+ def check_changed_dirs(project_root: str, changed_files: list[str]) -> str:
212
+ """Check directories containing changed files and return a text report.
213
+
214
+ Args:
215
+ project_root: Absolute path to the project root.
216
+ changed_files: List of changed file paths (relative or absolute).
217
+
218
+ Returns:
219
+ A text report. Empty string if no changed_files provided.
220
+ """
221
+ if not changed_files:
222
+ return ""
223
+
224
+ config = _load_config(project_root)
225
+ dirs_to_check: set[str] = set()
226
+ changed_info: list[dict] = []
227
+
228
+ for cf in changed_files:
229
+ abs_path = cf if os.path.isabs(cf) else os.path.join(project_root, cf)
230
+ rel_path = os.path.relpath(abs_path, project_root)
231
+
232
+ parent = os.path.dirname(abs_path)
233
+ if os.path.isdir(parent):
234
+ dirs_to_check.add(parent)
235
+
236
+ if os.path.isfile(abs_path):
237
+ lines = _count_lines(abs_path)
238
+ ext = os.path.splitext(rel_path)[1].lower()
239
+ is_code = ext in CODE_EXTENSIONS
240
+ size_label = ""
241
+ if is_code and lines >= 0:
242
+ if lines >= config["file_size_severe"]:
243
+ size_label = "严重过大"
244
+ elif lines >= config["file_size_critical"]:
245
+ size_label = "过大"
246
+ elif lines >= config["file_size_warning"]:
247
+ size_label = "较大"
248
+ changed_info.append({
249
+ "path": rel_path,
250
+ "lines": max(lines, 0),
251
+ "size_label": size_label,
252
+ "exists": True,
253
+ })
254
+ else:
255
+ changed_info.append({
256
+ "path": rel_path, "lines": 0,
257
+ "size_label": "", "exists": False,
258
+ })
259
+
260
+ parts = ["=== 变更文件 ==="]
261
+ for ci in changed_info:
262
+ if not ci["exists"]:
263
+ parts.append(f" [-] {ci['path']} (已删除)")
264
+ else:
265
+ note = f", {ci['size_label']}" if ci["size_label"] else ""
266
+ parts.append(f" [~] {ci['path']} ({ci['lines']} 行{note})")
267
+
268
+ dir_concerns: dict[str, dict] = {}
269
+ for dp in sorted(dirs_to_check):
270
+ di = _scan_dir(dp, config)
271
+ cs = _analyze_dir(di, config)
272
+ if cs:
273
+ rd = os.path.relpath(dp, project_root)
274
+ dir_concerns[rd] = {
275
+ "concerns": cs,
276
+ "file_count": di["file_count"],
277
+ "code_file_count": di["code_file_count"],
278
+ }
279
+
280
+ parts.append("")
281
+ parts.append("=== 目录结构关注 ===")
282
+ if dir_concerns:
283
+ for rd, info in dir_concerns.items():
284
+ parts.append(
285
+ f"\n{rd}/ ({info['file_count']} 文件, 其中 {info['code_file_count']} 个代码文件)"
286
+ )
287
+ parts.extend(info["concerns"])
288
+ else:
289
+ parts.append("未发现结构问题")
290
+
291
+ return "\n".join(parts)
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ MCP AI Supervisor Web UI 模組
4
+
5
+ 基於 FastAPI 和 WebSocket 的 Web 用戶介面,提供豐富的互動回饋功能。
6
+ 支援文字輸入、圖片上傳、命令執行等功能,設計採用現代化的 Web UI 架構。
7
+
8
+ 主要功能:
9
+ - FastAPI Web 應用程式
10
+ - WebSocket 實時通訊
11
+ - 多語言國際化支援
12
+ - 圖片上傳與預覽
13
+ - 命令執行與結果展示
14
+ - 響應式設計
15
+ - 本地和遠端環境適配
16
+ """
17
+
18
+ from .main import WebUIManager, get_web_ui_manager, launch_web_feedback_ui, stop_web_ui
19
+
20
+
21
+ __all__ = [
22
+ "WebUIManager",
23
+ "get_web_ui_manager",
24
+ "launch_web_feedback_ui",
25
+ "stop_web_ui",
26
+ ]
@@ -0,0 +1,8 @@
1
+ """
2
+ Web 常量模組
3
+ """
4
+
5
+ from .message_codes import MessageCodes, get_message_code
6
+
7
+
8
+ __all__ = ["MessageCodes", "get_message_code"]
@@ -0,0 +1,173 @@
1
+ """
2
+ 統一的訊息代碼定義
3
+
4
+ 這個模組定義了所有後端使用的訊息代碼常量。
5
+ 前端會根據這些代碼顯示對應的本地化訊息。
6
+
7
+ 使用方式:
8
+ from ..constants import MessageCodes, get_message_code
9
+
10
+ # 使用常量
11
+ code = MessageCodes.SESSION_FEEDBACK_SUBMITTED
12
+
13
+ # 或使用輔助函數
14
+ code = get_message_code("SESSION_FEEDBACK_SUBMITTED")
15
+ """
16
+
17
+
18
+ class MessageCodes:
19
+ """訊息代碼常量類"""
20
+
21
+ # ========== 系統相關 ==========
22
+ SYSTEM_CONNECTION_ESTABLISHED = "system.connectionEstablished"
23
+ SYSTEM_CONNECTION_LOST = "system.connectionLost"
24
+ SYSTEM_CONNECTION_RECONNECTING = "system.connectionReconnecting"
25
+ SYSTEM_CONNECTION_RECONNECTED = "system.connectionReconnected"
26
+ SYSTEM_CONNECTION_FAILED = "system.connectionFailed"
27
+ SYSTEM_WEBSOCKET_ERROR = "system.websocketError"
28
+ SYSTEM_WEBSOCKET_READY = "system.websocketReady"
29
+ SYSTEM_MEMORY_PRESSURE = "system.memoryPressure"
30
+ SYSTEM_SHUTDOWN = "system.shutdown"
31
+ SYSTEM_PROCESS_KILLED = "system.processKilled"
32
+ SYSTEM_HEARTBEAT_STOPPED = "system.heartbeatStopped"
33
+
34
+ # ========== 會話相關 ==========
35
+ SESSION_NO_ACTIVE = "session.noActiveSession"
36
+ SESSION_CREATED = "session.created"
37
+ SESSION_UPDATED = "session.updated"
38
+ SESSION_EXPIRED = "session.expired"
39
+ SESSION_TIMEOUT = "session.timeout"
40
+ SESSION_CLEANED = "session.cleaned"
41
+ SESSION_FEEDBACK_SUBMITTED = "session.feedbackSubmitted"
42
+ SESSION_USER_MESSAGE_RECORDED = "session.userMessageRecorded"
43
+ SESSION_HISTORY_SAVED = "session.historySaved"
44
+ SESSION_HISTORY_LOADED = "session.historyLoaded"
45
+ SESSION_MANUAL_CLEANUP = "session.manualCleanup"
46
+ SESSION_ERROR_CLEANUP = "session.errorCleanup"
47
+
48
+ # ========== 設定相關 ==========
49
+ SETTINGS_SAVED = "settingsAPI.saved"
50
+ SETTINGS_LOADED = "settingsAPI.loaded"
51
+ SETTINGS_CLEARED = "settingsAPI.cleared"
52
+ SETTINGS_SAVE_FAILED = "settingsAPI.saveFailed"
53
+ SETTINGS_LOAD_FAILED = "settingsAPI.loadFailed"
54
+ SETTINGS_CLEAR_FAILED = "settingsAPI.clearFailed"
55
+ SETTINGS_SET_FAILED = "settingsAPI.setFailed"
56
+ SETTINGS_INVALID_VALUE = "settingsAPI.invalidValue"
57
+ SETTINGS_LOG_LEVEL_UPDATED = "settingsAPI.logLevelUpdated"
58
+ SETTINGS_INVALID_LOG_LEVEL = "settingsAPI.invalidLogLevel"
59
+
60
+ # ========== 命令執行相關 ==========
61
+ COMMAND_EXECUTING = "commandStatus.executing"
62
+ COMMAND_COMPLETED = "commandStatus.completed"
63
+ COMMAND_FAILED = "commandStatus.failed"
64
+ COMMAND_INVALID = "commandStatus.invalid"
65
+ COMMAND_OUTPUT_RECEIVED = "commandStatus.outputReceived"
66
+ COMMAND_ERROR = "commandStatus.error"
67
+
68
+ # ========== 錯誤相關 ==========
69
+ ERROR_GENERIC = "error.generic"
70
+ ERROR_NETWORK = "error.network"
71
+ ERROR_SERVER = "error.server"
72
+ ERROR_TIMEOUT = "error.timeout"
73
+ ERROR_INVALID_INPUT = "error.invalidInput"
74
+ ERROR_OPERATION_FAILED = "error.operationFailed"
75
+ ERROR_USER_MESSAGE_FAILED = "error.userMessageFailed"
76
+ ERROR_GET_SESSIONS_FAILED = "error.getSessionsFailed"
77
+ ERROR_GET_LOG_LEVEL_FAILED = "error.getLogLevelFailed"
78
+ ERROR_RESOURCE_CLEANUP = "error.resourceCleanup"
79
+ ERROR_PROCESSING = "error.processing"
80
+
81
+ # ========== 檔案相關 ==========
82
+ FILE_UPLOAD_SUCCESS = "file.uploadSuccess"
83
+ FILE_UPLOAD_FAILED = "file.uploadFailed"
84
+ FILE_SIZE_TOO_LARGE = "file.sizeTooLarge"
85
+ FILE_TYPE_NOT_SUPPORTED = "file.typeNotSupported"
86
+ FILE_PROCESSING = "file.processing"
87
+ FILE_REMOVED = "file.removed"
88
+
89
+ # ========== 提示詞相關 ==========
90
+ PROMPT_SAVED = "prompt.saved"
91
+ PROMPT_DELETED = "prompt.deleted"
92
+ PROMPT_APPLIED = "prompt.applied"
93
+ PROMPT_IMPORT_SUCCESS = "prompt.importSuccess"
94
+ PROMPT_IMPORT_FAILED = "prompt.importFailed"
95
+ PROMPT_EXPORT_SUCCESS = "prompt.exportSuccess"
96
+ PROMPT_VALIDATION_FAILED = "prompt.validationFailed"
97
+
98
+
99
+ # 向後兼容的映射表(從舊的 key 到新的常量名稱)
100
+ LEGACY_KEY_MAPPING = {
101
+ # feedback_session.py 的舊 key
102
+ "FEEDBACK_SUBMITTED": "SESSION_FEEDBACK_SUBMITTED",
103
+ "SESSION_CLEANUP": "SESSION_CLEANED",
104
+ "TIMEOUT_CLEANUP": "SESSION_TIMEOUT",
105
+ "EXPIRED_CLEANUP": "SESSION_EXPIRED",
106
+ "MEMORY_PRESSURE_CLEANUP": "SYSTEM_MEMORY_PRESSURE",
107
+ "MANUAL_CLEANUP": "SESSION_MANUAL_CLEANUP",
108
+ "ERROR_CLEANUP": "SESSION_ERROR_CLEANUP",
109
+ "SHUTDOWN_CLEANUP": "SYSTEM_SHUTDOWN",
110
+ "COMMAND_EXECUTING": "COMMAND_EXECUTING",
111
+ "COMMAND_COMPLETED": "COMMAND_COMPLETED",
112
+ "COMMAND_FAILED": "COMMAND_FAILED",
113
+ "COMMAND_INVALID": "COMMAND_INVALID",
114
+ "COMMAND_ERROR": "COMMAND_ERROR",
115
+ "PROCESS_KILLED": "SYSTEM_PROCESS_KILLED",
116
+ "RESOURCE_CLEANUP_ERROR": "ERROR_RESOURCE_CLEANUP",
117
+ "HEARTBEAT_STOPPED": "SYSTEM_HEARTBEAT_STOPPED",
118
+ "PROCESSING_ERROR": "ERROR_PROCESSING",
119
+ "WEBSOCKET_READY": "SYSTEM_WEBSOCKET_READY",
120
+ # main_routes.py 的舊 key
121
+ "no_active_session": "SESSION_NO_ACTIVE",
122
+ "websocket_connected": "SYSTEM_CONNECTION_ESTABLISHED",
123
+ "new_session_created": "SESSION_CREATED",
124
+ "user_message_recorded": "SESSION_USER_MESSAGE_RECORDED",
125
+ "add_user_message_failed": "ERROR_USER_MESSAGE_FAILED",
126
+ "settings_saved": "SETTINGS_SAVED",
127
+ "save_failed": "SETTINGS_SAVE_FAILED",
128
+ "load_failed": "SETTINGS_LOAD_FAILED",
129
+ "settings_cleared": "SETTINGS_CLEARED",
130
+ "clear_failed": "SETTINGS_CLEAR_FAILED",
131
+ "session_history_saved": "SESSION_HISTORY_SAVED",
132
+ "get_sessions_failed": "ERROR_GET_SESSIONS_FAILED",
133
+ "get_log_level_failed": "ERROR_GET_LOG_LEVEL_FAILED",
134
+ "invalid_log_level": "SETTINGS_INVALID_LOG_LEVEL",
135
+ "log_level_updated": "SETTINGS_LOG_LEVEL_UPDATED",
136
+ "set_failed": "SETTINGS_SET_FAILED",
137
+ }
138
+
139
+
140
+ def get_message_code(key: str) -> str:
141
+ """
142
+ 獲取訊息代碼
143
+
144
+ 支援三種輸入方式:
145
+ 1. 直接使用常量名稱:get_message_code("SESSION_FEEDBACK_SUBMITTED")
146
+ 2. 使用舊的 key(向後兼容):get_message_code("FEEDBACK_SUBMITTED")
147
+ 3. 使用小寫的舊 key(向後兼容):get_message_code("feedback_submitted")
148
+
149
+ Args:
150
+ key: 訊息 key 或常量名稱
151
+
152
+ Returns:
153
+ 訊息代碼字串(例如:"session.feedbackSubmitted")
154
+ """
155
+ # 嘗試直接從 MessageCodes 獲取
156
+ if hasattr(MessageCodes, key):
157
+ return str(getattr(MessageCodes, key))
158
+
159
+ # 嘗試從映射表獲取(支援大寫和小寫)
160
+ upper_key = key.upper()
161
+ if upper_key in LEGACY_KEY_MAPPING:
162
+ constant_name = LEGACY_KEY_MAPPING[upper_key]
163
+ if hasattr(MessageCodes, constant_name):
164
+ return str(getattr(MessageCodes, constant_name))
165
+
166
+ # 如果是小寫的 key,也嘗試映射
167
+ if key in LEGACY_KEY_MAPPING:
168
+ constant_name = LEGACY_KEY_MAPPING[key]
169
+ if hasattr(MessageCodes, constant_name):
170
+ return str(getattr(MessageCodes, constant_name))
171
+
172
+ # 如果都找不到,返回一個預設格式
173
+ return f"unknown.{key}"
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ MCP AI Supervisor 核心模块
4
+
5
+ 提供循环机制与模式支持的核心组件:
6
+ - DelegateManager: 核心编排器
7
+ - TaskStateManager / TaskState / TaskPhase: 任务状态管理
8
+ - ResponseBuilder: 响应构建
9
+ - SceneDetector / SceneResult: 场景识别
10
+ - AutoResponder / QuestionType: 自动回复
11
+ """
12
+
13
+ from .auto_responder import AutoResponder, QuestionType
14
+ from .delegate_manager import DelegateManager, get_delegate_manager
15
+ from .response_builder import ResponseBuilder
16
+ from .scene_detector import SceneDetector, SceneResult
17
+ from .task_state import TaskPhase, TaskState, TaskStateManager
18
+
19
+ __all__ = [
20
+ "AutoResponder",
21
+ "DelegateManager",
22
+ "QuestionType",
23
+ "ResponseBuilder",
24
+ "SceneDetector",
25
+ "SceneResult",
26
+ "TaskPhase",
27
+ "TaskState",
28
+ "TaskStateManager",
29
+ "get_delegate_manager",
30
+ ]