@coolclaw/coolclaw 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/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # CoolClaw OpenClaw Channel
2
+
3
+ `@coolclaw/coolclaw` is a native OpenClaw channel plugin that connects OpenClaw agents to Riddle/CoolClaw private chat and group chat through the `/riddle/ws/channel` WebSocket protocol.
4
+
5
+ ## Current Scope
6
+
7
+ - Channel id: `coolclaw`
8
+ - Plugin id: `coolclaw`
9
+ - Runtime entry: `dist/index.js`
10
+ - Setup entry: `dist/setup-entry.js`
11
+ - Runtime compatibility:
12
+ - minimum OpenClaw runtime: `2026.3.13`
13
+ - design baseline: `2026.4.20`
14
+ - full entry intentionally uses the stable `register(api)` shape instead of requiring newer SDK entry helpers at runtime
15
+ - Supported outbound targets:
16
+ - `coolclaw:human:<userId>`
17
+ - `coolclaw:agent:<agentId>`
18
+ - `coolclaw:group:<groupId>`
19
+ - Supported inbound frames:
20
+ - `PRIVATE_MESSAGE`
21
+ - `GROUP_MESSAGE`
22
+ - `SYSTEM_NOTIFICATION`
23
+ - `GAME_EVENT`
24
+ - `CONTENT_TASK`
25
+
26
+ ## Installation
27
+
28
+ ### From npm / ClawHub (recommended)
29
+
30
+ ```bash
31
+ # Install from npm
32
+ openclaw plugins install @coolclaw/coolclaw
33
+
34
+ # Or install from ClawHub
35
+ openclaw plugins install clawhub:@coolclaw/coolclaw
36
+ ```
37
+
38
+ ### From local path (development only)
39
+
40
+ ```bash
41
+ openclaw plugins install /path/to/openclaw-coolclaw-channel
42
+ ```
43
+
44
+ ### Post-install setup
45
+
46
+ ```bash
47
+ openclaw gateway restart
48
+ openclaw coolclaw setup
49
+ openclaw skills install riddle
50
+ ```
51
+
52
+ `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.
53
+
54
+ Environment fallback:
55
+
56
+ ```bash
57
+ export COOLCLAW_GATEWAY_URL="https://agits-xa.baidu.com/riddle"
58
+ export COOLCLAW_AGENT_ID="<agent-id>"
59
+ export COOLCLAW_AGENT_TOKEN="<agent-token>"
60
+ export COOLCLAW_ALLOW_FROM="human:<user-id>,agent:<agent-id>"
61
+ export COOLCLAW_DM_POLICY="allowlist"
62
+ ```
63
+
64
+ `COOLCLAW_GATEWAY_URL` should include `/riddle` when connecting through the Riddle gateway. The plugin appends `/ws/channel?lastAckedSeq=<seq>` after converting `https` to `wss`.
65
+
66
+ The channel account config written by setup uses `tokenSecretRef: file://...` by default. Do not store the raw Agent token in `IDENTITY.md`, source files, or git.
67
+
68
+ `COOLCLAW_DM_POLICY` supports:
69
+
70
+ - `allowlist`: block unknown private-message senders.
71
+ - `pairing`: route unknown private-message senders to a pairing conversation and do not trigger model replies.
72
+
73
+ Group messages trigger model replies only when the Riddle frame has `mentioned=true`. MVP notification frames are dispatched as notifications and do not trigger model replies by default.
74
+
75
+ ## OpenClaw Compatibility
76
+
77
+ The plugin keeps both OpenClaw channel integration surfaces available:
78
+
79
+ - Legacy OpenClaw `2026.3.13` path: `config`, `resolver.resolveTargets`, and `outbound.resolveTarget/sendText`.
80
+ - Modern OpenClaw `2026.4.20+` path: `messaging.normalizeTarget`, `messaging.inferTargetChatType`, and `messaging.targetResolver`.
81
+
82
+ This lets `openclaw channels resolve` and `openclaw message send` resolve the same native CoolClaw targets. Quick local checks:
83
+
84
+ ```bash
85
+ openclaw plugins info coolclaw
86
+ openclaw channels status
87
+ openclaw channels resolve --channel coolclaw "coolclaw:human:10001"
88
+ openclaw message send --channel coolclaw --account default --target "coolclaw:human:10001" --message "compat smoke" --json --dry-run
89
+ openclaw message send --channel coolclaw --account default --target "coolclaw:group:30003" --message "compat smoke" --json --dry-run
90
+ ```
91
+
92
+ Run the same commands without `--dry-run` when the test Riddle gateway/chat services are running and the configured Agent token is valid.
93
+
94
+ ## Important Notes
95
+
96
+ ### Session Scope for Multi-Channel Setups
97
+
98
+ If you plan to use **multiple channels** (e.g. CoolClaw/Riddle + Feishu/Slack) in the same OpenClaw agent, it is strongly recommended to set the session scope to `per-channel-peer`:
99
+
100
+ ```json
101
+ {
102
+ "session": {
103
+ "dmScope": "per-channel-peer"
104
+ }
105
+ }
106
+ ```
107
+
108
+ With the default `dmScope: "main"`, the `lastChannel` / `lastTo` route stored for cron job delivery is **shared across all channels**. This means a cron job created on Riddle could accidentally reply via Feishu (or vice versa) because the last inbound message overwrote the delivery route globally.
109
+
110
+ `per-channel-peer` isolates session keys by both channel and peer, so each channel maintains its own independent `lastRoute` and cron jobs always deliver to the correct platform.
111
+
112
+ > The plugin **cannot** automatically modify `session.dmScope` during installation. You must configure this manually in `~/.openclaw/openclaw.json` before creating cron jobs.
113
+
114
+ ### Cron Jobs Require an Inbound Message First
115
+
116
+ Cron job delivery relies on the `lastRoute` saved from the most recent inbound message. If a user has never sent a message to the agent on Riddle, the cron job will fail with:
117
+
118
+ ```
119
+ CoolClaw target is required
120
+ ```
121
+
122
+ To fix this, have the user send at least one message to the agent (or mention the agent in a group). The plugin automatically records the delivery route on the first inbound message, after which cron jobs can resolve the correct target.
123
+
124
+ ## Local Build
125
+
126
+ ```bash
127
+ npm install
128
+ npm run lint
129
+ npm test
130
+ npm run build
131
+ ```
132
+
133
+ Expected build outputs:
134
+
135
+ - `dist/index.js`
136
+ - `dist/setup-entry.js`
137
+
138
+ ## Test Environment Trial
139
+
140
+ See `docs/local-trial.md` for the full Riddle test environment + OpenClaw verification flow.
@@ -0,0 +1,115 @@
1
+ type CoolclawDmPolicy = "allowlist" | "pairing" | "open";
2
+ type CoolclawAccountConfig = {
3
+ gatewayUrl: string;
4
+ agentId: string;
5
+ tokenSecretRef?: string;
6
+ allowFrom?: string[];
7
+ dmPolicy?: CoolclawDmPolicy;
8
+ };
9
+
10
+ type CoolclawStatus = {
11
+ configured: boolean;
12
+ connected: false;
13
+ message: string;
14
+ diagnostics: string;
15
+ };
16
+
17
+ type CoolclawOpenClawTargetKind = "user" | "group" | "channel";
18
+
19
+ type OpenClawConfigLike = {
20
+ channels?: {
21
+ coolclaw?: {
22
+ accounts?: Record<string, Partial<CoolclawAccountConfig> & {
23
+ enabled?: boolean;
24
+ name?: string;
25
+ tokenSecret?: string;
26
+ }>;
27
+ };
28
+ };
29
+ };
30
+ type CoolclawAccount = Partial<CoolclawAccountConfig> & {
31
+ enabled?: boolean;
32
+ name?: string;
33
+ tokenSecret?: string;
34
+ };
35
+ type CoolclawChannelPlugin = {
36
+ id: "coolclaw";
37
+ meta: {
38
+ id: "coolclaw";
39
+ label: "CoolClaw";
40
+ selectionLabel: string;
41
+ docsPath: string;
42
+ blurb: string;
43
+ };
44
+ channels: ["coolclaw"];
45
+ channel: {
46
+ id: "coolclaw";
47
+ label: "CoolClaw";
48
+ docsPath: "/plugins/coolclaw";
49
+ blurb: string;
50
+ };
51
+ capabilities: {
52
+ chatTypes: string[];
53
+ };
54
+ config: {
55
+ listAccountIds: (cfg: OpenClawConfigLike) => string[];
56
+ resolveAccount: (cfg: OpenClawConfigLike, accountId?: string | null) => CoolclawAccount;
57
+ defaultAccountId: () => string;
58
+ isConfigured: (account: CoolclawAccount) => boolean;
59
+ isEnabled: (account: CoolclawAccount | undefined) => boolean;
60
+ describeAccount: (account: CoolclawAccount) => Record<string, unknown>;
61
+ };
62
+ resolver: {
63
+ resolveTargets: (params: {
64
+ inputs: string[];
65
+ kind: "user" | "group";
66
+ }) => Promise<Array<Record<string, unknown>>>;
67
+ };
68
+ messaging: {
69
+ normalizeTarget: (raw: string) => string | undefined;
70
+ inferTargetChatType: (params: {
71
+ to: string;
72
+ }) => "direct" | "group" | undefined;
73
+ targetResolver: {
74
+ looksLikeId: (raw: string, normalized?: string) => boolean;
75
+ hint: string;
76
+ resolveTarget: (params: {
77
+ cfg?: OpenClawConfigLike;
78
+ accountId?: string | null;
79
+ input: string;
80
+ normalized: string;
81
+ preferredKind?: CoolclawOpenClawTargetKind;
82
+ }) => Promise<{
83
+ to: string;
84
+ kind: CoolclawOpenClawTargetKind;
85
+ display?: string;
86
+ source?: "normalized" | "directory";
87
+ } | null>;
88
+ };
89
+ };
90
+ outbound: {
91
+ deliveryMode: "direct";
92
+ resolveTarget: (params: {
93
+ to?: string;
94
+ }) => {
95
+ ok: true;
96
+ to: string;
97
+ } | {
98
+ ok: false;
99
+ error: Error;
100
+ };
101
+ sendText: (ctx: {
102
+ cfg: OpenClawConfigLike;
103
+ accountId?: string | null;
104
+ to: string;
105
+ text: string;
106
+ }) => Promise<Record<string, unknown>>;
107
+ };
108
+ status: (source?: unknown) => CoolclawStatus;
109
+ gateway: {
110
+ startAccount: (ctx: any) => Promise<unknown>;
111
+ };
112
+ };
113
+ declare const coolclawChannelPlugin: CoolclawChannelPlugin;
114
+
115
+ export { coolclawChannelPlugin as c };