@unblocklabs/unblock-memory 0.8.3 → 0.9.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 +194 -94
- package/dist/src/config.d.ts +2 -0
- package/dist/src/config.js +4 -2
- package/dist/src/diagnostics.d.ts +46 -2
- package/dist/src/diagnostics.js +11 -2
- package/dist/src/inside-out.js +3 -10
- package/dist/src/plugin.js +2 -0
- package/dist/src/response-judge.d.ts +1 -1
- package/dist/src/response-stages.d.ts +1 -1
- package/dist/src/response-text.d.ts +7 -0
- package/dist/src/response-text.js +14 -2
- package/dist/src/review-tools.js +4 -1
- package/dist/src/safety-config.d.ts +30 -0
- package/dist/src/safety-config.js +118 -0
- package/dist/src/safety-whisperer.d.ts +31 -0
- package/dist/src/safety-whisperer.js +302 -0
- package/dist/src/skill-whisperer.d.ts +1 -0
- package/dist/src/skill-whisperer.js +2 -2
- package/dist/src/typesafe-client.d.ts +2 -0
- package/dist/src/typesafe-client.js +7 -0
- package/dist/src/whisperer-prompt.d.ts +4 -2
- package/dist/src/whisperer-prompt.js +6 -5
- package/docs/configuration.md +166 -1
- package/openclaw.plugin.json +95 -1
- package/package.json +1 -1
package/docs/configuration.md
CHANGED
|
@@ -16,6 +16,7 @@ settings; a rotated credential file is reread without a restart.
|
|
|
16
16
|
| Skill Whisperer | `skillWhisperer.enabled`, skills corpus, host hooks | Best local vector candidate meeting `minScore` | Exclude failed candidates; successful siblings may qualify; no vector fallback |
|
|
17
17
|
| Memory Whisperer | `memoryWhisperer.enabled`, explicit approved corpora, host hooks | No hints | Exclude failed candidates; recall/deadline failures still suppress the turn |
|
|
18
18
|
| Complementary hints | Enabled Memory Whisperer + `complementaryHints` | No additional judgment; base hints also require a key | Keep baseline hints unless the total deadline expires |
|
|
19
|
+
| Safety Whisperer | `safetyWhisperer.enabled`, at least one scenario, host hooks (conversation access and prompt injection) | Could not check: the turn proceeds without safety prompts (fails open) | Fails open; recorded as could-not-check, never as no match |
|
|
19
20
|
| People store/tools | `people.enabled` | Available; automatic save review needs primer/key or verified manual alternative | Storage/inspection still available |
|
|
20
21
|
| People Whisperer | People + `people.whisperer.enabled`, host hooks, eligible person/dossier, no prior thread receipt | Unchanged local lookup | Unchanged local lookup |
|
|
21
22
|
| People Primer / automatic dossier save review | People + `peoplePrimer.enabled`, approved corpora | No judgment; save requires source-specific manual verification | No automatic save; verify/retry instead |
|
|
@@ -215,7 +216,7 @@ contract; these tables explain their effects.
|
|
|
215
216
|
| `typesafe.enabled` | `true` | Shared plugin provider gate; no feature is opted in merely by adding a key |
|
|
216
217
|
| `typesafe.apiKey` | Unset | Explicit inline key; mutually exclusive with key file; prefer file |
|
|
217
218
|
| `typesafe.apiKeyFile` | Unset | Absolute raw-key or dotenv file, reread at credential resolution; explicit missing file never falls back to a different key |
|
|
218
|
-
| `typesafe.timeoutMs` | `1500` | 1–10,000 per request for Skill/Memory Whisperer, quality/claim/cluster review and response audit; **primer and dossier save use `peoplePrimer.timeoutMs` instead** |
|
|
219
|
+
| `typesafe.timeoutMs` | `1500` | 1–10,000 per request for Skill/Memory Whisperer, quality/claim/cluster review and response audit; **primer and dossier save use `peoplePrimer.timeoutMs` and Safety Whisperer uses `safetyWhisperer.timeoutMs` instead** |
|
|
219
220
|
| `skillWhisperer.enabled` | `false` | Requires explicit skills corpus and appropriate host hook access; fixed 3-second total deadline |
|
|
220
221
|
| `skillWhisperer.historyMessages` | `5` | Nonnegative integer; prior visible messages used for routing |
|
|
221
222
|
| `skillWhisperer.minScore` | `0.5` | 0–1, **local vector fallback only**, ignored for TypeSafe shortlist admission |
|
|
@@ -230,6 +231,18 @@ contract; these tables explain their effects.
|
|
|
230
231
|
| `memoryWhisperer.cooldownTurns` | `10` | 0–1,000; recently injected evidence |
|
|
231
232
|
| `memoryWhisperer.timeoutMs` | `3000` | 1–10,000 total whisper deadline, not just the provider timeout |
|
|
232
233
|
| `memoryWhisperer.complementaryHints` | `false` | Optional extra redundancy judgment; does not expand retrieval or enable the feature |
|
|
234
|
+
| `safetyWhisperer.enabled` | `false` | Requires at least one scenario, a TypeSafe key and host hooks; see [Safety Whisperer](#safety-whisperer) |
|
|
235
|
+
| `safetyWhisperer.historyMessages` | `6` | 0–20 earlier visible messages, whole messages only, for resolving follow-ups |
|
|
236
|
+
| `safetyWhisperer.timeoutMs` | `3000` | 1–10,000 total deadline (credential and request); the host hook timeout must exceed the slowest enabled whisperer |
|
|
237
|
+
| `safetyWhisperer.excludedChannels` | `[]` | Up to 500 `{ provider, accountId, channelId, name? }`, matched case-insensitively; skips every scenario there |
|
|
238
|
+
| `safetyWhisperer.scenarios` | `[]` | Up to 20; unique `id` of letters, digits, `.`, `_` or `-` |
|
|
239
|
+
| `safetyWhisperer.scenarios[].instructions` | Required | Up to 2,000 characters: what the scenario covers, with exclusions; sent to TypeSafe |
|
|
240
|
+
| `safetyWhisperer.scenarios[].flaggedPrompt` | Required | Up to 2,000 characters, appended for matching unapproved requests; never sent to TypeSafe |
|
|
241
|
+
| `safetyWhisperer.scenarios[].minProbability` | `0.4` | 0–1 minimum yes-probability that the current request is covered |
|
|
242
|
+
| `safetyWhisperer.scenarios[].approvedRequestors` | `[]` | Up to 500 `{ provider, accountId, senderId, name? }`; `senderId` must match exactly; skip this scenario for them |
|
|
243
|
+
| `safetyWhisperer.scenarios[].excludedChannels` | `[]` | Up to 500 channels where only this scenario is skipped |
|
|
244
|
+
| `safetyWhisperer.scenarios[].agentIds` | Unset (every agent) | Non-empty list limits the scenario to these agents when one config serves several; normalized like OpenClaw agent IDs (lowercase) |
|
|
245
|
+
| `safetyWhisperer.scenarios[].enabled` | `true` | Disabled scenarios are never sent to TypeSafe |
|
|
233
246
|
|
|
234
247
|
No configured plugin credential means fallback to **`TYPESAFE_API_KEY` only** in
|
|
235
248
|
the Gateway environment. Unlike QMD's resolver, the plugin does not read a
|
|
@@ -364,6 +377,7 @@ boundary, not multi-tenant authorization. Approve sources for the agent's audien
|
|
|
364
377
|
| Cluster review | Up to 6 eligible complete sampled chunks, each at most 2,000 characters; conclusions only concern the sample |
|
|
365
378
|
| Response audit | Approved visible request/answer/context/feedback and bounded later response evidence, separated by assessment stage; optional current-index whole-short-document evidence from approved file corpora |
|
|
366
379
|
| Inside Out | Target human reply, nearest assistant text and bounded preceding visible history; channel-scoped speaker identity keys |
|
|
380
|
+
| Safety check | The complete current human message without OpenClaw's conversation-info header; the thread starter, replied-to message and channel messages since the last reply that arrived with it, which can include other people's names and message IDs; up to `historyMessages` earlier visible messages; and each eligible scenario's `instructions`. No sender, account or channel IDs from that header, approval lists or flagged prompts. A message wrapper Safety Whisperer does not recognize (anything other than Slack's) is sent whole, minus that header. |
|
|
367
381
|
| Standalone QMD query | Query, optional intent, selected excerpts, source paths and evaluation time; separate process/SDK credentials and collection scope |
|
|
368
382
|
|
|
369
383
|
Omitting tool-result/thinking/system fields does not remove their content if it
|
|
@@ -371,6 +385,157 @@ was quoted in ordinary visible text. Provider judgments are advisory; probabilit
|
|
|
371
385
|
or score is not proof. Enabling a feature approves only that feature's documented processing.
|
|
372
386
|
|
|
373
387
|
|
|
388
|
+
## Safety Whisperer
|
|
389
|
+
|
|
390
|
+
An optional, interim guardrail for agents that serve several people. Before the
|
|
391
|
+
main model runs on a human turn, it checks the current message against scenarios
|
|
392
|
+
you define, such as questions about one person's salary. When a requestor who is
|
|
393
|
+
not approved for a scenario asks something it covers, that scenario's
|
|
394
|
+
`flaggedPrompt` is appended next to their message for that turn.
|
|
395
|
+
|
|
396
|
+
**This is a prompt-level guardrail, not access control.** The classifier can miss
|
|
397
|
+
a request and the agent can ignore an injected instruction. It does not remove
|
|
398
|
+
sensitive information already available in context, memory or tools. An approved
|
|
399
|
+
requestor is not an approved audience: asking in a shared channel can still expose
|
|
400
|
+
an answer to everyone there. Use separate agents and real data-access controls for
|
|
401
|
+
hard boundaries.
|
|
402
|
+
|
|
403
|
+
```json
|
|
404
|
+
{
|
|
405
|
+
"safetyWhisperer": {
|
|
406
|
+
"enabled": true,
|
|
407
|
+
"excludedChannels": [
|
|
408
|
+
{ "name": "#leadership", "provider": "slack", "accountId": "work", "channelId": "C_LEADERSHIP" }
|
|
409
|
+
],
|
|
410
|
+
"scenarios": [
|
|
411
|
+
{
|
|
412
|
+
"id": "individual-salaries",
|
|
413
|
+
"instructions": "Requests about a specific individual employee's salary, pay or compensation, including colloquial phrasing such as how much someone makes or earns. Exclude vendors and contractors.",
|
|
414
|
+
"approvedRequestors": [
|
|
415
|
+
{ "name": "Dani", "provider": "slack", "accountId": "work", "senderId": "U_DANI" }
|
|
416
|
+
],
|
|
417
|
+
"excludedChannels": [
|
|
418
|
+
{ "name": "#people-ops", "provider": "slack", "accountId": "work", "channelId": "C_PEOPLE_OPS" }
|
|
419
|
+
],
|
|
420
|
+
"flaggedPrompt": "This requestor is not approved to access this information. Kindly tell them that; do not disclose the requested information."
|
|
421
|
+
}
|
|
422
|
+
]
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
The plugin entry also needs `hooks.allowConversationAccess: true`, and
|
|
428
|
+
`allowPromptInjection` must not be `false`; see [host controls](#host-controls).
|
|
429
|
+
|
|
430
|
+
### How each turn is checked
|
|
431
|
+
|
|
432
|
+
1. Only user-triggered turns are checked, every time: there is no cooldown. A
|
|
433
|
+
prompt rebuild for the same run reuses that run's result. Messages steered
|
|
434
|
+
into a run that is already working are not checked; see
|
|
435
|
+
[messages sent while the agent works](#messages-sent-while-the-agent-works).
|
|
436
|
+
2. A global `excludedChannels` match skips every scenario. A scenario's own
|
|
437
|
+
`excludedChannels` skip only that scenario. Thread replies and forum topics
|
|
438
|
+
use their channel.
|
|
439
|
+
3. Disabled scenarios, scenarios limited to other `agentIds`, and scenarios that
|
|
440
|
+
approve this requestor are dropped.
|
|
441
|
+
4. If none remain, no request is made. Otherwise one TypeSafe request asks one
|
|
442
|
+
independent yes/no question per remaining scenario. It includes the complete
|
|
443
|
+
current message, the channel context that arrived with it (thread starter,
|
|
444
|
+
replied-to message, chat history since the agent's last reply) and up to
|
|
445
|
+
`historyMessages` earlier visible messages. A follow-up like "What about
|
|
446
|
+
Sally?" or "answer the question above" is therefore judged in context, while
|
|
447
|
+
the current message is judged, not whether an earlier one mentioned the topic.
|
|
448
|
+
5. Every scenario scoring at least its `minProbability` adds its `flaggedPrompt`
|
|
449
|
+
in `<safety>` tags, last in the shared `<unblock_memory>` block after the
|
|
450
|
+
human message.
|
|
451
|
+
|
|
452
|
+
### Messages sent while the agent works
|
|
453
|
+
|
|
454
|
+
OpenClaw's default queue mode, `steer`, adds a message sent during an active run
|
|
455
|
+
to that run without building a new prompt, so the message is never checked. The
|
|
456
|
+
same applies when a person types `/queue steer` in a session. For agents that
|
|
457
|
+
rely on Safety Whisperer, set `messages.queue.mode` (and any
|
|
458
|
+
`messages.queue.byChannel` entries) to `followup` or `collect`; `memory_diagnostics`
|
|
459
|
+
and the Gateway log warn with `queue_mode_steer` until then. In `collect` mode,
|
|
460
|
+
queued messages from different people carry no single sender, so none of them is
|
|
461
|
+
approved.
|
|
462
|
+
|
|
463
|
+
### Identity
|
|
464
|
+
|
|
465
|
+
Approval and exclusions compare `provider`, `accountId`, and `senderId` or
|
|
466
|
+
`channelId` values from the host's trusted turn metadata. `senderId` must match
|
|
467
|
+
exactly. `provider`, `accountId` and `channelId` match case-insensitively, because
|
|
468
|
+
OpenClaw lowercases them in places. Names are labels only; display names, message
|
|
469
|
+
text and identity claims never count. Missing identity never approves anyone and
|
|
470
|
+
never excludes a channel, so turns without a sender ID, such as CLI or webchat,
|
|
471
|
+
are treated as unapproved. Email-based approval is not supported.
|
|
472
|
+
|
|
473
|
+
For Slack:
|
|
474
|
+
|
|
475
|
+
- `provider` is `slack`.
|
|
476
|
+
- `accountId` is the OpenClaw Slack account key, or `default` when the channel
|
|
477
|
+
has one account.
|
|
478
|
+
- `senderId` is the person's member ID (`U…`): in their Slack profile, choose
|
|
479
|
+
**Copy member ID**.
|
|
480
|
+
- `channelId` is the channel's ID (`C…` or `G…`), shown at the bottom of the
|
|
481
|
+
channel details.
|
|
482
|
+
|
|
483
|
+
Some runtimes do not pass sender identity to plugins; OpenClaw's Codex
|
|
484
|
+
app-server harness is one. There, every requestor is treated as unapproved,
|
|
485
|
+
exclusions may not apply, and `memory_diagnostics` counts `missing_identity`;
|
|
486
|
+
the first such turn is also logged.
|
|
487
|
+
|
|
488
|
+
### When the check cannot run
|
|
489
|
+
|
|
490
|
+
Safety Whisperer **fails open**: if the check cannot complete, the turn proceeds
|
|
491
|
+
with no safety prompt. A TypeSafe outage or missing key therefore turns the
|
|
492
|
+
guardrail off. The exception is a message too large to check: the requestor
|
|
493
|
+
controls its size, so every eligible scenario's `flaggedPrompt` is added instead.
|
|
494
|
+
`memory_diagnostics` reports each outcome under `whisperers.safety`, keeping
|
|
495
|
+
could-not-check separate from no match:
|
|
496
|
+
|
|
497
|
+
| Outcome | Meaning |
|
|
498
|
+
| --- | --- |
|
|
499
|
+
| `flagged` | At least one scenario matched; `matchedScenarios` counts matches by scenario ID |
|
|
500
|
+
| `no_match` | Checked; no scenario matched |
|
|
501
|
+
| `excluded` / `no_scenarios` | Skipped by a global exclusion, or nothing remained after filtering; no request |
|
|
502
|
+
| `empty_request` | The current message had no text, such as an attachment alone; not checked |
|
|
503
|
+
| `missing_key` / `typesafe_disabled` | Could not check: no credential, or TypeSafe disabled |
|
|
504
|
+
| `input_too_large` | Not checked: the current message exceeds the roughly 24k-token budget. It is never truncated; every eligible `flaggedPrompt` is added |
|
|
505
|
+
| `timed_out` / `failed` | Could not check: deadline, provider error or no usable answer |
|
|
506
|
+
| `partial_response` | Counted with `flagged`: some answers were unusable, and the confident matches were still added |
|
|
507
|
+
| `missing_identity` | Counted with the turn's outcome: the host passed no provider, account or sender ID |
|
|
508
|
+
| `cancelled` | The session ended or the Gateway stopped during the check |
|
|
509
|
+
|
|
510
|
+
Warnings include the outcome, error code, HTTP status and scenario count, never
|
|
511
|
+
message text; a missing key is logged once until it returns.
|
|
512
|
+
`memory_diagnostics` also reports `safety.active: false` with a `reason` when
|
|
513
|
+
settings or host controls prevent checks (`typesafe_disabled`,
|
|
514
|
+
`conversation_access_not_allowed`, `prompt_injection_not_allowed`,
|
|
515
|
+
`no_enabled_scenarios`), and a `warnings` list:
|
|
516
|
+
|
|
517
|
+
- `host_hook_timeout_below_whisperer_timeouts`: the host's `before_prompt_build`
|
|
518
|
+
timeout is shorter than the slowest enabled whisperer (`slowestWhispererMs`).
|
|
519
|
+
The host times out the plugin's whole contribution, so a slow Memory Whisperer
|
|
520
|
+
turn can drop a safety prompt even after diagnostics counted it as `flagged`.
|
|
521
|
+
- `queue_mode_steer`: see
|
|
522
|
+
[messages sent while the agent works](#messages-sent-while-the-agent-works).
|
|
523
|
+
|
|
524
|
+
The Gateway logs this status at startup when the feature is inactive or has a
|
|
525
|
+
warning.
|
|
526
|
+
|
|
527
|
+
### Writing scenarios
|
|
528
|
+
|
|
529
|
+
`instructions` are the classifier's entire definition of a scenario. Name the
|
|
530
|
+
subject, its synonyms and colloquial phrasing, and what is excluded. In the
|
|
531
|
+
source checkout's `eval/safety-whisperer/` cases, adding "pay … including how much
|
|
532
|
+
someone makes or earns" raised a compound request ("What does Bob make, and is he
|
|
533
|
+
on medical leave?") from 0.06 to 0.45–0.48 and lowered "When is payday?" from 0.45
|
|
534
|
+
to 0.18–0.21. With that wording, the 0.4 default `minProbability` made no errors
|
|
535
|
+
across 22 cases, while 0.5 missed the compound request. Lower it to catch more
|
|
536
|
+
borderline requests, or raise it for fewer false refusals. Test your own scenarios
|
|
537
|
+
there before relying on them.
|
|
538
|
+
|
|
374
539
|
## Inside Out
|
|
375
540
|
|
|
376
541
|
Inside Out records six independent emotion-presence probabilities for each human
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "unblock-memory",
|
|
3
3
|
"name": "Unblock Memory",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"description": "Indexes, retrieves, and analyzes configured workspace memory with existing QMD vectors.",
|
|
6
6
|
"kind": "memory",
|
|
7
7
|
"activation": { "onStartup": true },
|
|
@@ -92,6 +92,14 @@
|
|
|
92
92
|
"label": "Approved Hint Corpora",
|
|
93
93
|
"help": "Explicit non-skill corpus allowlist for automatic recall and TypeSafe processing. Session recall spans this agent's indexed sessions; the sessions corpus chatTypes setting controls direct-message inclusion."
|
|
94
94
|
},
|
|
95
|
+
"safetyWhisperer.enabled": {
|
|
96
|
+
"label": "Safety Whisperer",
|
|
97
|
+
"help": "Prompt-level guardrail, not access control. Sends every checked human message and bounded recent history to TypeSafe and appends a scenario's flaggedPrompt when an unapproved requestor's message matches. Fails open: if the check cannot run, the turn proceeds without it. Requires hook conversation access and prompt injection. Disabled by default."
|
|
98
|
+
},
|
|
99
|
+
"safetyWhisperer.scenarios": {
|
|
100
|
+
"label": "Safety Scenarios",
|
|
101
|
+
"help": "Each scenario is judged independently. Approval and exclusions match exact provider/account/sender or channel IDs from trusted channel metadata, never names or message text."
|
|
102
|
+
},
|
|
95
103
|
"people.enabled": {
|
|
96
104
|
"label": "PeopleSQL",
|
|
97
105
|
"help": "Enable the agent-local people store, Slack identity observation and people tools. Disabled by default; whispering and TypeSafe primer/review are separate opt-ins."
|
|
@@ -351,6 +359,92 @@
|
|
|
351
359
|
"minScore": 0.5,
|
|
352
360
|
"cooldownTurns": 10
|
|
353
361
|
}
|
|
362
|
+
},
|
|
363
|
+
"safetyWhisperer": {
|
|
364
|
+
"type": "object",
|
|
365
|
+
"additionalProperties": false,
|
|
366
|
+
"description": "Optional prompt-level guardrail for sensitive request scenarios. Fails open when the check cannot run.",
|
|
367
|
+
"properties": {
|
|
368
|
+
"enabled": { "type": "boolean", "default": false },
|
|
369
|
+
"historyMessages": { "type": "integer", "minimum": 0, "maximum": 20, "default": 6 },
|
|
370
|
+
"timeoutMs": { "type": "integer", "minimum": 1, "maximum": 10000, "default": 3000 },
|
|
371
|
+
"excludedChannels": {
|
|
372
|
+
"type": "array",
|
|
373
|
+
"maxItems": 500,
|
|
374
|
+
"description": "Channels where every safety scenario is skipped. Threads inherit their channel.",
|
|
375
|
+
"items": {
|
|
376
|
+
"type": "object",
|
|
377
|
+
"additionalProperties": false,
|
|
378
|
+
"required": ["provider", "accountId", "channelId"],
|
|
379
|
+
"properties": {
|
|
380
|
+
"name": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
381
|
+
"provider": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
382
|
+
"accountId": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
383
|
+
"channelId": { "type": "string", "pattern": "\\S", "maxLength": 256 }
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"scenarios": {
|
|
388
|
+
"type": "array",
|
|
389
|
+
"maxItems": 20,
|
|
390
|
+
"items": {
|
|
391
|
+
"type": "object",
|
|
392
|
+
"additionalProperties": false,
|
|
393
|
+
"required": ["id", "instructions", "flaggedPrompt"],
|
|
394
|
+
"properties": {
|
|
395
|
+
"id": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$" },
|
|
396
|
+
"enabled": { "type": "boolean", "default": true },
|
|
397
|
+
"instructions": { "type": "string", "pattern": "\\S", "maxLength": 2000, "description": "What requests this scenario covers, including exclusions." },
|
|
398
|
+
"flaggedPrompt": { "type": "string", "pattern": "\\S", "maxLength": 2000, "description": "Appended next to the human message when an unapproved requestor's message matches." },
|
|
399
|
+
"minProbability": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.4, "description": "Minimum TypeSafe yes-probability that the current request is covered." },
|
|
400
|
+
"agentIds": {
|
|
401
|
+
"type": "array",
|
|
402
|
+
"minItems": 1,
|
|
403
|
+
"maxItems": 500,
|
|
404
|
+
"description": "Limit the scenario to these agents; omit for every agent.",
|
|
405
|
+
"items": { "type": "string", "pattern": "\\S", "maxLength": 256 }
|
|
406
|
+
},
|
|
407
|
+
"approvedRequestors": {
|
|
408
|
+
"type": "array",
|
|
409
|
+
"maxItems": 500,
|
|
410
|
+
"items": {
|
|
411
|
+
"type": "object",
|
|
412
|
+
"additionalProperties": false,
|
|
413
|
+
"required": ["provider", "accountId", "senderId"],
|
|
414
|
+
"properties": {
|
|
415
|
+
"name": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
416
|
+
"provider": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
417
|
+
"accountId": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
418
|
+
"senderId": { "type": "string", "pattern": "\\S", "maxLength": 256 }
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
"excludedChannels": {
|
|
423
|
+
"type": "array",
|
|
424
|
+
"maxItems": 500,
|
|
425
|
+
"items": {
|
|
426
|
+
"type": "object",
|
|
427
|
+
"additionalProperties": false,
|
|
428
|
+
"required": ["provider", "accountId", "channelId"],
|
|
429
|
+
"properties": {
|
|
430
|
+
"name": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
431
|
+
"provider": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
432
|
+
"accountId": { "type": "string", "pattern": "\\S", "maxLength": 256 },
|
|
433
|
+
"channelId": { "type": "string", "pattern": "\\S", "maxLength": 256 }
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
"default": {
|
|
442
|
+
"enabled": false,
|
|
443
|
+
"historyMessages": 6,
|
|
444
|
+
"timeoutMs": 3000,
|
|
445
|
+
"excludedChannels": [],
|
|
446
|
+
"scenarios": []
|
|
447
|
+
}
|
|
354
448
|
}
|
|
355
449
|
}
|
|
356
450
|
}
|