@invago/mixin 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 +328 -4
- package/README.zh-CN.md +386 -69
- package/package.json +79 -1
- package/src/blaze-service.ts +24 -7
- package/src/channel.ts +185 -42
- package/src/config-schema.ts +36 -1
- package/src/config.ts +103 -10
- package/src/crypto.ts +5 -0
- package/src/inbound-handler.ts +1205 -576
- package/src/mixpay-service.ts +211 -0
- package/src/mixpay-store.ts +205 -0
- package/src/mixpay-worker.ts +353 -0
- package/src/outbound-plan.ts +216 -0
- package/src/reply-format.ts +89 -24
- package/src/runtime.ts +26 -0
- package/src/send-service.ts +35 -27
- package/src/shared.ts +25 -0
- package/src/status.ts +114 -0
- package/src/decrypt.ts +0 -126
package/README.md
CHANGED
|
@@ -24,6 +24,18 @@ openclaw plugins install @invago/mixin
|
|
|
24
24
|
|
|
25
25
|
`@invago/mixin` is the published npm package name. The OpenClaw runtime/plugin name remains `mixin`.
|
|
26
26
|
|
|
27
|
+
If the plugin is already installed, upgrade it with the plugin id:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
openclaw plugins update mixin
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To install a specific version for the first time:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
openclaw plugins install @invago/mixin@<version>
|
|
37
|
+
```
|
|
38
|
+
|
|
27
39
|
Then confirm the plugin is installed:
|
|
28
40
|
|
|
29
41
|
```bash
|
|
@@ -64,13 +76,29 @@ Edit your `openclaw.json` file manually and add both the channel configuration a
|
|
|
64
76
|
{
|
|
65
77
|
"channels": {
|
|
66
78
|
"mixin": {
|
|
67
|
-
"
|
|
79
|
+
"defaultAccount": "default",
|
|
68
80
|
"appId": "YOUR_APP_ID",
|
|
69
81
|
"sessionId": "YOUR_SESSION_ID",
|
|
70
82
|
"serverPublicKey": "YOUR_SERVER_PUBLIC_KEY_BASE64",
|
|
71
83
|
"sessionPrivateKey": "YOUR_SESSION_PRIVATE_KEY_BASE64",
|
|
72
84
|
"dmPolicy": "pairing",
|
|
73
85
|
"allowFrom": ["AUTHORIZED_USER_UUID"],
|
|
86
|
+
"requireMentionInGroup": true,
|
|
87
|
+
"mediaBypassMentionInGroup": true,
|
|
88
|
+
"mediaMaxMb": 30,
|
|
89
|
+
"audioSendAsVoiceByDefault": true,
|
|
90
|
+
"audioAutoDetectDuration": true,
|
|
91
|
+
"audioRequireFfprobe": false,
|
|
92
|
+
"mixpay": {
|
|
93
|
+
"enabled": true,
|
|
94
|
+
"payeeId": "YOUR_MIXPAY_PAYEE_ID",
|
|
95
|
+
"defaultSettlementAssetId": "YOUR_SETTLEMENT_ASSET_ID",
|
|
96
|
+
"expireMinutes": 15,
|
|
97
|
+
"pollIntervalSec": 30,
|
|
98
|
+
"allowedCreators": ["AUTHORIZED_USER_UUID"],
|
|
99
|
+
"notifyOnPending": false,
|
|
100
|
+
"notifyOnPaidLess": true
|
|
101
|
+
},
|
|
74
102
|
"proxy": {
|
|
75
103
|
"enabled": true,
|
|
76
104
|
"url": "socks5://127.0.0.1:10808",
|
|
@@ -136,18 +164,134 @@ Recommended configuration:
|
|
|
136
164
|
|
|
137
165
|
Use `per-account-channel-peer` instead if you run multiple Mixin accounts and want direct-message sessions isolated by both channel and account.
|
|
138
166
|
|
|
167
|
+
## Multi-Agent Routing Per Bot Account
|
|
168
|
+
|
|
169
|
+
OpenClaw supports routing different channel accounts to different agents through `bindings[].match.accountId`.
|
|
170
|
+
|
|
171
|
+
Recommended pattern:
|
|
172
|
+
|
|
173
|
+
- One Mixin bot account = one `accountId`
|
|
174
|
+
- One `accountId` = one agent binding
|
|
175
|
+
- Keep session isolation at `per-account-channel-peer` when you run multiple bot accounts
|
|
176
|
+
|
|
177
|
+
Example:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"session": {
|
|
182
|
+
"dmScope": "per-account-channel-peer"
|
|
183
|
+
},
|
|
184
|
+
"agents": {
|
|
185
|
+
"list": [
|
|
186
|
+
{
|
|
187
|
+
"id": "main",
|
|
188
|
+
"workspace": "E:/AI/workspace-main",
|
|
189
|
+
"default": true
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "sales",
|
|
193
|
+
"workspace": "E:/AI/workspace-sales"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"id": "support",
|
|
197
|
+
"workspace": "E:/AI/workspace-support"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
"bindings": [
|
|
202
|
+
{
|
|
203
|
+
"agentId": "main",
|
|
204
|
+
"match": {
|
|
205
|
+
"channel": "mixin",
|
|
206
|
+
"accountId": "default"
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"agentId": "sales",
|
|
211
|
+
"match": {
|
|
212
|
+
"channel": "mixin",
|
|
213
|
+
"accountId": "sales"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"agentId": "support",
|
|
218
|
+
"match": {
|
|
219
|
+
"channel": "mixin",
|
|
220
|
+
"accountId": "support"
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
],
|
|
224
|
+
"channels": {
|
|
225
|
+
"mixin": {
|
|
226
|
+
"defaultAccount": "default",
|
|
227
|
+
"accounts": {
|
|
228
|
+
"default": {
|
|
229
|
+
"name": "Main Bot",
|
|
230
|
+
"appId": "APP_ID_1",
|
|
231
|
+
"sessionId": "SESSION_ID_1",
|
|
232
|
+
"serverPublicKey": "SERVER_PUBLIC_KEY_1",
|
|
233
|
+
"sessionPrivateKey": "SESSION_PRIVATE_KEY_1"
|
|
234
|
+
},
|
|
235
|
+
"sales": {
|
|
236
|
+
"name": "Sales Bot",
|
|
237
|
+
"appId": "APP_ID_2",
|
|
238
|
+
"sessionId": "SESSION_ID_2",
|
|
239
|
+
"serverPublicKey": "SERVER_PUBLIC_KEY_2",
|
|
240
|
+
"sessionPrivateKey": "SESSION_PRIVATE_KEY_2"
|
|
241
|
+
},
|
|
242
|
+
"support": {
|
|
243
|
+
"name": "Support Bot",
|
|
244
|
+
"appId": "APP_ID_3",
|
|
245
|
+
"sessionId": "SESSION_ID_3",
|
|
246
|
+
"serverPublicKey": "SERVER_PUBLIC_KEY_3",
|
|
247
|
+
"sessionPrivateKey": "SESSION_PRIVATE_KEY_3"
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Notes:
|
|
256
|
+
|
|
257
|
+
- `match.accountId` binds one Mixin bot account to one agent.
|
|
258
|
+
- If `accountId` is omitted in a binding, OpenClaw treats it as the default account only.
|
|
259
|
+
- Use `accountId: "*"` only when you want one fallback agent for all Mixin accounts.
|
|
260
|
+
- If you need one specific group or DM to override the account-level routing, add a more specific `match.peer` binding. Peer matches win over `accountId` matches.
|
|
261
|
+
|
|
139
262
|
## Configuration Reference
|
|
140
263
|
|
|
141
264
|
| Parameter | Required | Default | Description |
|
|
142
265
|
|-----------|----------|---------|-------------|
|
|
143
|
-
| `
|
|
266
|
+
| `defaultAccount` | No | `default` | Default account ID used when `accounts` is configured |
|
|
144
267
|
| `appId` | Yes | - | Mixin App UUID |
|
|
145
268
|
| `sessionId` | Yes | - | Session UUID |
|
|
146
269
|
| `serverPublicKey` | Yes | - | Server Public Key (Base64) |
|
|
147
270
|
| `sessionPrivateKey` | Yes | - | Session Private Key (Ed25519 Base64) |
|
|
148
271
|
| `dmPolicy` | No | `pairing` | Direct-message policy: `pairing`, `allowlist`, `open`, or `disabled` |
|
|
149
272
|
| `allowFrom` | No | `[]` | Authorized user UUID whitelist |
|
|
150
|
-
| `
|
|
273
|
+
| `groupPolicy` | No | OpenClaw default | Group-message policy: `open`, `allowlist`, or `disabled` |
|
|
274
|
+
| `groupAllowFrom` | No | `[]` | Authorized sender UUID whitelist for group messages when `groupPolicy` uses allowlisting |
|
|
275
|
+
| `requireMentionInGroup` | No | `true` | Apply plugin-side trigger-word filtering to group messages that have already been delivered to the bot |
|
|
276
|
+
| `mediaBypassMentionInGroup` | No | `true` | Allow inbound group file/audio messages through even without trigger text |
|
|
277
|
+
| `mediaMaxMb` | No | `30` | Max inbound and outbound media size in MB |
|
|
278
|
+
| `audioSendAsVoiceByDefault` | No | `true` | Send OpenClaw native outbound audio as Mixin voice when possible |
|
|
279
|
+
| `audioAutoDetectDuration` | No | `true` | Detect native outbound audio duration with `ffprobe` before sending voice |
|
|
280
|
+
| `audioRequireFfprobe` | No | `false` | Fail native outbound audio instead of falling back to file when duration detection is unavailable |
|
|
281
|
+
| `mixpay.enabled` | No | `false` | Enable MixPay collect support for this Mixin account |
|
|
282
|
+
| `mixpay.payeeId` | Required when enabled | - | MixPay merchant/payee ID used to create one-time payment orders |
|
|
283
|
+
| `mixpay.defaultQuoteAssetId` | No | - | Default quote asset ID for collect templates or future collect commands |
|
|
284
|
+
| `mixpay.defaultSettlementAssetId` | No | - | Default settlement asset ID for MixPay orders |
|
|
285
|
+
| `mixpay.expireMinutes` | No | `15` | Default MixPay order expiration time in minutes |
|
|
286
|
+
| `mixpay.pollIntervalSec` | No | `30` | Poll interval in seconds for pending MixPay orders |
|
|
287
|
+
| `mixpay.allowedCreators` | No | `[]` | Optional sender UUID allowlist for creating MixPay collect orders |
|
|
288
|
+
| `mixpay.notifyOnPending` | No | `false` | Notify the chat when MixPay reports `pending` |
|
|
289
|
+
| `mixpay.notifyOnPaidLess` | No | `true` | Notify the chat when MixPay indicates an underpayment |
|
|
290
|
+
| `conversations.<conversationId>.enabled` | No | `true` | Enable or disable a specific group conversation |
|
|
291
|
+
| `conversations.<conversationId>.requireMention` | No | Inherit account | Override group trigger-word requirement for a specific conversation |
|
|
292
|
+
| `conversations.<conversationId>.allowFrom` | No | Inherit account | Override group sender allowlist for a specific conversation |
|
|
293
|
+
| `conversations.<conversationId>.mediaBypassMention` | No | Inherit account | Override whether file/audio messages bypass mention filtering |
|
|
294
|
+
| `conversations.<conversationId>.groupPolicy` | No | Inherit account | Override group policy for a specific conversation |
|
|
151
295
|
| `debug` | No | `false` | Debug mode |
|
|
152
296
|
| `proxy.enabled` | No | `false` | Enable per-plugin proxy |
|
|
153
297
|
| `proxy.url` | Required when enabled | - | Proxy URL such as `http://127.0.0.1:7890` or `socks5://127.0.0.1:10808` |
|
|
@@ -160,6 +304,73 @@ Use `per-account-channel-peer` instead if you run multiple Mixin accounts and wa
|
|
|
160
304
|
- Supported proxy URL styles depend on the underlying proxy agent stack; typical values are `http://...`, `https://...`, and `socks5://...`.
|
|
161
305
|
- You must provide your own proxy software or proxy server. The plugin only consumes a proxy, it does not create one.
|
|
162
306
|
|
|
307
|
+
## Group Access Control
|
|
308
|
+
|
|
309
|
+
Mixin now supports formal group access controls in addition to direct-message `dmPolicy`.
|
|
310
|
+
|
|
311
|
+
- `groupPolicy: "open"` allows any sender in a group conversation.
|
|
312
|
+
- `groupPolicy: "allowlist"` requires the sender UUID to appear in `groupAllowFrom`.
|
|
313
|
+
- `groupPolicy: "disabled"` blocks the entire conversation.
|
|
314
|
+
- `conversations.<conversationId>` overrides account-level group settings for that single conversation.
|
|
315
|
+
|
|
316
|
+
Important delivery boundary:
|
|
317
|
+
|
|
318
|
+
- In practice, Mixin group bots reliably receive messages when the bot is explicitly mentioned.
|
|
319
|
+
- `requireMentionInGroup: false` only disables this plugin's own post-delivery filtering.
|
|
320
|
+
- It does not guarantee that Mixin will deliver every non-mention group message to the bot.
|
|
321
|
+
- If a non-mention group message produces no read receipt and no inbound log, the message most likely was not delivered to the plugin by Mixin in the first place.
|
|
322
|
+
|
|
323
|
+
Example:
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"channels": {
|
|
328
|
+
"mixin": {
|
|
329
|
+
"groupPolicy": "allowlist",
|
|
330
|
+
"groupAllowFrom": ["USER_A_UUID"],
|
|
331
|
+
"conversations": {
|
|
332
|
+
"70000000-0000-0000-0000-000000000001": {
|
|
333
|
+
"requireMention": false,
|
|
334
|
+
"allowFrom": ["USER_B_UUID"],
|
|
335
|
+
"mediaBypassMention": false
|
|
336
|
+
},
|
|
337
|
+
"70000000-0000-0000-0000-000000000002": {
|
|
338
|
+
"enabled": false
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
How to get these values:
|
|
347
|
+
|
|
348
|
+
- `conversations.<conversationId>`: use the group's `conversation_id`. In practice, the easiest way is to let the group send a message to the bot once, then read the `conversationId` from the plugin logs or inbound event context. Mixin's conversation APIs also use the same `conversation_id` field for group conversations.
|
|
349
|
+
- `groupAllowFrom` or `conversations.<conversationId>.allowFrom`: use the sender's Mixin `user_id` UUID. Mixin user IDs can be learned when the user messages the bot, adds the bot as a contact, or authorizes the application.
|
|
350
|
+
- If you manage the group through Mixin APIs, the returned conversation payload also includes group participants with their `user_id` fields.
|
|
351
|
+
|
|
352
|
+
Recommended operational approach:
|
|
353
|
+
|
|
354
|
+
- Let the target group send one message to the bot
|
|
355
|
+
- Copy the logged `conversationId`
|
|
356
|
+
- Let the target member send one message, then copy that sender's `user_id`
|
|
357
|
+
- Put those values into `conversations.<conversationId>` and `groupAllowFrom` / `allowFrom`
|
|
358
|
+
|
|
359
|
+
Pairing-style group authorization:
|
|
360
|
+
|
|
361
|
+
- An unauthorized user can send `/mixin-group-auth` in the target group
|
|
362
|
+
- The plugin replies with a temporary approval code for that `conversationId`
|
|
363
|
+
- An operator must approve it in the OpenClaw terminal with `openclaw pairing approve mixin <code>`
|
|
364
|
+
- For non-default accounts, use `openclaw pairing approve --account <accountId> mixin <code>`
|
|
365
|
+
- Once approved, that entire group conversation is allowed without changing `openclaw.json`
|
|
366
|
+
- Repeated `/mixin-group-auth` requests from the same unauthorized group are rate-limited to avoid spam
|
|
367
|
+
|
|
368
|
+
Where to look in logs:
|
|
369
|
+
|
|
370
|
+
- The plugin logs route resolution like `peer.kind=group, peer.id=<conversationId>`, which gives you the group `conversationId`
|
|
371
|
+
- Unauthorized or filtered group logs include `group sender <user_id>` and `conversationId=<conversationId>`
|
|
372
|
+
- If needed, temporarily enable a stricter group policy and let one member send a message once; the rejection log is often the fastest way to collect both values
|
|
373
|
+
|
|
163
374
|
## Usage
|
|
164
375
|
|
|
165
376
|
- Direct message: `/status` or `Hello`
|
|
@@ -172,6 +383,7 @@ Useful OpenClaw commands:
|
|
|
172
383
|
```bash
|
|
173
384
|
openclaw plugins list
|
|
174
385
|
openclaw plugins info mixin
|
|
386
|
+
openclaw plugins update mixin
|
|
175
387
|
openclaw channels status --probe
|
|
176
388
|
openclaw status
|
|
177
389
|
```
|
|
@@ -180,6 +392,23 @@ Plugin-specific command:
|
|
|
180
392
|
|
|
181
393
|
- Send `/mixin-outbox` to inspect the current pending queue size, next retry time, and latest error.
|
|
182
394
|
- Send `/mixin-outbox purge-invalid` to remove old `APP_CARD` / `APP_BUTTON_GROUP` entries that are stuck on permanent invalid-field errors.
|
|
395
|
+
- Send `/mixin-group-auth` in a group to create a pending group-authorization request.
|
|
396
|
+
- Approve a pending group-authorization request in the OpenClaw terminal with `openclaw pairing approve mixin <code>`.
|
|
397
|
+
- For non-default accounts, use `openclaw pairing approve --account <accountId> mixin <code>`.
|
|
398
|
+
- Send `/collect status <orderId>` to refresh and inspect a stored MixPay collect order.
|
|
399
|
+
- Send `/collect recent` or `/collect recent 10` to list recent MixPay collect orders for the current conversation.
|
|
400
|
+
|
|
401
|
+
Companion onboarding CLI:
|
|
402
|
+
|
|
403
|
+
- This repository also includes a companion CLI at `tools/mixin-plugin-onboard/README.md`.
|
|
404
|
+
- It is bundled into the same npm package, `@invago/mixin`.
|
|
405
|
+
- It currently provides `info`, `doctor`, `install`, and `update` commands for local OpenClaw + Mixin plugin maintenance.
|
|
406
|
+
- Local examples:
|
|
407
|
+
- `node --import jiti/register.js tools/mixin-plugin-onboard/src/index.ts info`
|
|
408
|
+
- `node --import jiti/register.js tools/mixin-plugin-onboard/src/index.ts doctor`
|
|
409
|
+
- Installed package examples:
|
|
410
|
+
- `npx -y @invago/mixin info`
|
|
411
|
+
- `npx -y @invago/mixin doctor`
|
|
183
412
|
|
|
184
413
|
## Delivery and Retry Behavior
|
|
185
414
|
|
|
@@ -193,13 +422,14 @@ Plugin-specific command:
|
|
|
193
422
|
Current media behavior is split into outbound and inbound support:
|
|
194
423
|
|
|
195
424
|
- OpenClaw native outbound media is enabled through the channel `sendMedia` path.
|
|
425
|
+
- OpenClaw native `sendPayload` now uses the same Mixin outbound planner as buffered agent replies, so text/post/buttons/card/file/audio selection is consistent.
|
|
196
426
|
- The plugin sends outbound audio as `PLAIN_AUDIO` when it can resolve the media as audio and detect duration.
|
|
197
427
|
- If audio duration cannot be detected, the plugin falls back to regular file attachment sending.
|
|
198
428
|
- Non-audio outbound media is sent as Mixin file attachments.
|
|
199
429
|
- If OpenClaw sends both caption text and media, the plugin sends the text first and then the file.
|
|
200
430
|
- Voice-bubble style outbound audio is currently intended for the explicit `mixin-audio` template path.
|
|
201
431
|
- Inbound `PLAIN_DATA` and `PLAIN_AUDIO` messages are downloaded, saved locally, and attached to the OpenClaw inbound context through `MediaPath` / `MediaType`.
|
|
202
|
-
- Group attachment messages are allowed through even when `requireMentionInGroup` is enabled
|
|
432
|
+
- Group attachment messages are allowed through even when `requireMentionInGroup` is enabled, unless `mediaBypassMentionInGroup` is set to `false`.
|
|
203
433
|
|
|
204
434
|
Current limits:
|
|
205
435
|
|
|
@@ -213,6 +443,99 @@ Manual test guide:
|
|
|
213
443
|
|
|
214
444
|
- See [docs/media-testing.md](docs/media-testing.md) for ready-to-run prompts and expected results.
|
|
215
445
|
|
|
446
|
+
## MixPay Collect
|
|
447
|
+
|
|
448
|
+
Mixin now supports MixPay collection through one-time payment orders.
|
|
449
|
+
|
|
450
|
+
Current capabilities:
|
|
451
|
+
|
|
452
|
+
- `mixin-collect` explicit reply template creates a MixPay collect order
|
|
453
|
+
- Collect orders are stored locally under the OpenClaw state directory
|
|
454
|
+
- Pending orders are polled in the background
|
|
455
|
+
- Success and terminal status changes are sent back to the original conversation
|
|
456
|
+
- `/collect status <orderId>` refreshes the order from MixPay before replying
|
|
457
|
+
- `assetId` in the template can be omitted when `mixpay.defaultQuoteAssetId` is configured
|
|
458
|
+
|
|
459
|
+
Template example:
|
|
460
|
+
|
|
461
|
+
````text
|
|
462
|
+
```mixin-collect
|
|
463
|
+
{
|
|
464
|
+
"amount": "1",
|
|
465
|
+
"assetId": "c6d0c728-2624-429b-8e0d-d9d19b6592fa",
|
|
466
|
+
"memo": "Order #1001"
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
````
|
|
470
|
+
|
|
471
|
+
Rules:
|
|
472
|
+
|
|
473
|
+
- `amount` is required; `assetId` is required unless `mixpay.defaultQuoteAssetId` is configured
|
|
474
|
+
- `settlementAssetId`, `memo`, `orderId`, and `expireMinutes` are optional
|
|
475
|
+
- Payment success is confirmed from MixPay server-side query results, not only from the client page
|
|
476
|
+
- `mixpay.allowedCreators` can restrict who is allowed to create collect orders
|
|
477
|
+
|
|
478
|
+
Where funds arrive:
|
|
479
|
+
|
|
480
|
+
- For MixPay `Mixin account`, funds settle into the linked Mixin Wallet
|
|
481
|
+
- For MixPay `Mixin Robot account`, funds settle into the linked Mixin Robot Wallet
|
|
482
|
+
- Other MixPay account types settle into their own linked wallet types
|
|
483
|
+
|
|
484
|
+
Recommended setup for this plugin:
|
|
485
|
+
|
|
486
|
+
- Use a MixPay `Mixin account` or `Mixin Robot account`
|
|
487
|
+
- Use that account's UUID as `mixpay.payeeId`
|
|
488
|
+
- Set both `mixpay.defaultQuoteAssetId` and `mixpay.defaultSettlementAssetId` if you want templates to stay short
|
|
489
|
+
|
|
490
|
+
How to get the required values:
|
|
491
|
+
|
|
492
|
+
- `mixpay.payeeId`: get the UUID from the [MixPay Dashboard](https://dashboard.mixpay.me) settings page, or use the MixPay helper bot described in the official getting-started guide
|
|
493
|
+
- `mixpay.defaultQuoteAssetId`: choose the asset ID you want to quote prices in
|
|
494
|
+
- `mixpay.defaultSettlementAssetId`: choose the asset ID you want funds to settle into
|
|
495
|
+
|
|
496
|
+
Minimal recommended config:
|
|
497
|
+
|
|
498
|
+
```json
|
|
499
|
+
{
|
|
500
|
+
"channels": {
|
|
501
|
+
"mixin": {
|
|
502
|
+
"mixpay": {
|
|
503
|
+
"enabled": true,
|
|
504
|
+
"payeeId": "YOUR_MIXPAY_UUID",
|
|
505
|
+
"defaultQuoteAssetId": "YOUR_QUOTE_ASSET_ID",
|
|
506
|
+
"defaultSettlementAssetId": "YOUR_SETTLEMENT_ASSET_ID"
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
Where to put it:
|
|
514
|
+
|
|
515
|
+
- Single-account setup: put `mixpay` under `channels.mixin.mixpay`
|
|
516
|
+
- Multi-account setup: put it under `channels.mixin.accounts.<accountId>.mixpay`
|
|
517
|
+
- `mixpay` is account-scoped, so different Mixin bot accounts can use different MixPay settings
|
|
518
|
+
|
|
519
|
+
Field reference:
|
|
520
|
+
|
|
521
|
+
- `mixpay.enabled`: enable MixPay collect support for this Mixin account
|
|
522
|
+
- `mixpay.apiBaseUrl`: optional custom MixPay API base URL; normally leave it empty and use the default official endpoint
|
|
523
|
+
- `mixpay.payeeId`: the MixPay payee/merchant UUID that actually receives the funds; required when MixPay collect is enabled
|
|
524
|
+
- `mixpay.defaultQuoteAssetId`: default quoted asset ID; when set, `mixin-collect` can omit `assetId`
|
|
525
|
+
- `mixpay.defaultSettlementAssetId`: default settlement asset ID; controls which asset the order prefers to settle into
|
|
526
|
+
- `mixpay.expireMinutes`: default expiration time for newly created collect orders
|
|
527
|
+
- `mixpay.pollIntervalSec`: background polling interval for pending orders; shorter values detect paid orders faster but create more MixPay API traffic
|
|
528
|
+
- `mixpay.allowedCreators`: optional sender UUID allowlist; when non-empty, only these users can create collect orders in chat
|
|
529
|
+
- `mixpay.notifyOnPending`: whether to send a conversation update when MixPay reports the order as `pending`
|
|
530
|
+
- `mixpay.notifyOnPaidLess`: whether to send a conversation update when MixPay reports an underpayment
|
|
531
|
+
|
|
532
|
+
Practical guidance:
|
|
533
|
+
|
|
534
|
+
- If you only want the smallest working setup, configure `enabled`, `payeeId`, `defaultQuoteAssetId`, and `defaultSettlementAssetId`
|
|
535
|
+
- If you do not want everyone in an authorized chat to create collect orders, set `allowedCreators`
|
|
536
|
+
- If you do not run a private MixPay gateway, leave `apiBaseUrl` unset
|
|
537
|
+
- If you want fewer status messages in chat, keep `notifyOnPending: false`
|
|
538
|
+
|
|
216
539
|
## Explicit Reply Templates
|
|
217
540
|
|
|
218
541
|
When you want deterministic Mixin output instead of heuristic auto-selection, have the agent reply with exactly one fenced template block.
|
|
@@ -297,6 +620,7 @@ Rules:
|
|
|
297
620
|
- `mixin-file` and `mixin-audio` also accept JSON only.
|
|
298
621
|
- `mixin-audio` requires `duration` in seconds. `waveForm` is optional.
|
|
299
622
|
- `mixin-file` and `mixin-audio` require absolute local file paths on the machine where OpenClaw runs.
|
|
623
|
+
- Invalid explicit `mixin-*` templates are no longer dropped silently; the plugin now sends a visible `Mixin template error: ...` message instead.
|
|
300
624
|
- Button and card links must use `http://` or `https://`.
|
|
301
625
|
- Mixin clients may require your target domains to be present in the bot app's `Resource Patterns` allowlist.
|
|
302
626
|
|