@partme.ai/openclaw-web-stomp 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +155 -0
- package/README_CN.md +137 -0
- package/RELEASING.md +77 -0
- package/dist/chunk-ORWEBPDJ.js +379 -0
- package/dist/chunk-ORWEBPDJ.js.map +1 -0
- package/dist/chunk-PKJKPVTH.js +4333 -0
- package/dist/chunk-PKJKPVTH.js.map +1 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/setup-entry.d.ts +6 -0
- package/dist/setup-entry.js +16 -0
- package/dist/setup-entry.js.map +1 -0
- package/dist/stomp-server-FJO6VDEE.js +15 -0
- package/dist/stomp-server-FJO6VDEE.js.map +1 -0
- package/openclaw.plugin.json +130 -0
- package/package.json +89 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PartMe-AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# OpenClaw Web STOMP
|
|
4
|
+
|
|
5
|
+
**OpenClaw plugin — STOMP 1.x over WebSocket (`stomp-ws`) with topic bindings and `session.dmScope` isolation**
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
[English](./README.md) | [简体中文](./README_CN.md)
|
|
14
|
+
|
|
15
|
+
## Introduction
|
|
16
|
+
|
|
17
|
+
`@partme.ai/openclaw-web-stomp` is an [OpenClaw](https://github.com/openclaw/openclaw) **channel plugin** that exposes **STOMP over WebSocket** and bridges browser or Spring-style clients to agents. It follows the official channel pattern: [`defineChannelPluginEntry`](https://docs.openclaw.ai/plugins/sdk-entrypoints#definechannelpluginentry) and `ChannelPlugin` (not `definePluginEntry`).
|
|
18
|
+
|
|
19
|
+
Behavior is aligned with **`openclaw-mqtt`**, **`openclaw-web-mqtt`**, and **`openclaw-stomp` (TCP)**:
|
|
20
|
+
|
|
21
|
+
- **`subscribeTopics`** — inbound **SEND** (and optional **SUBSCRIBE**) allowlist using `*` / `#` patterns on full STOMP destinations.
|
|
22
|
+
- **`topicBindings`** — explicit `topicPattern → agentId` (+ optional `accountId`, `replyTopic` as reply destination).
|
|
23
|
+
- **Standard fallback** — destinations matching `agent.<id>` under `/queue/` (same idea as TCP STOMP plugin).
|
|
24
|
+
- **Session keys** — only from OpenClaw global **`session.dmScope`** via shared `buildSessionKeyFromDmScope` (no channel-local duplicate scope config).
|
|
25
|
+
|
|
26
|
+
## Capabilities
|
|
27
|
+
|
|
28
|
+
- **Gateway lifecycle** — server starts in `gateway.startAccount`, stops on abort (same model as `openclaw-web-mqtt`).
|
|
29
|
+
- **Status HTTP** — `GET /stomp-ws/status` (`auth: plugin`) — connections, subscription stats, ACK stats, redacted config snapshot.
|
|
30
|
+
- **Enterprise-style controls** — max connections, max frame / payload size, optional TLS (HTTPS server + WS upgrade), per-user `publishAllow` / `subscribeAllow` / `aclRules` (RabbitMQ-style topic ACL inspiration; see also [Web MQTT](https://www.rabbitmq.com/docs/web-mqtt) operational patterns).
|
|
31
|
+
- **`openclaw.setupEntry`** — `dist/setup-entry.js` for setup-only loads ([SDK setup](https://docs.openclaw.ai/plugins/sdk-setup)).
|
|
32
|
+
|
|
33
|
+
## Message flow
|
|
34
|
+
|
|
35
|
+
1. Client **CONNECT** (optional `login` / `passcode` per `channels["stomp-ws"].auth`).
|
|
36
|
+
2. Client **SUBSCRIBE** to `/topic/session.<sessionKey>` (or your policy-approved destinations).
|
|
37
|
+
3. Client **SEND** to a destination allowed by `subscribeTopics`.
|
|
38
|
+
4. Plugin resolves **agent** via `topicBindings` first, then standard agent destination fallback.
|
|
39
|
+
5. OpenClaw **`dispatchReplyFromConfig`** runs; replies publish to `replyTopic` or `/topic/session.<sessionKey>` derived from `dmScope`.
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
### Prerequisites
|
|
44
|
+
|
|
45
|
+
- OpenClaw `>= 2026.4.0`
|
|
46
|
+
- Node.js `22+`
|
|
47
|
+
|
|
48
|
+
### Install
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
openclaw plugins install @partme.ai/openclaw-web-stomp
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Minimal `openclaw.json`
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"session": {
|
|
59
|
+
"dmScope": "per-channel-peer"
|
|
60
|
+
},
|
|
61
|
+
"channels": {
|
|
62
|
+
"stomp-ws": {
|
|
63
|
+
"wsPort": 15674,
|
|
64
|
+
"path": "/ws",
|
|
65
|
+
"subscribeTopics": ["/queue/devices/+/in", "/queue/agent.*"],
|
|
66
|
+
"topicBindings": [
|
|
67
|
+
{
|
|
68
|
+
"topicPattern": "/queue/devices/*/in",
|
|
69
|
+
"agentId": "iot-agent",
|
|
70
|
+
"accountId": "default",
|
|
71
|
+
"replyTopic": "/topic/devices/reply"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"auth": {
|
|
75
|
+
"required": false,
|
|
76
|
+
"allowAnonymous": true
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Migration from legacy `channels.stomp`:** use **`channels["stomp-ws"]`** and channel id **`stomp-ws`**. Legacy keys under `channels.stomp` are merged for convenience but **`stomp-ws` overrides** on conflict.
|
|
84
|
+
|
|
85
|
+
## Session and `dmScope`
|
|
86
|
+
|
|
87
|
+
Session isolation uses **only** the OpenClaw root key **`session.dmScope`** (same as `mqtt`, `mqtt-ws`, `stomp-tcp`). Allowed values: `main`, `per-peer`, `per-channel-peer`, `per-account-channel-peer`.
|
|
88
|
+
|
|
89
|
+
- The plugin **does not** read a channel-local `session.dmScope` under `channels["stomp-ws"]` for isolation (if present elsewhere, it is ignored for this purpose).
|
|
90
|
+
- Inbound `from` is the STOMP **peer id** (headers `x-peer-id` / `peer-id` / `sender`, else login / `client-id` / connection id).
|
|
91
|
+
- Replies go to `topicBindings[].replyTopic` when set, otherwise **`/topic/session.<sessionKey>`** where `sessionKey` is from `buildSessionKeyFromDmScope` with `channel: "stomp-ws"`.
|
|
92
|
+
|
|
93
|
+
Match **`mqtt-ws` / `stomp-tcp`** docs for how each `dmScope` affects the session key string.
|
|
94
|
+
|
|
95
|
+
## Security
|
|
96
|
+
|
|
97
|
+
- **Production:** set `auth.required: true`, disable `allowAnonymous`, and use `auth.users` (plain `password` in config today — prefer env-backed secret injection or a reverse proxy for credential handling).
|
|
98
|
+
- **ACL:** optional `publishAllow`, `subscribeAllow`, and `aclRules` per user (same semantics as `openclaw-web-mqtt`).
|
|
99
|
+
- **TLS:** `tls.enabled` with `certFile` / `keyFile` starts HTTPS and attaches the WebSocket server; alternatively terminate TLS at your edge and proxy to plain `ws` internally.
|
|
100
|
+
- **Limits:** tune `maxConnections`, `limits.maxPayloadBytes`, `maxFrameSize`, and `limits.maxSubscriptionsPerClient` to match broker-style hardening (see [RabbitMQ Web MQTT](https://www.rabbitmq.com/docs/web-mqtt) for operational parallels).
|
|
101
|
+
|
|
102
|
+
## Troubleshooting
|
|
103
|
+
|
|
104
|
+
| Symptom | Check |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| CONNECT fails with `Authentication failed` | `auth.users` / `defaultUser`+`defaultPass`, or set `allowAnonymous: true` for dev. |
|
|
107
|
+
| SEND accepted but no agent reply | Gateway running, agent route for `stomp-ws`, `topicBindings` / fallback agent id, and client **SUBSCRIBE** to the actual reply destination (often `/topic/session.<sessionKey>`). |
|
|
108
|
+
| SUBSCRIBE ignored | If `subscribeTopics` is non-empty, destination must match a pattern; check `maxSubscriptionsPerClient`. |
|
|
109
|
+
| `test:client` timeout | Wrong `STOMP_SUBSCRIBE_DESTINATION` for current `session.dmScope`; inspect `GET /stomp-ws/status` and logs. |
|
|
110
|
+
|
|
111
|
+
## Testing
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pnpm test
|
|
115
|
+
pnpm run test:client
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Test client env vars: `STOMP_WS_URL`, `STOMP_LOGIN`, `STOMP_PASSCODE`, `STOMP_SEND_DESTINATION`, `STOMP_SUBSCRIBE_DESTINATION`, `STOMP_PAYLOAD`, `STOMP_TIMEOUT_MS`.
|
|
119
|
+
|
|
120
|
+
## GitHub Actions
|
|
121
|
+
|
|
122
|
+
| Workflow | Trigger | Purpose |
|
|
123
|
+
| --- | --- | --- |
|
|
124
|
+
| [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) | Push / PR `main` / `master` | pnpm install, typecheck, build, test, artifact `dist/` |
|
|
125
|
+
| [`.github/workflows/release.yml`](./.github/workflows/release.yml) | Tag `v*` / `workflow_dispatch` | Publish npm + GitHub Packages, GitHub Release |
|
|
126
|
+
|
|
127
|
+
## Publishing
|
|
128
|
+
|
|
129
|
+
- Package: `@partme.ai/openclaw-web-stomp`
|
|
130
|
+
- Secret: `NPM_TOKEN`
|
|
131
|
+
- Details: [`RELEASING.md`](./RELEASING.md)
|
|
132
|
+
|
|
133
|
+
## Project layout
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
src/
|
|
137
|
+
index.ts # defineChannelPluginEntry + registerFull
|
|
138
|
+
setup-entry.ts # defineSetupPluginEntry
|
|
139
|
+
channel.ts # ChannelPlugin + gateway.startAccount
|
|
140
|
+
stomp-server.ts # WS + STOMP frame handling
|
|
141
|
+
stomp-config.ts # resolve channels["stomp-ws"]
|
|
142
|
+
inbound.ts # dispatchReplyFromConfig + dmScope session key
|
|
143
|
+
dm-scope.ts # same logic as stomp-tcp / web-mqtt
|
|
144
|
+
route-inbound.ts # topicBindings + fallback
|
|
145
|
+
topic-router.ts # * / # matching
|
|
146
|
+
acl.ts # optional per-user destination ACL
|
|
147
|
+
outbound.ts # publish to /topic/session.<key>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## References
|
|
151
|
+
|
|
152
|
+
- [Building plugins](https://docs.openclaw.ai/plugins/building-plugins)
|
|
153
|
+
- [Channel plugins](https://docs.openclaw.ai/plugins/sdk-channel-plugins)
|
|
154
|
+
- [SDK entrypoints](https://docs.openclaw.ai/plugins/sdk-entrypoints)
|
|
155
|
+
- [Manifest](https://docs.openclaw.ai/plugins/manifest)
|
package/README_CN.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# OpenClaw Web STOMP
|
|
4
|
+
|
|
5
|
+
**OpenClaw 渠道插件 — WebSocket 上的 STOMP(`stomp-ws`),支持 topic 绑定与 `session.dmScope` 会话隔离**
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
[English](./README.md) | [简体中文](./README_CN.md)
|
|
14
|
+
|
|
15
|
+
## 简介
|
|
16
|
+
|
|
17
|
+
`@partme.ai/openclaw-web-stomp` 为 [OpenClaw](https://github.com/openclaw/openclaw) 提供 **STOMP over WebSocket** 渠道,便于浏览器、Spring 等客户端接入 Agent。实现上使用官方推荐的 [`defineChannelPluginEntry`](https://docs.openclaw.ai/plugins/sdk-entrypoints#definechannelpluginentry) 与 `ChannelPlugin`(**不要**用仅适用于非渠道的 `definePluginEntry`)。
|
|
18
|
+
|
|
19
|
+
路由与 **`openclaw-mqtt` / `openclaw-web-mqtt` / `openclaw-stomp`(TCP)** 保持一致:
|
|
20
|
+
|
|
21
|
+
- **`subscribeTopics`**:对 **SEND** 的 destination 做白名单(`SUBSCRIBE` 在非空时同样校验);支持 `*`、`#`。
|
|
22
|
+
- **`topicBindings`**:`topicPattern` → `agentId`,可选 `accountId`、`replyTopic`(回复 STOMP destination)。
|
|
23
|
+
- **标准回退**:与 TCP 版相同的 `agent.<id>` destination 解析。
|
|
24
|
+
- **会话键**:仅使用 OpenClaw 全局 **`session.dmScope`** 与 `buildSessionKeyFromDmScope`,**不**维护渠道私有隔离配置。
|
|
25
|
+
|
|
26
|
+
## 能力概览
|
|
27
|
+
|
|
28
|
+
- **网关生命周期**:在 `gateway.startAccount` 内启动 HTTP(S)+WS,abort 时停止(与 `openclaw-web-mqtt` 一致)。
|
|
29
|
+
- **状态接口**:`GET /stomp-ws/status`(`auth: plugin`)返回连接、订阅、ACK 统计与脱敏配置。
|
|
30
|
+
- **企业向控制**:连接数、帧/载荷上限、可选 TLS、用户级 `publishAllow` / `subscribeAllow` / `aclRules`(思路参考 RabbitMQ [Web MQTT](https://www.rabbitmq.com/docs/web-mqtt) 的运维与安全实践)。
|
|
31
|
+
- **setup 入口**:`package.json` → `openclaw.setupEntry` → `dist/setup-entry.js`(见 [SDK setup](https://docs.openclaw.ai/plugins/sdk-setup))。
|
|
32
|
+
|
|
33
|
+
## 消息流
|
|
34
|
+
|
|
35
|
+
1. 客户端 **CONNECT**(按 `auth` 校验 `login` / `passcode`)。
|
|
36
|
+
2. **SUBSCRIBE** 到 `/topic/session.<sessionKey>` 等允许的 destination。
|
|
37
|
+
3. **SEND** 到通过 `subscribeTopics` 的 destination。
|
|
38
|
+
4. 插件按 **`topicBindings` 优先**,否则标准 agent destination 回退解析 **agent**。
|
|
39
|
+
5. 调用 OpenClaw **`dispatchReplyFromConfig`**;回复发到绑定 **`replyTopic`** 或按 `dmScope` 生成的 **`/topic/session.<sessionKey>`**。
|
|
40
|
+
|
|
41
|
+
## 快速开始
|
|
42
|
+
|
|
43
|
+
### 环境
|
|
44
|
+
|
|
45
|
+
- OpenClaw `>= 2026.4.0`
|
|
46
|
+
- Node.js `22+`
|
|
47
|
+
|
|
48
|
+
### 安装
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
openclaw plugins install @partme.ai/openclaw-web-stomp
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 最小配置 `openclaw.json`
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"session": {
|
|
59
|
+
"dmScope": "per-channel-peer"
|
|
60
|
+
},
|
|
61
|
+
"channels": {
|
|
62
|
+
"stomp-ws": {
|
|
63
|
+
"wsPort": 15674,
|
|
64
|
+
"path": "/ws",
|
|
65
|
+
"subscribeTopics": ["/queue/devices/+/in"],
|
|
66
|
+
"topicBindings": [
|
|
67
|
+
{
|
|
68
|
+
"topicPattern": "/queue/devices/*/in",
|
|
69
|
+
"agentId": "iot-agent",
|
|
70
|
+
"replyTopic": "/topic/devices/reply"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"auth": {
|
|
74
|
+
"required": false,
|
|
75
|
+
"allowAnonymous": true
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**从旧版迁移:** 旧渠道 id `stomp` 与 `channels.stomp` 请改为 **`stomp-ws`** 与 **`channels["stomp-ws"]`**。为兼容过渡期,解析配置时会合并 `channels.stomp`,但 **`stomp-ws` 字段优先**。
|
|
83
|
+
|
|
84
|
+
## 会话与 `dmScope`
|
|
85
|
+
|
|
86
|
+
会话隔离**仅**依赖 OpenClaw 根配置 **`session.dmScope`**(与 `mqtt`、`mqtt-ws`、`stomp-tcp` 一致)。合法取值:`main`、`per-peer`、`per-channel-peer`、`per-account-channel-peer`。
|
|
87
|
+
|
|
88
|
+
- 本插件**不会**使用 `channels["stomp-ws"]` 下的私有 `session.dmScope` 做隔离。
|
|
89
|
+
- 入站 `from` 使用 STOMP **peerId**(帧头 `x-peer-id` / `peer-id` / `sender`,否则为 login / `client-id` / 连接 id)。
|
|
90
|
+
- 回复优先发往 `topicBindings[].replyTopic`;否则为 **`/topic/session.<sessionKey>`**,其中 `sessionKey` 由 `buildSessionKeyFromDmScope`(`channel: stomp-ws`)生成。
|
|
91
|
+
|
|
92
|
+
各 `dmScope` 档下会话键形态请对照 **`mqtt-ws` / `stomp-tcp`** 文档说明。
|
|
93
|
+
|
|
94
|
+
## 安全
|
|
95
|
+
|
|
96
|
+
- **生产环境**:建议 `auth.required: true`、关闭 `allowAnonymous`,使用 `auth.users`;当前实现为配置内明文 `password` 比对,更敏感场景请用环境变量注入或前置代理鉴权。
|
|
97
|
+
- **ACL**:可选 `publishAllow`、`subscribeAllow`、`aclRules`(与 `openclaw-web-mqtt` 同类)。
|
|
98
|
+
- **TLS**:`tls.enabled` 且配置证书时由本插件起 HTTPS 并挂载 WS;也可在边缘终止 TLS 后反代到内网 `ws`。
|
|
99
|
+
- **限额**:按需调整 `maxConnections`、`limits.maxPayloadBytes`、`maxFrameSize`、`limits.maxSubscriptionsPerClient`(运维思路可参考 [RabbitMQ Web MQTT](https://www.rabbitmq.com/docs/web-mqtt))。
|
|
100
|
+
|
|
101
|
+
## 排障
|
|
102
|
+
|
|
103
|
+
| 现象 | 排查 |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| CONNECT 报认证失败 | 检查 `auth.users` 或 `defaultUser`/`defaultPass`;开发环境可临时 `allowAnonymous: true`。 |
|
|
106
|
+
| SEND 有反应但无 Agent 回复 | 确认 Gateway 已起、路由包含 `stomp-ws`、`topicBindings`/默认 agent;客户端是否 **SUBSCRIBE** 了真实回复 destination(常为 `/topic/session.<sessionKey>`)。 |
|
|
107
|
+
| SUBSCRIBE 无效 | `subscribeTopics` 非空时 destination 必须匹配其一;是否触达 `maxSubscriptionsPerClient`。 |
|
|
108
|
+
| `test:client` 超时 | `STOMP_SUBSCRIBE_DESTINATION` 是否与当前 `session.dmScope` 下 session 一致;查看 `GET /stomp-ws/status` 与日志。 |
|
|
109
|
+
|
|
110
|
+
## 测试
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pnpm test
|
|
114
|
+
pnpm run test:client
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
环境变量见英文 README「Testing」一节。
|
|
118
|
+
|
|
119
|
+
## GitHub Actions 与发版
|
|
120
|
+
|
|
121
|
+
| 工作流 | 触发 | 说明 |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) | push / PR | 安装、类型检查、构建、测试、上传 `dist` |
|
|
124
|
+
| [`.github/workflows/release.yml`](./.github/workflows/release.yml) | 标签 `v*` | 发布 npm 与 GitHub Packages、创建 Release |
|
|
125
|
+
|
|
126
|
+
发版说明:[`RELEASING.md`](./RELEASING.md),需配置 Secret **`NPM_TOKEN`**。
|
|
127
|
+
|
|
128
|
+
## 目录结构
|
|
129
|
+
|
|
130
|
+
与英文 README「Project layout」一致:`index.ts`、`setup-entry.ts`、`channel.ts`、`stomp-server.ts`、`stomp-config.ts`、`inbound.ts`、`dm-scope.ts`、`route-inbound.ts`、`topic-router.ts`、`acl.ts`、`outbound.ts`。
|
|
131
|
+
|
|
132
|
+
## 参考链接
|
|
133
|
+
|
|
134
|
+
- [Building plugins](https://docs.openclaw.ai/plugins/building-plugins)
|
|
135
|
+
- [Channel plugins](https://docs.openclaw.ai/plugins/sdk-channel-plugins)
|
|
136
|
+
- [SDK entrypoints](https://docs.openclaw.ai/plugins/sdk-entrypoints)
|
|
137
|
+
- [Manifest](https://docs.openclaw.ai/plugins/manifest)
|
package/RELEASING.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Releasing `@partme.ai/openclaw-web-stomp`
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- npm package name: `@partme.ai/openclaw-web-stomp`
|
|
6
|
+
- repository secret: `NPM_TOKEN`
|
|
7
|
+
- Node.js 22+ (see `package.json` → `engines`)
|
|
8
|
+
|
|
9
|
+
## CI (continuous integration)
|
|
10
|
+
|
|
11
|
+
Workflow: `.github/workflows/ci.yml`
|
|
12
|
+
|
|
13
|
+
| Trigger | Behavior |
|
|
14
|
+
|---------|----------|
|
|
15
|
+
| **Push** to `main` or `master` | `pnpm install --frozen-lockfile` → typecheck → build → test → upload **`dist/`** artifact |
|
|
16
|
+
| **Pull request** targeting `main` or `master` | Same as push |
|
|
17
|
+
|
|
18
|
+
## Version tag rule (required for Releases & Packages)
|
|
19
|
+
|
|
20
|
+
GitHub **Releases** and **Packages** are created only when you push a **git tag**, not a branch.
|
|
21
|
+
|
|
22
|
+
| Rule | Detail |
|
|
23
|
+
|------|--------|
|
|
24
|
+
| **Format** | `v` + **semver**, same as `package.json` → `version` |
|
|
25
|
+
| **Example** | If `"version": "0.2.0"` in `package.json`, the tag **must** be **`v0.2.0`** |
|
|
26
|
+
| **Not** | A branch name (e.g. `feature/v0.1.0`) does **not** trigger the `publish` job |
|
|
27
|
+
| **Workflow** | `.github/workflows/release.yml` runs the `publish` job only for refs like `refs/tags/v*` |
|
|
28
|
+
|
|
29
|
+
After pushing `v0.2.0`, Actions publishes to npmjs + GitHub Packages and creates a GitHub Release with the `.tgz`.
|
|
30
|
+
|
|
31
|
+
## Local release check
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm install --frozen-lockfile
|
|
35
|
+
pnpm run typecheck
|
|
36
|
+
pnpm run build
|
|
37
|
+
pnpm test
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Bump version and tag (recommended)
|
|
41
|
+
|
|
42
|
+
Use pnpm so `package.json` and git tag stay aligned:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pnpm version patch # or minor / major — updates package.json and creates commit + tag vX.Y.Z
|
|
46
|
+
git push origin main --follow-tags
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or set the version manually, then tag **exactly** `v` + that version:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Example: package.json already says "0.2.0"
|
|
53
|
+
git tag -a v0.2.0 -m "v0.2.0"
|
|
54
|
+
git push origin v0.2.0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Release workflow publishes on `v*` tags. npm publish is skipped if that version already exists on npm.
|
|
58
|
+
|
|
59
|
+
## GitHub Packages (`npm.pkg.github.com`)
|
|
60
|
+
|
|
61
|
+
GitHub’s npm registry requires the package scope to match the repository owner. The workflow publishes **`@partme.ai/openclaw-web-stomp`** to npmjs, and **`@<github-owner>/openclaw-web-stomp`** (for example **`@partme-ai/openclaw-web-stomp`**) to GitHub Packages. Install from GitHub Packages only when you intentionally use that registry and auth (PAT with `read:packages`).
|
|
62
|
+
|
|
63
|
+
## Manual publish from GitHub Actions
|
|
64
|
+
|
|
65
|
+
1. Open **Actions** → **Release**
|
|
66
|
+
2. Click **Run workflow** (this runs the `package` job only; it does **not** publish to npm/GitHub Packages/Release unless the run is from a **`v*`** tag)
|
|
67
|
+
3. For a real publish, push a **`vX.Y.Z`** tag as above, then confirm logs show:
|
|
68
|
+
- `Published @partme.ai/openclaw-web-stomp@x.y.z` (npmjs)
|
|
69
|
+
- `Published @<github-owner>/openclaw-web-stomp@x.y.z` (GitHub Packages)
|
|
70
|
+
|
|
71
|
+
## Common issues
|
|
72
|
+
|
|
73
|
+
- **No Releases / Packages on GitHub**: No **`v*`** tag has been pushed yet — push `v` + semver matching `package.json`.
|
|
74
|
+
- **`ERR_PNPM_OUTDATED_LOCKFILE`**: Run `pnpm install` locally and commit the updated `pnpm-lock.yaml` whenever `package.json` dependencies change.
|
|
75
|
+
- `npm ERR! 403`: version already published or token permissions insufficient
|
|
76
|
+
- `NPM_TOKEN is not set`: add secret in repo settings
|
|
77
|
+
- `npm whoami` failed: token expired or wrong scope permission
|