RedLotus 1.0.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 (166) hide show
  1. redlotus/API/QQ.py +154 -0
  2. redlotus/API/WeChat.py +94 -0
  3. redlotus/API/__init__.py +0 -0
  4. redlotus/API/base.py +631 -0
  5. redlotus/API/config.yaml.example +25 -0
  6. redlotus/API/qq_media_helpers.py +201 -0
  7. redlotus/ModelGateway/ModelChecker.py +788 -0
  8. redlotus/ModelGateway/__init__.py +0 -0
  9. redlotus/ModelGateway/agent_factory.py +134 -0
  10. redlotus/ModelGateway/model_factory.py +179 -0
  11. redlotus/ModelGateway/usage_accounting.py +403 -0
  12. redlotus/RAG/DataBase.py +296 -0
  13. redlotus/RAG/RAG.py +181 -0
  14. redlotus/RAG/__init__.py +3 -0
  15. redlotus/RAG/embedding_function.py +115 -0
  16. redlotus/RAG/storage_path.py +79 -0
  17. redlotus/__init__.py +0 -0
  18. redlotus/agent_core/__init__.py +1 -0
  19. redlotus/agent_core/cli_controller.py +357 -0
  20. redlotus/agent_core/entrypoint.py +38 -0
  21. redlotus/agent_core/goal_mode.py +161 -0
  22. redlotus/agent_core/input_messages.py +60 -0
  23. redlotus/agent_core/memory_runtime.py +76 -0
  24. redlotus/agent_core/roles.py +92 -0
  25. redlotus/agent_core/system.py +827 -0
  26. redlotus/cli/__init__.py +27 -0
  27. redlotus/cli/cli_commands.py +840 -0
  28. redlotus/cli/cli_ui.py +92 -0
  29. redlotus/cli/completer.py +104 -0
  30. redlotus/cli/completion.py +127 -0
  31. redlotus/cli/diff_view.py +140 -0
  32. redlotus/cli/file_ref.py +238 -0
  33. redlotus/cli/output.py +149 -0
  34. redlotus/cli/panel.py +446 -0
  35. redlotus/cli/pending_review.py +128 -0
  36. redlotus/cli/render.py +192 -0
  37. redlotus/cli/repl.py +152 -0
  38. redlotus/cli/tui.py +934 -0
  39. redlotus/config/__init__.py +0 -0
  40. redlotus/config/app_config.py +273 -0
  41. redlotus/config.json +115 -0
  42. redlotus/infra/__init__.py +0 -0
  43. redlotus/infra/logger.py +187 -0
  44. redlotus/infra/path_sandbox.py +74 -0
  45. redlotus/infra/paths.py +85 -0
  46. redlotus/infra/persist_utils.py +94 -0
  47. redlotus/infra/shared_http.py +36 -0
  48. redlotus/infra/subprocess_runner.py +73 -0
  49. redlotus/prompt.py +125 -0
  50. redlotus/prompts/LongTermMemory/MEMORY_GUIDANCE.md +19 -0
  51. redlotus/prompts/LongTermMemory/soul_user_consolidation.md +60 -0
  52. redlotus/prompts/common_conduct.md +28 -0
  53. redlotus/prompts/context_compress_structured_system.md +49 -0
  54. redlotus/prompts/coordinator_system.md +24 -0
  55. redlotus/prompts/goal_iteration.md +34 -0
  56. redlotus/prompts/manager_planning_continue.md +11 -0
  57. redlotus/prompts/manager_planning_new.md +14 -0
  58. redlotus/prompts/manager_summary.md +16 -0
  59. redlotus/prompts/manager_system.md +44 -0
  60. redlotus/prompts/skills_layout.md +11 -0
  61. redlotus/prompts/worker_system.md +52 -0
  62. redlotus/runtime/__init__.py +0 -0
  63. redlotus/runtime/lifecycle.py +546 -0
  64. redlotus/runtime/runtime_state.py +141 -0
  65. redlotus/runtime/tool_telemetry.py +117 -0
  66. redlotus/runtime/worker_result.py +71 -0
  67. redlotus/skills/SkillsManager.py +252 -0
  68. redlotus/skills/SkillsTools.py +156 -0
  69. redlotus/skills/__init__.py +0 -0
  70. redlotus/skills/agent-browser-clawdbot/.clawhub/origin.json +7 -0
  71. redlotus/skills/agent-browser-clawdbot/SKILL.md +206 -0
  72. redlotus/skills/agent-browser-clawdbot/_meta.json +6 -0
  73. redlotus/skills/agentic-coding/SKILL.md +150 -0
  74. redlotus/skills/agentic-coding/handoff.md +34 -0
  75. redlotus/skills/agentic-coding/memory-template.md +86 -0
  76. redlotus/skills/agentic-coding/prompt-contracts.md +69 -0
  77. redlotus/skills/agentic-coding/protocol.md +65 -0
  78. redlotus/skills/agentic-coding/setup.md +52 -0
  79. redlotus/skills/bfl-api/SKILL.md +264 -0
  80. redlotus/skills/bfl-api/references/api-key-setup.md +55 -0
  81. redlotus/skills/bfl-api/references/code-examples/curl-examples.sh +160 -0
  82. redlotus/skills/bfl-api/references/code-examples/python-client.py +476 -0
  83. redlotus/skills/bfl-api/references/code-examples/typescript-client.ts +480 -0
  84. redlotus/skills/bfl-api/references/endpoints.md +286 -0
  85. redlotus/skills/bfl-api/references/error-handling.md +334 -0
  86. redlotus/skills/bfl-api/references/polling-patterns.md +240 -0
  87. redlotus/skills/bfl-api/references/rate-limiting.md +246 -0
  88. redlotus/skills/bfl-api/references/webhook-integration.md +339 -0
  89. redlotus/skills/ci-cd/.clawhub/origin.json +7 -0
  90. redlotus/skills/ci-cd/SKILL.md +81 -0
  91. redlotus/skills/ci-cd/_meta.json +6 -0
  92. redlotus/skills/ci-cd/mobile.md +115 -0
  93. redlotus/skills/ci-cd/templates.md +138 -0
  94. redlotus/skills/ci-cd/web.md +123 -0
  95. redlotus/skills/crypto-backtest/.clawhub/origin.json +7 -0
  96. redlotus/skills/crypto-backtest/SKILL.md +63 -0
  97. redlotus/skills/crypto-backtest/_meta.json +6 -0
  98. redlotus/skills/crypto-backtest/references/custom_strategy.md +41 -0
  99. redlotus/skills/crypto-backtest/references/strategy_notes.md +33 -0
  100. redlotus/skills/crypto-backtest/scripts/backtest_engine.py +364 -0
  101. redlotus/skills/crypto-backtest/scripts/sweep.py +94 -0
  102. redlotus/skills/flux-best-practices/SKILL.md +82 -0
  103. redlotus/skills/flux-best-practices/rules/core-principles.md +138 -0
  104. redlotus/skills/flux-best-practices/rules/flux1-models.md +176 -0
  105. redlotus/skills/flux-best-practices/rules/flux2-models.md +202 -0
  106. redlotus/skills/flux-best-practices/rules/hex-color-prompting.md +210 -0
  107. redlotus/skills/flux-best-practices/rules/i2i-prompting.md +293 -0
  108. redlotus/skills/flux-best-practices/rules/json-structured-prompting.md +241 -0
  109. redlotus/skills/flux-best-practices/rules/model-selection-guide.md +246 -0
  110. redlotus/skills/flux-best-practices/rules/multi-reference-editing.md +241 -0
  111. redlotus/skills/flux-best-practices/rules/negative-prompt-alternatives.md +202 -0
  112. redlotus/skills/flux-best-practices/rules/t2i-prompting.md +230 -0
  113. redlotus/skills/flux-best-practices/rules/typography-text.md +241 -0
  114. redlotus/skills/manage-skills/SKILL.md +124 -0
  115. redlotus/skills/skill-creator-operator/SKILL.md +88 -0
  116. redlotus/skills/skill-creator-operator/references/LINKS.md +11 -0
  117. redlotus/skills/skill-creator-operator/references/OVERVIEW.md +11 -0
  118. redlotus/skills/skill-creator-operator/references/PRINCIPLES.md +37 -0
  119. redlotus/skills/skill-creator-operator/scripts/scaffold-skill.mjs +47 -0
  120. redlotus/skills/skill-template/SKILL.md +119 -0
  121. redlotus/skills/skill-template/scripts/script.sh +101 -0
  122. redlotus/skills/skill-template/scripts/skill-tmpl.sh +427 -0
  123. redlotus/skills/skill-template/tips.md +10 -0
  124. redlotus/skills/skill-vetter-1.0.0/SKILL.md +138 -0
  125. redlotus/skills/talib-technical-analysis/.clawhub/origin.json +7 -0
  126. redlotus/skills/talib-technical-analysis/SKILL.md +81 -0
  127. redlotus/skills/talib-technical-analysis/_meta.json +6 -0
  128. redlotus/skills/talib-technical-analysis/human_summary.md +16 -0
  129. redlotus/skills/talib-technical-analysis/references/ANTI_PATTERNS.md +67 -0
  130. redlotus/skills/talib-technical-analysis/references/COMPONENTS.md +14 -0
  131. redlotus/skills/talib-technical-analysis/references/CONSTRAINTS.md +16 -0
  132. redlotus/skills/talib-technical-analysis/references/LOCKS.md +46 -0
  133. redlotus/skills/talib-technical-analysis/references/USE_CASES.md +8 -0
  134. redlotus/skills/talib-technical-analysis/references/WISDOM.md +48 -0
  135. redlotus/skills/talib-technical-analysis/references/components/abstract_api_-stateful.md +22 -0
  136. redlotus/skills/talib-technical-analysis/references/components/c_library_binding_layer.md +7 -0
  137. redlotus/skills/talib-technical-analysis/references/components/code_generation.md +13 -0
  138. redlotus/skills/talib-technical-analysis/references/components/function_api_-batch.md +13 -0
  139. redlotus/skills/talib-technical-analysis/references/components/series_support_layer.md +7 -0
  140. redlotus/skills/talib-technical-analysis/references/components/stream_api_-incremental.md +13 -0
  141. redlotus/skills/talib-technical-analysis/references/seed.yaml +3134 -0
  142. redlotus/skills/web-scraping/SKILL.md +75 -0
  143. redlotus/tools/BasicTools.py +684 -0
  144. redlotus/tools/ExtractFileContent.py +427 -0
  145. redlotus/tools/ImageGeneration.py +114 -0
  146. redlotus/tools/ManagementTools.py +301 -0
  147. redlotus/tools/WorkerOrchestrator.py +437 -0
  148. redlotus/tools/__init__.py +21 -0
  149. redlotus/tools/browser_session.py +195 -0
  150. redlotus/tools/conversation_log.py +297 -0
  151. redlotus/tools/memory/__init__.py +21 -0
  152. redlotus/tools/memory/chat_history.py +38 -0
  153. redlotus/tools/memory/consolidation.py +53 -0
  154. redlotus/tools/memory/hygiene.py +121 -0
  155. redlotus/tools/memory/ltm.py +464 -0
  156. redlotus/tools/memory/message_text.py +226 -0
  157. redlotus/tools/memory/stm.py +553 -0
  158. redlotus/workspace/__init__.py +0 -0
  159. redlotus/workspace/workspace.py +146 -0
  160. redlotus/workspace/workspace_load.py +118 -0
  161. redlotus/workspace/workspace_picker.py +43 -0
  162. redlotus-1.0.0.dist-info/METADATA +116 -0
  163. redlotus-1.0.0.dist-info/RECORD +166 -0
  164. redlotus-1.0.0.dist-info/WHEEL +5 -0
  165. redlotus-1.0.0.dist-info/entry_points.txt +2 -0
  166. redlotus-1.0.0.dist-info/top_level.txt +1 -0
