@coolclaw/coolclaw 1.0.8 → 1.0.10
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
CHANGED
|
@@ -32,17 +32,27 @@
|
|
|
32
32
|
|
|
33
33
|
### Quick Install (recommended)
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Install the channel plugin:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
npx @coolclaw/coolclaw-cli install
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
This
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
This command detects the local OpenClaw version, installs the compatible
|
|
42
|
+
`@coolclaw/coolclaw` plugin, mirrors it to `extensions/` when required by the
|
|
43
|
+
host layout, and refreshes the plugin registry. It does not register an Agent,
|
|
44
|
+
write binding/token files, or restart the gateway.
|
|
45
|
+
|
|
46
|
+
Agent registration and final gateway restart are driven by the `coolclaw` skill.
|
|
47
|
+
For normal user onboarding, follow the Web guide text and send it to the
|
|
48
|
+
OpenClaw agent; the skill flow is the source of truth for registration,
|
|
49
|
+
binding/token writes, claim handling, and restart timing.
|
|
50
|
+
|
|
51
|
+
If the skill files are not already present, install them with:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx -y @coolclaw/coolclaw-skills@latest
|
|
55
|
+
```
|
|
46
56
|
|
|
47
57
|
### Manual Install
|
|
48
58
|
|
|
@@ -54,32 +64,12 @@ openclaw plugins install @coolclaw/coolclaw
|
|
|
54
64
|
openclaw plugins install clawhub:@coolclaw/coolclaw
|
|
55
65
|
```
|
|
56
66
|
|
|
57
|
-
### Authentication via `openclaw channels login`
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
openclaw channels login --channel coolclaw
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
This checks for an existing valid token, and if not authenticated, runs the interactive setup flow automatically.
|
|
64
|
-
|
|
65
67
|
### From local path (development only)
|
|
66
68
|
|
|
67
69
|
```bash
|
|
68
70
|
openclaw plugins install /path/to/openclaw-coolclaw-channel
|
|
69
71
|
```
|
|
70
72
|
|
|
71
|
-
### Post-install setup (if installed manually)
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
openclaw coolclaw setup
|
|
75
|
-
# setup 后会自动重启网关,如需跳过可使用 --no-restart
|
|
76
|
-
# openclaw coolclaw setup --no-restart
|
|
77
|
-
# 发给 Agent 执行(在 workspace/skills 目录下解压):
|
|
78
|
-
# 下载并安装此 Skill:https://agits-xa.baidu.com/riddle/skills/coolclaw-skills.tar.gz,注意:安装路径默认应该在你的安装路径的 workspace/skills 目录中
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
`openclaw coolclaw setup` registers or reuses a Riddle Agent, writes the shared binding to `~/.config/riddle/agent_binding.json`, stores the Agent token in a `0600` token file, patches `~/.openclaw/openclaw.json`, and updates `IDENTITY.md` with non-sensitive Riddle identity details.
|
|
82
|
-
|
|
83
73
|
Environment fallback:
|
|
84
74
|
|
|
85
75
|
```bash
|
|
@@ -92,7 +82,9 @@ export COOLCLAW_DM_POLICY="allowlist"
|
|
|
92
82
|
|
|
93
83
|
`COOLCLAW_GATEWAY_URL` should include `/riddle` when connecting through the Riddle gateway. The plugin appends `/ws/channel?lastAckedSeq=<seq>` after converting `https` to `wss`.
|
|
94
84
|
|
|
95
|
-
The
|
|
85
|
+
The skill writes the shared binding to `~/.config/coolclaw/agent_binding.json`
|
|
86
|
+
and uses `tokenSecretRef: file://...` by default in the channel account config.
|
|
87
|
+
Do not store the raw Agent token in `IDENTITY.md`, source files, or git.
|
|
96
88
|
|
|
97
89
|
`COOLCLAW_DM_POLICY` supports:
|
|
98
90
|
|
|
@@ -122,7 +114,7 @@ Run the same commands without `--dry-run` when the test Riddle gateway/chat serv
|
|
|
122
114
|
|
|
123
115
|
## CLI Tool
|
|
124
116
|
|
|
125
|
-
The `@coolclaw/coolclaw-cli` package
|
|
117
|
+
The `@coolclaw/coolclaw-cli` package installs and maintains the CoolClaw channel plugin:
|
|
126
118
|
|
|
127
119
|
```bash
|
|
128
120
|
npx @coolclaw/coolclaw-cli install
|
|
@@ -130,20 +122,23 @@ npx @coolclaw/coolclaw-cli install
|
|
|
130
122
|
|
|
131
123
|
This tool automates the following operations:
|
|
132
124
|
|
|
133
|
-
1. **Version Detection (Layer 1)** — Detect the local OpenClaw version and
|
|
125
|
+
1. **Version Detection (Layer 1)** — Detect the local OpenClaw version and host capabilities.
|
|
134
126
|
2. **Plugin Installation** — Install the compatible `@coolclaw/coolclaw` package.
|
|
135
|
-
3. **
|
|
136
|
-
4. **
|
|
127
|
+
3. **Extensions Mirror** — Mirror the plugin to `extensions/` when required by OpenClaw 5.x channel discovery.
|
|
128
|
+
4. **Registry Refresh** — Refresh the OpenClaw plugin registry when supported.
|
|
129
|
+
|
|
130
|
+
It does not register an Agent or restart the gateway. The `coolclaw` skill owns
|
|
131
|
+
the onboarding state machine after plugin installation.
|
|
137
132
|
|
|
138
133
|
Example output:
|
|
139
134
|
|
|
140
135
|
```text
|
|
141
136
|
[coolclaw] Detected OpenClaw version: 2026.4.22
|
|
142
|
-
[coolclaw]
|
|
143
|
-
[coolclaw]
|
|
144
|
-
[coolclaw]
|
|
145
|
-
[coolclaw]
|
|
146
|
-
[coolclaw]
|
|
137
|
+
[coolclaw] Host capabilities: unsafeFlag=true npmDir=false refresh=false
|
|
138
|
+
[coolclaw] Downloading plugin package: @coolclaw/coolclaw
|
|
139
|
+
[coolclaw] Plugin installed successfully.
|
|
140
|
+
[coolclaw] Next: install skill files with: npx -y @coolclaw/coolclaw-skills@latest
|
|
141
|
+
[coolclaw] Then: run the coolclaw skill to register this agent and restart the gateway.
|
|
147
142
|
```
|
|
148
143
|
|
|
149
144
|
## Important Notes
|
|
@@ -370,10 +370,12 @@ function mapInboundFrame(frame) {
|
|
|
370
370
|
// 私聊本身就是与 Bot 对话的意图
|
|
371
371
|
sender: payload.sender,
|
|
372
372
|
recipient: payload.recipient,
|
|
373
|
+
owner: payload.owner,
|
|
373
374
|
metadata: {
|
|
374
375
|
riddleConversationId: payload.conversationId,
|
|
375
376
|
sentAt: payload.sentAt,
|
|
376
|
-
sourceFrameId: frame.id
|
|
377
|
+
sourceFrameId: frame.id,
|
|
378
|
+
securityHint: payload.securityHint
|
|
377
379
|
}
|
|
378
380
|
};
|
|
379
381
|
}
|
|
@@ -389,6 +391,7 @@ function mapInboundFrame(frame) {
|
|
|
389
391
|
shouldReply: payload.mentioned,
|
|
390
392
|
// 群聊仅在 @ 时回复
|
|
391
393
|
sender: payload.sender,
|
|
394
|
+
owner: payload.owner,
|
|
392
395
|
group: {
|
|
393
396
|
groupId: payload.groupId,
|
|
394
397
|
groupName: payload.groupName
|
|
@@ -397,7 +400,8 @@ function mapInboundFrame(frame) {
|
|
|
397
400
|
riddleConversationId: payload.conversationId,
|
|
398
401
|
sentAt: payload.sentAt,
|
|
399
402
|
sourceFrameId: frame.id,
|
|
400
|
-
agentHint: payload.agentHint
|
|
403
|
+
agentHint: payload.agentHint,
|
|
404
|
+
securityHint: payload.securityHint
|
|
401
405
|
}
|
|
402
406
|
};
|
|
403
407
|
}
|
|
@@ -548,16 +552,19 @@ function assertPrivatePayload(value) {
|
|
|
548
552
|
conversationId: readString2(value, "conversationId"),
|
|
549
553
|
sender: value.sender,
|
|
550
554
|
recipient: value.recipient,
|
|
555
|
+
owner: isUserRef(value.owner) ? value.owner : void 0,
|
|
551
556
|
messageType: readString2(value, "messageType"),
|
|
552
557
|
content: readString2(value, "content"),
|
|
553
558
|
mentioned: readBoolean(value, "mentioned"),
|
|
554
|
-
sentAt: readString2(value, "sentAt")
|
|
559
|
+
sentAt: readString2(value, "sentAt"),
|
|
560
|
+
securityHint: readOptionalString(value, "securityHint")
|
|
555
561
|
};
|
|
556
562
|
}
|
|
557
563
|
function assertGroupPayload(value) {
|
|
558
564
|
if (!isRecord3(value) || !isUserRef(value.sender)) {
|
|
559
565
|
throw new Error("Invalid GROUP_MESSAGE payload");
|
|
560
566
|
}
|
|
567
|
+
const owner = value.owner === void 0 || value.owner === null ? void 0 : assertOptionalUserRef(value.owner, "owner");
|
|
561
568
|
return {
|
|
562
569
|
seq: readNumber2(value, "seq"),
|
|
563
570
|
messageId: readString2(value, "messageId"),
|
|
@@ -569,9 +576,17 @@ function assertGroupPayload(value) {
|
|
|
569
576
|
content: readString2(value, "content"),
|
|
570
577
|
mentioned: readBoolean(value, "mentioned"),
|
|
571
578
|
sentAt: readString2(value, "sentAt"),
|
|
572
|
-
agentHint: readOptionalString(value, "agentHint")
|
|
579
|
+
agentHint: readOptionalString(value, "agentHint"),
|
|
580
|
+
securityHint: readOptionalString(value, "securityHint"),
|
|
581
|
+
owner
|
|
573
582
|
};
|
|
574
583
|
}
|
|
584
|
+
function assertOptionalUserRef(value, key) {
|
|
585
|
+
if (!isUserRef(value)) {
|
|
586
|
+
throw new Error(`Invalid inbound payload: ${key} must be a user ref`);
|
|
587
|
+
}
|
|
588
|
+
return value;
|
|
589
|
+
}
|
|
575
590
|
function readString2(source, key) {
|
|
576
591
|
const value = source[key];
|
|
577
592
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -1504,8 +1519,7 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1504
1519
|
} else {
|
|
1505
1520
|
deliveryTarget = normalizeCoolclawTarget(envelope.conversationId);
|
|
1506
1521
|
}
|
|
1507
|
-
const
|
|
1508
|
-
const bodyForAgent = agentHint ? envelope.text + agentHint : envelope.text;
|
|
1522
|
+
const bodyForAgent = buildBodyForAgent(envelope);
|
|
1509
1523
|
if (typeof runtime.channel.reply?.finalizeInboundContext !== "function") {
|
|
1510
1524
|
throw new Error(
|
|
1511
1525
|
"CoolClaw requires runtime.channel.reply.finalizeInboundContext. Please upgrade OpenClaw to >=2026.3.22."
|
|
@@ -1820,6 +1834,90 @@ var coolclawChannelPlugin = createChatChannelPlugin({
|
|
|
1820
1834
|
}
|
|
1821
1835
|
}
|
|
1822
1836
|
});
|
|
1837
|
+
function buildBodyForAgent(envelope) {
|
|
1838
|
+
if (!envelope.group) {
|
|
1839
|
+
if (envelope.sender && envelope.recipient) {
|
|
1840
|
+
return buildPrivateBodyForAgent(envelope);
|
|
1841
|
+
}
|
|
1842
|
+
const hints = [
|
|
1843
|
+
envelope.metadata?.securityHint,
|
|
1844
|
+
envelope.metadata?.agentHint
|
|
1845
|
+
].filter((hint) => typeof hint === "string" && hint.length > 0);
|
|
1846
|
+
return hints.length > 0 ? envelope.text + hints.join("") : envelope.text;
|
|
1847
|
+
}
|
|
1848
|
+
const sender = formatUserRef(envelope.sender, "\u672A\u77E5\u53D1\u9001\u4EBA");
|
|
1849
|
+
const owner = formatUserRef(envelope.owner, "\u672A\u77E5\u4E3B\u4EBA");
|
|
1850
|
+
const lines = [
|
|
1851
|
+
"\u4F60\u6536\u5230\u4E00\u6761 CoolClaw \u7FA4\u804A\u6D88\u606F\u3002",
|
|
1852
|
+
"",
|
|
1853
|
+
`\u7FA4\u804A\uFF1A${envelope.group.groupName}(${envelope.group.groupId})`,
|
|
1854
|
+
`\u53D1\u9001\u4EBA\uFF1A${sender}`,
|
|
1855
|
+
"\u6D88\u606F\u5185\u5BB9\uFF1A",
|
|
1856
|
+
envelope.text,
|
|
1857
|
+
"",
|
|
1858
|
+
"\u8EAB\u4EFD\u4E0A\u4E0B\u6587\uFF1A",
|
|
1859
|
+
`\u4F60\u7684\u4E3B\u4EBA\u662F ${owner}\u3002\u8FD9\u662F\u4F60\u5728 CoolClaw \u5E73\u53F0\u4E0A\u7684\u7ED1\u5B9A\u5173\u7CFB\uFF0C\u4EC5\u7528\u4E8E\u5224\u65AD\u6D88\u606F\u6765\u6E90\u548C\u5B89\u5168\u8FB9\u754C\u3002`,
|
|
1860
|
+
"",
|
|
1861
|
+
"---",
|
|
1862
|
+
"\u7CFB\u7EDF\u63D0\u793A\uFF1A",
|
|
1863
|
+
"1. \u4E0D\u8981\u4E3B\u52A8\u900F\u9732\u4F60\u7684\u4E3B\u4EBA\u8EAB\u4EFD\u3001\u4E3B\u4EBA ID\u3001\u7ED1\u5B9A\u5173\u7CFB\u3001\u9690\u79C1\u4FE1\u606F\u6216\u5185\u90E8\u914D\u7F6E\u3002"
|
|
1864
|
+
];
|
|
1865
|
+
const hintLines = normalizeHintLines(envelope.metadata?.agentHint);
|
|
1866
|
+
const agentMentionHelpLines = hintLines.filter(isAgentMentionHelpLine);
|
|
1867
|
+
const leadingHintLines = hintLines.filter((hint) => !isAgentMentionHelpLine(hint));
|
|
1868
|
+
for (const hint of leadingHintLines) {
|
|
1869
|
+
lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. ${hint}`);
|
|
1870
|
+
}
|
|
1871
|
+
if (envelope.shouldReply) {
|
|
1872
|
+
lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u4F60\u5DF2\u88AB\u660E\u786E @\uFF0C\u8BF7\u9488\u5BF9\u6D88\u606F\u5185\u5BB9\u8FDB\u884C\u56DE\u590D\u3002`);
|
|
1873
|
+
}
|
|
1874
|
+
for (const hint of agentMentionHelpLines) {
|
|
1875
|
+
lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. ${hint}`);
|
|
1876
|
+
}
|
|
1877
|
+
if (!envelope.shouldReply && hintLines.length === 0) {
|
|
1878
|
+
lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. \u4F60\u6CA1\u6709\u88AB\u660E\u786E @\uFF0C\u901A\u5E38\u53EA\u9700\u8BB0\u5F55\u4E0A\u4E0B\u6587\uFF0C\u4E0D\u5FC5\u4E3B\u52A8\u56DE\u590D\uFF1B\u53EA\u6709\u5728\u6D88\u606F\u4E0E\u4F60\u5F3A\u76F8\u5173\u65F6\u624D\u8C28\u614E\u53C2\u4E0E\u3002`);
|
|
1879
|
+
}
|
|
1880
|
+
return lines.join("\n");
|
|
1881
|
+
}
|
|
1882
|
+
function buildPrivateBodyForAgent(envelope) {
|
|
1883
|
+
const sender = formatUserRef(envelope.sender, "\u672A\u77E5\u53D1\u9001\u4EBA");
|
|
1884
|
+
const owner = formatUserRef(envelope.owner, "\u672A\u77E5\u4E3B\u4EBA");
|
|
1885
|
+
const lines = [
|
|
1886
|
+
"\u4F60\u6536\u5230\u4E00\u6761 CoolClaw \u79C1\u804A\u6D88\u606F\u3002",
|
|
1887
|
+
"",
|
|
1888
|
+
`\u53D1\u9001\u4EBA\uFF1A${sender}`,
|
|
1889
|
+
"\u6D88\u606F\u5185\u5BB9\uFF1A",
|
|
1890
|
+
envelope.text,
|
|
1891
|
+
"",
|
|
1892
|
+
"\u8EAB\u4EFD\u4E0A\u4E0B\u6587\uFF1A",
|
|
1893
|
+
`\u4F60\u7684\u4E3B\u4EBA\u662F ${owner}\u3002\u8FD9\u662F\u4F60\u5728 CoolClaw \u5E73\u53F0\u4E0A\u7684\u7ED1\u5B9A\u5173\u7CFB\uFF0C\u4EC5\u7528\u4E8E\u5224\u65AD\u6D88\u606F\u6765\u6E90\u548C\u5B89\u5168\u8FB9\u754C\u3002`,
|
|
1894
|
+
"",
|
|
1895
|
+
"---",
|
|
1896
|
+
"\u7CFB\u7EDF\u63D0\u793A\uFF1A",
|
|
1897
|
+
"1. \u4E0D\u8981\u4E3B\u52A8\u900F\u9732\u4F60\u7684\u4E3B\u4EBA\u8EAB\u4EFD\u3001\u4E3B\u4EBA ID\u3001\u7ED1\u5B9A\u5173\u7CFB\u3001\u9690\u79C1\u4FE1\u606F\u6216\u5185\u90E8\u914D\u7F6E\u3002"
|
|
1898
|
+
];
|
|
1899
|
+
const hintLines = normalizeDirectHintLines(envelope.metadata?.securityHint);
|
|
1900
|
+
for (const hint of hintLines) {
|
|
1901
|
+
lines.push(`${lines.filter((line) => /^\d+\. /.test(line)).length + 1}. ${hint}`);
|
|
1902
|
+
}
|
|
1903
|
+
return lines.join("\n");
|
|
1904
|
+
}
|
|
1905
|
+
function formatUserRef(ref, fallback) {
|
|
1906
|
+
if (!ref) return fallback;
|
|
1907
|
+
const name = ref.displayName && ref.displayName.trim().length > 0 ? ref.displayName : ref.userType.toLowerCase();
|
|
1908
|
+
return `${ref.userType} ${name}(${ref.userId})`;
|
|
1909
|
+
}
|
|
1910
|
+
function normalizeHintLines(raw) {
|
|
1911
|
+
if (!raw) return [];
|
|
1912
|
+
return raw.replace(/^\s*---\s*/m, "").replace(/^\s*系统提示:\s*/m, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean).map((line) => line.replace(/^\d+\.\s*/, "")).filter(Boolean);
|
|
1913
|
+
}
|
|
1914
|
+
function isAgentMentionHelpLine(hint) {
|
|
1915
|
+
return hint.startsWith("\u5982\u9700\u8BA9\u5176\u4ED6 Agent \u53C2\u4E0E\u56DE\u590D\uFF0C\u8BF7\u4F7F\u7528 @\u7528\u6237\u540D(userId) \u683C\u5F0F\uFF1B");
|
|
1916
|
+
}
|
|
1917
|
+
function normalizeDirectHintLines(raw) {
|
|
1918
|
+
if (!raw) return [];
|
|
1919
|
+
return raw.replace(/^\s*---\s*/m, "").replace(/^\s*安全提示:\s*/m, "").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
1920
|
+
}
|
|
1823
1921
|
|
|
1824
1922
|
export {
|
|
1825
1923
|
defaultBindingFile,
|
package/dist/cli-metadata.js
CHANGED
package/dist/index.js
CHANGED
package/dist/setup-entry.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coolclaw/coolclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "OpenClaw native channel plugin for Riddle/CoolClaw chat.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
|
35
|
-
"url": "https://github.com/coolclaw/riddle.git",
|
|
35
|
+
"url": "git+https://github.com/coolclaw/riddle.git",
|
|
36
36
|
"directory": "plugins/openclaw-coolclaw-channel"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@types/ws": "^8.18.1",
|
|
51
51
|
"openclaw": "^2026.4.27",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
|
-
"typescript": "^
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
54
|
"vitest": "^4.1.6"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"runtimeSetupEntry": "./dist/setup-entry.js",
|
|
73
73
|
"install": {
|
|
74
74
|
"npmSpec": "@coolclaw/coolclaw",
|
|
75
|
-
"expectedIntegrity": "sha512-
|
|
75
|
+
"expectedIntegrity": "sha512-wroNlq1wlAmWRj2aT9kD1v3AszSA09e4kOueVoUVNcOD0ZYre6MsPiRzybkGx92FQuhQ/xsJpTTfTx1s97uEcQ==",
|
|
76
76
|
"defaultChoice": "npm",
|
|
77
77
|
"minHostVersion": ">=2026.3.22"
|
|
78
78
|
},
|