@flomesh/ztm-chat 2026.2.15

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.
Files changed (3) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +865 -0
  3. package/package.json +65 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 flomesh-io
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,865 @@
1
+ # ZTM Chat Channel Plugin for OpenClaw
2
+
3
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/flomesh-io/openclaw-channel-plugin-ztm/test.yml)](https://github.com/flomesh-io/openclaw-channel-plugin-ztm/actions)
4
+ [![Test Coverage](https://img.shields.io/badge/coverage-66%25-yellow)](https://github.com/flomesh-io/openclaw-channel-plugin-ztm)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green)](LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178c6)](https://www.typescriptlang.org/)
7
+ [![Release Version](https://img.shields.io/github/v/release/flomesh-io/openclaw-channel-plugin-ztm?sort=date)](https://github.com/flomesh-io/openclaw-channel-plugin-ztm/releases/latest)
8
+
9
+ This plugin integrates OpenClaw with ZTM (Zero Trust Mesh) Chat, enabling decentralized P2P messaging through the ZTM network.
10
+
11
+ ## Architecture
12
+
13
+ ```mermaid
14
+ flowchart TB
15
+ subgraph ZTM["ZTM Network"]
16
+ User["ZTM User"]
17
+ Agent["ZTM Agent"]
18
+ end
19
+
20
+ subgraph OpenClaw["OpenClaw Gateway"]
21
+ Plugin["ztm-chat Plugin"]
22
+ Dispatcher["Message Dispatcher"]
23
+ AgentLLM["AI Agent"]
24
+ end
25
+
26
+ subgraph Storage["Local Storage"]
27
+ State["Message State"]
28
+ Pairing["Pairing Store"]
29
+ end
30
+
31
+ User -->|"DM/Group Message"| Agent
32
+ Agent -->|"Chat App API"| Plugin
33
+ Plugin -->|"Route"| Dispatcher
34
+ Dispatcher -->|"Check Policy"| AgentLLM
35
+ AgentLLM -->|"Response"| Plugin
36
+ Plugin -->|"Chat App API"| Agent
37
+ Agent -->|"Deliver"| User
38
+
39
+ Plugin --> State
40
+ Plugin --> Pairing
41
+ ```
42
+
43
+ **Data Flow:**
44
+ 1. User sends message to ZTM Agent
45
+ 2. Plugin polls Chat App API for new messages
46
+ 3. Dispatcher checks DM/Group policy
47
+ 4. If allowed, route to AI Agent
48
+ 5. AI Agent generates response
49
+ 6. Plugin sends response via Chat App API
50
+ 7. ZTM Agent delivers to user
51
+
52
+ ## Features
53
+
54
+ - **Peer-to-Peer Messaging**: Send and receive messages with other ZTM users
55
+ - **Remote Connection**: Connect to ZTM Agent from anywhere via HTTP API
56
+ - **Secure**: Supports mTLS authentication with ZTM certificates
57
+ - **Decentralized**: Messages flow through the ZTM P2P network
58
+ - **Multi-Account**: Support for multiple ZTM bot accounts with isolated state
59
+ - **User Discovery**: Browse and discover other users in your ZTM mesh
60
+ - **Real-Time Updates**: Watch mechanism with polling fallback
61
+ - **Message Deduplication**: Prevents duplicate message processing
62
+ - **Structured Logging**: Context-aware logger with sensitive data filtering
63
+ - **Interactive Wizard**: CLI-guided configuration setup
64
+ - **Group Chat Support**: Multi-user group conversations with permission control
65
+ - **Fine-Grained Access Control**: Per-group policies, mention gating, and tool restrictions
66
+
67
+ ## Installation
68
+
69
+ ### 1. Install ZTM CLI
70
+
71
+ Download ZTM from GitHub releases and install to `/usr/local/bin`:
72
+
73
+ ```bash
74
+ # Download (example: v1.0.4 for Linux x86_64)
75
+ curl -L "https://github.com/flomesh-io/ztm/releases/download/v1.0.4/ztm-aio-v1.0.4-generic_linux-x86_64.tar.gz" -o /tmp/ztm.tar.gz
76
+
77
+ # Extract
78
+ tar -xzf /tmp/ztm.tar.gz -C /tmp
79
+
80
+ # Install to /usr/local/bin (requires sudo)
81
+ sudo mv /tmp/bin/ztm /usr/local/bin/ztm
82
+
83
+ # Cleanup
84
+ rm /tmp/ztm.tar.gz
85
+
86
+ # Verify
87
+ ztm version
88
+ ```
89
+
90
+ ### 2. Start ZTM Agent
91
+
92
+ ```bash
93
+ ztm start agent
94
+ ```
95
+
96
+ The agent will start listening on `http://localhost:7777` by default.
97
+
98
+ ### 3. Install Plugin
99
+
100
+ ```bash
101
+ openclaw plugins install -l .
102
+
103
+ # Or install from npm (when published)
104
+ # npm install -g @ztm/openclaw-ztm-chat
105
+ # openclaw plugins install @ztm/openclaw-ztm-chat
106
+ ```
107
+
108
+ ### 4. Run Configuration Wizard
109
+
110
+ ```bash
111
+ openclaw ztm-chat-wizard
112
+ ```
113
+
114
+ The wizard will guide you through:
115
+ 1. **ZTM Agent URL** (default: `http://localhost:7777`)
116
+ 2. **Permit Server URL** (default: `https://ztm-portal.flomesh.io:7779/permit`)
117
+ 3. **Bot Username** (default: `openclaw-bot`)
118
+ 4. **Security Settings**
119
+ - DM Policy: `pairing` (recommended), `allow`, or `deny`
120
+ - Allow From: Whitelist of usernames (or `*` for all)
121
+ 5. **Group Chat Settings** (if enabled)
122
+ - Enable Groups: Yes/No
123
+ - Group Policy: `allowlist`, `open`, or `disabled`
124
+ - Require Mention: Yes/No (default: Yes)
125
+ 6. **Summary & Save**
126
+
127
+ ### 5. Restart OpenClaw
128
+
129
+ ```bash
130
+ openclaw gateway restart
131
+ ```
132
+
133
+ ## Group Chat
134
+
135
+ ### Overview
136
+
137
+ ZTM Chat supports group conversations with fine-grained permission control. When `enableGroups` is enabled, the bot can:
138
+
139
+ - Receive and process messages from group chats
140
+ - Reply to group messages with @mention support
141
+ - Apply per-group access policies
142
+ - Restrict available tools based on group membership
143
+
144
+ ### How It Works
145
+
146
+ ```mermaid
147
+ flowchart LR
148
+ subgraph Group["Group Chat"]
149
+ User1["Member 1"]
150
+ User2["Member 2"]
151
+ User3["Member 3"]
152
+ end
153
+
154
+ subgraph ZTM["ZTM Agent"]
155
+ Agent[("Chat API")]
156
+ end
157
+
158
+ User1 -.->|"@mention"| Agent
159
+ User2 -.->|"@mention"| Agent
160
+ User3 -.->|"@mention"| Agent
161
+
162
+ Agent -->|"Poll messages"| Plugin
163
+ Plugin -->|"Check policy"| Plugin
164
+ Plugin -->|"AI Response"| Agent
165
+ Agent -->|"Deliver"| Group
166
+ ```
167
+
168
+ ### Enabling Group Chat
169
+
170
+ ```bash
171
+ # Enable via wizard
172
+ openclaw ztm-chat-wizard
173
+ # Select "Enable Groups" when prompted
174
+
175
+ # Or manually in openclaw.yaml
176
+ ```
177
+
178
+ ### Group Policy Modes
179
+
180
+ | Policy | Behavior |
181
+ |--------|----------|
182
+ | `open` | Allow all group messages (with optional mention requirement) |
183
+ | `allowlist` | Only allow whitelisted senders |
184
+ | `disabled` | Block all group messages |
185
+
186
+ ### Mention Gating
187
+
188
+ When `requireMention` is enabled (default), the bot will only process messages that @mention the bot username:
189
+
190
+ ```
191
+ # Bot username: my-bot
192
+
193
+ # These messages will be processed:
194
+ @my-bot can you help me?
195
+ Hey @my-bot what's up?
196
+
197
+ # These messages will be ignored:
198
+ hello everyone!
199
+ good morning
200
+ ```
201
+
202
+ **Note:** `requireMention` applies to ALL users, including the group creator. This ensures even the group owner must explicitly mention the bot to trigger a response.
203
+
204
+ ### Per-Group Configuration
205
+
206
+ You can configure different policies for different groups:
207
+
208
+ ```yaml
209
+ channels:
210
+ ztm-chat:
211
+ accounts:
212
+ my-bot:
213
+ enableGroups: true
214
+ groupPolicy: allowlist # Default for unknown groups
215
+ requireMention: true # Global default (can be overridden per group)
216
+ groupPermissions:
217
+ alice/team:
218
+ groupPolicy: open
219
+ requireMention: false
220
+ bob/project-x:
221
+ groupPolicy: allowlist
222
+ requireMention: true
223
+ allowFrom: [bob, charlie, david]
224
+ private/secret-group:
225
+ groupPolicy: disabled
226
+ ```
227
+
228
+ ### Tool Restrictions
229
+
230
+ Control which tools are available in each group:
231
+
232
+ ```yaml
233
+ channels:
234
+ ztm-chat:
235
+ accounts:
236
+ my-bot:
237
+ groupPermissions:
238
+ alice/team:
239
+ groupPolicy: open
240
+ requireMention: false
241
+ tools:
242
+ allow:
243
+ - group:messaging
244
+ - group:sessions
245
+ - group:runtime
246
+ toolsBySender:
247
+ admin:
248
+ alsoAllow:
249
+ - exec
250
+ - fs
251
+ ```
252
+
253
+ #### Tool Policy Options
254
+
255
+ | Option | Description |
256
+ |--------|-------------|
257
+ | `tools.allow` | Only allow these tools (deny all others) |
258
+ | `tools.deny` | Deny these tools (allow all others) |
259
+ | `toolsBySender.{user}.alsoAllow` | Additional tools for specific users |
260
+ | `toolsBySender.{user}.deny` | Deny tools for specific users |
261
+
262
+ #### Default Tools
263
+
264
+ By default, groups only have access to:
265
+ - `group:messaging` - Send/receive messages
266
+ - `group:sessions` - Session management
267
+
268
+ ### Creator Privileges
269
+
270
+ Group creators have special privileges that allow them to bypass certain policy checks:
271
+
272
+ | Check | Creator Bypass? |
273
+ |-------|---------------|
274
+ | `groupPolicy` (disabled/allowlist/open) | ✅ Yes |
275
+ | `allowFrom` whitelist | ✅ Yes |
276
+ | `requireMention` | ❌ No (still required) |
277
+
278
+ This ensures the bot owner can always interact with their own groups while still requiring explicit @mentions to trigger responses.
279
+
280
+ ## Usage
281
+
282
+ ### Sending a Message
283
+
284
+ From any ZTM user, send a message to your bot:
285
+
286
+ ```
287
+ Hello! Can you help me with something?
288
+ ```
289
+
290
+ The bot will respond through OpenClaw's AI agent.
291
+
292
+ ### Pairing Mode
293
+
294
+ By default, the bot uses **pairing mode** (`dmPolicy: "pairing"`):
295
+
296
+ 1. **New users** must be approved before they can send messages
297
+ 2. When an unapproved user sends a message, the bot sends them a pairing code
298
+ 3. Approve users using the CLI with their pairing code
299
+
300
+ #### List Pending Requests
301
+
302
+ ```bash
303
+ openclaw pairing list ztm-chat
304
+ ```
305
+
306
+ #### Approve a Pairing Request
307
+
308
+ ```bash
309
+ openclaw pairing approve ztm-chat <code>
310
+ ```
311
+
312
+ #### Pairing Mode Policies
313
+
314
+ | Policy | Behavior |
315
+ |--------|----------|
316
+ | `allow` | Accept messages from all users (no approval needed) |
317
+ | `deny` | Reject messages from all users (except allowFrom list) |
318
+ | `pairing` | Require explicit approval for new users (recommended) |
319
+
320
+ ## CLI Commands
321
+
322
+ ### Plugin Commands
323
+
324
+ ```bash
325
+ # Setup wizard
326
+ openclaw ztm-chat-wizard
327
+
328
+ # Auto-discover existing configuration
329
+ openclaw ztm-chat-discover
330
+ ```
331
+
332
+ ### Channel Commands
333
+
334
+ ```bash
335
+ # Check channel status
336
+ openclaw channels status ztm-chat
337
+
338
+ # View configuration
339
+ openclaw channels describe ztm-chat
340
+
341
+ # Probe connection
342
+ openclaw channels status ztm-chat --probe
343
+
344
+ # Enable/disable channel
345
+ openclaw channels disable ztm-chat
346
+ openclaw channels enable ztm-chat
347
+
348
+ # List connected peers
349
+ openclaw channels directory ztm-chat peers
350
+
351
+ # List groups (if enabled)
352
+ openclaw channels directory ztm-chat groups
353
+ ```
354
+
355
+ ### Pairing Commands
356
+
357
+ ```bash
358
+ # List pending pairing requests
359
+ openclaw pairing list ztm-chat
360
+
361
+ # Approve a pairing request
362
+ openclaw pairing approve ztm-chat <code>
363
+ ```
364
+
365
+ ## Configuration
366
+
367
+ ### Configuration File
368
+
369
+ Configuration is stored in `openclaw.yaml` under `channels.ztm-chat`:
370
+
371
+ #### Mode 1: Server (from permit server)
372
+
373
+ ```yaml
374
+ channels:
375
+ ztm-chat:
376
+ enabled: true
377
+ accounts:
378
+ my-bot:
379
+ agentUrl: "http://localhost:7777"
380
+ permitSource: "server"
381
+ permitUrl: "https://ztm-portal.flomesh.io:7779/permit"
382
+ meshName: "production-mesh"
383
+ username: "my-bot"
384
+ enableGroups: true
385
+ autoReply: true
386
+ dmPolicy: "pairing"
387
+ allowFrom:
388
+ - alice
389
+ - trusted-team
390
+ groupPolicy: "allowlist"
391
+ requireMention: true
392
+ groupPermissions:
393
+ alice/team:
394
+ creator: "alice"
395
+ group: "team"
396
+ groupPolicy: "open"
397
+ requireMention: false
398
+ allowFrom: []
399
+ tools:
400
+ ```
401
+
402
+ #### Mode 2: File (from local permit.json)
403
+
404
+ ```yaml
405
+ channels:
406
+ ztm-chat:
407
+ enabled: true
408
+ accounts:
409
+ my-bot:
410
+ agentUrl: "http://localhost:7777"
411
+ permitSource: "file"
412
+ permitFilePath: "/path/to/permit.json"
413
+ meshName: "production-mesh"
414
+ username: "my-bot"
415
+ enableGroups: true
416
+ autoReply: true
417
+ dmPolicy: "pairing"
418
+ allowFrom:
419
+ - alice
420
+ - trusted-team
421
+ groupPolicy: "allowlist"
422
+ requireMention: true
423
+ groupPermissions:
424
+ alice/team:
425
+ creator: "alice"
426
+ group: "team"
427
+ groupPolicy: "open"
428
+ requireMention: false
429
+ allowFrom: []
430
+ tools:
431
+ allow:
432
+ - group:messaging
433
+ - group:sessions
434
+ - group:runtime
435
+ toolsBySender:
436
+ admin:
437
+ alsoAllow:
438
+ - exec
439
+ ```
440
+
441
+ ### Configuration Options
442
+
443
+ **Required:**
444
+
445
+ | Option | Type | Description |
446
+ |--------|------|-------------|
447
+ | `agentUrl` | string | ZTM Agent API URL |
448
+ | `permitSource` | string | Permit source: `"server"` (from permit server) or `"file"` (from local file) |
449
+ | `meshName` | string | Name of your ZTM mesh |
450
+ | `username` | string | Bot's ZTM username |
451
+
452
+ **Required (when permitSource is "server"):**
453
+
454
+ | Option | Type | Description |
455
+ |--------|------|-------------|
456
+ | `permitUrl` | string | Permit Server URL |
457
+
458
+ **Required (when permitSource is "file"):**
459
+
460
+ | Option | Type | Description |
461
+ |--------|------|-------------|
462
+ | `permitFilePath` | string | Path to local permit.json file |
463
+
464
+ **Optional - Basic:**
465
+
466
+ | Option | Type | Default | Description |
467
+ |--------|------|---------|-------------|
468
+ | `enabled` | boolean | `true` | Enable/disable account |
469
+ | `enableGroups` | boolean | `false` | Enable group chat support |
470
+ | `autoReply` | boolean | `true` | Automatically reply to messages |
471
+ | `dmPolicy` | string | `"pairing"` | DM policy: `allow`, `deny`, `pairing` |
472
+ | `allowFrom` | string[] | `[]` | List of approved usernames |
473
+ | `permitFilePath` | string | - | Path to permit.json file (when permitSource is `"file"`) |
474
+
475
+ **Optional - Group:**
476
+
477
+ | Option | Type | Default | Description |
478
+ |--------|------|---------|-------------|
479
+ | `groupPolicy` | string | `"allowlist"` | Default group policy: `open`, `allowlist`, `disabled` |
480
+ | `requireMention` | boolean | `true` | Require @mention for group messages (global default) |
481
+ | `groupPermissions` | object | `{}` | Per-group permission overrides |
482
+
483
+ ### Group Permission Options
484
+
485
+ | Option | Type | Description |
486
+ |--------|------|-------------|
487
+ | `groupPolicy` | string | Policy for this group: `open`, `allowlist`, `disabled` |
488
+ | `requireMention` | boolean | Require @mention to process message (default: `true`) |
489
+ | `allowFrom` | string[] | Whitelist of allowed senders |
490
+ | `tools.allow` | string[] | Only allow these tools |
491
+ | `tools.deny` | string[] | Deny these tools |
492
+ | `toolsBySender` | object | Sender-specific tool overrides |
493
+
494
+ ### Environment Variables
495
+
496
+ | Variable | Description |
497
+ |----------|-------------|
498
+ | `ZTM_CHAT_LOG_LEVEL` | Logging level: `debug`, `info`, `warn`, `error` |
499
+
500
+ ## Message Flow
501
+
502
+ ### Direct Message (DM)
503
+
504
+ ```mermaid
505
+ sequenceDiagram
506
+ participant U as ZTM User
507
+ participant A as ZTM Agent
508
+ participant P as Plugin
509
+ participant B as AI Agent
510
+
511
+ U->>A: 1. Send DM to bot
512
+ A->>A: 2. Store message
513
+ P->>A: 3. Poll /api/meshes/{mesh}/apps/ztm/chat/api/peers/{bot}/messages
514
+ A->>P: 4. Return new messages
515
+ P->>P: 5. Check DM policy (allow/deny/pairing)
516
+ alt Policy allows
517
+ P->>B: 6. Route to AI agent
518
+ B->>P: 7. Generate response
519
+ P->>A: 8. Send via Chat App API
520
+ A->>U: 9. Deliver to recipient
521
+ else Policy denied
522
+ P->>P: 6. Ignore message
523
+ end
524
+ ```
525
+
526
+ ### Group Message
527
+
528
+ ```mermaid
529
+ sequenceDiagram
530
+ participant M as ZTM Member
531
+ participant A as ZTM Agent
532
+ participant P as Plugin
533
+ participant B as AI Agent
534
+
535
+ M->>A: 1. Send @mention to group
536
+ A->>A: 2. Store message
537
+ P->>A: 3. Poll Chat App API for new messages
538
+ A->>P: 4. Return new messages
539
+ P->>P: 5. Get group permissions (creator/groupId)
540
+ P->>P: 6. Check: creator? → allow
541
+ P->>P: 7. Check: policy (open/allowlist/disabled)
542
+ P->>P: 8. Check: allowFrom whitelist
543
+ P->>P: 9. Check: requireMention (@{bot})
544
+ alt All checks pass
545
+ P->>B: 10. Route to AI agent (with tools filter)
546
+ B->>P: 11. Generate response
547
+ P->>A: 12. Send reply to group
548
+ A->>M: 13. Deliver to all members
549
+ else Any check fails
550
+ P->>P: Log and ignore message
551
+ end
552
+ ```
553
+
554
+ ### Message Processing Pipeline
555
+
556
+ ```mermaid
557
+ flowchart TD
558
+ A[Incoming Message] --> B{isGroup?}
559
+
560
+ B -->|No| C[DM Flow]
561
+ B -->|Yes| D[Group Flow]
562
+
563
+ C --> C1{DM Policy}
564
+ C1 -->|allow| E[Route to AI]
565
+ C1 -->|deny| F[Ignore]
566
+ C1 -->|pairing| G{Paired?}
567
+ G -->|Yes| E
568
+ G -->|No| H[Send Pairing Request]
569
+
570
+ D --> D1{Get Group Permissions}
571
+ D1 --> D2{Is Creator?}
572
+ D2 -->|Yes| E
573
+ D2 -->|No| D3{Policy}
574
+ D3 -->|disabled| F
575
+ D3 -->|allowlist| D4{In allowFrom?}
576
+ D3 -->|open| D5{requireMention?}
577
+ D4 -->|Yes| E
578
+ D4 -->|No| F
579
+ D5 -->|Yes| D6{Mention?}
580
+ D5 -->|No| E
581
+ D6 -->|Yes| E
582
+ D6 -->|No| F
583
+
584
+ E --> E1{Resolve Agent Route}
585
+ E1 --> E2{Dispatch to Agent}
586
+ E2 --> E3{Filter Tools}
587
+
588
+ E3 --> I[Generate Response]
589
+ I --> J{Send Response}
590
+ J -->|DM| J1[sendZTMMessage]
591
+ J -->|Group| J2[sendGroupMessage]
592
+
593
+ F --> K[Log and Ignore]
594
+ H --> K
595
+ ```
596
+
597
+ ### Policy Decision Matrix
598
+
599
+ **DM Policy Check Order:**
600
+
601
+ | Step | Condition | Next Step |
602
+ |------|-----------|-----------|
603
+ | 1 | Empty sender | → Deny (ignore) |
604
+ | 2 | Sender in `allowFrom` config | → Allow (whitelisted) |
605
+ | 3 | Sender in pairing store | → Allow (whitelisted) |
606
+ | 4 | Policy = `allow` | → Allow (allowed) |
607
+ | 5 | Policy = `deny` | → Deny (denied) |
608
+ | 6 | Policy = `pairing` | → Send pairing request |
609
+
610
+ **Group Policy Check Order:**
611
+
612
+ | Step | Condition | Next Step |
613
+ |------|-----------|-----------|
614
+ | 1 | Empty sender | → Deny (ignore) |
615
+ | 2 | Sender = creator | → Step 6 (bypass policy) |
616
+ | 3 | groupPolicy = `disabled` | → Deny (denied) |
617
+ | 4 | groupPolicy = `allowlist` + not in allowFrom | → Deny (whitelisted) |
618
+ | 5 | groupPolicy = `open` | → Continue |
619
+ | 6 | requireMention = true + no @mention | → Deny (mention_required) |
620
+ | 7 | All checks passed | → Allow (creator/whitelisted/allowed) |
621
+
622
+ **Result Actions:**
623
+
624
+ | Action | Description |
625
+ |--------|-------------|
626
+ | `process` | Message allowed, route to AI agent |
627
+ | `ignore` | Message denied, log and discard |
628
+ | `pairing` | Send pairing request to user |
629
+
630
+ ## ZTM API
631
+
632
+ The plugin uses the ZTM Agent API for identity/mesh operations and the Chat App API for messaging:
633
+
634
+ ### Agent API (Identity & Mesh)
635
+
636
+ | Method | Path | Description |
637
+ |--------|------|-------------|
638
+ | GET | `/api/identity` | Get agent identity (certificate) |
639
+ | GET | `/api/meshes/{meshName}` | Get mesh connection status |
640
+ | POST | `/api/meshes/{meshName}` | Join mesh with permit data |
641
+
642
+ ### Chat App API
643
+
644
+ | Method | Path | Description |
645
+ |--------|------|-------------|
646
+ | GET | `/api/meshes/{meshName}/apps/ztm/chat/api/users` | List all users in mesh |
647
+ | GET | `/api/meshes/{meshName}/apps/ztm/chat/api/chats` | Get all chats (DMs and groups) |
648
+ | GET | `/api/meshes/{meshName}/apps/ztm/chat/api/peers/{peer}/messages` | Get peer messages (with since/before) |
649
+ | POST | `/api/meshes/{meshName}/apps/ztm/chat/api/peers/{peer}/messages` | Send message to peer |
650
+ | GET | `/api/meshes/{meshName}/apps/ztm/chat/api/groups/{creator}/{group}/messages` | Get group messages |
651
+ | POST | `/api/meshes/{meshName}/apps/ztm/chat/api/groups/{creator}/{group}/messages` | Send message to group |
652
+
653
+ ### Message API Parameters
654
+
655
+ | Parameter | Type | Description |
656
+ |-----------|------|-------------|
657
+ | `since` | number | Get messages after this timestamp (Unix ms) |
658
+ | `before` | number | Get messages before this timestamp (Unix ms) |
659
+ | `limit` | number | Maximum number of messages to return (default: 50) |
660
+
661
+ ### Example API Calls
662
+
663
+ ```bash
664
+ # Get agent identity (certificate)
665
+ curl http://localhost:7777/api/identity
666
+
667
+ # Get mesh status
668
+ curl http://localhost:7777/api/meshes/openclaw-mesh
669
+
670
+ # Join mesh (with permit data)
671
+ curl -X POST http://localhost:7777/api/meshes/openclaw-mesh \
672
+ -H "Content-Type: application/json" \
673
+ -d '{"ca":"...","agent":{"certificate":"..."},"bootstraps":["host:port"]}'
674
+
675
+ # List users
676
+ curl http://localhost:7777/api/meshes/openclaw-mesh/apps/ztm/chat/api/users
677
+
678
+ # Get peer messages (last 10)
679
+ curl "http://localhost:7777/api/meshes/openclaw-mesh/apps/ztm/chat/api/peers/alice/messages?limit=10"
680
+
681
+ # Send message to peer
682
+ curl -X POST http://localhost:7777/api/meshes/openclaw-mesh/apps/ztm/chat/api/peers/alice/messages \
683
+ -H "Content-Type: application/json" \
684
+ -d '{"text": "Hello!"}'
685
+
686
+ # Get group messages
687
+ curl "http://localhost:7777/api/meshes/openclaw-mesh/apps/ztm/chat/api/groups/alice/team/messages"
688
+
689
+ # Send message to group
690
+ curl -X POST http://localhost:7777/api/meshes/openclaw-mesh/apps/ztm/chat/api/groups/alice/team/messages \
691
+ -H "Content-Type: application/json" \
692
+ -d '{"text": "Hello everyone!"}'
693
+ ```
694
+
695
+ ## Troubleshooting
696
+
697
+ ### Connection Failed
698
+
699
+ 1. Verify ZTM Agent is running:
700
+ ```bash
701
+ curl http://localhost:7777/api/meshes
702
+ ```
703
+
704
+ 2. Check mesh name matches:
705
+ ```bash
706
+ curl http://localhost:7777/api/meshes
707
+ ```
708
+
709
+ 3. Check plugin logs:
710
+ ```bash
711
+ openclaw logs --level debug --channel ztm-chat
712
+ ```
713
+
714
+ ### No Messages Received
715
+
716
+ 1. Check bot username is correct in configuration
717
+ 2. Verify ZTM Agent is running:
718
+ ```bash
719
+ curl http://localhost:7777/api/meshes
720
+ ```
721
+ 3. Check mesh connectivity:
722
+ ```bash
723
+ openclaw channels status ztm-chat --probe
724
+ ```
725
+
726
+ ## Development
727
+
728
+ ### Running Tests
729
+
730
+ ```bash
731
+ npm install
732
+ npm test # Run all tests
733
+ npm test:watch # Watch mode
734
+ ```
735
+
736
+ ### Test Coverage
737
+
738
+ ```
739
+ Test Files 59 passed (59)
740
+ Tests 1354 passed (1354)
741
+
742
+ Coverage: ~70% Statements | ~60% Branches | ~65% Functions | ~70% Lines
743
+
744
+ Coverage Areas:
745
+ - Group Policy: Creator bypass, requireMention, allowlist, open/disabled modes
746
+ - DM Policy: allow/deny/pairing modes, pairing flow
747
+ - Configuration: Schema validation, defaults, helpers
748
+ - Onboarding: Wizard flow, buildConfig
749
+ - Messaging: Processing, dispatch, deduplication, polling, watcher
750
+ - Runtime: State management, pairing store, persistence, caching
751
+ - API: ZTM client, mesh connectivity, permit
752
+ - Utils: Logger, retry, validation, result handling, concurrency
753
+ - Channel: Gateway, plugin, config
754
+ - DI: Container, dependency resolution
755
+ - Types: Result, common utilities, errors
756
+ ```
757
+
758
+ ### Debug Logging
759
+
760
+ ```bash
761
+ ZTM_CHAT_LOG_LEVEL=debug openclaw restart
762
+ ```
763
+
764
+ ## Project Structure
765
+
766
+ ```
767
+ .
768
+ ├── index.ts # Plugin entry point
769
+ ├── index.test.ts # Plugin tests
770
+ ├── package.json # NPM package config
771
+ ├── openclaw.plugin.json # OpenClaw plugin manifest
772
+ ├── tsconfig.json # TypeScript config
773
+ ├── vitest.config.ts # Test config
774
+ ├── eslint.config.js # ESLint config
775
+ ├── prettier.config.js # Prettier config
776
+ └── src/
777
+ ├── api/ # ZTM API client
778
+ │ ├── ztm-api.ts # Main API client factory
779
+ │ ├── chat-api.ts # Send/receive messages
780
+ │ ├── message-api.ts # Message operations (list, read, delete)
781
+ │ ├── mesh-api.ts # Mesh network operations
782
+ │ ├── file-api.ts # File transfers
783
+ │ ├── request.ts # HTTP request utilities with retry
784
+ │ ├── test-utils.ts # Test utilities for API
785
+ │ └── index.ts # Barrel exports
786
+ ├── channel/ # OpenClaw channel adapter
787
+ │ ├── plugin.ts # Main plugin definition
788
+ │ ├── gateway.ts # Account lifecycle
789
+ │ ├── config.ts # Account configuration resolution
790
+ │ ├── state.ts # Account state management
791
+ │ ├── connectivity-manager.ts # Mesh connectivity monitoring
792
+ │ ├── message-dispatcher.ts # Message dispatch to callbacks
793
+ │ └── index.ts # Barrel exports
794
+ ├── config/ # Configuration
795
+ │ ├── schema.ts # TypeBox schema definitions
796
+ │ ├── defaults.ts # Default values
797
+ │ ├── validation.ts # Config validation
798
+ │ ├── helpers.ts # Config helpers
799
+ │ └── index.ts # Barrel exports
800
+ ├── connectivity/ # Network connectivity
801
+ │ ├── mesh.ts # Mesh operations
802
+ │ ├── permit.ts # Permit management
803
+ │ └── index.ts # Barrel exports
804
+ ├── core/ # Core business logic
805
+ │ ├── group-policy.ts # Group permissions
806
+ │ ├── dm-policy.ts # DM policy
807
+ │ └── index.ts # Barrel exports
808
+ ├── di/ # Dependency injection
809
+ │ ├── container.ts # DI container
810
+ │ ├── index.ts # Service factories & barrel exports
811
+ │ └── example-usage.ts # Usage examples
812
+ ├── messaging/ # Message processing
813
+ │ ├── processor.ts # Message validation & normalization
814
+ │ ├── chat-processor.ts # High-level chat processing
815
+ │ ├── message-processor-helpers.ts # Shared utilities
816
+ │ ├── dispatcher.ts # Policy checking & dispatch
817
+ │ ├── outbound.ts # Send messages
818
+ │ ├── watcher.ts # Watch mechanism
819
+ │ ├── polling.ts # Polling fallback
820
+ │ ├── index.ts # Barrel exports
821
+ │ └── *.test.ts # Test files
822
+ ├── onboarding/ # Setup wizard
823
+ │ ├── onboarding.ts # CLI wizard implementation
824
+ │ └── index.ts # Barrel exports
825
+ ├── runtime/ # Runtime management
826
+ │ ├── runtime.ts # Runtime provider interface
827
+ │ ├── state.ts # Account runtime state
828
+ │ ├── store.ts # Message state persistence
829
+ │ ├── pairing-store.ts # Pairing request persistence
830
+ │ ├── cache.ts # LRU cache for group permissions
831
+ │ ├── repository.ts # Repository interfaces
832
+ │ ├── repository-impl.ts # Repository implementations
833
+ │ └── index.ts # Barrel exports
834
+ ├── types/ # TypeScript types
835
+ │ ├── api.ts # ZTM API types
836
+ │ ├── config.ts # Configuration types
837
+ │ ├── common.ts # Common types (Result, etc)
838
+ │ ├── errors.ts # Custom error classes
839
+ │ ├── group-policy.ts # Group policy types
840
+ │ ├── messaging.ts # Message types
841
+ │ ├── runtime.ts # Runtime types
842
+ │ ├── connectivity.ts # Connectivity types
843
+ │ └── index.ts # Barrel exports
844
+ ├── utils/ # Utilities
845
+ │ ├── logger.ts # Context-aware logger
846
+ │ ├── validation.ts # Input validation
847
+ │ ├── retry.ts # Retry utilities
848
+ │ ├── result.ts # Result/Either type
849
+ │ ├── error.ts # Error handling
850
+ │ ├── guards.ts # Type guards
851
+ │ ├── concurrency.ts # Concurrency utilities
852
+ │ ├── log-sanitize.ts # Log sanitization
853
+ │ ├── paths.ts # Path utilities
854
+ │ ├── time-boundaries.ts # Time utilities
855
+ │ └── index.ts # Barrel exports
856
+ ├── mocks/ # Test mocks
857
+ │ ├── ztm-client.ts # Mock ZTM client
858
+ │ └── index.ts # Barrel exports
859
+ └── test-utils/ # Test utilities
860
+ ├── fixtures.ts # Test fixtures
861
+ ├── mocks.ts # Test mocks
862
+ ├── helpers.ts # Test helpers
863
+ ├── vitest-setup.ts # Vitest setup
864
+ └── index.ts # Barrel exports
865
+ ```
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@flomesh/ztm-chat",
3
+ "version": "2026.2.15",
4
+ "description": "ZTM Chat channel plugin for OpenClaw",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "overrides": {
18
+ "tar": ">=7.5.7"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "typecheck": "tsc --noEmit",
25
+ "lint": "eslint src --ext .ts",
26
+ "format": "prettier --write \"src/**/*.ts\"",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "dependencies": {
30
+ "@sinclair/typebox": "^0.34.48",
31
+ "openclaw": "^2026.2.9"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^24.10.13",
35
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
36
+ "@typescript-eslint/parser": "^8.0.0",
37
+ "@vitest/coverage-v8": "^4.0.18",
38
+ "eslint": "^9.0.0",
39
+ "prettier": "^3.0.0",
40
+ "typescript": "^5.9.3",
41
+ "vitest": "^4.0.18"
42
+ },
43
+ "openclaw": {
44
+ "extensions": [
45
+ "./index.ts"
46
+ ],
47
+ "channel": {
48
+ "id": "ztm-chat",
49
+ "label": "ZTM Chat",
50
+ "selectionLabel": "ZTM Chat",
51
+ "blurb": "Decentralized P2P messaging via ZTM network",
52
+ "aliases": ["ztm"],
53
+ "order": 40,
54
+ "quickstartAllowFrom": true
55
+ },
56
+ "install": {
57
+ "npmSpec": "@flomesh/ztm-chat",
58
+ "localPath": "extensions/ztm-chat",
59
+ "defaultChoice": "npm"
60
+ }
61
+ },
62
+ "publishConfig": {
63
+ "access": "public"
64
+ }
65
+ }