redlotus/API/QQ.py ADDED
@@ -0,0 +1,154 @@
1
+ import inspect
2
+ import os
3
+ import re
4
+ import sys
5
+ from functools import partial
6
+ from pathlib import Path
7
+
8
+ # ncatbot 在导入时即冻结配置(从 NCATBOT_CONFIG_PATH 读取配置文件路径),
9
+ # 故须在导入 ncatbot 之前指向 config.yaml(用户配置目录,首次从随包模板 seed),否则会回退到 input() 阻塞。
10
+ from redlotus.infra.paths import resource_root, user_config_dir
11
+
12
+
13
+ def _ensure_bot_config_path() -> Path:
14
+ cfg = user_config_dir() / "config.yaml"
15
+ if not cfg.exists():
16
+ tmpl = resource_root() / "API" / "config.yaml.example"
17
+ try:
18
+ cfg.parent.mkdir(parents=True, exist_ok=True)
19
+ if tmpl.is_file():
20
+ cfg.write_text(tmpl.read_text(encoding="utf-8"), encoding="utf-8")
21
+ except OSError:
22
+ return tmpl
23
+ return cfg
24
+
25
+
26
+ os.environ.setdefault("NCATBOT_CONFIG_PATH", str(_ensure_bot_config_path()))
27
+
28
+ from ncatbot.core import BaseMessageEvent, BotClient, GroupMessageEvent, MetaEvent
29
+ from ncatbot.plugin_system import on_message
30
+ from ncatbot.utils import config
31
+ from ncatbot.utils.config import strong_password_check
32
+
33
+ from redlotus.infra import logger
34
+ from redlotus.config.app_config import get_env
35
+ from redlotus.agent_core.input_messages import UserMessage
36
+ from redlotus.API.base import BotBase
37
+ from redlotus.API.qq_media_helpers import extract_media
38
+
39
+ class QQBot(BotBase):
40
+ _ENV_AGENT_TIMEOUT = "QQ_AGENT_TIMEOUT_S"
41
+ _ENV_SEND_TIMEOUT = "QQ_SEND_REPLY_TIMEOUT_S"
42
+ _FILE_ALLOW_EXT = frozenset({
43
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".mp4", ".mov", ".mkv", ".webm",
44
+ ".pdf", ".txt", ".md", ".docx", ".xlsx", ".csv", ".json",
45
+ })
46
+
47
+ def __init__(self):
48
+ super().__init__()
49
+ if uin := get_env("QQBOT_ID", warn=False):
50
+ config.set_bot_uin(uin)
51
+ self._bot_client = BotClient()
52
+ self._bot_client.add_shutdown_handler(self._on_shutdown)
53
+
54
+ @property
55
+ def platform_tag(self) -> str:
56
+ return "QQ"
57
+
58
+ @property
59
+ def session_prefix(self) -> str:
60
+ return "qq_"
61
+
62
+ def clean_text(self, raw: str) -> str:
63
+ return re.sub(r"\[CQ:[^\]]+\]", "", raw or "").strip()
64
+
65
+ def _is_at_me(self, event: BaseMessageEvent) -> bool:
66
+ if not isinstance(event, GroupMessageEvent):
67
+ return True
68
+ msg = getattr(event, "message", None)
69
+ return msg is not None and msg.is_user_at(config.bt_uin)
70
+
71
+ def _session_id(self, event: BaseMessageEvent) -> str:
72
+ if isinstance(event, GroupMessageEvent):
73
+ return f"group_{event.group_id}"
74
+ return f"private_{event.user_id}"
75
+
76
+ async def _reply_event(self, event: BaseMessageEvent, text: str) -> None:
77
+ sig = inspect.signature(event.reply)
78
+ await (
79
+ event.reply(text=text, at=False)
80
+ if "at" in sig.parameters
81
+ else event.reply(text=text)
82
+ )
83
+
84
+ async def _extract_attachments(self, event: BaseMessageEvent) -> list:
85
+ return await extract_media(self._bot_client.api, event, self._FILE_ALLOW_EXT)
86
+
87
+ async def _on_shutdown(self, _: MetaEvent) -> None:
88
+ await self.release_all_resources_async()
89
+
90
+ async def _handle_message(self, event: BaseMessageEvent) -> None:
91
+ raw_text = (event.raw_message or "").strip()
92
+ if not raw_text or (isinstance(event, GroupMessageEvent) and not self._is_at_me(event)):
93
+ return
94
+ session_id = self._session_id(event)
95
+ user_text = self.clean_text(raw_text)
96
+ attachments = await self._extract_attachments(event)
97
+ user_text, attachments = await self._partition_document_attachments(user_text, attachments)
98
+ await self.dispatch_user_message(
99
+ session_id,
100
+ UserMessage(text=user_text, attachments=attachments),
101
+ partial(self._reply_event, event),
102
+ )
103
+
104
+ def _register_handlers(self) -> None:
105
+ on_message(self._handle_message)
106
+
107
+ def _doctor(self) -> None:
108
+ """启动前体检:配置缺失/无效时立即报错退出,避免 ncatbot 回退到 input() 静默卡死。"""
109
+ config_path = Path(os.environ["NCATBOT_CONFIG_PATH"])
110
+ if not config_path.is_file():
111
+ logger.error(
112
+ f"[QQ] 找不到 NapCat 配置文件 {config_path}。"
113
+ f"请在 {config_path.parent} 下放置 config.yaml(参照随包模板)。"
114
+ )
115
+ sys.exit(1)
116
+ uin = str(config.bt_uin or "")
117
+ if uin in ("", "None", "123456"):
118
+ logger.error(
119
+ "[QQ] 机器人 QQ 号未配置。请设置环境变量 QQBOT_ID,"
120
+ f"或在 {config_path} 中填写 bt_uin。"
121
+ )
122
+ sys.exit(1)
123
+ token = config.napcat.webui_token
124
+ if not strong_password_check(token):
125
+ logger.error(
126
+ f"[QQ] NapCat WebUI 令牌强度不足({config_path} 的 napcat.webui_token)。"
127
+ f"请改为至少 12 位、含数字与大小写字母及特殊符号的强密码。"
128
+ )
129
+ sys.exit(1)
130
+
131
+ def run(
132
+ self,
133
+ *,
134
+ debug: bool = True,
135
+ remote_mode: bool = True,
136
+ enable_webui_interaction: bool = False,
137
+ **kwargs,
138
+ ):
139
+ self._doctor()
140
+ self._released = False
141
+ self._register_handlers()
142
+ try:
143
+ self._bot_client.run_frontend(
144
+ debug=debug,
145
+ remote_mode=remote_mode,
146
+ enable_webui_interaction=enable_webui_interaction,
147
+ **kwargs,
148
+ )
149
+ finally:
150
+ self.release_all_resources()
151
+
152
+
153
+ if __name__ == "__main__":
154
+ QQBot().run()
redlotus/API/WeChat.py ADDED
@@ -0,0 +1,94 @@
1
+ import asyncio
2
+ import base64
3
+ from functools import partial
4
+
5
+ from pydantic_ai import BinaryContent, ImageUrl
6
+ from wechatbot import WeChatBot
7
+
8
+ from redlotus.infra import logger
9
+ from redlotus.agent_core.input_messages import UserMessage
10
+ from redlotus.API.base import BotBase
11
+
12
+ class WeChatAgentBot(BotBase):
13
+ _ENV_AGENT_TIMEOUT = "WECHAT_AGENT_TIMEOUT_S"
14
+ _ENV_SEND_TIMEOUT = "WECHAT_SEND_REPLY_TIMEOUT_S"
15
+ _MIME_MAP = {
16
+ "image": "image/jpeg",
17
+ "voice": "audio/mpeg",
18
+ "video": "video/mp4",
19
+ "file": "application/octet-stream",
20
+ }
21
+
22
+ @property
23
+ def platform_tag(self) -> str:
24
+ return "WeChat"
25
+
26
+ @property
27
+ def session_prefix(self) -> str:
28
+ return "wx_"
29
+
30
+ async def _build_user_message(self, bot: WeChatBot, msg) -> UserMessage:
31
+ """Build a UserMessage from text plus downloaded media bytes."""
32
+ text = self.clean_text(msg.text or "")
33
+ attachments: list = []
34
+ try:
35
+ media = await bot.download(msg)
36
+ except Exception as e:
37
+ logger.warning(f"[WeChat] 下载媒体失败: {e}")
38
+ media = None
39
+ if media is not None and getattr(media, "data", None):
40
+ filename = getattr(media, "file_name", None) or ""
41
+ mtype = (getattr(media, "type", None) or "").lower()
42
+ mime = self.guess_download_mime(filename=filename, media_type_key=mtype)
43
+ if mtype == "image":
44
+ b64 = base64.standard_b64encode(media.data).decode("ascii")
45
+ attachments.append(ImageUrl(url=f"data:{mime};base64,{b64}"))
46
+ else:
47
+ text, consumed = await self._inline_document_bytes(
48
+ text,
49
+ media.data,
50
+ media_type=mime,
51
+ filename=filename or None,
52
+ )
53
+ if not consumed:
54
+ attachments.append(BinaryContent(data=media.data, media_type=mime))
55
+ return UserMessage(text=text, attachments=attachments)
56
+
57
+ async def _handle_message(self, bot: WeChatBot, msg) -> None:
58
+ if not msg.user_id:
59
+ return
60
+ session_id = f"{self.session_prefix}{msg.user_id}"
61
+ user_message = await self._build_user_message(bot, msg)
62
+ await self.dispatch_user_message(
63
+ session_id,
64
+ user_message,
65
+ partial(bot.reply, msg),
66
+ )
67
+
68
+ async def _async_main(self) -> None:
69
+ self._released = False
70
+ kwargs: dict = {
71
+ "on_qr_url": lambda url: logger.info(f"[WeChat] 请扫码登录: {url}"),
72
+ "on_scanned": lambda: logger.info("[WeChat] 已扫码,确认登录中..."),
73
+ "on_expired": lambda: logger.warning("[WeChat] 登录二维码已过期"),
74
+ "on_error": lambda err: logger.error(f"[WeChat] SDK 错误: {err}"),
75
+ }
76
+
77
+ bot = WeChatBot(**kwargs)
78
+ await bot.login()
79
+ bot.on_message(partial(self._handle_message, bot))
80
+ try:
81
+ await bot.start()
82
+ finally:
83
+ await self.release_all_resources_async()
84
+ try:
85
+ bot.stop()
86
+ except Exception as e:
87
+ logger.debug("[WeChat] bot.stop 失败: %s", e)
88
+
89
+ def run(self) -> None:
90
+ asyncio.run(self._async_main())
91
+
92
+
93
+ if __name__ == "__main__":
94
+ WeChatAgentBot().run()
File without changes