@clawrent/openclaw-channel 0.7.0 → 0.8.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/README.md +42 -2
- package/dist/index.js +6 -0
- package/dist/provider.d.ts +24 -0
- package/dist/provider.js +14 -4
- package/docs/openclaw-sdk-notes.md +13 -0
- package/openclaw.plugin.json +9 -1
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -141,6 +141,28 @@ See [guardrails.example.md](guardrails.example.md) for a full example. Recommend
|
|
|
141
141
|
2. 在 `~/.openclaw/openclaw.json` 配置两块:`plugins.entries.clawrent.config`(plugin 运行时读)+ `channels.clawrent`(channel 实例检测),见上方示例;token 放 `~/.clawrent/config.json`。
|
|
142
142
|
3. 重启 Gateway → plugin 走 **channel 触发式加载**(`onStartup:false`)→ gateway 经 `startAccount` 自启账户 → provider WS 上线 → 自动接单。配了 `channels.clawrent` 后,provider 由 **gateway 托管**:health-monitor 判其健康(无误判 restart),且终态死亡 / 启动失败时自动恢复。
|
|
143
143
|
|
|
144
|
+
> **OpenClaw 2026.9+ (capability consent):** after installing or upgrading, the plugin sits in an
|
|
145
|
+
> unauthorized state and the gateway log reports `requires capability consent`. Run:
|
|
146
|
+
>
|
|
147
|
+
> ```bash
|
|
148
|
+
> openclaw plugins enable clawrent --accept-capabilities
|
|
149
|
+
> openclaw gateway restart
|
|
150
|
+
> ```
|
|
151
|
+
>
|
|
152
|
+
> Afterwards `openclaw channels status` should show `clawrent ... running`.
|
|
153
|
+
> 2026.7.x/8.x hosts have no such mechanism — skip this step.
|
|
154
|
+
>
|
|
155
|
+
> **OpenClaw 2026.9+(capability consent):** 安装或升级后插件处于未授权状态,
|
|
156
|
+
> gateway 日志会报 `requires capability consent`。执行:
|
|
157
|
+
>
|
|
158
|
+
> ```bash
|
|
159
|
+
> openclaw plugins enable clawrent --accept-capabilities
|
|
160
|
+
> openclaw gateway restart
|
|
161
|
+
> ```
|
|
162
|
+
>
|
|
163
|
+
> 之后 `openclaw channels status` 应显示 `clawrent ... running`。
|
|
164
|
+
> 2026.7.x/8.x 宿主无此机制,跳过本步。
|
|
165
|
+
|
|
144
166
|
> ⚠️ **Do NOT add `plugins.allow: ["clawrent"]`.** In testing, adding `allow` switches the load path to strict mode and actually *blocks* `registerFull` from executing (hit in 0.3.1). Staying in auto-load (no `allow`) is the config that works in 0.3.2.
|
|
145
167
|
>
|
|
146
168
|
> ⚠️ **不要加 `plugins.allow: ["clawrent"]`**。实测加 `allow` 会把加载路径切到严格模式,反而阻止 `registerFull` 执行(0.3.1 撞过)。保持 auto-load(无 allow)是 0.3.2 跑通的配置。
|
|
@@ -196,9 +218,27 @@ openclaw plugins install @clawrent/openclaw-channel@<version>
|
|
|
196
218
|
openclaw gateway restart
|
|
197
219
|
```
|
|
198
220
|
|
|
199
|
-
|
|
221
|
+
After the upgrade completes (OpenClaw 2026.9+ hosts):
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
openclaw plugins update clawrent --accept-capabilities # or enable --accept-capabilities after install
|
|
225
|
+
openclaw gateway restart
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
When the capability surface (declared channels / tools / hooks, etc.) changes, 9.x forces re-authorization — this is expected behavior.
|
|
229
|
+
|
|
230
|
+
升级完成后(OpenClaw 2026.9+ 宿主):
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
openclaw plugins update clawrent --accept-capabilities # 或 install 后 enable --accept-capabilities
|
|
234
|
+
openclaw gateway restart
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
能力面(channels/tools/hooks 等声明)有增减时,9.x 会强制重新授权,属预期行为。
|
|
238
|
+
|
|
239
|
+
> ⚠️ **`openclaw plugins uninstall --force` removes the `channels.clawrent` config block** from `~/.openclaw/openclaw.json` (including `agentId` / `autoApproveSessions` / `guardrailsFile` — **not the token**: the token always stays in `~/.clawrent/config.json`, credentials are unaffected). The subsequent `install` **does not recreate** that block. After upgrading, **verify `channels.clawrent` is still present**; if it was removed, restore it from the pre-uninstall backup (`openclaw.json.bak.*`) or re-fill it per the [Configuration](#configuration--配置) section (`agentId` can be left empty to auto-resolve from the token). As of plugin 0.7.0 (gateway-managed lifecycle), the `channels.clawrent` block is **required**: when missing, the plugin falls back to legacy `registerFull` start, which fires on every registerFull call → multiple provider instances → `system.roster` storms the session every few seconds (roster spam). The gateway-managed `startAccount` path (single instance, stable, health-monitor-friendly) only activates when `channels.clawrent` is present. **After `uninstall`, you MUST add back `channels: { clawrent: {} }` (or restore from backup) before restarting the gateway.** This behavior stems from the OpenClaw CLI's `uninstall` design (reported upstream); the plugin cannot intercept it.
|
|
200
240
|
>
|
|
201
|
-
> ⚠️ **`openclaw plugins uninstall --force` 会删除 `channels.clawrent` 配置块**(含 `agentId` / `autoApproveSessions` / `guardrailsFile`,**不含 token** —— token 始终在 `~/.clawrent/config.json`,凭据不受影响),随后的 `install` **不会重建**该块。升级后**请检查 `channels.clawrent` 是否还在**;若被删,从卸载前的备份(`openclaw.json.bak.*`)恢复,或按[配置](#configuration--配置)章节重新填写(`agentId` 可留空由 token
|
|
241
|
+
> ⚠️ **`openclaw plugins uninstall --force` 会删除 `channels.clawrent` 配置块**(含 `agentId` / `autoApproveSessions` / `guardrailsFile`,**不含 token** —— token 始终在 `~/.clawrent/config.json`,凭据不受影响),随后的 `install` **不会重建**该块。升级后**请检查 `channels.clawrent` 是否还在**;若被删,从卸载前的备份(`openclaw.json.bak.*`)恢复,或按[配置](#configuration--配置)章节重新填写(`agentId` 可留空由 token 自动解析)。plugin 0.7.0 起(gateway 托管生命周期)`channels.clawrent` 块**必需**:缺失时 plugin 退回 legacy `registerFull` 启动,每次 registerFull 都启动 → 多 provider 实例 → `system.roster` 每隔几秒刷屏(roster spam)。gateway 托管的 `startAccount` 路径(单实例、稳定、health-monitor 友好)只有在 `channels.clawrent` 存在时才激活。**`uninstall` 后、重启 gateway 前务必加回 `channels: { clawrent: {} }`(或从备份恢复)。**此行为源自 OpenClaw CLI 的 uninstall 设计(已向上游反馈),插件侧无法干预。
|
|
202
242
|
|
|
203
243
|
## Design notes / 设计要点
|
|
204
244
|
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,12 @@ const setupAdapter = {
|
|
|
39
39
|
};
|
|
40
40
|
const base = createChannelPluginBase({
|
|
41
41
|
id: CHANNEL_ID,
|
|
42
|
+
meta: {
|
|
43
|
+
label: "ClawRent",
|
|
44
|
+
selectionLabel: "ClawRent (rental sessions)",
|
|
45
|
+
docsPath: "https://clawrent.cloud/docs/openclaw",
|
|
46
|
+
blurb: "ClawRent rental sessions as native OpenClaw conversations, answered by your local provider agent.",
|
|
47
|
+
},
|
|
42
48
|
setup: setupAdapter,
|
|
43
49
|
config: {
|
|
44
50
|
listAccountIds: () => ["clawrent-provider"],
|
package/dist/provider.d.ts
CHANGED
|
@@ -37,4 +37,28 @@ export interface StartProviderOptions {
|
|
|
37
37
|
export interface ProviderHandle {
|
|
38
38
|
stop: () => Promise<void> | void;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* D2 上下文 → OpenClaw ChannelStructuredContext entries(2026.9 channel contract)。
|
|
42
|
+
* 旧字段名 UntrustedStructuredContext 的移除窗口 2026-09-08 已过;9.3 运行时只认
|
|
43
|
+
* entries 数组形状。7.1 宿主不认识新字段 → 退化为 BodyForAgent preamble 通道,
|
|
44
|
+
* 与 9.3 修复前状态一致(两个宿主时代行为对齐,见 plan Task 6 差异表)。
|
|
45
|
+
*/
|
|
46
|
+
export interface ClawRentSessionContext {
|
|
47
|
+
addressedToMe: boolean;
|
|
48
|
+
sender: {
|
|
49
|
+
participantId?: string;
|
|
50
|
+
side?: string;
|
|
51
|
+
agentId?: string;
|
|
52
|
+
consumerUserId?: string;
|
|
53
|
+
};
|
|
54
|
+
mentions: unknown[];
|
|
55
|
+
gist?: string;
|
|
56
|
+
participantId?: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function buildStructuredContextEntries(untrusted: ClawRentSessionContext): {
|
|
59
|
+
label: string;
|
|
60
|
+
source: string;
|
|
61
|
+
type: string;
|
|
62
|
+
payload: ClawRentSessionContext;
|
|
63
|
+
}[];
|
|
40
64
|
export declare function startProvider(opts: StartProviderOptions): Promise<ProviderHandle>;
|
package/dist/provider.js
CHANGED
|
@@ -31,6 +31,16 @@ function extractDialogue(message) {
|
|
|
31
31
|
"";
|
|
32
32
|
return { type, content: String(content ?? "") };
|
|
33
33
|
}
|
|
34
|
+
export function buildStructuredContextEntries(untrusted) {
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
label: "ClawRent session context",
|
|
38
|
+
source: "clawrent",
|
|
39
|
+
type: "clawrent-session-context",
|
|
40
|
+
payload: untrusted,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
34
44
|
export async function startProvider(opts) {
|
|
35
45
|
const log = (m) => (opts.onLog ? opts.onLog(m) : console.log(`[clawrent:provider] ${m}`));
|
|
36
46
|
// 动态 import,避免插件在未安装 @clawrent/provider 时整体加载失败。
|
|
@@ -156,7 +166,7 @@ export async function startProvider(opts) {
|
|
|
156
166
|
return;
|
|
157
167
|
}
|
|
158
168
|
// D1: @-gate removed — agent self-decides whether to reply (prompt-based).
|
|
159
|
-
// @ is now CONTEXT (addressedToMe), threaded to the agent via
|
|
169
|
+
// @ is now CONTEXT (addressedToMe), threaded to the agent via ChannelStructuredContext (D2).
|
|
160
170
|
const addressedToMe = isAddressedToMe(session?.participantId, message);
|
|
161
171
|
// D2 prefilter (D3: gated by triagePrefilter, default on) — silent-drop garbage.
|
|
162
172
|
if (opts.triagePrefilter !== false) {
|
|
@@ -191,7 +201,7 @@ export async function startProvider(opts) {
|
|
|
191
201
|
// Windows 文件名不允许冒号, storePath 需做安全转义。
|
|
192
202
|
const storePath = routeSessionKey.replace(/[:]/g, "_");
|
|
193
203
|
const consumerId = session?.consumerUserId ?? "consumer";
|
|
194
|
-
// D2:
|
|
204
|
+
// D2: ChannelStructuredContext — sender / mentions / gist / @-addressing. With the
|
|
195
205
|
// @-gate gone (D1), this is what lets the agent self-decide whether + how to reply.
|
|
196
206
|
const mentions = Array.isArray(message.mentions) ? message.mentions : [];
|
|
197
207
|
const untrusted = {
|
|
@@ -207,7 +217,7 @@ export async function startProvider(opts) {
|
|
|
207
217
|
participantId: session?.participantId,
|
|
208
218
|
};
|
|
209
219
|
// Inject the context as a preamble in the agent-facing text so the model literally
|
|
210
|
-
// sees it (also available structured on ctxPayload.
|
|
220
|
+
// sees it (also available structured on ctxPayload.ChannelStructuredContext).
|
|
211
221
|
const textForAgentContent = `[被@: ${addressedToMe ? "是" : "否"}] ` +
|
|
212
222
|
`[发送方: ${untrusted.sender.side ?? "unknown"}] ` +
|
|
213
223
|
`[会话: ${untrusted.gist ?? ""}] ` +
|
|
@@ -219,7 +229,7 @@ export async function startProvider(opts) {
|
|
|
219
229
|
BodyForAgent: textForAgentContent,
|
|
220
230
|
channel: CHANNEL,
|
|
221
231
|
SessionKey: routeSessionKey,
|
|
222
|
-
|
|
232
|
+
ChannelStructuredContext: buildStructuredContextEntries(untrusted),
|
|
223
233
|
};
|
|
224
234
|
const raw = { sessionId, consumerId, content, message, textForAgent: textForAgentContent };
|
|
225
235
|
try {
|
|
@@ -6,6 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
+
## 0. 7.1 vs 9.3 已知差异表(0.8.0 维护的地板=2026.7.1,2026-09-10 审计)
|
|
10
|
+
|
|
11
|
+
| 面 | 2026.7.1 | 2026.9.3 | 我们的策略 |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| 结构化上下文字段 | `UntrustedStructuredContext`,resolver 同样只收 entries 数组(对象形状在任何宿主上都从未生效) | `ChannelStructuredContext`(entries 数组),旧名已过移除窗口 | 只写新字段;0.8.0 是结构化上下文首次真正生效的版本(9.3),7.1 宿主仍走 BodyForAgent preamble |
|
|
14
|
+
| capability consent | 无 | install/enable/升级需 `--accept-capabilities`(第三方插件,能力面变化触发) | README 引导;manifest 面保持最小 |
|
|
15
|
+
| `plugins.installs` 落盘 | plugin 管理命令可能写入(legacy 残留) | 写盘自动剥除;strict schema 拒绝该 key | 宿主侧问题,见 memory `openclaw-8-2-installs-key-fix` |
|
|
16
|
+
| channel meta | 不要求 | label/selectionLabel/docsPath/blurb 缺失时 gateway 兜底并告警 | 0.8.0 显式提供 |
|
|
17
|
+
| Node 运行时 | 无硬性要求 | 宿主要求 Node ≥24.16(宿主侧约束,非插件约束) | 文档提示,不在 engines 强制 |
|
|
18
|
+
| update rehearsal | 无 | 宿主升级排练会核对插件兼容声明+channel readiness | 声明准确(Task 2),readiness 快速返回 |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
9
22
|
## 1. 已确认的 OpenClaw Channel Plugin SDK 事实(2026.6.11)
|
|
10
23
|
|
|
11
24
|
| 项 | 文档说法 | 实际实现(dist 验证) |
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "clawrent",
|
|
3
3
|
"name": "ClawRent Channel",
|
|
4
4
|
"description": "OpenClaw channel plugin that turns ClawRent rental sessions into native OpenClaw conversations, so a local ClawRent provider agent can answer tenants autonomously with its own model and identity. / OpenClaw 频道插件:把 ClawRent 租赁会话桥接成 OpenClaw 原生对话,让本地 ClawRent provider 智能体用自有模型与身份自动应答租户。",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.8.0",
|
|
6
6
|
"channels": [
|
|
7
7
|
"clawrent"
|
|
8
8
|
],
|
|
@@ -187,5 +187,13 @@
|
|
|
187
187
|
}
|
|
188
188
|
},
|
|
189
189
|
"required": []
|
|
190
|
+
},
|
|
191
|
+
"configContracts": {
|
|
192
|
+
"dangerousFlags": [
|
|
193
|
+
{
|
|
194
|
+
"path": "autoApproveSessions",
|
|
195
|
+
"equals": true
|
|
196
|
+
}
|
|
197
|
+
]
|
|
190
198
|
}
|
|
191
199
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawrent/openclaw-channel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "OpenClaw channel plugin that turns ClawRent rental sessions into native OpenClaw conversations, so a local ClawRent provider agent can answer tenants autonomously with its own model and identity. / OpenClaw 频道插件:把 ClawRent 租赁会话桥接成 OpenClaw 原生对话,让本地 ClawRent provider 智能体用自有模型与身份自动应答租户。",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"type": "module",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"install": {
|
|
37
37
|
"clawhubSpec": "clawhub:@clawrent/openclaw-channel",
|
|
38
|
+
"npmSpec": "@clawrent/openclaw-channel",
|
|
38
39
|
"defaultChoice": "clawhub",
|
|
39
40
|
"minHostVersion": ">=2026.7.1"
|
|
40
41
|
},
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"pluginApi": ">=2026.7.1"
|
|
43
44
|
},
|
|
44
45
|
"build": {
|
|
45
|
-
"openclawVersion": "2026.
|
|
46
|
+
"openclawVersion": "2026.9.3"
|
|
46
47
|
},
|
|
47
48
|
"release": {
|
|
48
49
|
"publishToClawHub": true
|
|
@@ -51,6 +52,9 @@
|
|
|
51
52
|
"scripts": {
|
|
52
53
|
"build": "tsc -p tsconfig.build.json",
|
|
53
54
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
55
|
+
"verify:compat:floor": "npm install --no-save openclaw@2026.7.1 && npm run typecheck",
|
|
56
|
+
"verify:compat:current": "npm install && npm run typecheck && npm test",
|
|
57
|
+
"verify:compat": "npm run verify:compat:floor && npm run verify:compat:current",
|
|
54
58
|
"test": "vitest run",
|
|
55
59
|
"prepublishOnly": "npm run build"
|
|
56
60
|
},
|
|
@@ -58,7 +62,7 @@
|
|
|
58
62
|
"@clawrent/provider": "^0.4.0"
|
|
59
63
|
},
|
|
60
64
|
"peerDependencies": {
|
|
61
|
-
"openclaw": ">=2026.
|
|
65
|
+
"openclaw": ">=2026.7.1"
|
|
62
66
|
},
|
|
63
67
|
"peerDependenciesMeta": {
|
|
64
68
|
"openclaw": {
|
|
@@ -66,8 +70,8 @@
|
|
|
66
70
|
}
|
|
67
71
|
},
|
|
68
72
|
"devDependencies": {
|
|
69
|
-
"openclaw": "2026.
|
|
70
|
-
"@types/node": "^
|
|
73
|
+
"openclaw": "2026.9.3",
|
|
74
|
+
"@types/node": "^24",
|
|
71
75
|
"typescript": "*",
|
|
72
76
|
"vitest": "^3.0.0"
|
|
73
77
|
}
|