lightclawbot 0.0.2__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.
@@ -0,0 +1 @@
1
+ recursive-include lightclawbot *.yaml
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: lightclawbot
3
+ Version: 0.0.2
4
+ Summary: LightClaw platform plugin for Hermes Agent — connects via native WebSocket to LightClaw server
5
+ Author: lhanyun
6
+ License-Expression: MIT
7
+ Keywords: hermes,hermes-agent,lightclaw,plugin,websocket,chatbot
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Communications :: Chat
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+
19
+ # lightclawbot
20
+
21
+ LightClaw 平台适配器插件,为 Hermes Agent 提供通过 WebSocket 接入 LightClaw 服务端的能力,使 Hermes Agent 能与 LightClaw 用户进行实时对话、收发文件附件、发送打字指示符,以及通过 cron 定时推送消息。
22
+
23
+ ```
24
+ 用户(前端) ←→ LightClaw Server ←→ lightclawbot ←→ Hermes AIAgent
25
+ (WebSocket) (本插件,非侵入)
26
+ ```
27
+
28
+ ---
29
+
30
+ ## 工作原理
31
+
32
+ lightclawbot 采用 Hermes Agent 的**插件注册机制**集成,**不修改主仓库任何源码**。
33
+
34
+ Hermes Agent 启动时会:
35
+ 1. 通过 `config.yaml` 的 `plugins.enabled` 列表加载启用的插件;
36
+ 2. 在 `~/.hermes/plugins/lightclawbot/` 下查找 `__init__.py` + `plugin.yaml`;
37
+ 3. 调用插件的 `register(ctx)` 函数注册 adapter。
38
+
39
+ 注册后自动获得:
40
+
41
+ - `Platform("lightclawbot")` 动态枚举成员
42
+ - gateway 启动时创建并连接 `LightClawAdapter`
43
+ - `send_message` tool 通过 `_send_via_adapter()` 路由
44
+ - cron delivery 到 `lightclawbot:<chat_id>` 自动生效
45
+ - 用户授权遵循 `LIGHTCLAW_ALLOWED_USERS` 环境变量
46
+
47
+ ---
48
+
49
+ ## 前置条件
50
+
51
+ | 要求 | 最低版本 |
52
+ |---|---|
53
+ | Python | 3.11+ |
54
+ | Hermes Agent | 已安装 |
55
+ | aiohttp | 3.9+(由宿主 Hermes Agent 提供) |
56
+
57
+ > 本插件不直接声明 `aiohttp` 依赖;它由宿主 Hermes Agent 环境提供。
58
+
59
+ ---
60
+
61
+ ## 环境变量配置
62
+
63
+ 在 `~/.hermes/.env` 中设置以下变量:
64
+
65
+ | 变量 | 必填 | 说明 |
66
+ |---|---|---|
67
+ | `LIGHTCLAW_API_KEY` | **是** | Bearer Token |
68
+ | `LIGHTCLAW_ALLOW_ALL_USERS` | 否 | 设为 `true` 接受所有用户消息 |
69
+
70
+ **最简配置示例:**
71
+
72
+ ```dotenv
73
+ LIGHTCLAW_API_KEY=your-secret-api-key
74
+ LIGHTCLAW_ALLOW_ALL_USERS=true
75
+ ```
76
+
77
+ ---
78
+
79
+ ## 启动网关
80
+
81
+ 完成配置后正常启动 Hermes 网关:
82
+
83
+ ```bash
84
+ hermes gateway start
85
+ ```
86
+
87
+ 只要 `LIGHTCLAW_API_KEY` 已设置,LightClaw 适配器就会自动建立连接。日志中应出现:
88
+
89
+ ```
90
+ [lightclawbot] Bot clientId: xxxx, 1 key(s) mapped
91
+ [lightclawbot] Connected (sid=xxxx)
92
+ ```
93
+
94
+ ---
95
+
96
+ ## Cron 定时投递
97
+
98
+ 在 Hermes Agent 内创建定时任务时,指定 `deliver` 参数即可将结果推送到 LightClaw:
99
+
100
+ ```
101
+ deliver=lightclawbot:<chat_id>
102
+ ```
103
+
104
+ **示例(在 Hermes Agent 对话中):**
105
+
106
+ ```
107
+ 每天早上 9 点发送新闻摘要。deliver=lightclawbot:123456
108
+ ```
109
+
110
+ 也可以设置全局默认投递目标:
111
+
112
+ ```dotenv
113
+ LIGHTCLAW_HOME_CHANNEL=123456
114
+ ```
115
+
116
+ ---
117
+
118
+ ## 项目结构
119
+
120
+ ```
121
+ lightclawbot/
122
+ ├── __init__.py register(ctx) 插件入口
123
+ ├── plugin.yaml 插件元数据(kind: platform)
124
+ └── src/ adapter 实现
125
+ ├── __init__.py 公开 API
126
+ ├── adapter.py 主类 + 生命周期
127
+ ├── config.py 常量 + 工具函数
128
+ ├── inbound.py 入站消息处理
129
+ ├── outbound.py 出站消息发送
130
+ ├── history.py 历史记录/会话列表响应
131
+ ├── media.py 媒体类型探测与格式化
132
+ ├── file_storage.py 文件上传/下载 REST API
133
+ ├── download_handler.py 客户端下载请求处理
134
+ ├── tenancy.py 多租户 API key 映射
135
+ └── socket/
136
+ ├── native_socket.py WebSocket 连接循环
137
+ └── reliable_emitter.py ACK 重试发送
138
+ ```
139
+
140
+ ---
141
+
142
+ ## 常见问题排查
143
+
144
+ ### Bot 未上线 / 收不到消息
145
+
146
+ 1. 确认 `LIGHTCLAW_API_KEY` 已设置且非空(`cat ~/.hermes/.env | grep LIGHTCLAW`)
147
+ 2. 确认 `config.yaml` 中 `plugins.enabled` 包含 `lightclawbot`
148
+ 3. 检查网关日志中是否出现 `[lightclawbot] Connected`;若无,WebSocket 握手失败
149
+
150
+ ### `aiohttp not installed`
151
+
152
+ ```bash
153
+ # 在 hermes 的 venv 里安装
154
+ ~/.hermes/hermes-agent/venv/bin/pip install "aiohttp>=3.9,<4"
155
+ ```
156
+
157
+ ### 插件未被发现
158
+
159
+ 确认以下两点:
160
+
161
+ ```bash
162
+ # 1. 插件目录存在且结构正确
163
+ ls ~/.hermes/plugins/lightclawbot/
164
+ # 应当看到 __init__.py 和 plugin.yaml
165
+
166
+ # 2. config.yaml 已启用
167
+ grep -A2 plugins ~/.hermes/config.yaml
168
+ # plugins:
169
+ # enabled:
170
+ # - lightclawbot
171
+ ```
172
+
173
+ ---
174
+
175
+ ## License
176
+
177
+ MIT
@@ -0,0 +1,159 @@
1
+ # lightclawbot
2
+
3
+ LightClaw 平台适配器插件,为 Hermes Agent 提供通过 WebSocket 接入 LightClaw 服务端的能力,使 Hermes Agent 能与 LightClaw 用户进行实时对话、收发文件附件、发送打字指示符,以及通过 cron 定时推送消息。
4
+
5
+ ```
6
+ 用户(前端) ←→ LightClaw Server ←→ lightclawbot ←→ Hermes AIAgent
7
+ (WebSocket) (本插件,非侵入)
8
+ ```
9
+
10
+ ---
11
+
12
+ ## 工作原理
13
+
14
+ lightclawbot 采用 Hermes Agent 的**插件注册机制**集成,**不修改主仓库任何源码**。
15
+
16
+ Hermes Agent 启动时会:
17
+ 1. 通过 `config.yaml` 的 `plugins.enabled` 列表加载启用的插件;
18
+ 2. 在 `~/.hermes/plugins/lightclawbot/` 下查找 `__init__.py` + `plugin.yaml`;
19
+ 3. 调用插件的 `register(ctx)` 函数注册 adapter。
20
+
21
+ 注册后自动获得:
22
+
23
+ - `Platform("lightclawbot")` 动态枚举成员
24
+ - gateway 启动时创建并连接 `LightClawAdapter`
25
+ - `send_message` tool 通过 `_send_via_adapter()` 路由
26
+ - cron delivery 到 `lightclawbot:<chat_id>` 自动生效
27
+ - 用户授权遵循 `LIGHTCLAW_ALLOWED_USERS` 环境变量
28
+
29
+ ---
30
+
31
+ ## 前置条件
32
+
33
+ | 要求 | 最低版本 |
34
+ |---|---|
35
+ | Python | 3.11+ |
36
+ | Hermes Agent | 已安装 |
37
+ | aiohttp | 3.9+(由宿主 Hermes Agent 提供) |
38
+
39
+ > 本插件不直接声明 `aiohttp` 依赖;它由宿主 Hermes Agent 环境提供。
40
+
41
+ ---
42
+
43
+ ## 环境变量配置
44
+
45
+ 在 `~/.hermes/.env` 中设置以下变量:
46
+
47
+ | 变量 | 必填 | 说明 |
48
+ |---|---|---|
49
+ | `LIGHTCLAW_API_KEY` | **是** | Bearer Token |
50
+ | `LIGHTCLAW_ALLOW_ALL_USERS` | 否 | 设为 `true` 接受所有用户消息 |
51
+
52
+ **最简配置示例:**
53
+
54
+ ```dotenv
55
+ LIGHTCLAW_API_KEY=your-secret-api-key
56
+ LIGHTCLAW_ALLOW_ALL_USERS=true
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 启动网关
62
+
63
+ 完成配置后正常启动 Hermes 网关:
64
+
65
+ ```bash
66
+ hermes gateway start
67
+ ```
68
+
69
+ 只要 `LIGHTCLAW_API_KEY` 已设置,LightClaw 适配器就会自动建立连接。日志中应出现:
70
+
71
+ ```
72
+ [lightclawbot] Bot clientId: xxxx, 1 key(s) mapped
73
+ [lightclawbot] Connected (sid=xxxx)
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Cron 定时投递
79
+
80
+ 在 Hermes Agent 内创建定时任务时,指定 `deliver` 参数即可将结果推送到 LightClaw:
81
+
82
+ ```
83
+ deliver=lightclawbot:<chat_id>
84
+ ```
85
+
86
+ **示例(在 Hermes Agent 对话中):**
87
+
88
+ ```
89
+ 每天早上 9 点发送新闻摘要。deliver=lightclawbot:123456
90
+ ```
91
+
92
+ 也可以设置全局默认投递目标:
93
+
94
+ ```dotenv
95
+ LIGHTCLAW_HOME_CHANNEL=123456
96
+ ```
97
+
98
+ ---
99
+
100
+ ## 项目结构
101
+
102
+ ```
103
+ lightclawbot/
104
+ ├── __init__.py register(ctx) 插件入口
105
+ ├── plugin.yaml 插件元数据(kind: platform)
106
+ └── src/ adapter 实现
107
+ ├── __init__.py 公开 API
108
+ ├── adapter.py 主类 + 生命周期
109
+ ├── config.py 常量 + 工具函数
110
+ ├── inbound.py 入站消息处理
111
+ ├── outbound.py 出站消息发送
112
+ ├── history.py 历史记录/会话列表响应
113
+ ├── media.py 媒体类型探测与格式化
114
+ ├── file_storage.py 文件上传/下载 REST API
115
+ ├── download_handler.py 客户端下载请求处理
116
+ ├── tenancy.py 多租户 API key 映射
117
+ └── socket/
118
+ ├── native_socket.py WebSocket 连接循环
119
+ └── reliable_emitter.py ACK 重试发送
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 常见问题排查
125
+
126
+ ### Bot 未上线 / 收不到消息
127
+
128
+ 1. 确认 `LIGHTCLAW_API_KEY` 已设置且非空(`cat ~/.hermes/.env | grep LIGHTCLAW`)
129
+ 2. 确认 `config.yaml` 中 `plugins.enabled` 包含 `lightclawbot`
130
+ 3. 检查网关日志中是否出现 `[lightclawbot] Connected`;若无,WebSocket 握手失败
131
+
132
+ ### `aiohttp not installed`
133
+
134
+ ```bash
135
+ # 在 hermes 的 venv 里安装
136
+ ~/.hermes/hermes-agent/venv/bin/pip install "aiohttp>=3.9,<4"
137
+ ```
138
+
139
+ ### 插件未被发现
140
+
141
+ 确认以下两点:
142
+
143
+ ```bash
144
+ # 1. 插件目录存在且结构正确
145
+ ls ~/.hermes/plugins/lightclawbot/
146
+ # 应当看到 __init__.py 和 plugin.yaml
147
+
148
+ # 2. config.yaml 已启用
149
+ grep -A2 plugins ~/.hermes/config.yaml
150
+ # plugins:
151
+ # enabled:
152
+ # - lightclawbot
153
+ ```
154
+
155
+ ---
156
+
157
+ ## License
158
+
159
+ MIT
@@ -0,0 +1,88 @@
1
+ """
2
+ lightclawbot — LightClaw platform plugin for Hermes Agent.
3
+
4
+ Registers the LightClaw adapter via the Hermes plugin discovery system.
5
+ No source-code modifications to lighthouse-hermes are required — the adapter
6
+ is discovered automatically when this package is placed under
7
+ ``~/.hermes/plugins/lightclawbot/`` or installed via pip (entry_points).
8
+ """
9
+
10
+ import os
11
+
12
+
13
+ def _get_version() -> str:
14
+ """Return package version from importlib.metadata, with fallback."""
15
+ try:
16
+ from importlib.metadata import version
17
+
18
+ return version("lightclawbot")
19
+ except Exception:
20
+ return "0.0.0"
21
+
22
+
23
+ __version__ = _get_version()
24
+
25
+
26
+ def _load_platform_hint() -> str:
27
+ """Return the LightClaw-specific LLM capability hint.
28
+
29
+ Only contents that are *unique* to LightClaw belong here. The generic
30
+ ``MEDIA:/absolute/path/to/file`` protocol, supported extensions and
31
+ text post-processing are owned by the framework
32
+ (``BasePlatformAdapter.extract_media`` + ``PLATFORM_HINTS`` in
33
+ ``agent/prompt_builder.py``) and are intentionally NOT re-stated here.
34
+ """
35
+ return (
36
+ "You are on LightClaw, a WebSocket-based messaging platform. "
37
+ "Markdown formatting is supported (code blocks, bold, italic, tables). "
38
+ "You can send files natively by including MEDIA:/absolute/path/to/file "
39
+ "in your reply; the file is delivered to the user as an on-demand "
40
+ "download link (no need to upload or build https URLs yourself). "
41
+ "For cron jobs / reminders / scheduled tasks, always set "
42
+ "deliver='lightclawbot:<chat_id>' so results reach the user instead of "
43
+ "being saved locally."
44
+ )
45
+
46
+
47
+ def _validate_config(config) -> bool:
48
+ """Check whether the platform config has enough info to connect."""
49
+ extra = getattr(config, "extra", {}) or {}
50
+ return bool(extra.get("api_keys") or os.getenv("LIGHTCLAW_API_KEY", ""))
51
+
52
+
53
+ def _is_connected(config) -> bool:
54
+ """Check whether the platform is sufficiently configured (for status display)."""
55
+ extra = getattr(config, "extra", {}) or {}
56
+ return bool(extra.get("api_keys"))
57
+
58
+
59
+ def register(ctx):
60
+ """Called by the Hermes plugin discovery system.
61
+
62
+ Registers the LightClaw platform adapter so that:
63
+ - Platform("lightclawbot") resolves to a dynamic enum member
64
+ - The gateway creates and connects a LightClawAdapter at startup
65
+ - send_message routes to the adapter via _send_via_adapter()
66
+ - Cron delivery to "lightclawbot:<chat_id>" works automatically
67
+ - User authorization respects LIGHTCLAW_ALLOWED_USERS env var
68
+ """
69
+ from .src import LightClawAdapter, check_lightclaw_requirements
70
+
71
+ ctx.register_platform(
72
+ name="lightclawbot",
73
+ label="LightClawBot",
74
+ adapter_factory=lambda cfg: LightClawAdapter(cfg),
75
+ check_fn=check_lightclaw_requirements,
76
+ validate_config=_validate_config,
77
+ is_connected=_is_connected,
78
+ required_env=["LIGHTCLAW_API_KEY"],
79
+ install_hint="See https://pypi.org/project/lightclawbot/",
80
+ allowed_users_env="LIGHTCLAW_ALLOWED_USERS",
81
+ allow_all_env="LIGHTCLAW_ALLOW_ALL_USERS",
82
+ max_message_length=4096,
83
+ emoji="⚡",
84
+ platform_hint=_load_platform_hint(),
85
+ )
86
+
87
+
88
+ __all__ = ["register", "__version__"]
@@ -0,0 +1,10 @@
1
+ name: lightclawbot
2
+ kind: platform
3
+ version: 0.0.2
4
+ description: >
5
+ LightClaw gateway adapter for Hermes Agent.
6
+ Connects to a LightClaw-compatible server via native WebSocket,
7
+ receiving user messages and sending AI responses back through the same protocol.
8
+ author: lhanyun
9
+ requires_env:
10
+ - LIGHTCLAW_API_KEY
@@ -0,0 +1,37 @@
1
+ """
2
+ LightClaw platform adapter for Hermes Agent.
3
+
4
+ Connects to a LightClaw-compatible server via native WebSocket,
5
+ receiving user messages and sending AI responses back through the same protocol.
6
+
7
+ Protocol (post socket-rewrite):
8
+ - Auth: POST /cgi/ticket → { code:0, data:{ client:{ extra:'{"botId":"..."}' }, ticket:"..." } }
9
+ - Transport: Native WebSocket wss://<domain>/ws/agent?ticket=<ticket>&enableMultiLogin=false
10
+ - Framing: Raw JSON { "event": "<name>", "data": {...} }
11
+ - Handshake: server sends { "event": "__handshake__", "data": { "id": "<socket_id>" } }
12
+ - ACK: server sends { "event": "message:ack", "data": { "relatedMsgId": "<msgId>" } }
13
+ - Events: message:private (bidirectional), history/sessions request/response
14
+ - Kinds: text, typing_start, stream_chunk, stream_end, typing_stop
15
+
16
+ Package layout (mirrors lightclaw/src/):
17
+ config.py ← constants + utils (config.ts)
18
+ socket/reliable_emitter.py ← ACK-based send (socket/reliable-emitter.ts)
19
+ socket/native_socket.py ← connection loop (socket/native-socket.ts)
20
+ inbound.py ← inbound handler + media (inbound.ts + media.ts)
21
+ outbound.py ← send API (outbound.ts)
22
+ adapter.py ← LightClawAdapter + singleton (gateway.ts)
23
+ """
24
+
25
+ # Public API — kept stable so existing callers need no changes:
26
+ # gateway/platforms/__init__.py → from .lightclaw import LightClawAdapter
27
+ # gateway/run.py → from gateway.platforms.lightclaw import LightClawAdapter, check_lightclaw_requirements
28
+ # tools/send_message_tool.py → from gateway.platforms.lightclaw import get_active_adapter
29
+
30
+ from .adapter import LightClawAdapter, get_active_adapter
31
+ from .config import check_lightclaw_requirements
32
+
33
+ __all__ = [
34
+ "LightClawAdapter",
35
+ "check_lightclaw_requirements",
36
+ "get_active_adapter",
37
+ ]