fastclaw-ai 1.1.0__tar.gz
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.
- fastclaw_ai-1.1.0/PKG-INFO +114 -0
- fastclaw_ai-1.1.0/fastclaw/README.md +80 -0
- fastclaw_ai-1.1.0/fastclaw/__init__.py +32 -0
- fastclaw_ai-1.1.0/fastclaw/__main__.py +18 -0
- fastclaw_ai-1.1.0/fastclaw/cli.py +231 -0
- fastclaw_ai-1.1.0/fastclaw/core/__init__.py +43 -0
- fastclaw_ai-1.1.0/fastclaw/core/app.py +778 -0
- fastclaw_ai-1.1.0/fastclaw/core/config.py +86 -0
- fastclaw_ai-1.1.0/fastclaw/core/paths.py +21 -0
- fastclaw_ai-1.1.0/fastclaw/core/prompts.py +110 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/__init__.py +10 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/__init__.py +17 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/base.py +53 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/client.py +166 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/feishu.py +431 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/handlers.py +312 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/imessage.py +151 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/channels/telegram.py +183 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/cron_scheduler.py +264 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/event_bus.py +93 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/router.py +1084 -0
- fastclaw_ai-1.1.0/fastclaw/gateway/server.py +178 -0
- fastclaw_ai-1.1.0/fastclaw/main.py +406 -0
- fastclaw_ai-1.1.0/fastclaw/webui/index.html +1236 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/css/element-plus-theme.css +1 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/css/element-plus.css +1 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/js/element-plus-icons.min.js +3 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/js/element-plus-zh-cn.min.js +2 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/js/element-plus.full.min.js +72 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/js/marked.min.js +69 -0
- fastclaw_ai-1.1.0/fastclaw/webui/static/js/vue3.prod.js +11 -0
- fastclaw_ai-1.1.0/fastclaw/webui/test.html +23 -0
- fastclaw_ai-1.1.0/fastclaw_ai.egg-info/PKG-INFO +114 -0
- fastclaw_ai-1.1.0/fastclaw_ai.egg-info/SOURCES.txt +38 -0
- fastclaw_ai-1.1.0/fastclaw_ai.egg-info/dependency_links.txt +1 -0
- fastclaw_ai-1.1.0/fastclaw_ai.egg-info/entry_points.txt +2 -0
- fastclaw_ai-1.1.0/fastclaw_ai.egg-info/requires.txt +13 -0
- fastclaw_ai-1.1.0/fastclaw_ai.egg-info/top_level.txt +1 -0
- fastclaw_ai-1.1.0/pyproject.toml +69 -0
- fastclaw_ai-1.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastclaw-ai
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: FastClaw - AI Agent Framework with multi-channel support
|
|
5
|
+
Author: kandada
|
|
6
|
+
License: GPL-3.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/kandada/fastclaw
|
|
8
|
+
Project-URL: Repository, https://github.com/kandada/fastclaw.git
|
|
9
|
+
Project-URL: Issues, https://github.com/kandada/fastclaw/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/kandada/fastclaw#readme
|
|
11
|
+
Keywords: ai,agent,llm,chatbot,fastmind
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: fastmind>=0.1.9
|
|
23
|
+
Requires-Dist: openai>=1.0.0
|
|
24
|
+
Requires-Dist: websockets>=10.0
|
|
25
|
+
Requires-Dist: fastapi>=0.100.0
|
|
26
|
+
Requires-Dist: uvicorn[standard]>=0.35.0
|
|
27
|
+
Requires-Dist: httpx>=0.23.0
|
|
28
|
+
Requires-Dist: anyio>=4.5
|
|
29
|
+
Requires-Dist: croniter>=6.2.0
|
|
30
|
+
Requires-Dist: lark-oapi>=1.0.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
34
|
+
|
|
35
|
+
# FastClaw
|
|
36
|
+
|
|
37
|
+
a python-based light but strong lobster
|
|
38
|
+
|
|
39
|
+
## Design Philosophy
|
|
40
|
+
|
|
41
|
+
FastClaw is built on the core concept of **event-driven agent orchestration**. Key design principles:
|
|
42
|
+
|
|
43
|
+
- **Graph-based Agent**: Uses a directed graph to orchestrate agent behavior, supporting conditional branching between nodes (e.g., tool execution, response generation)
|
|
44
|
+
- **Event Streaming**: Real-time streaming output of LLM responses for better user experience
|
|
45
|
+
- **Tool System**: Extensible tool framework supporting Shell commands, skills, and custom integrations
|
|
46
|
+
- **Session Management**: Persistent conversation history with multi-session support
|
|
47
|
+
- **Cron Scheduling**: Built-in cron-style task scheduling for automated workflows
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
### Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/kandada/fastclaw.git
|
|
55
|
+
cd fastclaw
|
|
56
|
+
pip install -r requirements.txt
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Start Server
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python main.py start
|
|
63
|
+
# or want it remaining in background:
|
|
64
|
+
nohup python main.py start > fastclaw.log 2>&1 &
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Agent Configuration
|
|
68
|
+
```bash
|
|
69
|
+
vim workspace/data/agents/main_agent/metadata.json
|
|
70
|
+
# Edit the file to configure your LLM provider and API key
|
|
71
|
+
# Currently supports OpenAI gateway models (DeepSeek, OpenAI, etc.), recommended: deepseek-chat
|
|
72
|
+
# Default agent is main_agent. To switch, modify workspace/data/settings.json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Access at http://localhost:8765
|
|
76
|
+
You can also select agents and enter API keys in the Settings page.
|
|
77
|
+
API key must be provided for the agent to work properly.
|
|
78
|
+
|
|
79
|
+
### CLI Usage
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Interactive chat
|
|
83
|
+
python main.py chat
|
|
84
|
+
|
|
85
|
+
# New session
|
|
86
|
+
python main.py chat --new
|
|
87
|
+
|
|
88
|
+
# Check status
|
|
89
|
+
python main.py status
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Features
|
|
93
|
+
|
|
94
|
+
- 🤖 **LLM-powered** - Built on [FastMind](https://github.com/kandada/fastmind) framework with streaming support
|
|
95
|
+
- 🔧 **Tool Calling** - Execute Shell commands, skills, and more
|
|
96
|
+
- ⏰ **Cron Jobs** - Schedule tasks with cron expressions
|
|
97
|
+
- 💬 **Multi-channel** - Feishu, iMessage integrations
|
|
98
|
+
- 🎨 **Extensible** - Easy to add custom skills and agents
|
|
99
|
+
|
|
100
|
+
## License
|
|
101
|
+
|
|
102
|
+
GPL-3.0
|
|
103
|
+
|
|
104
|
+
## Acknowledgments
|
|
105
|
+
|
|
106
|
+
Inspired by [OpenClaw](https://github.com/openclaw/openclaw). Special thanks to the open source community.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
FastClaw is powerful, but its use depends entirely on the user - all responsibility lies with the user yourself.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
Author:[xiefujin](https://github.com/kandada) email: 490021684@qq.com,welcome to contact me.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# FastClaw
|
|
2
|
+
|
|
3
|
+
a python-based light but strong lobster
|
|
4
|
+
|
|
5
|
+
## Design Philosophy
|
|
6
|
+
|
|
7
|
+
FastClaw is built on the core concept of **event-driven agent orchestration**. Key design principles:
|
|
8
|
+
|
|
9
|
+
- **Graph-based Agent**: Uses a directed graph to orchestrate agent behavior, supporting conditional branching between nodes (e.g., tool execution, response generation)
|
|
10
|
+
- **Event Streaming**: Real-time streaming output of LLM responses for better user experience
|
|
11
|
+
- **Tool System**: Extensible tool framework supporting Shell commands, skills, and custom integrations
|
|
12
|
+
- **Session Management**: Persistent conversation history with multi-session support
|
|
13
|
+
- **Cron Scheduling**: Built-in cron-style task scheduling for automated workflows
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
git clone https://github.com/kandada/fastclaw.git
|
|
21
|
+
cd fastclaw
|
|
22
|
+
pip install -r requirements.txt
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Start Server
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
python main.py start
|
|
29
|
+
# or want it remaining in background:
|
|
30
|
+
nohup python main.py start > fastclaw.log 2>&1 &
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Agent Configuration
|
|
34
|
+
```bash
|
|
35
|
+
vim workspace/data/agents/main_agent/metadata.json
|
|
36
|
+
# Edit the file to configure your LLM provider and API key
|
|
37
|
+
# Currently supports OpenAI gateway models (DeepSeek, OpenAI, etc.), recommended: deepseek-chat
|
|
38
|
+
# Default agent is main_agent. To switch, modify workspace/data/settings.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Access at http://localhost:8765
|
|
42
|
+
You can also select agents and enter API keys in the Settings page.
|
|
43
|
+
API key must be provided for the agent to work properly.
|
|
44
|
+
|
|
45
|
+
### CLI Usage
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Interactive chat
|
|
49
|
+
python main.py chat
|
|
50
|
+
|
|
51
|
+
# New session
|
|
52
|
+
python main.py chat --new
|
|
53
|
+
|
|
54
|
+
# Check status
|
|
55
|
+
python main.py status
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- 🤖 **LLM-powered** - Built on [FastMind](https://github.com/kandada/fastmind) framework with streaming support
|
|
61
|
+
- 🔧 **Tool Calling** - Execute Shell commands, skills, and more
|
|
62
|
+
- ⏰ **Cron Jobs** - Schedule tasks with cron expressions
|
|
63
|
+
- 💬 **Multi-channel** - Feishu, iMessage integrations
|
|
64
|
+
- 🎨 **Extensible** - Easy to add custom skills and agents
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
GPL-3.0
|
|
69
|
+
|
|
70
|
+
## Acknowledgments
|
|
71
|
+
|
|
72
|
+
Inspired by [OpenClaw](https://github.com/openclaw/openclaw). Special thanks to the open source community.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
FastClaw is powerful, but its use depends entirely on the user - all responsibility lies with the user yourself.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
Author:[xiefujin](https://github.com/kandada) email: 490021684@qq.com,welcome to contact me.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FastClaw - AI Agent Framework
|
|
3
|
+
|
|
4
|
+
支持三种运行方式:
|
|
5
|
+
1. 直接运行: cd fastclaw && python main.py
|
|
6
|
+
2. 模块运行: python -m fastclaw
|
|
7
|
+
3. pip 安装后: fastclaw start
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__version__ = "1.1.0"
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
# ===== 路径处理 =====
|
|
17
|
+
|
|
18
|
+
_PKG_DIR = Path(__file__).resolve().parent
|
|
19
|
+
_PROJECT_ROOT = _PKG_DIR.parent
|
|
20
|
+
|
|
21
|
+
# 设置默认 FASTCLAW_WORKSPACE 环境变量
|
|
22
|
+
# 优先级:已设置的环境变量 > 项目根目录的 workspace/ > ~/.fastclaw/workspace
|
|
23
|
+
_default_workspace = _PROJECT_ROOT / "workspace"
|
|
24
|
+
if os.environ.get("FASTCLAW_WORKSPACE") is None:
|
|
25
|
+
if _default_workspace.exists() and _default_workspace.is_dir():
|
|
26
|
+
os.environ["FASTCLAW_WORKSPACE"] = str(_default_workspace)
|
|
27
|
+
else:
|
|
28
|
+
os.environ["FASTCLAW_WORKSPACE"] = str(Path.home() / ".fastclaw" / "workspace")
|
|
29
|
+
|
|
30
|
+
# 确保项目根目录在 sys.path(用于直接运行模式)
|
|
31
|
+
if str(_PROJECT_ROOT) not in sys.path:
|
|
32
|
+
sys.path.insert(0, str(_PROJECT_ROOT))
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
支持 python -m fastclaw 运行
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import asyncio
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
_PKG_DIR = Path(__file__).resolve().parent
|
|
10
|
+
_PROJECT_ROOT = _PKG_DIR.parent
|
|
11
|
+
|
|
12
|
+
if str(_PROJECT_ROOT) not in sys.path:
|
|
13
|
+
sys.path.insert(0, str(_PROJECT_ROOT))
|
|
14
|
+
|
|
15
|
+
from fastclaw.main import main as fastclaw_main
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
asyncio.run(fastclaw_main())
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# cli.py
|
|
2
|
+
"""FastClaw 命令行界面"""
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
import sys
|
|
6
|
+
import logging
|
|
7
|
+
import uuid
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from termcolor import colored
|
|
12
|
+
except ImportError:
|
|
13
|
+
|
|
14
|
+
def colored(text, color=None):
|
|
15
|
+
return text
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
from fastmind import Event
|
|
19
|
+
|
|
20
|
+
if __package__ in (None, ""):
|
|
21
|
+
from core.app import start
|
|
22
|
+
from gateway.channels.handlers import (
|
|
23
|
+
handle_channel_command,
|
|
24
|
+
load_sessions,
|
|
25
|
+
save_sessions,
|
|
26
|
+
get_last_session,
|
|
27
|
+
)
|
|
28
|
+
else:
|
|
29
|
+
from .core.app import start
|
|
30
|
+
from .gateway.channels.handlers import (
|
|
31
|
+
handle_channel_command,
|
|
32
|
+
load_sessions,
|
|
33
|
+
save_sessions,
|
|
34
|
+
get_last_session,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
logging.disable(logging.WARNING)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def create_cli_session():
|
|
41
|
+
"""创建 CLI 会话并保存到 sessions.json"""
|
|
42
|
+
sessions = load_sessions()
|
|
43
|
+
new_session_id = f"cli_{uuid.uuid4().hex[:8]}"
|
|
44
|
+
sessions[new_session_id] = {
|
|
45
|
+
"session_id": new_session_id,
|
|
46
|
+
"agent_id": "main_agent",
|
|
47
|
+
"created_at": str(uuid.uuid4()),
|
|
48
|
+
"last_active_time": int(__import__("time").time()),
|
|
49
|
+
}
|
|
50
|
+
save_sessions(sessions)
|
|
51
|
+
return new_session_id
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def chat(new_session=False, session_id=None):
|
|
55
|
+
"""交互式对话"""
|
|
56
|
+
api = await start()
|
|
57
|
+
if session_id:
|
|
58
|
+
pass
|
|
59
|
+
elif new_session:
|
|
60
|
+
session_id = create_cli_session()
|
|
61
|
+
else:
|
|
62
|
+
last_session = get_last_session("cli")
|
|
63
|
+
if last_session:
|
|
64
|
+
session_id = last_session
|
|
65
|
+
else:
|
|
66
|
+
session_id = create_cli_session()
|
|
67
|
+
|
|
68
|
+
print("=" * 50)
|
|
69
|
+
print("FastClaw CLI (输入 'quit' 退出)")
|
|
70
|
+
print("支持命令: /new, /clear, /session <id>, /session_list")
|
|
71
|
+
print("=" * 50)
|
|
72
|
+
|
|
73
|
+
async def consume_stream():
|
|
74
|
+
"""消费流式输出事件"""
|
|
75
|
+
buffer = ""
|
|
76
|
+
thinking_buffer = ""
|
|
77
|
+
thinking_shown = False
|
|
78
|
+
try:
|
|
79
|
+
async for event in api.stream_events(session_id):
|
|
80
|
+
if event.type == "stream.thinking":
|
|
81
|
+
delta = event.payload.get("delta", "")
|
|
82
|
+
delta_clean = delta.replace("\n", " ").replace("\r", " ")
|
|
83
|
+
if not thinking_shown:
|
|
84
|
+
thinking_shown = True
|
|
85
|
+
thinking_buffer = ""
|
|
86
|
+
print(f"{colored('[思考中...] ', 'cyan')}", end="", flush=True)
|
|
87
|
+
thinking_buffer += delta_clean
|
|
88
|
+
display_text = thinking_buffer[:200]
|
|
89
|
+
print(
|
|
90
|
+
f"\r{colored('[思考中...] ', 'cyan')}{display_text}",
|
|
91
|
+
end="",
|
|
92
|
+
flush=True,
|
|
93
|
+
)
|
|
94
|
+
elif event.type == "stream.chunk":
|
|
95
|
+
if thinking_shown:
|
|
96
|
+
print("\r" + " " * 80, end="", flush=True)
|
|
97
|
+
print("\r", end="", flush=True)
|
|
98
|
+
thinking_shown = False
|
|
99
|
+
thinking_buffer = ""
|
|
100
|
+
delta = event.payload.get("delta", "")
|
|
101
|
+
buffer += delta
|
|
102
|
+
try:
|
|
103
|
+
print(delta, end="", flush=True)
|
|
104
|
+
except (UnicodeEncodeError, UnicodeDecodeError):
|
|
105
|
+
safe_delta = delta.encode("utf-8", errors="replace").decode(
|
|
106
|
+
"utf-8", errors="replace"
|
|
107
|
+
)
|
|
108
|
+
print(safe_delta, end="", flush=True)
|
|
109
|
+
elif event.type == "stream.fragment":
|
|
110
|
+
if thinking_shown:
|
|
111
|
+
print("\r" + " " * 80, end="", flush=True)
|
|
112
|
+
print("\r", end="", flush=True)
|
|
113
|
+
thinking_shown = False
|
|
114
|
+
thinking_buffer = ""
|
|
115
|
+
tool_calls = event.payload.get("tool_calls", [])
|
|
116
|
+
if tool_calls:
|
|
117
|
+
seen = set()
|
|
118
|
+
unique_names = []
|
|
119
|
+
for tc in tool_calls:
|
|
120
|
+
name = tc.get("function", {}).get("name", "unknown")
|
|
121
|
+
if name not in seen:
|
|
122
|
+
seen.add(name)
|
|
123
|
+
unique_names.append(name)
|
|
124
|
+
print(f"[执行工具: {', '.join(unique_names)}]")
|
|
125
|
+
content = event.payload.get("content", "")
|
|
126
|
+
if content:
|
|
127
|
+
pass
|
|
128
|
+
elif event.type == "stream.end":
|
|
129
|
+
if thinking_shown:
|
|
130
|
+
print("\r" + " " * 80, end="", flush=True)
|
|
131
|
+
print("\r", end="", flush=True)
|
|
132
|
+
thinking_shown = False
|
|
133
|
+
thinking_buffer = ""
|
|
134
|
+
print()
|
|
135
|
+
return buffer
|
|
136
|
+
elif event.type == "stream.error":
|
|
137
|
+
if thinking_shown:
|
|
138
|
+
print("\r" + " " * 80, end="", flush=True)
|
|
139
|
+
print("\r", end="", flush=True)
|
|
140
|
+
thinking_shown = False
|
|
141
|
+
thinking_buffer = ""
|
|
142
|
+
print(f"\n[错误: {event.payload.get('error', '未知错误')}]")
|
|
143
|
+
return None
|
|
144
|
+
except asyncio.CancelledError:
|
|
145
|
+
return buffer
|
|
146
|
+
except Exception as e:
|
|
147
|
+
print(f"\n[异常: {e}]")
|
|
148
|
+
return buffer
|
|
149
|
+
|
|
150
|
+
async def handle_cli_command(
|
|
151
|
+
text: str, current_session_id: str
|
|
152
|
+
) -> tuple[bool, str]:
|
|
153
|
+
"""处理 CLI 命令,返回 (是否已处理, 是否需要更新session_id, 新的session_id)"""
|
|
154
|
+
text = text.strip()
|
|
155
|
+
new_session_id = current_session_id
|
|
156
|
+
|
|
157
|
+
if text == "/new":
|
|
158
|
+
new_session_id = create_cli_session()
|
|
159
|
+
print(f"\n已创建新会话: {new_session_id}")
|
|
160
|
+
return True, new_session_id
|
|
161
|
+
|
|
162
|
+
elif text == "/clear":
|
|
163
|
+
from fastclaw.core.config import get_sessions_dir
|
|
164
|
+
|
|
165
|
+
session_dir = get_sessions_dir() / current_session_id
|
|
166
|
+
messages_file = session_dir / "messages.jsonl"
|
|
167
|
+
if messages_file.exists():
|
|
168
|
+
messages_file.unlink()
|
|
169
|
+
print(f"\n已清空当前会话 {current_session_id} 的聊天记录")
|
|
170
|
+
return True, current_session_id
|
|
171
|
+
|
|
172
|
+
elif text.startswith("/session "):
|
|
173
|
+
parts = text.split(" ", 1)
|
|
174
|
+
if len(parts) == 2:
|
|
175
|
+
target_id = parts[1].strip()
|
|
176
|
+
sessions = load_sessions()
|
|
177
|
+
if target_id in sessions:
|
|
178
|
+
print(f"\n已切换到会话: {target_id}")
|
|
179
|
+
new_session_id = target_id
|
|
180
|
+
else:
|
|
181
|
+
print(f"\n未找到会话: {target_id}")
|
|
182
|
+
return True, current_session_id
|
|
183
|
+
|
|
184
|
+
elif text == "/session_list":
|
|
185
|
+
sessions = load_sessions()
|
|
186
|
+
if sessions:
|
|
187
|
+
print("\n当前所有会话:")
|
|
188
|
+
for sid, info in sessions.items():
|
|
189
|
+
marker = " <-- 当前" if sid == current_session_id else ""
|
|
190
|
+
agent = info.get("agent_id", "unknown")
|
|
191
|
+
print(f" - {sid} (agent: {agent}){marker}")
|
|
192
|
+
else:
|
|
193
|
+
print("\n当前没有会话")
|
|
194
|
+
return True, current_session_id
|
|
195
|
+
|
|
196
|
+
return False, current_session_id
|
|
197
|
+
|
|
198
|
+
while True:
|
|
199
|
+
try:
|
|
200
|
+
user_input = input(f"\n你 ({session_id}): ").strip()
|
|
201
|
+
if not user_input:
|
|
202
|
+
continue
|
|
203
|
+
if user_input.lower() == "quit":
|
|
204
|
+
break
|
|
205
|
+
|
|
206
|
+
is_command, new_session_id = await handle_cli_command(
|
|
207
|
+
user_input, session_id
|
|
208
|
+
)
|
|
209
|
+
session_id = new_session_id
|
|
210
|
+
if is_command:
|
|
211
|
+
continue
|
|
212
|
+
|
|
213
|
+
event = Event("user.message", {"text": user_input}, session_id)
|
|
214
|
+
await api.push_event(session_id, event)
|
|
215
|
+
|
|
216
|
+
await consume_stream()
|
|
217
|
+
|
|
218
|
+
except KeyboardInterrupt:
|
|
219
|
+
print("\n\n退出...")
|
|
220
|
+
break
|
|
221
|
+
except EOFError:
|
|
222
|
+
print("\n\n退出...")
|
|
223
|
+
break
|
|
224
|
+
except Exception as e:
|
|
225
|
+
print(f"\n错误: {e}")
|
|
226
|
+
|
|
227
|
+
await api.stop()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if __name__ == "__main__":
|
|
231
|
+
asyncio.run(chat())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""FastClaw 核心引擎"""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
_IS_PACKAGE_MODE = __package__ and __package__.startswith("fastclaw.")
|
|
6
|
+
|
|
7
|
+
if _IS_PACKAGE_MODE:
|
|
8
|
+
from .app import (
|
|
9
|
+
app,
|
|
10
|
+
start,
|
|
11
|
+
SKILLS,
|
|
12
|
+
load_skills,
|
|
13
|
+
load_agent_config,
|
|
14
|
+
load_settings,
|
|
15
|
+
calculate_tokens,
|
|
16
|
+
count_messages_tokens,
|
|
17
|
+
)
|
|
18
|
+
from .prompts import format_system_prompt, SYSTEM_PROMPT
|
|
19
|
+
else:
|
|
20
|
+
from core.app import (
|
|
21
|
+
app,
|
|
22
|
+
start,
|
|
23
|
+
SKILLS,
|
|
24
|
+
load_skills,
|
|
25
|
+
load_agent_config,
|
|
26
|
+
load_settings,
|
|
27
|
+
calculate_tokens,
|
|
28
|
+
count_messages_tokens,
|
|
29
|
+
)
|
|
30
|
+
from core.prompts import format_system_prompt, SYSTEM_PROMPT
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"app",
|
|
34
|
+
"start",
|
|
35
|
+
"SKILLS",
|
|
36
|
+
"load_skills",
|
|
37
|
+
"load_agent_config",
|
|
38
|
+
"load_settings",
|
|
39
|
+
"calculate_tokens",
|
|
40
|
+
"count_messages_tokens",
|
|
41
|
+
"format_system_prompt",
|
|
42
|
+
"SYSTEM_PROMPT",
|
|
43
|
+
]
|